Fixing wishlist, collection, and individual of those pages.

This commit is contained in:
Bradley Shellnut 2024-04-17 12:02:51 -07:00
parent abe4f129c4
commit 842e9c72bf
7 changed files with 225 additions and 273 deletions

View file

@ -4,7 +4,6 @@
import type { CollectionItems } from '../../schema'; import type { CollectionItems } from '../../schema';
export let game: GameType | CollectionItems; export let game: GameType | CollectionItems;
export let detailed: boolean = false;
export let variant: 'default' | 'compact' = 'default'; export let variant: 'default' | 'compact' = 'default';
// Naive and assumes description is only on our GameType at the moment // Naive and assumes description is only on our GameType at the moment

View file

@ -2,7 +2,7 @@ import { type Actions, error, fail } from '@sveltejs/kit';
import { and, eq } from 'drizzle-orm'; import { and, eq } from 'drizzle-orm';
import { superValidate } from 'sveltekit-superforms/server'; import { superValidate } from 'sveltekit-superforms/server';
import { zod } from 'sveltekit-superforms/adapters'; import { zod } from 'sveltekit-superforms/adapters';
import { redirect } from 'sveltekit-flash-message/server' import { redirect } from 'sveltekit-flash-message/server';
import { modifyListGameSchema, type ListGame } from '$lib/validations/zod-schemas'; import { modifyListGameSchema, type ListGame } from '$lib/validations/zod-schemas';
import { search_schema } from '$lib/zodValidation.js'; import { search_schema } from '$lib/zodValidation.js';
import db from '$lib/drizzle'; import db from '$lib/drizzle';
@ -10,93 +10,38 @@ import { collection_items, collections, games } from '../../../../schema';
import { notSignedInMessage } from '$lib/flashMessages'; import { notSignedInMessage } from '$lib/flashMessages';
export async function load(event) { export async function load(event) {
const { url, locals } = event; const user = event.locals.user;
const user = locals.user;
if (!user) { if (!user) {
redirect(302, '/login', notSignedInMessage, event); redirect(302, '/login', notSignedInMessage, event);
} }
// console.log('locals load', locals);
const searchParams = Object.fromEntries(url?.searchParams);
console.log('searchParams', searchParams);
const q = searchParams?.q;
const limit = parseInt(searchParams?.limit) || 10;
const skip = parseInt(searchParams?.skip) || 0;
const searchData = {
q,
limit,
skip
};
const searchForm = await superValidate(searchData, zod(search_schema));
const listManageForm = await superValidate(zod(modifyListGameSchema));
try { try {
const collection = await db.query.collections.findFirst({ const userCollections = await db.query.collections.findMany({
where: eq(collections.user_id, user.id) columns: {
cuid: true,
name: true,
created_at: true,
},
where: eq(collections.user_id, user.id),
}); });
console.log('collection', collection); console.log('collections', userCollections);
if (!collection) { if (userCollections?.length === 0) {
console.log('Collection was not found'); console.log('Collection was not found');
return fail(404, {}); return fail(404, {});
// collection = await prisma.collection.create({
// data: {
// user_id: session.userId
// }
// });
}
const collectionItems = await db.query.collection_items.findMany({
where: eq(collection_items.collection_id, collection.id),
with: {
game: {
columns: {
id: true,
name: true,
thumb_url: true
}
}
},
offset: skip,
limit
});
console.log('collection_items', collectionItems);
const items: ListGame[] = [];
for (const item of collectionItems) {
console.log('item', item);
const game = item.game;
if (game) {
let collectionItem: ListGame = {
id: game.id,
collection_id: item.collection_id,
name: game.name,
thumb_url: game.thumb_url,
times_played: item.times_played,
in_collection: true
};
items.push(collectionItem);
}
} }
return { return {
searchForm, collections: userCollections,
listManageForm,
collection: items
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
return { return {
searchForm, collections: [],
listManageForm,
collection: []
}; };
}; }
export const actions: Actions = { export const actions: Actions = {
// Add game to a wishlist // Add game to a wishlist
@ -109,7 +54,7 @@ export const actions: Actions = {
const user = event.locals.user; const user = event.locals.user;
const game = await db.query.games.findFirst({ const game = await db.query.games.findFirst({
where: eq(games.id, form.data.id) where: eq(games.id, form.data.id),
}); });
if (!game) { if (!game) {
@ -124,7 +69,7 @@ export const actions: Actions = {
try { try {
const collection = await db.query.collections.findFirst({ const collection = await db.query.collections.findFirst({
where: eq(collections.user_id, user.id) where: eq(collections.user_id, user.id),
}); });
if (!collection) { if (!collection) {
@ -135,11 +80,11 @@ export const actions: Actions = {
await db.insert(collection_items).values({ await db.insert(collection_items).values({
game_id: game.id, game_id: game.id,
collection_id: collection.id, collection_id: collection.id,
times_played: 0 times_played: 0,
}); });
return { return {
form form,
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -170,7 +115,7 @@ export const actions: Actions = {
} }
const game = await db.query.games.findFirst({ const game = await db.query.games.findFirst({
where: eq(games.id, form.data.id) where: eq(games.id, form.data.id),
}); });
if (!game) { if (!game) {
@ -180,7 +125,7 @@ export const actions: Actions = {
try { try {
const collection = await db.query.collections.findFirst({ const collection = await db.query.collections.findFirst({
where: eq(collections.user_id, locals.user.id) where: eq(collections.user_id, locals.user.id),
}); });
if (!collection) { if (!collection) {
@ -188,17 +133,21 @@ export const actions: Actions = {
return error(404, 'Collection not found'); return error(404, 'Collection not found');
} }
await db.delete(collection_items).where(and( await db
eq(collection_items.collection_id, collection.id), .delete(collection_items)
eq(collection_items.game_id, game.id) .where(
)); and(
eq(collection_items.collection_id, collection.id),
eq(collection_items.game_id, game.id),
),
);
return { return {
form form,
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
return error(500, 'Something went wrong'); return error(500, 'Something went wrong');
} }
} },
}; };

View file

@ -1,76 +1,40 @@
<script lang="ts"> <script lang="ts">
// import { tick, onDestroy } from 'svelte';
import Game from '$components/Game.svelte';
export let data; export let data;
console.log(`Page data: ${JSON.stringify(data)}`); let collections = data?.collections || [];
let collectionItems = data?.collection || [];
console.log('collectionItems', collectionItems);
// 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();
// }
</script> </script>
<svelte:head> <svelte:head>
<title>Your Collection | Bored Game</title> <title>Your Collections | Bored Game</title>
</svelte:head> </svelte:head>
<h1>Your Collection</h1> <h1>Your Collections</h1>
<!-- <input type="text" id="search" name="search" placeholder="Search Your Collection" bind:value={$searchStore.search} /> -->
<div class="games"> <div class="collections">
<div class="games-list"> <div class="collection-list">
{#if collectionItems.length === 0} {#if collections.length === 0}
<h2>No games in your collection</h2> <h2>You have no collections</h2>
{:else} {:else}
{#each collectionItems as game (game.game_id)} {#each collections as collection}
<Game {game} /> <div class="collection grid gap-0.5">
<h2><a href="/collections/{collection.cuid}">{collection.name}</a></h2>
<h3>Created at: {new Date(collection.created_at).toLocaleString()}</h3>
</div>
{/each} {/each}
{/if} {/if}
</div> </div>
<!-- {#if $collectionStore.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} -->
</div> </div>
<style lang="postcss"> <style lang="postcss">
h1 { h1 {
margin: 1.5rem 0rem; margin: 1.5rem 0;
width: 100%; width: 100%;
} }
.games { .collections {
margin: 2rem 0rem; margin: 2rem 0;
} }
.games-list { .collection-list {
display: grid; display: grid;
grid-template-columns: repeat(3, minmax(200px, 1fr)); grid-template-columns: repeat(3, minmax(200px, 1fr));
gap: 2rem; gap: 2rem;

View file

@ -1,32 +1,55 @@
import { error, type Actions } from '@sveltejs/kit'; import { type Actions, error, fail } from '@sveltejs/kit';
import { and, eq } from 'drizzle-orm'; import { and, eq } from 'drizzle-orm';
import { zod } from 'sveltekit-superforms/adapters'; import { zod } from 'sveltekit-superforms/adapters';
import { superValidate } from 'sveltekit-superforms/server'; import { superValidate } from 'sveltekit-superforms/server';
import { redirect } from 'sveltekit-flash-message/server'; import { redirect } from 'sveltekit-flash-message/server';
import { modifyListGameSchema } from '$lib/validations/zod-schemas'; import { type ListGame, modifyListGameSchema } from '$lib/validations/zod-schemas';
import db from '$lib/drizzle.js'; import db from '$lib/drizzle.js';
import { notSignedInMessage } from '$lib/flashMessages.js'; import { notSignedInMessage } from '$lib/flashMessages.js';
import { games, wishlist_items, wishlists } from '../../../../../schema.js'; import { collections, games, collection_items } from '../../../../../schema.js';
import { search_schema } from '$lib/zodValidation';
export async function load(event) { export async function load(event) {
const { params, locals } = event; const { locals, params, url } = event;
if (!locals.user) { const { user } = locals;
const { id } = params;
if (!user) {
redirect(302, '/login', notSignedInMessage, event); redirect(302, '/login', notSignedInMessage, event);
} }
console.log('Wishlist load User id', locals.user.id); const searchParams = Object.fromEntries(url?.searchParams);
console.log('searchParams', searchParams);
const q = searchParams?.q;
const limit = parseInt(searchParams?.limit) || 10;
const skip = parseInt(searchParams?.skip) || 0;
const searchData = {
q,
limit,
skip,
};
const searchForm = await superValidate(searchData, zod(search_schema));
const listManageForm = await superValidate(zod(modifyListGameSchema));
try { try {
const wishlist = await db.query.wishlists.findFirst({ const collection = await db.query.collections.findFirst({
where: eq(wishlists.user_id, locals.user.id), where: and(eq(collections.user_id, user.id), eq(collections.id, id)),
}); });
console.log('collection', collection);
if (!wishlist) { if (!collection) {
redirect(302, '/404'); console.log('Collection was not found');
return fail(404, {});
// collection = await prisma.collection.create({
// data: {
// user_id: session.userId
// }
// });
} }
const items = await db.query.wishlist_items.findMany({ const collectionItems = await db.query.collection_items.findMany({
where: eq(wishlist_items.wishlist_id, wishlist.id), where: eq(collection_items.collection_id, collection.id),
with: { with: {
game: { game: {
columns: { columns: {
@ -36,59 +59,84 @@ export async function load(event) {
}, },
}, },
}, },
offset: skip,
limit,
}); });
console.log('wishlist', wishlist); console.log('collection_items', collectionItems);
const items: ListGame[] = [];
for (const item of collectionItems) {
console.log('item', item);
const game = item.game;
if (game) {
let collectionItem: ListGame = {
id: game.id,
collection_id: item.collection_id,
name: game.name,
thumb_url: game.thumb_url,
times_played: item.times_played,
in_collection: true,
};
items.push(collectionItem);
}
}
return { return {
items, searchForm,
listManageForm,
collection: items,
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
redirect(302, '/404');
return {
searchForm,
listManageForm,
collection: [],
};
} }
export const actions: Actions = { export const actions: Actions = {
// Add game to a wishlist // Add game to a wishlist
add: async (event) => { add: async (event) => {
const { locals } = event;
const form = await superValidate(event, zod(modifyListGameSchema)); const form = await superValidate(event, zod(modifyListGameSchema));
try { if (!event.locals.user) {
if (!locals.user) { throw fail(401);
redirect(302, '/login', notSignedInMessage, event); }
}
const game = await db.query.games.findFirst({ const user = event.locals.user;
where: eq(games.id, form.data.id), const game = await db.query.games.findFirst({
where: eq(games.id, form.data.id),
});
if (!game) {
// game = await prisma.game.create({
// data: {
// name: form.name
// }
// });
console.log('game not found');
redirect(302, '/404');
}
try {
const collection = await db.query.collections.findFirst({
where: eq(collections.user_id, user.id),
}); });
if (!game) { if (!collection) {
// game = await prisma.game.create({ console.log('Wishlist not found');
// data: { return error(404, 'Wishlist not found');
// name: form.name
// }
// });
console.log('game not found');
redirect(302, '/404');
} }
if (game) { await db.insert(collection_items).values({
const wishlist = await db.query.wishlists.findFirst({ game_id: game.id,
where: eq(wishlists.user_id, locals.user.id), collection_id: collection.id,
}); times_played: 0,
});
if (!wishlist) {
console.log('Wishlist not found');
return error(404, 'Wishlist not found');
}
await db.insert(wishlist_items).values({
game_id: game.id,
wishlist_id: wishlist.id,
});
}
return { return {
form, form,
@ -99,17 +147,16 @@ export const actions: Actions = {
} }
}, },
// Create new wishlist // Create new wishlist
create: async (event) => { create: async ({ locals }) => {
const { locals } = event;
if (!locals.user) { if (!locals.user) {
redirect(302, '/login', notSignedInMessage, event); throw fail(401);
} }
return error(405, 'Method not allowed'); return error(405, 'Method not allowed');
}, },
// Delete a wishlist // Delete a wishlist
delete: async ({ locals }) => { delete: async ({ locals }) => {
if (!locals.user) { if (!locals.user) {
redirect(302, '/login'); throw fail(401);
} }
return error(405, 'Method not allowed'); return error(405, 'Method not allowed');
}, },
@ -118,41 +165,37 @@ export const actions: Actions = {
const { locals } = event; const { locals } = event;
const form = await superValidate(event, zod(modifyListGameSchema)); const form = await superValidate(event, zod(modifyListGameSchema));
try { if (!locals.user) {
if (!locals.user) { throw fail(401);
redirect(302, '/login', notSignedInMessage, event); }
}
const game = await db.query.games.findFirst({ const game = await db.query.games.findFirst({
where: eq(games.id, form.data.id), where: eq(games.id, form.data.id),
});
if (!game) {
console.log('game not found');
redirect(302, '/404');
}
try {
const collection = await db.query.collections.findFirst({
where: eq(collections.user_id, locals.user.id),
}); });
if (!game) { if (!collection) {
// game = await prisma.game.create({ console.log('Collection not found');
// data: { return error(404, 'Collection not found');
// name: form.name
// }
// });
console.log('game not found');
redirect(302, '/404');
} }
if (game) { await db
const wishlist = await db.query.wishlists.findFirst({ .delete(collection_items)
where: eq(wishlists.user_id, locals.user.id), .where(
}); and(
eq(collection_items.collection_id, collection.id),
if (!wishlist) { eq(collection_items.game_id, game.id),
console.log('Wishlist not found'); ),
return error(404, 'Wishlist not found'); );
}
await db
.delete(wishlist_items)
.where(
and(eq(wishlist_items.wishlist_id, wishlist.id), eq(wishlist_items.game_id, game.id)),
);
}
return { return {
form, form,

View file

@ -6,47 +6,40 @@ import { redirect } from 'sveltekit-flash-message/server';
import { modifyListGameSchema } from '$lib/validations/zod-schemas'; import { modifyListGameSchema } from '$lib/validations/zod-schemas';
import db from '$lib/drizzle.js'; import db from '$lib/drizzle.js';
import { notSignedInMessage } from '$lib/flashMessages.js'; import { notSignedInMessage } from '$lib/flashMessages.js';
import { games, wishlist_items, wishlists } from '../../../../schema.js'; import { collections, games, wishlist_items, wishlists } from '../../../../schema.js';
export async function load(event) { export async function load(event) {
const { params, locals } = event; const user = event.locals.user;
if (!locals.user) { if (!user) {
redirect(302, '/login', notSignedInMessage, event); redirect(302, '/login', notSignedInMessage, event);
} }
console.log('Wishlist load User id', locals.user.id);
try { try {
const wishlist = await db.query.wishlists.findFirst({ const userWishlists = await db.query.wishlists.findMany({
where: eq(wishlists.user_id, locals.user.id) columns: {
cuid: true,
name: true,
created_at: true,
},
where: eq(wishlists.user_id, user.id),
}); });
console.log('wishlists', userWishlists);
if (!wishlist) { if (userWishlists?.length === 0) {
redirect(302, '/404'); console.log('Wishlists not found');
return fail(404, {});
} }
const items = await db.query.wishlist_items.findMany({
where: eq(wishlist_items.wishlist_id, wishlist.id),
with: {
game: {
columns: {
id: true,
name: true,
thumb_url: true
}
}
}
});
console.log('wishlist', wishlist);
return { return {
items wishlists: userWishlists,
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
redirect(302, '/404');
return {
wishlists: [],
};
} }
export const actions: Actions = { export const actions: Actions = {
@ -61,7 +54,7 @@ export const actions: Actions = {
} }
const game = await db.query.games.findFirst({ const game = await db.query.games.findFirst({
where: eq(games.id, form.data.id) where: eq(games.id, form.data.id),
}); });
if (!game) { if (!game) {
@ -76,7 +69,7 @@ export const actions: Actions = {
if (game) { if (game) {
const wishlist = await db.query.wishlists.findFirst({ const wishlist = await db.query.wishlists.findFirst({
where: eq(wishlists.user_id, locals.user.id) where: eq(wishlists.user_id, locals.user.id),
}); });
if (!wishlist) { if (!wishlist) {
@ -85,13 +78,13 @@ export const actions: Actions = {
} }
await db.insert(wishlist_items).values({ await db.insert(wishlist_items).values({
game_id: game.id, game_id: game.id,
wishlist_id: wishlist.id wishlist_id: wishlist.id,
}); });
} }
return { return {
form form,
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -124,7 +117,7 @@ export const actions: Actions = {
} }
const game = await db.query.games.findFirst({ const game = await db.query.games.findFirst({
where: eq(games.id, form.data.id) where: eq(games.id, form.data.id),
}); });
if (!game) { if (!game) {
@ -139,7 +132,7 @@ export const actions: Actions = {
if (game) { if (game) {
const wishlist = await db.query.wishlists.findFirst({ const wishlist = await db.query.wishlists.findFirst({
where: eq(wishlists.user_id, locals.user.id) where: eq(wishlists.user_id, locals.user.id),
}); });
if (!wishlist) { if (!wishlist) {
@ -147,18 +140,19 @@ export const actions: Actions = {
return error(404, 'Wishlist not found'); return error(404, 'Wishlist not found');
} }
await db.delete(wishlist_items).where(and( await db
eq(wishlist_items.wishlist_id, wishlist.id), .delete(wishlist_items)
eq(wishlist_items.game_id, game.id) .where(
)); and(eq(wishlist_items.wishlist_id, wishlist.id), eq(wishlist_items.game_id, game.id)),
);
} }
return { return {
form form,
}; };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
return error(500, 'Something went wrong'); return error(500, 'Something went wrong');
} }
} },
}; };

View file

@ -1,38 +1,40 @@
<script lang="ts"> <script lang="ts">
import Game from '$components/Game.svelte';
export let data; export let data;
console.log('data', data); let wishlists = data?.wishlists || [];
const items = data.items || [];
</script> </script>
<svelte:head> <svelte:head>
<title>{`Your Wishlist | Bored Game`}</title> <title>Your Wishlists | Bored Game</title>
</svelte:head> </svelte:head>
<h1>Your wishlist</h1> <h1>Your wishlists</h1>
<div class="games-list"> <div class="wishlists">
{#if items.length > 0} <div class="wishlist-list">
{#each items as item (item.id)} {#if wishlists.length === 0}
<Game game={item.game} /> <h2>You have no wishlists</h2>
{/each} {:else}
{:else} {#each wishlists as wishlist}
<h2>Sorry no games found!</h2> <div class="collection grid gap-0.5">
{/if} <h2><a href="/wishlists/{wishlist.cuid}">{wishlist.name}</a></h2>
<h3>Created at: {new Date(wishlist.created_at).toLocaleString()}</h3>
</div>
{/each}
{/if}
</div>
</div> </div>
<style lang="postcss"> <style lang="postcss">
h1 { h1 {
margin: 1.5rem 0rem; margin: 1.5rem 0;
width: 100%; width: 100%;
} }
.games { .wishlists {
margin: 2rem 0rem; margin: 2rem 0;
} }
.games-list { .wishlist-list {
display: grid; display: grid;
grid-template-columns: repeat(3, minmax(200px, 1fr)); grid-template-columns: repeat(3, minmax(200px, 1fr));
gap: 2rem; gap: 2rem;
@ -45,4 +47,4 @@
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
</style> </style>

View file

@ -10,6 +10,7 @@ import { games, wishlist_items, wishlists } from '../../../../../schema.js';
export async function load(event) { export async function load(event) {
const { params, locals } = event; const { params, locals } = event;
const { id } = params;
if (!locals.user) { if (!locals.user) {
redirect(302, '/login', notSignedInMessage, event); redirect(302, '/login', notSignedInMessage, event);
} }
@ -17,8 +18,8 @@ export async function load(event) {
console.log('Wishlist load User id', locals.user.id); console.log('Wishlist load User id', locals.user.id);
try { try {
const wishlist = await db.query.wishlists.findFirst({ const wishlist = await db.query.wishlists.findMany({
where: eq(wishlists.user_id, locals.user.id), where: and(eq(wishlists.user_id, locals.user.id), eq(wishlists.cuid, id)),
}); });
if (!wishlist) { if (!wishlist) {