Updating dependencies, fixing search, fixing wishlist add and remove, fixing game page, not showing buttons on list of games, and adding helper components.

This commit is contained in:
Bradley Shellnut 2023-08-13 22:12:02 -07:00
parent c4a141a1ff
commit bdfc1dfd3f
28 changed files with 988 additions and 748 deletions

View file

@ -1,3 +1,3 @@
{ {
"cSpell.words": ["iconify", "kickstarter", "msrp"] "cSpell.words": ["iconify", "kickstarter", "lucide", "msrp"]
} }

View file

@ -22,18 +22,18 @@
"seed": "ts-node --esm prisma/seed.ts" "seed": "ts-node --esm prisma/seed.ts"
}, },
"devDependencies": { "devDependencies": {
"@melt-ui/pp": "^0.0.7", "@melt-ui/pp": "^0.1.2",
"@playwright/test": "^1.36.2", "@playwright/test": "^1.37.0",
"@sveltejs/adapter-auto": "^1.0.3", "@sveltejs/adapter-auto": "^1.0.3",
"@sveltejs/adapter-vercel": "^1.0.6", "@sveltejs/adapter-vercel": "^1.0.6",
"@sveltejs/kit": "^1.22.4", "@sveltejs/kit": "^1.22.5",
"@types/cookie": "^0.5.1", "@types/cookie": "^0.5.1",
"@types/node": "^18.17.1", "@types/node": "^18.17.5",
"@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0", "@typescript-eslint/parser": "^5.62.0",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.15",
"eslint": "^8.46.0", "eslint": "^8.47.0",
"eslint-config-prettier": "^8.9.0", "eslint-config-prettier": "^8.10.0",
"eslint-plugin-svelte": "^2.32.4", "eslint-plugin-svelte": "^2.32.4",
"just-clone": "^6.2.0", "just-clone": "^6.2.0",
"just-debounce-it": "^3.2.0", "just-debounce-it": "^3.2.0",
@ -44,18 +44,18 @@
"prettier": "^2.8.8", "prettier": "^2.8.8",
"prettier-plugin-svelte": "^2.10.1", "prettier-plugin-svelte": "^2.10.1",
"prisma": "^5.1.1", "prisma": "^5.1.1",
"sass": "^1.64.2", "sass": "^1.65.1",
"svelte": "^4.1.2", "svelte": "^4.2.0",
"svelte-check": "^3.4.6", "svelte-check": "^3.5.0",
"svelte-preprocess": "^5.0.4", "svelte-preprocess": "^5.0.4",
"svelte-sequential-preprocessor": "^2.0.1", "svelte-sequential-preprocessor": "^2.0.1",
"sveltekit-flash-message": "^2.1.0", "sveltekit-flash-message": "^2.1.3",
"sveltekit-superforms": "^1.5.0", "sveltekit-superforms": "^1.5.1",
"tailwindcss": "^3.3.3", "tailwindcss": "^3.3.3",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.6.1", "tslib": "^2.6.1",
"typescript": "^5.1.6", "typescript": "^5.1.6",
"vite": "^4.4.8", "vite": "^4.4.9",
"vitest": "^0.25.3", "vitest": "^0.25.3",
"zod": "^3.21.4" "zod": "^3.21.4"
}, },
@ -70,9 +70,9 @@
"@iconify-icons/line-md": "^1.2.23", "@iconify-icons/line-md": "^1.2.23",
"@iconify-icons/mdi": "^1.2.47", "@iconify-icons/mdi": "^1.2.47",
"@lucia-auth/adapter-mysql": "^2.0.0", "@lucia-auth/adapter-mysql": "^2.0.0",
"@lucia-auth/adapter-prisma": "^3.0.0", "@lucia-auth/adapter-prisma": "^3.0.1",
"@lukeed/uuid": "^2.0.1", "@lukeed/uuid": "^2.0.1",
"@melt-ui/svelte": "^0.27.3", "@melt-ui/svelte": "^0.34.6",
"@prisma/client": "5.1.1", "@prisma/client": "5.1.1",
"@types/feather-icons": "^4.29.1", "@types/feather-icons": "^4.29.1",
"class-variance-authority": "^0.6.1", "class-variance-authority": "^0.6.1",
@ -82,9 +82,9 @@
"iconify-icon": "^1.0.8", "iconify-icon": "^1.0.8",
"just-kebab-case": "^4.2.0", "just-kebab-case": "^4.2.0",
"loader": "^2.1.1", "loader": "^2.1.1",
"lucia": "^2.0.0", "lucia": "^2.3.0",
"lucide-svelte": "^0.256.1", "lucide-svelte": "^0.256.1",
"open-props": "^1.5.10", "open-props": "^1.5.11",
"radix-svelte": "^0.8.0", "radix-svelte": "^0.8.0",
"svelte-french-toast": "^1.2.0", "svelte-french-toast": "^1.2.0",
"svelte-lazy": "^1.2.1", "svelte-lazy": "^1.2.1",

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,8 @@ model User {
receiveEmail Boolean @default(false) receiveEmail Boolean @default(false)
token String? @unique token String? @unique
collection Collection? collection Collection?
wishlist Wishlist[] wishlist Wishlist?
list List[]
theme String @default("system") theme String @default("system")
created_at DateTime @default(now()) @db.Timestamp(6) created_at DateTime @default(now()) @db.Timestamp(6)
updated_at DateTime @updatedAt @db.Timestamp(6) updated_at DateTime @updatedAt @db.Timestamp(6)
@ -101,7 +102,6 @@ model CollectionItem {
model Wishlist { model Wishlist {
id String @id @default(cuid()) id String @id @default(cuid())
name String
user_id String @unique user_id String @unique
user User @relation(references: [id], fields: [user_id]) user User @relation(references: [id], fields: [user_id])
items WishlistItem[] items WishlistItem[]
@ -123,6 +123,30 @@ model WishlistItem {
@@map("wishlist_items") @@map("wishlist_items")
} }
model List {
id String @id @default(cuid())
name String
user_id String @unique
user User @relation(references: [id], fields: [user_id])
items ListItem[]
@@index([user_id])
@@map("lists")
}
model ListItem {
id String @id @default(cuid())
list_id String @unique
list List @relation(references: [id], fields: [list_id], onDelete: Cascade)
game_id String @unique
game Game @relation(references: [id], fields: [game_id])
created_at DateTime @default(now()) @db.Timestamp(6)
updated_at DateTime @updatedAt @db.Timestamp(6)
@@index([game_id, list_id])
@@map("list_items")
}
model Game { model Game {
id String @id @default(cuid()) id String @id @default(cuid())
name String name String
@ -152,6 +176,7 @@ model Game {
expansions Expansion[] expansions Expansion[]
collection_items CollectionItem[] collection_items CollectionItem[]
wishlist_items WishlistItem[] wishlist_items WishlistItem[]
list_items ListItem[]
external_id String @unique external_id String @unique
created_at DateTime @default(now()) @db.Timestamp(6) created_at DateTime @default(now()) @db.Timestamp(6)
updated_at DateTime @updatedAt @db.Timestamp(6) updated_at DateTime @updatedAt @db.Timestamp(6)

View file

0
src/lib/apis/wishlist.ts Normal file
View file

View file

@ -0,0 +1,138 @@
<script lang="ts">
import { enhance } from "$app/forms";
import { fly } from "svelte/transition";
import { createSelect, melt } from "@melt-ui/svelte";
import { Check, ChevronDown, MinusCircle, PlusCircle } from "lucide-svelte";
import Button from "./ui/button/Button.svelte";
import type { Collection, Wishlist } from "@prisma/client";
export let game_id: string;
export let collection: Collection;
export let wishlist: Wishlist;
export let in_wishlist = false;
export let in_collection = false;
export let lists = [];
const handleChange = ({ curr, next }) => {
console.log({ curr, next });
return next;
}
const {
elements: { trigger, menu, option, label, group, groupLabel },
states: { valueLabel, open },
helpers: { isSelected },
} = createSelect({
forceVisible: true,
onValueChange: handleChange
});
console.log({ in_collection, in_wishlist });
let options: Record<string, string> = {};
let list_of_lists = [];
if (!in_collection) {
options[collection.id] = 'Add to collection';
}
if (!in_wishlist) {
options[wishlist.id] = 'Add to wishlist';
}
lists.forEach((list) => {
if (!list?.in_list) {
options[list.id] = list.name;
}
});
</script>
{#if in_wishlist}
<form method="POST" action={`/wishlist?/remove`} use:enhance>
<input type="hidden" name="id" value={game_id} />
<Button variant="destructive" type="submit">
<MinusCircle class="square-5" /> Remove from wishlist
</Button>
</form>
{:else}
<form method="POST" action='/wishlist?/add' use:enhance>
<input type="hidden" name="id" value={game_id} />
<Button variant="destructive" type="submit">
<PlusCircle class="square-5" /> Add to wishlist
</Button>
</form>
{/if}
{#if in_collection}
<form method="POST" action='/collection?/remove' use:enhance>
<input type="hidden" name="id" value={game_id} />
<Button variant="destructive" type="submit">
<MinusCircle class="square-5" /> Remove from collection
</Button>
</form>
{:else}
<form method="POST" action='/collection?/add' use:enhance>
<input type="hidden" name="id" value={game_id} />
<Button variant="destructive" type="submit">
<PlusCircle class="square-5" /> Add to collection
</Button>
</form>
{/if}
<div class="flex flex-col gap-1">
<!-- svelte-ignore a11y-label-has-associated-control - $label contains the 'for' attribute -->
<button
class="flex h-10 min-w-[220px] items-center justify-between rounded-md bg-white px-3 py-2 text-black-500 transition-opacity hover:opacity-90"
use:melt={$trigger}
aria-label="Wishlist"
>
{$valueLabel || 'Add to...'}
<ChevronDown class="square-5" />
</button>
{#if $open}
<div
class="z-10 flex max-h-[360px] flex-col overflow-y-auto rounded-md bg-white p-1 focus:!ring-0"
use:melt={$menu}
transition:fly={{ duration: 150, y: -5 }}
>
{#each Object.entries(options) as [key, value]}
<div
class="flex relative cursor-pointer rounded-md py-1 pl-8 pr-4 text-neutral-800 focus:z-10 focus:text-purple-700 data-[highlighted]:bg-purple-50 data-[selected]:bg-purple-100 data-[highlighted]:text-purple-900 data-[selected]:text-purple-900"
use:melt={$option({ value: key, label: value })}
>
{value}
{#if $isSelected(key)}
<div class="check">
<Check class="square-4" />
</div>
{/if}
</div>
{/each}
</div>
{/if}
</div>
<!-- <CardFooter>
<div class="grid gap-2 place-items-center">
<form method="POST" action={`/collection?/${existsInCollection ? 'remove' : 'add'}`}>
<input type="hidden" name="id" value={game.id} />
<Button variant={existsInCollection ? 'destructive' : 'default'}>
{collectionText}
{#if existsInCollection}
<iconify-icon class="ml-2" icon={minusCircle} width="24" height="24" />
{:else}
<iconify-icon class="ml-2" icon={plusCircle} width="24" height="24" />
{/if}
</Button>
</form>
<!-- Add dropdown for wishlist add -->
<!--- <form method="POST" action={`/wishlist?/${existsInWishlist ? 'remove' : 'add'}`}>
<input type="hidden" name="id" value={game.id} />
<Button variant={existsInWishlist ? 'destructive' : 'default'}>
{wishlistText}
{#if existsInWishlist}
<iconify-icon class="ml-2" icon={minusCircle} width="24" height="24" />
{:else}
<iconify-icon class="ml-2" icon={plusCircle} width="24" height="24" />
{/if}
</Button>
</form>
</div>
</CardFooter> -->

View file

View file

@ -1,89 +1,18 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from 'svelte';
import { Image } from 'svelte-lazy-loader';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import plusCircle from '@iconify-icons/line-md/plus-circle';
import minusCircle from '@iconify-icons/line-md/minus-circle';
import { superForm } from 'sveltekit-superforms/client';
// import Button from '$lib/components/button/index.svelte';
import type { GameType, SavedGameType } from '$lib/types'; import type { GameType, SavedGameType } from '$lib/types';
import { collectionStore } from '$lib/stores/collectionStore'; import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '$components/ui/card';
import { wishlistStore } from '$lib/stores/wishlistStore';
import { addToCollection, removeFromCollection } from '$lib/util/manipulateCollection';
import { addToWishlist } from '$lib/util/manipulateWishlist';
import { browser } from '$app/environment';
import { binarySearchOnStore } from '$lib/util/binarySearchOnStore';
import { convertToSavedGame } from '$lib/util/gameMapper';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '$components/ui/card';
import { Button } from '$components/ui/button'; import { Button } from '$components/ui/button';
import type { SuperValidated } from 'sveltekit-superforms';
import type { ListGameSchema } from '$lib/zodValidation';
import type { CollectionItem } from '@prisma/client'; import type { CollectionItem } from '@prisma/client';
// export let data: SuperValidated<ListGameSchema>; // export let data: SuperValidated<ListGameSchema>;
export let game: GameType | CollectionItem; export let game: GameType | CollectionItem;
export let detailed: boolean = false; export let detailed: boolean = false;
// const { form, errors, enhance, delayed } = superForm(data);
// data={modifyListForm}
// const dispatch = createEventDispatcher();
// function removeGameFromWishlist() {
// dispatch('handleRemoveWishlist', game);
// }
// function removeGameFromCollection() {
// dispatch('handleRemoveCollection', game);
// }
function onCollectionClick() {
if (existsInCollection) {
removeGameFromCollection();
} else {
let index = binarySearchOnStore($collectionStore, convertToSavedGame(game), 'en');
addToCollection(game, index);
if (browser) {
localStorage.collection = JSON.stringify($collectionStore);
}
}
}
function onWishlistClick() {
if (existsInWishlist) {
removeGameFromWishlist();
} else {
addToWishlist(game);
if (browser) {
localStorage.wishlist = JSON.stringify($wishlistStore);
}
}
}
// Naive and assumes description is only on our GameType at the moment // Naive and assumes description is only on our GameType at the moment
function isGameType(game: GameType | SavedGameType): game is GameType { function isGameType(game: GameType | SavedGameType): game is GameType {
return (game as GameType).description !== undefined; return (game as GameType).description !== undefined;
} }
// function lazy(img: HTMLImageElement) {
// function loaded() {
// img.classList.add('loaded');
// img.classList.remove('loading');
// }
// if (img.complete) {
// loaded();
// } else {
// img.classList.add('loading');
// img.onload = () => loaded();
// }
// }
// $: existsInCollection = $collectionStore.find((item: SavedGameType) => item.id === game.id);
// $: existsInWishlist = $wishlistStore.find((item: SavedGameType) => item.id === game.id);
$: existsInCollection = game.in_collection;
$: existsInWishlist = game.in_wishlist;
$: collectionText = existsInCollection ? 'Remove from collection' : 'Add to collection';
$: wishlistText = existsInWishlist ? 'Remove from wishlist' : 'Add to wishlist';
</script> </script>
<article class="grid grid-template-cols-2 gap-4" transition:fade|global> <article class="grid grid-template-cols-2 gap-4" transition:fade|global>
@ -113,32 +42,6 @@
</div> </div>
</a> </a>
</CardContent> </CardContent>
<CardFooter>
<div class="grid gap-2 place-items-center">
<form method="POST" action={`/collection?/${existsInCollection ? 'remove' : 'add'}`}>
<input type="hidden" name="id" value={game.id} />
<Button variant={existsInCollection ? 'destructive' : 'default'} on:click={onCollectionClick}>
{collectionText}
{#if existsInCollection}
<iconify-icon class="ml-2" icon={minusCircle} width="24" height="24" />
{:else}
<iconify-icon class="ml-2" icon={plusCircle} width="24" height="24" />
{/if}
</Button>
</form>
<form method="POST" action={`/wishlist?/${existsInWishlist ? 'remove' : 'add'}`}>
<input type="hidden" name="id" value={game.id} />
<Button variant={existsInWishlist ? 'destructive' : 'default'} on:click={onWishlistClick}>
{wishlistText}
{#if existsInWishlist}
<iconify-icon class="ml-2" icon={minusCircle} width="24" height="24" />
{:else}
<iconify-icon class="ml-2" icon={plusCircle} width="24" height="24" />
{/if}
</Button>
</form>
</div>
</CardFooter>
</Card> </Card>
</article> </article>

View file

@ -1,32 +1,21 @@
<script lang="ts"> <script lang="ts">
import { tick } from 'svelte'; import { tick } from 'svelte';
import { fade } from 'svelte/transition'; import { fade, fly } from 'svelte/transition';
import { applyAction, type SubmitFunction } from '$app/forms';
import { superForm } from 'sveltekit-superforms/client'; import { superForm } from 'sveltekit-superforms/client';
import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte'; import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte';
import type { SuperValidated } from 'sveltekit-superforms/index'; import type { SuperValidated } from 'sveltekit-superforms/index';
// import { Disclosure, DisclosureButton, DisclosurePanel } from '@rgossiaux/svelte-headlessui';
// import { ChevronRightIcon } from '@rgossiaux/svelte-heroicons/solid';
import { boredState } from '$lib/stores/boredState'; import { boredState } from '$lib/stores/boredState';
import AdvancedSearch from '$lib/components/search/advancedSearch/index.svelte'; import AdvancedSearch from '$lib/components/search/advancedSearch/index.svelte';
import { xl, md, sm } from '$lib/stores/mediaQueryStore'; import { xl, md, sm } from '$lib/stores/mediaQueryStore';
import { gameStore } from '$lib/stores/gameSearchStore'; import { gameStore } from '$lib/stores/gameSearchStore';
import { toast } from '../../toast/toast';
import Pagination from '$lib/components/pagination/index.svelte'; import Pagination from '$lib/components/pagination/index.svelte';
import Game from '$lib/components/game/index.svelte'; import Game from '$lib/components/game/index.svelte';
import { ToastType, type GameType, type SavedGameType } from '$lib/types'; import { type GameType, type SavedGameType } from '$lib/types';
// import SkeletonPlaceholder from '../../SkeletonPlaceholder.svelte'; import type { SearchSchema } from '$lib/zodValidation';
import RemoveCollectionDialog from '../../dialog/RemoveCollectionDialog.svelte';
import RemoveWishlistDialog from '../../dialog/RemoveWishlistDialog.svelte';
import type { ListGameSchema, SearchSchema } from '$lib/zodValidation';
import { Label } from '$components/ui/label'; import { Label } from '$components/ui/label';
import { Input } from '$components/ui/input'; import { Input } from '$components/ui/input';
import { Button } from '$components/ui/button'; import { Button } from '$components/ui/button';
interface RemoveGameEvent extends Event {
detail: GameType | SavedGameType;
}
export let data; export let data;
console.log("text search data", data); console.log("text search data", data);
export let showButton: boolean = false; export let showButton: boolean = false;
@ -34,7 +23,6 @@
const { games, totalCount } = data?.searchData; const { games, totalCount } = data?.searchData;
const { form, errors, enhance, constraints, message }: SuperValidated<SearchSchema> = superForm(data.form); const { form, errors, enhance, constraints, message }: SuperValidated<SearchSchema> = superForm(data.form);
// const { form: modifyListForm, errors: listErrors, constraints: listConstraints, enhance: listEnhance, message: listMessage } : SuperValidated<ListGameSchema> = superForm(data.modifyListForm);
let gameToRemove: GameType | SavedGameType; let gameToRemove: GameType | SavedGameType;
let numberOfGameSkeleton = 1; let numberOfGameSkeleton = 1;
@ -47,7 +35,6 @@
let name = form?.name || ''; let name = form?.name || '';
let disclosureOpen = $errors.length > 0 || false; let disclosureOpen = $errors.length > 0 || false;
// $: skip = (page - 1) * pageSize;
$: showPagination = totalCount > pageSize; $: showPagination = totalCount > pageSize;
if ($xl) { if ($xl) {
@ -60,12 +47,6 @@
numberOfGameSkeleton = 1; numberOfGameSkeleton = 1;
} }
// let placeholderList = [...Array(numberOfGameSkeleton).keys()];
// if (form?.error) {
// disclosureOpen = true;
// }
async function handleNextPageEvent(event: CustomEvent) { async function handleNextPageEvent(event: CustomEvent) {
if (+event?.detail?.page === page + 1) { if (+event?.detail?.page === page + 1) {
page += 1; page += 1;
@ -89,54 +70,6 @@
submitButton.click(); submitButton.click();
} }
// function handleRemoveCollection(event: RemoveGameEvent) {
// gameToRemove = event?.detail;
// boredState.update((n) => ({
// ...n,
// dialog: { isOpen: true, content: RemoveCollectionDialog, additionalData: gameToRemove }
// }));
// }
// function handleRemoveWishlist(event: RemoveGameEvent) {
// gameToRemove = event?.detail;
// boredState.update((n) => ({
// ...n,
// dialog: { isOpen: true, content: RemoveWishlistDialog, additionalData: gameToRemove }
// }));
// }
// const submitSearch: SubmitFunction = ({ form, data, action, cancel }) => {
// const { name } = Object.fromEntries(data);
// if (!disclosureOpen && name?.length === 0) {
// toast.send('Please enter a search term', {
// duration: 3000,
// type: ToastType.ERROR,
// dismissible: true
// });
// cancel();
// return;
// }
// gameStore.removeAll();
// boredState.update((n) => ({ ...n, loading: true }));
// return async ({ result }) => {
// boredState.update((n) => ({ ...n, loading: false }));
// // `result` is an `ActionResult` object
// if (result.type === 'error') {
// toast.send('Error!', { duration: 3000, type: ToastType.ERROR, dismissible: true });
// await applyAction(result);
// } else if (result.type === 'success') {
// gameStore.removeAll();
// gameStore.addAll(result?.data?.searchData?.games);
// totalItems = result?.data?.searchData?.totalCount;
// // toast.send('Success!', { duration: 3000, type: ToastType.INFO, dismissible: true });
// await applyAction(result);
// } else {
// await applyAction(result);
// }
// };
// };
const dev = process.env.NODE_ENV !== 'production'; const dev = process.env.NODE_ENV !== 'production';
// TODO: Keep all Pagination Values on back and forth browser // TODO: Keep all Pagination Values on back and forth browser
@ -147,7 +80,7 @@
<SuperDebug data={$form} /> <SuperDebug data={$form} />
{/if} {/if}
<form id="search-form" action="/search" method="GET"> <form id="search-form" action="/search" method="GET" use:enhance>
<div class="search"> <div class="search">
<fieldset class="text-search" aria-busy={submitting} disabled={submitting}> <fieldset class="text-search" aria-busy={submitting} disabled={submitting}>
<Label for="label">Search</Label> <Label for="label">Search</Label>

View file

@ -265,6 +265,11 @@ const searchResultSchema = z.object({
count: z.number() count: z.number()
}); });
export const WishlistSchema = z.object({
name: z.string(),
id: z.string()
});
// export const game_raw_schema_json = zodToJsonSchema(game_schema, { // export const game_raw_schema_json = zodToJsonSchema(game_schema, {
// $refStrategy: 'none', // $refStrategy: 'none',
// }); // });

View file

@ -1,6 +1,6 @@
import { fail, redirect } from '@sveltejs/kit'; import { fail, redirect } from '@sveltejs/kit';
import { setError, superValidate } from 'sveltekit-superforms/server'; import { setError, superValidate } from 'sveltekit-superforms/server';
import type { PageServerLoad } from '../$types.js'; import type { PageServerLoad } from '../../$types.js';
import prisma from '$lib/prisma.js'; import prisma from '$lib/prisma.js';
import { modifyListGameSchema, type ListGame } from '$lib/config/zod-schemas.js'; import { modifyListGameSchema, type ListGame } from '$lib/config/zod-schemas.js';
import type { CollectionItemWithGame } from '$lib/types.js'; import type { CollectionItemWithGame } from '$lib/types.js';
@ -127,7 +127,7 @@ export const actions = {
} }
if (game) { if (game) {
const wishlist = await prisma.wishlist.create({ const wishlist = await prisma.collectionItem.create({
data: { data: {
user_id: session.userId, user_id: session.userId,
name: form.name name: form.name

View file

@ -0,0 +1,35 @@
import prisma from '$lib/prisma.js';
import { redirect } from '@sveltejs/kit';
export async function load({ params, locals }) {
const session = await locals.auth.validate();
if (!session) {
throw redirect(302, '/auth/signin');
}
try {
let wishlists = await prisma.wishlist.findMany({
where: {
user_id: session.userId
}
});
if (wishlists.length === 0) {
const wishlist = await prisma.wishlist.create({
data: {
user_id: session.userId
}
});
wishlists.push(wishlist);
}
return {
wishlists
};
} catch (e) {
console.error(e);
}
return {
wishlists: []
};
}

View file

@ -0,0 +1,41 @@
<script lang="ts">
import Transition from '$lib/components/transition/index.svelte';
export let data;
const wishlists = data.wishlists || [];
</script>
<aside class="wishlists">
<h2>Your Wishlists</h2>
<div class="separator"></div>
{#each wishlists as wishlist}
<h2 class="wishlist"><a href={`/wishlist/${wishlist.id}`}>{wishlist.name}</a></h2>
{/each}
</aside>
<div class="content">
<Transition url={data.url} transition={{ type: 'page' }}>
<slot />
</Transition>
</div>
<style lang="postcss">
.wishlists {
position: fixed;
left: 0;
padding-left: 2rem;
}
.separator {
margin: 5px 0;
height: 1px;
--tw-bg-opacity: 1;
background-color: rgba(0, 0, 0, 1);
background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
}
.wishlist {
margin-bottom: 1rem;
}
</style>

View file

@ -0,0 +1,126 @@
import { fail, redirect } from '@sveltejs/kit';
import { superValidate } from 'sveltekit-superforms/server';
import prisma from '$lib/prisma.js';
import { list_game_request_schema } from '$lib/zodValidation';
export async function load({ params, locals }) {
const session = await locals.auth.validate();
if (!session) {
throw redirect(302, '/auth/signin');
}
try {
let wishlist = await prisma.wishlist.findUnique({
where: {
id: params.id,
AND: {
user_id: session.userId
}
},
include: {
items: {
include: {
game: {
select: {
id: true,
name: true,
thumb_url: true
}
}
}
}
}
});
return {
wishlist
};
} catch (e) {
console.error(e);
return {};
}
}
export const actions = {
// Add game to a wishlist
add: async (event) => {
const { params, locals, request } = event;
const form = await superValidate(event, modifyListGameSchema);
const session = await locals.auth.validate();
if (!session) {
throw redirect(302, '/auth/signin');
}
let game = await prisma.game.findUnique({
where: {
id: form.id
}
});
if (!game) {
// game = await prisma.game.create({
// data: {
// name: form.name
// }
// });
return fail(400, {
message: 'Game not found'
});
}
const wishlist = await prisma.wishlist.findUnique({
where: {
id: params.id
}
});
if (wishlist?.user_id !== session.userId) {
return fail(401, {
message: 'Unauthorized'
});
}
if (!wishlist) {
throw redirect(302, '/404');
}
const wishlistItem = await prisma.wishlistItem.create({
data: {
game_id: game.id,
wishlist_id: wishlist.id
}
});
if (!wishlistItem) {
return fail(500, {
message: 'Something went wrong'
});
}
return {
form
};
},
// Create new wishlist
create: async ({ params, locals, request }) => {
const session = await locals.auth.validate();
if (!session) {
throw redirect(302, '/auth/signin');
}
},
// Delete a wishlist
delete: async ({ params, locals, request }) => {
const session = await locals.auth.validate();
if (!session) {
throw redirect(302, '/auth/signin');
}
},
// Remove game from a wishlist
remove: async ({ params, locals, request }) => {
const session = await locals.auth.validate();
if (!session) {
throw redirect(302, '/auth/signin');
}
}
};

View file

@ -0,0 +1,24 @@
<script lang="ts">
import Game from '$lib/components/game/index.svelte';
export let data;
console.log('data', data);
const wishlist = data.wishlist;
const gamesItems = wishlist?.items;
</script>
<svelte:head>
<title>{`Wishlist ${wishlist.name} | Bored Game`}</title>
</svelte:head>
<h1>{wishlist.name}</h1>
<h2>Games on your wishlist:</h2>
<div class="games-list">
{#if gamesItems.length > 0}
{#each gamesItems as game (game.id)}
<Game {game} />
{/each}
{:else}
<h2>Sorry no games found!</h2>
{/if}
</div>

View file

@ -1,7 +1,8 @@
import { redirect } from '@sveltejs/kit'; import { error, redirect } from '@sveltejs/kit';
import { superValidate } from 'sveltekit-superforms/server'; import { superValidate } from 'sveltekit-superforms/server';
import prisma from '$lib/prisma.js'; import prisma from '$lib/prisma.js';
import { list_game_request_schema } from '$lib/zodValidation'; import { list_game_request_schema } from '$lib/zodValidation';
import { modifyListGameSchema } from '$lib/config/zod-schemas.js';
export async function load({ params, locals }) { export async function load({ params, locals }) {
const session = await locals.auth.validate(); const session = await locals.auth.validate();
@ -9,72 +10,98 @@ export async function load({ params, locals }) {
throw redirect(302, '/auth/signin'); throw redirect(302, '/auth/signin');
} }
console.log('Wishlist load User id', session.user);
try { try {
let wishlists = await prisma.wishlist.findMany({ let wishlist = await prisma.wishlist.findUnique({
where: { where: {
user_id: session.userId user_id: session?.user?.userId
}, },
include: { include: {
items: true items: {
include: {
game: {
select: {
id: true,
name: true,
thumb_url: true
}
}
}
}
} }
}); });
if (wishlists.length === 0) { if (!wishlist) {
const wishlist = await prisma.wishlist.create({ throw redirect(302, '/404');
data: {
user_id: session.userId,
name: 'My Wishlist'
}
});
wishlists.push(wishlist);
} }
console.log('wishlist', wishlist);
return { return {
wishlists games: wishlist?.items
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
redirect(302, '/404');
} }
export const actions = { export const actions = {
// Add game to a wishlist // Add game to a wishlist
add: async (event) => { add: async (event) => {
const { params, locals, request } = event; const { params, locals, request } = event;
const form = await superValidate(event, list_game_request_schema); const form = await superValidate(event, modifyListGameSchema);
const session = await locals.auth.validate(); try {
if (!session) { const session = await locals.auth.validate();
throw redirect(302, '/auth/signin'); if (!session) {
} throw redirect(302, '/auth/signin');
let game = await prisma.game.findUnique({
where: {
id: form.id
} }
});
if (!game) { let game = await prisma.game.findUnique({
game = await prisma.game.create({ where: {
data: { id: form.data.id
name: form.name
} }
}); });
throw redirect(302, '/404');
}
if (game) { if (!game) {
const wishlist = await prisma.wishlist.create({ // game = await prisma.game.create({
data: { // data: {
user_id: session.userId, // name: form.name
name: form.name // }
// });
console.log('game not found');
throw redirect(302, '/404');
}
if (game) {
const wishlist = await prisma.wishlist.findUnique({
where: {
user_id: session.user.userId
}
});
if (!wishlist) {
console.log('Wishlist not found');
return error(404, 'Wishlist not found');
} }
});
}
return { await prisma.wishlistItem.create({
form data: {
}; game_id: game.id,
wishlist_id: wishlist.id
}
});
}
return {
form
};
} catch (e) {
console.error(e);
return error(500, 'Something went wrong');
}
}, },
// Create new wishlist // Create new wishlist
create: async ({ params, locals, request }) => { create: async ({ params, locals, request }) => {
@ -91,10 +118,58 @@ export const actions = {
} }
}, },
// Remove game from a wishlist // Remove game from a wishlist
remove: async ({ params, locals, request }) => { remove: async (event) => {
const session = await locals.auth.validate(); const { params, locals, request } = event;
if (!session) { const form = await superValidate(event, modifyListGameSchema);
throw redirect(302, '/auth/signin');
try {
const session = await locals.auth.validate();
if (!session) {
throw redirect(302, '/auth/signin');
}
let game = await prisma.game.findUnique({
where: {
id: form.data.id
}
});
if (!game) {
// game = await prisma.game.create({
// data: {
// name: form.name
// }
// });
console.log('game not found');
throw redirect(302, '/404');
}
if (game) {
const wishlist = await prisma.wishlist.findUnique({
where: {
user_id: session.user.userId
}
});
if (!wishlist) {
console.log('Wishlist not found');
return error(404, 'Wishlist not found');
}
await prisma.wishlistItem.delete({
where: {
wishlist_id: wishlist.id,
game_id: game.id
}
});
}
return {
form
};
} catch (e) {
console.error(e);
return error(500, 'Something went wrong');
} }
} }
}; };

View file

@ -1,134 +1,22 @@
<script lang="ts"> <script lang="ts">
// import { tick, onDestroy } from 'svelte'; import Game from '$lib/components/game/index.svelte';
// import Game from '$lib/components/game/index.svelte';
// import { wishlistStore } from '$lib/stores/wishlistStore';
// import type { GameType, SavedGameType } from '$lib/types';
// import { boredState } from '$lib/stores/boredState';
// import Pagination from '$lib/components/pagination/index.svelte';
// import RemoveWishlistDialog from '$lib/components/dialog/RemoveWishlistDialog.svelte';
// import RemoveCollectionDialog from '$lib/components/dialog/RemoveCollectionDialog.svelte';
// import { createSearchStore, searchHandler } from '$lib/stores/search';
// let gameToRemove: GameType | SavedGameType;
// let pageSize = 10;
// let page = 1;
// const searchStore = createSearchStore($wishlistStore);
// console.log('searchStore', $searchStore);
// const unsubscribe = searchStore.subscribe((model) => searchHandler(model));
// onDestroy(() => {
// unsubscribe();
// });
// $: skip = (page - 1) * pageSize;
// $: gamesShown = $searchStore.filtered.slice(skip, skip + pageSize);
// $: totalItems = $searchStore.search === '' ? $wishlistStore.length : $searchStore.filtered.length;
// interface RemoveGameEvent extends Event {
// detail: GameType | SavedGameType;
// }
// function handleRemoveCollection(event: RemoveGameEvent) {
// gameToRemove = event?.detail;
// boredState.update((n) => ({
// ...n,
// dialog: { isOpen: true, content: RemoveCollectionDialog, additionalData: gameToRemove }
// }));
// }
// function handleRemoveWishlist(event: RemoveGameEvent) {
// gameToRemove = event?.detail;
// boredState.update((n) => ({
// ...n,
// dialog: { isOpen: true, content: RemoveWishlistDialog, additionalData: gameToRemove }
// }));
// }
// async function handleNextPageEvent(event: CustomEvent) {
// if (+event?.detail?.page === page + 1) {
// page += 1;
// }
// await tick();
// }
// async function handlePreviousPageEvent(event: CustomEvent) {
// if (+event?.detail?.page === page - 1) {
// page -= 1;
// }
// await tick();
// }
// async function handlePerPageEvent(event: CustomEvent) {
// page = 1;
// pageSize = event.detail.pageSize;
// await tick();
// }
export let data; export let data;
const wishlists = data.wishlists || []; console.log('data', data);
const games = data.games;
</script> </script>
<svelte:head> <svelte:head>
<title>Your Wishlist | Bored Game</title> <title>{`Your Wishlist | Bored Game`}</title>
</svelte:head> </svelte:head>
<h1>Your Wishlist</h1> <h2>Games on your wishlist:</h2>
{#each wishlists as wishlist} <div class="games-list">
<h2>{wishlist.name}</h2> {#if games.length > 0}
{/each} {#each games as game (game.id)}
<!-- <input type="text" id="search" name="search" placeholder="Search Your Wishlist" bind:value={$searchStore.search} /> <Game {game} />
{/each}
<div class="games"> {:else}
<div class="games-list"> <h2>Sorry no games found!</h2>
{#if $wishlistStore.length === 0}
<h2>No games in your wishlist</h2>
{:else}
{#each gamesShown as game}
<Game
on:handleRemoveWishlist={handleRemoveWishlist}
on:handleRemoveCollection={handleRemoveCollection}
{game}
/>
{/each}
{/if}
</div>
{#if $wishlistStore.length !== 0}
<Pagination
{pageSize}
{page}
{totalItems}
forwardText="Next"
backwardText="Prev"
pageSizes={[10, 25, 50, 100]}
on:nextPageEvent={handleNextPageEvent}
on:previousPageEvent={handlePreviousPageEvent}
on:perPageEvent={handlePerPageEvent}
/>
{/if} {/if}
</div> --> </div>
<style lang="scss">
h1 {
margin: 1.5rem 0rem;
width: 100%;
}
.games {
margin: 2rem 0rem;
}
.games-list {
display: grid;
grid-template-columns: repeat(3, minmax(200px, 1fr));
gap: 2rem;
@media (max-width: 800px) {
grid-template-columns: 1fr 1fr;
}
@media (max-width: 550px) {
grid-template-columns: 1fr;
}
}
</style>

View file

@ -11,7 +11,6 @@
import Header from '$lib/components/header/index.svelte'; import Header from '$lib/components/header/index.svelte';
import Footer from '$lib/components/footer.svelte'; import Footer from '$lib/components/footer.svelte';
import Loading from '$lib/components/loading.svelte'; import Loading from '$lib/components/loading.svelte';
import Transition from '$lib/components/transition/index.svelte';
import Portal from '$lib/Portal.svelte'; import Portal from '$lib/Portal.svelte';
import { boredState } from '$lib/stores/boredState'; import { boredState } from '$lib/stores/boredState';
import { collectionStore } from '$lib/stores/collectionStore'; import { collectionStore } from '$lib/stores/collectionStore';
@ -123,9 +122,9 @@
<Header user={data.user} /> <Header user={data.user} />
<main> <main>
<Transition url={data.url} transition={{ type: 'page' }}> <!-- <Transition url={data.url} transition={{ type: 'page' }}> -->
<slot /> <slot />
</Transition> <!-- </Transition> -->
</main> </main>
<Footer /> <Footer />

View file

@ -0,0 +1,33 @@
import { error } from '@sveltejs/kit';
// Fetch collection for user
// export function GET({ url, locals }) {
// if (!locals.user) {
// throw error(401, {});
// }
// const
// const searchParams = Object.fromEntries(url.searchParams);
// const q = searchParams?.q;
// const limit = parseInt(searchParams?.limit) || 10;
// const skip = parseInt(searchParams?.skip) || 0;
// return new Response();
// }
// // Create a new collection for user
// export function POST({ url }) {
// const searchParams = Object.fromEntries(url.searchParams);
// const q = searchParams?.q;
// const limit = parseInt(searchParams?.limit) || 10;
// const skip = parseInt(searchParams?.skip) || 0;
// }
// // Update or Create a collection
// export function PUT({ url }) {
// const searchParams = Object.fromEntries(url.searchParams);
// const q = searchParams?.q;
// const limit = parseInt(searchParams?.limit) || 10;
// const skip = parseInt(searchParams?.skip) || 0;
// }
//

View file

@ -0,0 +1,74 @@
import { error, json } from '@sveltejs/kit';
import prisma from '$lib/prisma.js';
import type { CollectionItemWithGame } from '$lib/types.js';
// Search a user's collection
export async function GET({ url, locals, params }) {
const searchParams = Object.fromEntries(url.searchParams);
const q = searchParams?.q || '';
const limit = parseInt(searchParams?.limit) || 10;
const skip = parseInt(searchParams?.skip) || 0;
const order = searchParams?.order || 'asc';
const sort = searchParams?.sort || 'name';
const collection_id = params.id;
const session = await locals.auth.validate();
console.log('url', url);
console.log('username', locals?.user?.id);
if (!session) {
throw error(401, { message: 'Unauthorized' });
}
let collection = await prisma.collection.findUnique({
where: {
user_id: locals.user.userId
}
});
console.log('collection', collection);
if (!collection) {
console.log('Collection was not found');
throw error(404, { message: 'Collection was not found' });
}
try {
const orderBy = { [sort]: order };
let collection_items: CollectionItemWithGame[] = await prisma.collectionItem.findMany({
where: {
collection_id,
AND: [
{
game: {
name: {
contains: q
}
}
}
]
},
orderBy: [
{
game: {
...orderBy
}
}
],
include: {
game: {
select: {
id: true,
name: true,
thumb_url: true
}
}
},
skip,
take: limit
});
return json(collection_items);
} catch (e) {
console.error(e);
throw error(500, { message: 'Something went wrong' });
}
}

View file

@ -71,12 +71,10 @@ export const actions = {
user_id: user.id user_id: user.id
}, },
create: { create: {
user_id: user.id, user_id: user.id
name: 'My Wishlist'
}, },
update: { update: {
user_id: user.id, user_id: user.id
name: 'My Wishlist'
} }
}); });
} }

View file

@ -89,8 +89,7 @@ export const actions = {
}); });
await prisma.wishlist.create({ await prisma.wishlist.create({
data: { data: {
user_id: user.userId, user_id: user.userId
name: 'My Wishlist'
} }
}); });

View file

@ -12,9 +12,44 @@ export const load = async ({ params, setHeaders, locals }) => {
} }
}); });
console.log('found game', game); console.log('found game', game);
if (!game) {
throw error(404, 'not found');
}
const wishlist = await prisma.wishlist.findUnique({
where: {
user_id: user.userId
},
include: {
items: {
where: {
game_id: game.id
}
}
}
});
const collection = await prisma.collection.findUnique({
where: {
user_id: user.userId
},
include: {
items: {
where: {
game_id: game.id
}
}
}
});
return { return {
game, game,
user user,
in_wishlist: wishlist?.items?.length !== 0 || false,
in_collection: collection?.items?.length !== 0 || false,
wishlist,
collection
}; };
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View file

@ -3,20 +3,14 @@
import { Image } from 'svelte-lazy-loader'; import { Image } from 'svelte-lazy-loader';
import minusCircle from '@iconify-icons/line-md/minus-circle'; import minusCircle from '@iconify-icons/line-md/minus-circle';
import plusCircle from '@iconify-icons/line-md/plus-circle'; import plusCircle from '@iconify-icons/line-md/plus-circle';
import type { GameType, SavedGameType } from '$lib/types'; import type { SavedGameType } from '$lib/types';
import { collectionStore } from '$lib/stores/collectionStore'; import { collectionStore } from '$lib/stores/collectionStore';
import { wishlistStore } from '$lib/stores/wishlistStore'; import { wishlistStore } from '$lib/stores/wishlistStore';
import RemoveCollectionDialog from '$lib/components/dialog/RemoveCollectionDialog.svelte';
import { addToCollection } from '$lib/util/manipulateCollection';
import type { PageData } from './$types'; import type { PageData } from './$types';
import { boredState } from '$lib/stores/boredState';
import { browser } from '$app/environment';
import LinkWithIcon from '$lib/components/LinkWithIcon.svelte'; import LinkWithIcon from '$lib/components/LinkWithIcon.svelte';
import { addToWishlist } from '$lib/util/manipulateWishlist';
import RemoveWishlistDialog from '$lib/components/dialog/RemoveWishlistDialog.svelte';
import { binarySearchOnStore } from '$lib/util/binarySearchOnStore';
import { convertToSavedGame } from '$lib/util/gameMapper';
import { Button } from '$components/ui/button'; import { Button } from '$components/ui/button';
import AddToList from '$components/AddToList.svelte';
import { Dices } from 'lucide-svelte';
$: existsInCollection = $collectionStore.find((item: SavedGameType) => item.id === game.id); $: existsInCollection = $collectionStore.find((item: SavedGameType) => item.id === game.id);
$: existsInWishlist = $wishlistStore.find((item: SavedGameType) => item.id === game.id); $: existsInWishlist = $wishlistStore.find((item: SavedGameType) => item.id === game.id);
@ -25,56 +19,11 @@
export let data: PageData; export let data: PageData;
console.log('data', data); console.log('data', data);
// let game: GameType;
$: ({ game, user } = data); $: ({ game, user, wishlist, collection, in_collection, in_wishlist } = data);
// let game = data?.game;
// export let game: GameType = data?.game;
let seeMore: boolean = false; let seeMore: boolean = false;
console.log('game', game); console.log('game', game);
// let firstParagraphEnd = 0;
// if (game?.description?.indexOf('</p>') > 0) {
// firstParagraphEnd = game?.description?.indexOf('</p>') + 4;
// } else if (game?.description?.indexOf('</ p>') > 0) {
// firstParagraphEnd = game?.description?.indexOf('</ p>') + 5;
// }
function onCollectionClick() {
if (existsInCollection) {
removeFromCollection();
} else {
let index = binarySearchOnStore($collectionStore, convertToSavedGame(game), 'en');
console.log(`Binary index: ${index}`)
addToCollection(game, index);
if (browser) {
localStorage.collection = JSON.stringify($collectionStore);
}
}
}
function onWishlistClick() {
if (existsInWishlist) {
removeFromWishList();
} else {
addToWishlist(game);
if (browser) {
localStorage.wishlist = JSON.stringify($wishlistStore);
}
}
}
function removeFromCollection() {
boredState.update((n) => ({
...n,
dialog: { isOpen: true, content: RemoveCollectionDialog, additionalData: game }
}));
}
function removeFromWishList() {
boredState.update((n) => ({
...n,
dialog: { isOpen: true, content: RemoveWishlistDialog, additionalData: game }
}));
}
</script> </script>
<svelte:head> <svelte:head>
@ -86,7 +35,11 @@
<section class="game"> <section class="game">
<div> <div>
<a class="thumbnail" href={game.url}> <a class="thumbnail" href={game.url}>
<Image src={game.thumb_url} alt={`Image of ${game.name}`} /> {#if game?.thumb_url}
<Image src={game.thumb_url} alt={`Image of ${game.name}`} />
{:else}
<Dices />
{/if}
<!-- <img src={game.image_url} alt={`Image of ${game.name}`} /> --> <!-- <img src={game.image_url} alt={`Image of ${game.name}`} /> -->
</a> </a>
</div> </div>
@ -110,24 +63,7 @@
</LinkWithIcon> </LinkWithIcon>
</div> </div>
{#if user?.username} {#if user?.username}
<div style="display: grid; gap: 1.5rem; place-content: center;"> <AddToList {in_collection} {in_wishlist} game_id={game.id} {wishlist} {collection} />
<Button size="md" kind={existsInCollection ? 'danger' : 'primary'} icon on:click={onCollectionClick}>
{collectionText}
{#if existsInCollection}
<iconify-icon icon={minusCircle} width="24" height="24" />
{:else}
<iconify-icon icon={plusCircle} width="24" height="24" />
{/if}
</Button>
<Button kind={existsInWishlist ? 'danger' : 'primary'} icon on:click={onWishlistClick}>
{wishlistText}
{#if existsInWishlist}
<iconify-icon icon={minusCircle} width="24" height="24" />
{:else}
<iconify-icon icon={plusCircle} width="24" height="24" />
{/if}
</Button>
</div>
{:else} {:else}
<span> <span>
<Button href="/auth/signup">Sign Up</Button> or <Button href="/auth/signin">Sign In</Button> to add to a list. <Button href="/auth/signup">Sign Up</Button> or <Button href="/auth/signin">Sign In</Button> to add to a list.

View file

@ -21,7 +21,7 @@ import type { PageServerLoad } from '../$types.js';
* an array of all the games fetched. If any error occurred during the operation, it returns an object with totalCount as 0 and games as empty array. * an array of all the games fetched. If any error occurred during the operation, it returns an object with totalCount as 0 and games as empty array.
* @throws will throw an error if the response received from fetching games operation is not OK (200). * @throws will throw an error if the response received from fetching games operation is not OK (200).
*/ */
async function searchForGames(urlQueryParams: SearchQuery, locals, eventFetch) { async function searchForGames(urlQueryParams: SearchQuery, eventFetch) {
try { try {
console.log('urlQueryParams search games', urlQueryParams); console.log('urlQueryParams search games', urlQueryParams);
// let games = await prisma.game.findMany({ // let games = await prisma.game.findMany({
@ -104,8 +104,8 @@ async function searchForGames(urlQueryParams: SearchQuery, locals, eventFetch) {
console.log('totalCount', totalCount); console.log('totalCount', totalCount);
gameList.forEach((game) => { gameList.forEach((game) => {
if (game?.min_players && game?.max_players) { if (game?.min_players && game?.max_players) {
game.players = `${game.min_players}-${game.max_players}`; game.players = `${game.min_players} - ${game.max_players}`;
game.playtime = `${game.min_playtime}-${game.max_playtime}`; game.playtime = `${game.min_playtime} - ${game.max_playtime}`;
} }
const boredGame = mapAPIGameToBoredGame(game); const boredGame = mapAPIGameToBoredGame(game);
createOrUpdateGame(boredGame); createOrUpdateGame(boredGame);
@ -114,51 +114,6 @@ async function searchForGames(urlQueryParams: SearchQuery, locals, eventFetch) {
} }
} }
if (locals?.user) {
const game_ids = games.map((game) => game.id);
console.log('game_ids', game_ids);
const collections = await prisma.collection.findMany({
where: {
user_id: locals.user.id
},
include: {
items: {
where: {
game_id: {
in: game_ids
}
}
}
}
});
console.log('collections', collections);
const wishlists = await prisma.wishlist.findMany({
where: {
user_id: locals.user.id
},
include: {
items: {
where: {
id: {
in: game_ids
}
}
}
}
});
// console.log('wishlist_items', wishlist_items);
for (const game of games) {
console.log(
'Checking collection',
collections.findIndex((item) => item.items.some((i) => i.game_id === game.id))
);
game.in_collection =
collections.findIndex((item) => item.items.some((i) => i.game_id === game.id)) === 0;
game.in_wishlist =
wishlists.findIndex((item) => item.items.some((i) => i.game_id === game.id)) === 0;
}
}
return { return {
totalCount, totalCount,
games games
@ -290,42 +245,54 @@ export const load: PageServerLoad = async ({ params, locals, request, fetch, url
}; };
// fields: ('id,name,min_age,min_players,max_players,thumb_url,min_playtime,max_playtime,min_age,description'); // fields: ('id,name,min_age,min_players,max_players,thumb_url,min_playtime,max_playtime,min_age,description');
try {
if (form.data?.minAge) { if (form.data?.minAge) {
if (form.data?.exactMinAge) { if (form.data?.exactMinAge) {
queryParams.min_age = form.data?.minAge; queryParams.min_age = form.data?.minAge;
} else { } else {
queryParams.gt_min_age = form.data?.minAge === 1 ? 0 : form.data?.minAge - 1; queryParams.gt_min_age = form.data?.minAge === 1 ? 0 : form.data?.minAge - 1;
}
} }
}
if (form.data?.minPlayers) { if (form.data?.minPlayers) {
if (form.data?.exactMinPlayers) { if (form.data?.exactMinPlayers) {
queryParams.min_players = form.data?.minPlayers; queryParams.min_players = form.data?.minPlayers;
} else { } else {
queryParams.gt_min_players = form.data?.minPlayers === 1 ? 0 : form.data?.minPlayers - 1; queryParams.gt_min_players = form.data?.minPlayers === 1 ? 0 : form.data?.minPlayers - 1;
}
} }
} if (form.data?.maxPlayers) {
if (form.data?.maxPlayers) { if (form.data?.exactMaxPlayers) {
if (form.data?.exactMaxPlayers) { queryParams.max_players = form.data?.maxPlayers;
queryParams.max_players = form.data?.maxPlayers; } else {
} else { queryParams.lt_max_players = form.data?.maxPlayers + 1;
queryParams.lt_max_players = form.data?.maxPlayers + 1; }
} }
const newQueryParams: Record<string, string> = {};
for (const key in queryParams) {
newQueryParams[key] = `${queryParams[key as keyof SearchQuery]}`;
}
const urlQueryParams = new URLSearchParams(newQueryParams);
const searchData = await searchForGames(urlQueryParams, fetch);
// console.log('searchData', searchData);
return {
form,
// modifyListForm,
searchData
};
} catch (e) {
console.log(`Error searching board games ${e}`);
} }
const newQueryParams: Record<string, string> = {};
for (const key in queryParams) {
newQueryParams[key] = `${queryParams[key as keyof SearchQuery]}`;
}
const urlQueryParams = new URLSearchParams(newQueryParams);
const searchData = await searchForGames(urlQueryParams, locals, fetch);
return { return {
form, form,
// modifyListForm, searchData: {
searchData totalCount: 0,
games: []
},
wishlists: []
}; };
}; };

View file

@ -28,4 +28,5 @@ const config = {
componentPath: './src/lib/components/ui' componentPath: './src/lib/components/ui'
} }
}; };
export default config; export default config;