mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Updating dependencies, upgrade latest svelte 5, and updating to use svelte 5 in most places.
This commit is contained in:
parent
8c47357605
commit
63ac7dfd76
22 changed files with 1000 additions and 1145 deletions
48
package.json
48
package.json
|
|
@ -23,48 +23,48 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@melt-ui/pp": "^0.3.2",
|
"@melt-ui/pp": "^0.3.2",
|
||||||
"@melt-ui/svelte": "^0.81.0",
|
"@melt-ui/svelte": "^0.81.0",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.45.1",
|
||||||
"@resvg/resvg-js": "^2.6.2",
|
"@resvg/resvg-js": "^2.6.2",
|
||||||
"@sveltejs/adapter-auto": "^3.2.2",
|
"@sveltejs/adapter-auto": "^3.2.2",
|
||||||
"@sveltejs/enhanced-img": "^0.2.1",
|
"@sveltejs/enhanced-img": "^0.2.1",
|
||||||
"@sveltejs/kit": "^2.5.14",
|
"@sveltejs/kit": "^2.5.18",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
||||||
"@types/cookie": "^0.6.0",
|
"@types/cookie": "^0.6.0",
|
||||||
"@types/node": "^20.14.2",
|
"@types/node": "^20.14.10",
|
||||||
"@types/pg": "^8.11.6",
|
"@types/pg": "^8.11.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
"@typescript-eslint/eslint-plugin": "^7.13.0",
|
||||||
"@typescript-eslint/parser": "^7.12.0",
|
"@typescript-eslint/parser": "^7.13.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"drizzle-kit": "^0.22.7",
|
"drizzle-kit": "^0.22.8",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.39.3",
|
"eslint-plugin-svelte": "^2.41.0",
|
||||||
"just-clone": "^6.2.0",
|
"just-clone": "^6.2.0",
|
||||||
"just-debounce-it": "^3.2.0",
|
"just-debounce-it": "^3.2.0",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.39",
|
||||||
"postcss-import": "^16.1.0",
|
"postcss-import": "^16.1.0",
|
||||||
"postcss-load-config": "^5.1.0",
|
"postcss-load-config": "^5.1.0",
|
||||||
"postcss-preset-env": "^9.5.14",
|
"postcss-preset-env": "^9.5.16",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.3.2",
|
||||||
"prettier-plugin-svelte": "^3.2.4",
|
"prettier-plugin-svelte": "^3.2.5",
|
||||||
"sass": "^1.77.5",
|
"sass": "^1.77.6",
|
||||||
"satori": "^0.10.13",
|
"satori": "^0.10.13",
|
||||||
"satori-html": "^0.3.2",
|
"satori-html": "^0.3.2",
|
||||||
"svelte": "^4.2.18",
|
"svelte": "5.0.0-next.175",
|
||||||
"svelte-check": "^3.8.0",
|
"svelte-check": "^3.8.4",
|
||||||
"svelte-headless-table": "^0.18.2",
|
"svelte-headless-table": "^0.18.2",
|
||||||
"svelte-meta-tags": "^3.1.2",
|
"svelte-meta-tags": "^3.1.2",
|
||||||
"svelte-preprocess": "^5.1.4",
|
"svelte-preprocess": "^5.1.4",
|
||||||
"svelte-sequential-preprocessor": "^2.0.1",
|
"svelte-sequential-preprocessor": "^2.0.1",
|
||||||
"sveltekit-flash-message": "^2.4.4",
|
"sveltekit-flash-message": "^2.4.4",
|
||||||
"sveltekit-rate-limiter": "^0.5.1",
|
"sveltekit-rate-limiter": "^0.5.1",
|
||||||
"sveltekit-superforms": "^2.15.1",
|
"sveltekit-superforms": "^2.15.2",
|
||||||
"tailwindcss": "^3.4.4",
|
"tailwindcss": "^3.4.4",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"tslib": "^2.6.3",
|
"tslib": "^2.6.3",
|
||||||
"tsx": "^4.15.4",
|
"tsx": "^4.16.2",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.5.3",
|
||||||
"vite": "^5.3.1",
|
"vite": "^5.3.3",
|
||||||
"vitest": "^1.6.0",
|
"vitest": "^1.6.0",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
|
|
@ -79,12 +79,12 @@
|
||||||
"@iconify-icons/mdi": "^1.2.48",
|
"@iconify-icons/mdi": "^1.2.48",
|
||||||
"@lucia-auth/adapter-drizzle": "^1.0.7",
|
"@lucia-auth/adapter-drizzle": "^1.0.7",
|
||||||
"@lukeed/uuid": "^2.0.1",
|
"@lukeed/uuid": "^2.0.1",
|
||||||
"@neondatabase/serverless": "^0.9.3",
|
"@neondatabase/serverless": "^0.9.4",
|
||||||
"@paralleldrive/cuid2": "^2.2.2",
|
"@paralleldrive/cuid2": "^2.2.2",
|
||||||
"@sveltejs/adapter-vercel": "^5.3.2",
|
"@sveltejs/adapter-vercel": "^5.4.1",
|
||||||
"@types/feather-icons": "^4.29.4",
|
"@types/feather-icons": "^4.29.4",
|
||||||
"@vercel/og": "^0.5.20",
|
"@vercel/og": "^0.5.20",
|
||||||
"bits-ui": "^0.21.10",
|
"bits-ui": "^0.21.11",
|
||||||
"boardgamegeekclient": "^1.9.1",
|
"boardgamegeekclient": "^1.9.1",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
|
@ -93,7 +93,7 @@
|
||||||
"dotenv-expand": "^11.0.6",
|
"dotenv-expand": "^11.0.6",
|
||||||
"drizzle-orm": "^0.31.2",
|
"drizzle-orm": "^0.31.2",
|
||||||
"feather-icons": "^4.29.2",
|
"feather-icons": "^4.29.2",
|
||||||
"formsnap": "^1.0.0",
|
"formsnap": "^1.0.1",
|
||||||
"html-entities": "^2.5.2",
|
"html-entities": "^2.5.2",
|
||||||
"iconify-icon": "^2.1.0",
|
"iconify-icon": "^2.1.0",
|
||||||
"just-capitalize": "^3.2.0",
|
"just-capitalize": "^3.2.0",
|
||||||
|
|
@ -101,8 +101,8 @@
|
||||||
"loader": "^2.1.1",
|
"loader": "^2.1.1",
|
||||||
"lucia": "3.2.0",
|
"lucia": "3.2.0",
|
||||||
"lucide-svelte": "^0.390.0",
|
"lucide-svelte": "^0.390.0",
|
||||||
"open-props": "^1.7.4",
|
"open-props": "^1.7.5",
|
||||||
"oslo": "^1.2.0",
|
"oslo": "^1.2.1",
|
||||||
"pg": "^8.12.0",
|
"pg": "^8.12.0",
|
||||||
"postgres": "^3.4.4",
|
"postgres": "^3.4.4",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
|
|
@ -112,6 +112,6 @@
|
||||||
"tailwind-merge": "^2.3.0",
|
"tailwind-merge": "^2.3.0",
|
||||||
"tailwind-variants": "^0.2.1",
|
"tailwind-variants": "^0.2.1",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"zod-to-json-schema": "^3.23.0"
|
"zod-to-json-schema": "^3.23.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1718
pnpm-lock.yaml
1718
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -41,6 +41,16 @@ export default async function seed(db: db) {
|
||||||
|
|
||||||
console.log('Admin user created.', adminUser);
|
console.log('Admin user created.', adminUser);
|
||||||
|
|
||||||
|
await db
|
||||||
|
.insert(schema.collections)
|
||||||
|
.values({ user_id: adminUser[0].id })
|
||||||
|
.onConflictDoNothing();
|
||||||
|
|
||||||
|
await db
|
||||||
|
.insert(schema.wishlists)
|
||||||
|
.values({ user_id: adminUser[0].id })
|
||||||
|
.onConflictDoNothing();
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.insert(schema.userRoles)
|
.insert(schema.userRoles)
|
||||||
.values({
|
.values({
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
const { children } = $props();
|
||||||
|
|
||||||
function portal(node: HTMLElement) {
|
function portal(node: HTMLElement) {
|
||||||
let target;
|
let target;
|
||||||
|
|
||||||
|
|
@ -25,5 +27,5 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div use:portal hidden>
|
<div use:portal hidden>
|
||||||
<slot />
|
{@render children()}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,112 +1,112 @@
|
||||||
<script>
|
<script>
|
||||||
/**
|
/**
|
||||||
* @event {boolean} check
|
* @event {boolean} check
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the value of the checkbox
|
* Specify the value of the checkbox
|
||||||
* @type {any}
|
* @type {any}
|
||||||
*/
|
*/
|
||||||
export let value = '';
|
export let value = '';
|
||||||
|
|
||||||
/** Specify whether the checkbox is checked */
|
/** Specify whether the checkbox is checked */
|
||||||
export let checked = false;
|
export let checked = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the bound group
|
* Specify the bound group
|
||||||
* @type {any[]}
|
* @type {any[]}
|
||||||
*/
|
*/
|
||||||
export let group = undefined;
|
export let group = undefined;
|
||||||
|
|
||||||
/** Specify whether the checkbox is indeterminate */
|
/** Specify whether the checkbox is indeterminate */
|
||||||
export let indeterminate = false;
|
export let indeterminate = false;
|
||||||
|
|
||||||
/** Set to `true` to display the skeleton state */
|
/** Set to `true` to display the skeleton state */
|
||||||
export let skeleton = false;
|
export let skeleton = false;
|
||||||
|
|
||||||
/** Set to `true` to mark the field as required */
|
/** Set to `true` to mark the field as required */
|
||||||
export let required = false;
|
export let required = false;
|
||||||
|
|
||||||
/** Set to `true` for the checkbox to be read-only */
|
/** Set to `true` for the checkbox to be read-only */
|
||||||
export let readonly = false;
|
export let readonly = false;
|
||||||
|
|
||||||
/** Set to `true` to disable the checkbox */
|
/** Set to `true` to disable the checkbox */
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
|
|
||||||
/** Specify the label text */
|
/** Specify the label text */
|
||||||
export let labelText = '';
|
export let labelText = '';
|
||||||
|
|
||||||
/** Set to `true` to visually hide the label text */
|
/** Set to `true` to visually hide the label text */
|
||||||
export let hideLabel = false;
|
export let hideLabel = false;
|
||||||
|
|
||||||
/** Set a name for the input element */
|
/** Set a name for the input element */
|
||||||
export let name = '';
|
export let name = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the title attribute for the label element
|
* Specify the title attribute for the label element
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
export let title = undefined;
|
export let title = undefined;
|
||||||
|
|
||||||
/** Set an id for the input label */
|
/** Set an id for the input label */
|
||||||
export let id = 'ccs-' + Math.random().toString(36);
|
export let id = 'ccs-' + Math.random().toString(36);
|
||||||
|
|
||||||
/** Obtain a reference to the input HTML element */
|
/** Obtain a reference to the input HTML element */
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import CheckboxSkeleton from './CheckboxSkeleton.svelte';
|
import CheckboxSkeleton from './CheckboxSkeleton.svelte';
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
$: useGroup = Array.isArray(group);
|
$: useGroup = Array.isArray(group);
|
||||||
$: checked = useGroup ? group.includes(value) : checked;
|
$: checked = useGroup ? group.includes(value) : checked;
|
||||||
$: dispatch('check', checked);
|
$: dispatch('check', checked);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||||
{#if skeleton}
|
{#if skeleton}
|
||||||
<CheckboxSkeleton {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave />
|
<CheckboxSkeleton {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave />
|
||||||
{:else}
|
{:else}
|
||||||
<div
|
<div
|
||||||
class:bx--form-item={true}
|
class:bx--form-item={true}
|
||||||
class:bx--checkbox-wrapper={true}
|
class:bx--checkbox-wrapper={true}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
on:click
|
on:click
|
||||||
on:mouseover
|
on:mouseover
|
||||||
on:mouseenter
|
on:mouseenter
|
||||||
on:mouseleave
|
on:mouseleave
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
{value}
|
{value}
|
||||||
{checked}
|
{checked}
|
||||||
{disabled}
|
{disabled}
|
||||||
{id}
|
{id}
|
||||||
{indeterminate}
|
{indeterminate}
|
||||||
{name}
|
{name}
|
||||||
{required}
|
{required}
|
||||||
{readonly}
|
{readonly}
|
||||||
class:bx--checkbox={true}
|
class:bx--checkbox={true}
|
||||||
on:change={() => {
|
on:change={() => {
|
||||||
if (useGroup) {
|
if (useGroup) {
|
||||||
group = group.includes(value)
|
group = group.includes(value)
|
||||||
? group.filter((_value) => _value !== value)
|
? group.filter((_value) => _value !== value)
|
||||||
: [...group, value];
|
: [...group, value];
|
||||||
} else {
|
} else {
|
||||||
checked = !checked;
|
checked = !checked;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
on:change
|
on:change
|
||||||
on:blur
|
on:blur
|
||||||
/>
|
/>
|
||||||
<label for={id} {title} class:bx--checkbox-label={true}>
|
<label for={id} {title} class:bx--checkbox-label={true}>
|
||||||
<span class:bx--checkbox-label-text={true} class:bx--visually-hidden={hideLabel}>
|
<span class:bx--checkbox-label-text={true} class:bx--visually-hidden={hideLabel}>
|
||||||
<slot name="labelText">
|
<slot name="labelText">
|
||||||
{labelText}
|
{labelText}
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,13 @@
|
||||||
import Logo from '$components/logo.svelte';
|
import Logo from '$components/logo.svelte';
|
||||||
import type { Users } from '$db/schema';
|
import type { Users } from '$db/schema';
|
||||||
|
|
||||||
export let user: Users | null = null;
|
type HeaderProps = {
|
||||||
|
user: Users | null;
|
||||||
|
};
|
||||||
|
|
||||||
console.log('header user', user);
|
let { user = null }: HeaderProps = $props();
|
||||||
|
|
||||||
let avatar: string;
|
let avatar: string = $derived(user?.username?.slice(0, 1).toUpperCase() || ':)');
|
||||||
|
|
||||||
$: if (user) {
|
|
||||||
avatar = user.username?.slice(0, 1).toUpperCase() || ':)';
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let url: string;
|
const { url, ariaLabel = `Link to ${url}`, external = false, children }: { url: string; ariaLabel?: string; external?: boolean; children: any } = $props();
|
||||||
export let ariaLabel = `Link to ${url}`;
|
|
||||||
export let external = false;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|
@ -10,7 +8,7 @@
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
aria-label={`Board Game Atlas Link for ${ariaLabel}`}
|
aria-label={`Board Game Atlas Link for ${ariaLabel}`}
|
||||||
>
|
>
|
||||||
<slot />
|
{@render children()}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
// import {
|
|
||||||
// Dialog,
|
|
||||||
// DialogDescription,
|
|
||||||
// DialogOverlay,
|
|
||||||
// DialogTitle
|
|
||||||
// } from '@rgossiaux/svelte-headlessui';
|
|
||||||
import { boredState } from '$lib/stores/boredState';
|
import { boredState } from '$lib/stores/boredState';
|
||||||
import { collectionStore } from '$lib/stores/collectionStore';
|
import { collectionStore } from '$lib/stores/collectionStore';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,24 @@ export function userNotFullyAuthenticated(user: User | null, session: Session |
|
||||||
return user && session && session.isTwoFactorAuthEnabled && !session.isTwoFactorAuthenticated;
|
return user && session && session.isTwoFactorAuthEnabled && !session.isTwoFactorAuthenticated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the user is not fully authenticated.
|
||||||
|
*
|
||||||
|
* @param {User | null} user - The user object.
|
||||||
|
* @param {Session | null} session - The session object.
|
||||||
|
* @returns {boolean} True if the user is not fully authenticated, otherwise false.
|
||||||
|
*/
|
||||||
export function userNotAuthenticated(user: User | null, session: Session | null) {
|
export function userNotAuthenticated(user: User | null, session: Session | null) {
|
||||||
return !user || !session || userNotFullyAuthenticated(user, session);
|
return !user || !session || userNotFullyAuthenticated(user, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the user is fully authenticated.
|
||||||
|
*
|
||||||
|
* @param {User | null} user - The user object.
|
||||||
|
* @param {Session | null} session - The session object.
|
||||||
|
* @returns {boolean} True if the user is fully authenticated, otherwise false.
|
||||||
|
*/
|
||||||
export function userFullyAuthenticated(user: User | null, session: Session | null) {
|
export function userFullyAuthenticated(user: User | null, session: Session | null) {
|
||||||
return !userNotAuthenticated(user, session);
|
return !userNotAuthenticated(user, session);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
import { theme } from '$state/theme';
|
import { theme } from '$state/theme';
|
||||||
import toast, { Toaster } from 'svelte-french-toast';
|
import toast, { Toaster } from 'svelte-french-toast';
|
||||||
|
|
||||||
export let data;
|
const { data } = $props();
|
||||||
$: ({ user } = data);
|
const { user } = data;
|
||||||
|
|
||||||
const flash = getFlash(page, {
|
const flash = getFlash(page, {
|
||||||
clearOnNavigate: true,
|
clearOnNavigate: true,
|
||||||
|
|
@ -14,26 +14,27 @@
|
||||||
clearArray: true
|
clearArray: true
|
||||||
});
|
});
|
||||||
|
|
||||||
onMount(() => {
|
$effect(() => {
|
||||||
// set the theme to the user's active theme
|
// set the theme to the user's active theme
|
||||||
$theme = user?.theme || 'system';
|
$theme = user?.theme || 'system';
|
||||||
document.querySelector('html')?.setAttribute('data-theme', $theme);
|
document.querySelector('html')?.setAttribute('data-theme', $theme);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if ($flash) {
|
||||||
|
if ($flash.type === 'success') {
|
||||||
|
toast.success($flash.message);
|
||||||
|
} else {
|
||||||
|
toast.error($flash.message, {
|
||||||
|
duration: 5000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$: if ($flash) {
|
// Clearing the flash message could sometimes
|
||||||
if ($flash.type === 'success') {
|
// be required here to avoid double-toasting.
|
||||||
toast.success($flash.message);
|
flash.set(undefined);
|
||||||
} else {
|
|
||||||
toast.error($flash.message, {
|
|
||||||
duration: 5000
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// Clearing the flash message could sometimes
|
|
||||||
// be required here to avoid double-toasting.
|
|
||||||
flash.set(undefined);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>Do the admin stuff</h1>
|
<h1>Do the admin stuff</h1>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import DataTable from './user-table.svelte';
|
import DataTable from './user-table.svelte';
|
||||||
export let data;
|
const { data } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>Users</h1>
|
<h1>Users</h1>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
// import AddRolesForm from './add-roles-form.svelte';
|
// import AddRolesForm from './add-roles-form.svelte';
|
||||||
|
|
||||||
export let data;
|
const { data } = $props();
|
||||||
|
|
||||||
const { user, availableRoles } = data;
|
const { user, availableRoles } = data;
|
||||||
const { user_roles }: { user_roles: { role: { name: string, cuid: string } }[] } = user;
|
const { user_roles }: { user_roles: { role: { name: string, cuid: string } }[] } = user;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let data;
|
const { data } = $props();
|
||||||
let collections = data?.collections || [];
|
let collections = data?.collections || [];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,8 @@ export const actions: Actions = {
|
||||||
return fail(401);
|
return fail(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = event.locals.user;
|
|
||||||
|
|
||||||
const dbUser = await db.query.users.findFirst({
|
const dbUser = await db.query.users.findFirst({
|
||||||
where: eq(users.id, user.id),
|
where: eq(users.id, user!.id),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!dbUser?.hashed_password) {
|
if (!dbUser?.hashed_password) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import Header from '$components/Header.svelte';
|
import Header from '$components/Header.svelte';
|
||||||
import Footer from '$components/Footer.svelte';
|
import Footer from '$components/Footer.svelte';
|
||||||
|
|
||||||
export let data;
|
const { data, children } = $props();
|
||||||
|
|
||||||
console.log('layout data user', data.user);
|
console.log('layout data user', data.user);
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<Header user={data.user} />
|
<Header user={data.user} />
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<slot />
|
{@render children()}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import type { MetaTagsProps } from 'svelte-meta-tags';
|
||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import db from '../../db';
|
import db from '../../db';
|
||||||
import { collections, wishlists } from '$db/schema';
|
import { collections, users, wishlists } from '$db/schema';
|
||||||
import { userFullyAuthenticated } from '$lib/server/auth-utils';
|
import { userFullyAuthenticated } from '$lib/server/auth-utils';
|
||||||
|
|
||||||
export const load: PageServerLoad = async (event) => {
|
export const load: PageServerLoad = async (event) => {
|
||||||
|
|
@ -42,6 +42,10 @@ export const load: PageServerLoad = async (event) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (userFullyAuthenticated(user, session)) {
|
if (userFullyAuthenticated(user, session)) {
|
||||||
|
const dbUser = await db.query.users.findFirst({
|
||||||
|
where: eq(users.id, user!.id!),
|
||||||
|
});
|
||||||
|
|
||||||
console.log('Sending back user details');
|
console.log('Sending back user details');
|
||||||
const userWishlists = await db.query.wishlists.findMany({
|
const userWishlists = await db.query.wishlists.findMany({
|
||||||
columns: {
|
columns: {
|
||||||
|
|
@ -60,7 +64,16 @@ export const load: PageServerLoad = async (event) => {
|
||||||
|
|
||||||
console.log('Wishlists', userWishlists);
|
console.log('Wishlists', userWishlists);
|
||||||
console.log('Collections', userCollection);
|
console.log('Collections', userCollection);
|
||||||
return { metaTagsChild: metaTags, user, wishlists: userWishlists, collections: userCollection };
|
return {
|
||||||
|
metaTagsChild: metaTags,
|
||||||
|
user: {
|
||||||
|
firstName: dbUser?.first_name,
|
||||||
|
lastName: dbUser?.last_name,
|
||||||
|
username: dbUser?.username,
|
||||||
|
},
|
||||||
|
wishlists: userWishlists,
|
||||||
|
collections: userCollection,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { metaTagsChild: metaTags, user: null, wishlists: [], collections: [] };
|
return { metaTagsChild: metaTags, user: null, wishlists: [], collections: [] };
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let data;
|
const { data } = $props();
|
||||||
|
|
||||||
const { user, wishlists = [], collections = []} = data;
|
const { user, wishlists = [], collections = []} = data;
|
||||||
|
|
||||||
|
const welcome = $derived(`${data?.user?.firstName} ${data?.user?.lastName}` || user?.username)
|
||||||
|
|
||||||
|
$inspect(data);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{#if user}
|
{#if user}
|
||||||
<h1>Welcome, {user.username}!</h1>
|
<h1>Welcome, {welcome}!</h1>
|
||||||
<div>
|
<div>
|
||||||
<h2>You wishlists:</h2>
|
<h2>You wishlists:</h2>
|
||||||
{#each wishlists as wishlist}
|
{#each wishlists as wishlist}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,15 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Image } from 'svelte-lazy-loader';
|
import { Image } from 'svelte-lazy-loader';
|
||||||
import { Dices, ExternalLinkIcon, MinusIcon, PlusIcon } from 'lucide-svelte';
|
import { Dices, ExternalLinkIcon, MinusIcon, PlusIcon } from 'lucide-svelte';
|
||||||
import type { SavedGameType } from '$lib/types';
|
|
||||||
import { collectionStore } from '$lib/stores/collectionStore';
|
|
||||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
import { Button } from '$components/ui/button';
|
import { Button } from '$components/ui/button';
|
||||||
import AddToList from '$components/AddToList.svelte';
|
import AddToList from '$components/AddToList.svelte';
|
||||||
import Badge from '$components/ui/badge/badge.svelte';
|
import Badge from '$components/ui/badge/badge.svelte';
|
||||||
|
|
||||||
$: existsInCollection = $collectionStore.find((item: SavedGameType) => item.id === game.id);
|
const { data } = $props();
|
||||||
$: existsInWishlist = $wishlistStore.find((item: SavedGameType) => item.id === game.id);
|
const { game, user, in_collection, in_wishlist } = data;
|
||||||
// $: collectionText = existsInCollection ? 'Remove from collection' : 'Add to collection';
|
|
||||||
// $: wishlistText = existsInWishlist ? 'Remove from wishlist' : 'Add to wishlist';
|
|
||||||
|
|
||||||
export let data: PageData;
|
let seeMore: boolean = $state(false);
|
||||||
console.log('data', data);
|
|
||||||
|
|
||||||
$: ({ game, user, wishlist, collection, in_collection, in_wishlist } = data);
|
|
||||||
|
|
||||||
let seeMore: boolean = false;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|
@ -86,7 +76,7 @@
|
||||||
<section class="description" class:show={seeMore} class:hide={!seeMore} style="margin-top: 2rem;">
|
<section class="description" class:show={seeMore} class:hide={!seeMore} style="margin-top: 2rem;">
|
||||||
{@html game?.description}
|
{@html game?.description}
|
||||||
</section>
|
</section>
|
||||||
<button class="btn button-icon" type="button" on:click={() => (seeMore = !seeMore)}
|
<button class="btn button-icon" type="button" onclick={() => (seeMore = !seeMore)}
|
||||||
>See
|
>See
|
||||||
{#if !seeMore}
|
{#if !seeMore}
|
||||||
More
|
More
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
import { redirect } from 'sveltekit-flash-message/server';
|
|
||||||
import { notSignedInMessage } from '$lib/flashMessages';
|
|
||||||
|
|
||||||
export async function load(event) {
|
export async function load(event) {
|
||||||
const { url, locals } = event;
|
const { url, locals } = event;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
import Logo from "$lib/components/logo.svelte";
|
import Logo from "$lib/components/logo.svelte";
|
||||||
import Transition from '$lib/components/transition.svelte';
|
import Transition from '$lib/components/transition.svelte';
|
||||||
|
|
||||||
export let data;
|
let { data, children } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
style="
|
style="
|
||||||
background-image:
|
background-image:
|
||||||
url(https://images.unsplash.com/photo-1588591795084-1770cb3be374?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80"
|
url(https://images.unsplash.com/photo-1588591795084-1770cb3be374?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80"
|
||||||
/>
|
></div>
|
||||||
<div class="quote-wrapper">
|
<div class="quote-wrapper">
|
||||||
<blockquote class="quote">
|
<blockquote class="quote">
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="auth-form">
|
<div class="auth-form">
|
||||||
<Transition url={data.url} transition={{ type: 'page' }}>
|
<Transition url={data.url} transition={{ type: 'page' }}>
|
||||||
<slot />
|
{@render children()}
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
import * as Alert from "$components/ui/alert";
|
import * as Alert from "$components/ui/alert";
|
||||||
import { boredState } from '$lib/stores/boredState.js';
|
import { boredState } from '$lib/stores/boredState.js';
|
||||||
|
|
||||||
export let data;
|
let { data } = $props();
|
||||||
|
|
||||||
const superLoginForm = superForm(data.form, {
|
const superLoginForm = superForm(data.form, {
|
||||||
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
|
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@
|
||||||
|
|
||||||
const dev = process.env.NODE_ENV !== 'production';
|
const dev = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
export let data;
|
const { data, children } = $props();
|
||||||
$: ({ user } = data);
|
const { user } = data;
|
||||||
|
|
||||||
$: metaTags = {
|
const metaTags = $derived({
|
||||||
titleTemplate: '%s | Bored Game',
|
titleTemplate: '%s | Bored Game',
|
||||||
description: 'Bored Game, keep track of your games.',
|
description: 'Bored Game, keep track of your games.',
|
||||||
openGraph: {
|
openGraph: {
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
description: 'Bored Game, keep track of your games',
|
description: 'Bored Game, keep track of your games',
|
||||||
},
|
},
|
||||||
...$page.data.metaTagsChild
|
...$page.data.metaTagsChild
|
||||||
}
|
});
|
||||||
|
|
||||||
const flash = getFlash(page, {
|
const flash = getFlash(page, {
|
||||||
clearOnNavigate: true,
|
clearOnNavigate: true,
|
||||||
|
|
@ -41,34 +41,21 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$: if ($flash) {
|
$effect(() => {
|
||||||
if ($flash.type === 'success') {
|
if ($flash) {
|
||||||
toast.success($flash.message);
|
if ($flash.type === 'success') {
|
||||||
} else {
|
toast.success($flash.message);
|
||||||
toast.error($flash.message, {
|
} else {
|
||||||
duration: 5000
|
toast.error($flash.message, {
|
||||||
});
|
duration: 5000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clearing the flash message could sometimes
|
||||||
|
// be required here to avoid double-toasting.
|
||||||
|
flash.set(undefined);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// Clearing the flash message could sometimes
|
|
||||||
// be required here to avoid double-toasting.
|
|
||||||
flash.set(undefined);
|
|
||||||
}
|
|
||||||
// flash.subscribe(($flash) => {
|
|
||||||
// if (!$flash) return;
|
|
||||||
|
|
||||||
// if ($flash.type === 'success') {
|
|
||||||
// toast.success($flash.message);
|
|
||||||
// } else {
|
|
||||||
// toast.error($flash.message, {
|
|
||||||
// duration: 5000
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Clearing the flash message could sometimes
|
|
||||||
// // be required here to avoid double-toasting.
|
|
||||||
// flash.set(undefined);
|
|
||||||
// });
|
|
||||||
|
|
||||||
onNavigate(async (navigation) => {
|
onNavigate(async (navigation) => {
|
||||||
if (!document.startViewTransition) return;
|
if (!document.startViewTransition) return;
|
||||||
|
|
@ -91,7 +78,7 @@
|
||||||
<PageLoadingIndicator />
|
<PageLoadingIndicator />
|
||||||
|
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<slot />
|
{@render children()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Toaster />
|
<Toaster />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue