Compare commits
No commits in common. "8ba01a5019cb6b216f137750bf231132c9cfcd86" and "ca5fdef4fcd876efe05722d90dfa819773f48474" have entirely different histories.
8ba01a5019
...
ca5fdef4fc
49 changed files with 868 additions and 1671 deletions
32
Dockerfile
32
Dockerfile
|
@ -1,37 +1,35 @@
|
||||||
# Base Stage
|
|
||||||
FROM node:21-slim AS base
|
|
||||||
|
|
||||||
ENV PNPM_HOME="/pnpm"
|
FROM node:18-alpine AS base
|
||||||
ENV PATH="$PNPM_HOME:$PATH"
|
|
||||||
|
|
||||||
RUN corepack enable
|
RUN npm i -g pnpm
|
||||||
|
|
||||||
|
FROM base AS dependencies
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package.json pnpm-lock.yaml ./
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
|
||||||
# Dependencies Stage for Production
|
RUN pnpm install --frozen-lockfile
|
||||||
FROM base AS deps
|
|
||||||
|
|
||||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
|
|
||||||
|
|
||||||
# Build Stage
|
|
||||||
FROM base AS build
|
FROM base AS build
|
||||||
|
|
||||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN pnpm run build
|
COPY --from=dependencies /app/node_modules ./node_modules
|
||||||
|
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
RUN pnpm prune --prod
|
||||||
|
|
||||||
# Deploy Stage
|
|
||||||
FROM base AS deploy
|
FROM base AS deploy
|
||||||
|
|
||||||
COPY --from=deps /app/node_modules /app/node_modules
|
WORKDIR /app
|
||||||
COPY --from=build /app/build /app/build
|
|
||||||
|
|
||||||
# Run as non-root user
|
COPY --from=build /app/build ./build
|
||||||
USER node
|
COPY --from=build /app/node_modules ./node_modules
|
||||||
|
COPY --from=build /app/package.json ./package.json
|
||||||
|
|
||||||
ARG PORT=3000
|
ARG PORT=3000
|
||||||
|
|
||||||
|
|
54
package.json
54
package.json
|
@ -17,38 +17,38 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.0",
|
"clsx": "^2.0.0",
|
||||||
"lucide-svelte": "^0.330.0",
|
"lucide-svelte": "^0.279.0",
|
||||||
"marked": "^12.0.0",
|
"marked": "^7.0.5",
|
||||||
"svelte-boring-avatars": "^1.2.5",
|
"svelte-boring-avatars": "^1.2.4",
|
||||||
"tailwind-merge": "^2.2.1"
|
"tailwind-merge": "^1.14.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@melt-ui/pp": "^0.3.0",
|
"@melt-ui/pp": "^0.1.4",
|
||||||
"@melt-ui/svelte": "^0.73.0",
|
"@melt-ui/svelte": "^0.50.1",
|
||||||
"@playwright/test": "^1.41.2",
|
"@playwright/test": "^1.40.0",
|
||||||
"@sveltejs/adapter-node": "^4.0.1",
|
"@sveltejs/adapter-node": "^1.3.1",
|
||||||
"@sveltejs/kit": "^2.5.0",
|
"@sveltejs/kit": "^1.27.6",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
"@types/marked": "^5.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.0.1",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
"@typescript-eslint/parser": "^7.0.1",
|
"@typescript-eslint/parser": "^5.62.0",
|
||||||
"autoprefixer": "^10.4.17",
|
"autoprefixer": "^10.4.16",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.54.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^8.10.0",
|
||||||
"eslint-plugin-svelte": "^2.35.1",
|
"eslint-plugin-svelte": "^2.35.1",
|
||||||
"postcss": "^8.4.35",
|
"postcss": "^8.4.31",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^2.8.8",
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
"prettier-plugin-svelte": "^2.10.1",
|
||||||
"prettier-plugin-tailwindcss": "^0.5.11",
|
"prettier-plugin-tailwindcss": "^0.4.1",
|
||||||
"svelte": "^4.2.10",
|
"svelte": "^4.2.7",
|
||||||
"svelte-check": "^3.6.4",
|
"svelte-check": "^3.6.1",
|
||||||
"svelte-sequential-preprocessor": "^2.0.1",
|
"svelte-sequential-preprocessor": "^2.0.1",
|
||||||
"sveltekit-superforms": "^2.1.0",
|
"sveltekit-superforms": "^1.10.2",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.3.5",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.2",
|
||||||
"vite": "^5.1.1",
|
"vite": "^4.5.0",
|
||||||
"vitest": "^1.2.2",
|
"vitest": "^0.32.4",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2081
pnpm-lock.yaml
generated
2081
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -80,13 +80,10 @@
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
@apply border-border text-white;
|
@apply border-border text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply text-foreground bg-gradient-to-b from-primary-800 to-primary-900;
|
@apply text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +91,6 @@
|
||||||
.console {
|
.console {
|
||||||
@apply relative top-0.5 inline-block;
|
@apply relative top-0.5 inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:-webkit-autofill,
|
input:-webkit-autofill,
|
||||||
input:-webkit-autofill:hover,
|
input:-webkit-autofill:hover,
|
||||||
input:-webkit-autofill:focus,
|
input:-webkit-autofill:focus,
|
||||||
|
|
4
src/app.d.ts
vendored
4
src/app.d.ts
vendored
|
@ -7,10 +7,10 @@ declare global {
|
||||||
namespace App {
|
namespace App {
|
||||||
// interface Error {}
|
// interface Error {}
|
||||||
interface Locals {
|
interface Locals {
|
||||||
user: User | null;
|
user?: User;
|
||||||
}
|
}
|
||||||
interface PageData {
|
interface PageData {
|
||||||
user: User | null;
|
user?: User;
|
||||||
}
|
}
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
}
|
}
|
||||||
|
|
24
src/app.html
24
src/app.html
|
@ -1,6 +1,28 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fr">
|
<html lang="fr" class="scroll-smooth bg-gradient-to-b from-primary-800 to-primary-900">
|
||||||
<head>
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/x-icon" href="%sveltekit.assets%/favicon.ico" />
|
||||||
|
<link
|
||||||
|
rel="apple-touch-icon"
|
||||||
|
sizes="180x180"
|
||||||
|
href="%sveltekit.assets%/assets/icons/apple-touch-icon.png"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="32x32"
|
||||||
|
href="%sveltekit.assets%/assets/icons/favicon-32x32.png"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="16x16"
|
||||||
|
href="%sveltekit.assets%/assets/icons/favicon-16x16.png"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover" class="relative min-h-screen">
|
<body data-sveltekit-preload-data="hover" class="relative min-h-screen">
|
||||||
|
|
|
@ -4,27 +4,24 @@ import { API_URL } from '$env/static/private';
|
||||||
|
|
||||||
import type { User } from '$lib/types';
|
import type { User } from '$lib/types';
|
||||||
|
|
||||||
export const handle: Handle = async ({ event, resolve }) => {
|
export const handle = (async ({ event, resolve }) => {
|
||||||
const session = event.cookies.get('session');
|
const session = event.cookies.get('session');
|
||||||
|
|
||||||
if (!session) {
|
if (session) {
|
||||||
event.locals.user = null;
|
const res = await fetch(`${API_URL}/player/`, {
|
||||||
return resolve(event);
|
headers: {
|
||||||
}
|
Authorization: `Bearer ${session}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const res = await fetch(`${API_URL}/player/`, {
|
if (res.ok) {
|
||||||
headers: {
|
const user = (await res.json()) as User;
|
||||||
Authorization: `Bearer ${session}`
|
event.locals.user = user;
|
||||||
|
} else {
|
||||||
|
event.locals.user = undefined;
|
||||||
|
event.cookies.delete('session');
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (res.ok) {
|
|
||||||
const user = (await res.json()) as User;
|
|
||||||
event.locals.user = user;
|
|
||||||
} else {
|
|
||||||
event.locals.user = null;
|
|
||||||
event.cookies.delete('session', { path: '/' });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolve(event);
|
return await resolve(event);
|
||||||
};
|
}) satisfies Handle;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { clsx, type ClassValue } from 'clsx';
|
import { clsx, type ClassValue } from 'clsx';
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
export const cn = (...inputs: ClassValue[]) => {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib/Utils';
|
||||||
|
|
||||||
export let name: string;
|
export let name: string;
|
||||||
export let src: string;
|
export let src: string;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { cn } from '$lib/Utils';
|
||||||
|
import type { Chapter } from '$lib/types';
|
||||||
import { Trophy } from 'lucide-svelte';
|
import { Trophy } from 'lucide-svelte';
|
||||||
|
|
||||||
import type { Chapter } from '$lib/types';
|
|
||||||
import { cn } from '$lib/utils';
|
|
||||||
|
|
||||||
import ChevronRight from './Icons/ChevronRight.svelte';
|
import ChevronRight from './Icons/ChevronRight.svelte';
|
||||||
|
import Button from './ui/Button.svelte';
|
||||||
|
|
||||||
export let chapter: Chapter;
|
export let chapter: Chapter;
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
let className: string | undefined | null = undefined;
|
let className: string | undefined | null = undefined;
|
||||||
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { page } from '$app/stores';
|
|
||||||
|
|
||||||
import { siteConfig } from '$lib/config/site';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svelte:head>
|
|
||||||
{#key $page.url.pathname}
|
|
||||||
<title>{siteConfig.title}</title>
|
|
||||||
<meta name="title" content={siteConfig.title} />
|
|
||||||
<meta name="description" content={siteConfig.description} />
|
|
||||||
<meta name="keywords" content={siteConfig.keywords.join(',')} />
|
|
||||||
<meta name="author" content={siteConfig.author} />
|
|
||||||
|
|
||||||
<meta name="theme-color" content={siteConfig.themeColor} />
|
|
||||||
|
|
||||||
<meta name="robots" content="index,follow" />
|
|
||||||
|
|
||||||
<meta itemprop="name" content={siteConfig.title} />
|
|
||||||
<meta itemprop="description" content={siteConfig.description} />
|
|
||||||
<meta itemprop="image" content={siteConfig.imageUrl} />
|
|
||||||
|
|
||||||
<meta property="og:site_name" content={siteConfig.name} />
|
|
||||||
<meta property="og:title" content={siteConfig.title} />
|
|
||||||
<meta property="og:description" content={siteConfig.description} />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:url" content={siteConfig.url + $page.url.pathname} />
|
|
||||||
<meta property="og:image" content={siteConfig.imageUrl} />
|
|
||||||
<meta property="og:image:alt" content={siteConfig.title} />
|
|
||||||
<meta property="og:locale" content={siteConfig.locale} />
|
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
|
||||||
<meta name="twitter:site" content={siteConfig.url} />
|
|
||||||
<meta name="twitter:title" content={siteConfig.title} />
|
|
||||||
<meta name="twitter:description" content={siteConfig.description} />
|
|
||||||
<meta name="twitter:image" content={siteConfig.imageUrl} />
|
|
||||||
<meta name="twitter:image:alt" content={siteConfig.title} />
|
|
||||||
<meta name="twitter:creator" content={siteConfig.twitter.creator} />
|
|
||||||
|
|
||||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
|
||||||
|
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/assets/icons/apple-touch-icon.png" />
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/assets/icons/favicon-32x32.png" />
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/assets/icons/favicon-16x16.png" />
|
|
||||||
{/key}
|
|
||||||
</svelte:head>
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib/Utils';
|
||||||
import type { Puzzle } from '$lib/types';
|
import type { Puzzle } from '$lib/types';
|
||||||
import ChevronRight from './Icons/ChevronRight.svelte';
|
import ChevronRight from './Icons/ChevronRight.svelte';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib/Utils';
|
||||||
|
|
||||||
import Badge from '$lib/components/Icons/Badge.svelte';
|
import Badge from '$lib/components/Icons/Badge.svelte';
|
||||||
import Code from '$lib/components/Icons/Code.svelte';
|
import Code from '$lib/components/Icons/Code.svelte';
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||||
import { type VariantProps, cva } from 'class-variance-authority';
|
import { type VariantProps, cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
|
// TODO: Remove this
|
||||||
|
|
||||||
export const buttonVariants = cva(
|
export const buttonVariants = cva(
|
||||||
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLInputAttributes } from 'svelte/elements';
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
|
|
||||||
type FormInputEvent<T extends Event = Event> = T & {
|
type FormInputEvent<T extends Event = Event> = T & {
|
||||||
currentTarget: EventTarget & HTMLInputElement;
|
currentTarget: EventTarget & HTMLInputElement;
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
export const siteConfig = {
|
|
||||||
name: 'Peer-at Code',
|
|
||||||
url: 'https://app.peerat.dev',
|
|
||||||
title: 'Peer-at Code',
|
|
||||||
description: 'Apprendre la programmation et la cybersécurité en s\'amusant.',
|
|
||||||
imageUrl: 'https://my-site.com/images/og-image.jpg',
|
|
||||||
keywords: ['peerat', 'code', 'cybersecurite', 'programmation', 'apprendre en s\'amusant'],
|
|
||||||
author: 'peerat',
|
|
||||||
locale: 'fr',
|
|
||||||
twitter: {
|
|
||||||
creator: '@peerat'
|
|
||||||
},
|
|
||||||
themeColor: '#110F15'
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SiteConfig = typeof siteConfig;
|
|
1
src/lib/index.ts
Normal file
1
src/lib/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './Utils';
|
|
@ -1 +1 @@
|
||||||
export * from './database';
|
export * from './Database';
|
||||||
|
|
|
@ -1,14 +1,43 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
|
|
||||||
import Metadata from '$lib/components/Metadata.svelte';
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
import Toaster from '$lib/components/Toaster.svelte';
|
import Toaster from '$lib/components/Toaster.svelte';
|
||||||
|
|
||||||
|
$: origin = $page.url.origin;
|
||||||
|
$: domain = $page.url.hostname;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Metadata />
|
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<script defer data-domain="app.peerat.dev" src="https://plosibl.peerat.dev/js/script.js"></script>
|
<title>Peer-at Code</title>
|
||||||
|
|
||||||
|
<meta name="title" content="Peer-at Code" />
|
||||||
|
<meta name="description" content="Apprendre la programmation et la cybersécurité en s'amusant." />
|
||||||
|
<meta name="theme-color" content="#110F15" />
|
||||||
|
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<meta name="language" content="French" />
|
||||||
|
|
||||||
|
<!-- Open Graph / Facebook -->
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content={origin} />
|
||||||
|
<meta property="og:title" content="Peer-at Code" />
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Apprendre la programmation et la cybersécurité en s'amusant."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Twitter -->
|
||||||
|
<meta property="twitter:card" content="summary_large_image" />
|
||||||
|
<meta property="twitter:url" content={origin} />
|
||||||
|
<meta property="twitter:title" content="Peer-at Code" />
|
||||||
|
<meta
|
||||||
|
property="twitter:description"
|
||||||
|
content="Apprendre la programmation et la cybersécurité en s'amusant."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<script defer data-domain={domain} src="https://plosibl.peerat.dev/js/script.js"></script>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<Toaster />
|
<Toaster />
|
||||||
|
|
|
@ -2,6 +2,6 @@ import { redirect } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
export const load = (async ({ locals: { user } }) => {
|
export const load = (async ({ locals: { user } }) => {
|
||||||
if (user) redirect(303, '/dashboard');
|
if (user) throw redirect(303, '/dashboard');
|
||||||
redirect(303, '/sign-in');
|
throw redirect(303, '/sign-in');
|
||||||
}) satisfies PageServerLoad;
|
}) satisfies PageServerLoad;
|
||||||
|
|
2
src/routes/+page.svelte
Normal file
2
src/routes/+page.svelte
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<script lang="ts">
|
||||||
|
</script>
|
|
@ -2,5 +2,5 @@ import { redirect, type ServerLoad } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const load: ServerLoad = async ({ locals: { user }, parent }) => {
|
export const load: ServerLoad = async ({ locals: { user }, parent }) => {
|
||||||
await parent();
|
await parent();
|
||||||
if (!user) redirect(303, '/sign-in');
|
if (!user) throw redirect(303, '/sign-in');
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,13 +17,13 @@ export const load = (async ({ parent, fetch, cookies, params: { chapterId } }) =
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
redirect(302, '/dashboard/chapters');
|
throw redirect(302, '/dashboard/chapters');
|
||||||
}
|
}
|
||||||
|
|
||||||
const chapter = (await res.json()) as Chapter;
|
const chapter = (await res.json()) as Chapter;
|
||||||
|
|
||||||
if (!chapter || !chapter.show) {
|
if (!chapter || !chapter.show) {
|
||||||
redirect(302, '/dashboard/chapters');
|
throw redirect(302, '/dashboard/chapters');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,5 +4,5 @@ import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
export const load = (async ({ parent, params: { chapterId } }) => {
|
export const load = (async ({ parent, params: { chapterId } }) => {
|
||||||
await parent();
|
await parent();
|
||||||
redirect(303, chapterId ? `/dashboard/chapters/${chapterId}` : `/dashboard/chapters`);
|
throw redirect(303, chapterId ? `/dashboard/chapters/${chapterId}` : `/dashboard/chapters`);
|
||||||
}) satisfies PageServerLoad;
|
}) satisfies PageServerLoad;
|
||||||
|
|
|
@ -11,7 +11,7 @@ export const load = (async ({ parent, fetch, cookies, params: { chapterId, puzzl
|
||||||
const session = cookies.get('session');
|
const session = cookies.get('session');
|
||||||
|
|
||||||
if (isNaN(parseInt(puzzleId))) {
|
if (isNaN(parseInt(puzzleId))) {
|
||||||
redirect(303, `/dashboard/chapters/${chapterId}`);
|
throw redirect(303, `/dashboard/chapters/${chapterId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = await fetch(`${API_URL}/chapter/${chapterId}`, {
|
let res = await fetch(`${API_URL}/chapter/${chapterId}`, {
|
||||||
|
@ -21,20 +21,20 @@ export const load = (async ({ parent, fetch, cookies, params: { chapterId, puzzl
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
redirect(303, `/dashboard/chapters`);
|
throw redirect(303, `/dashboard/chapters`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const chapter = (await res.json()) as Chapter;
|
const chapter = (await res.json()) as Chapter;
|
||||||
|
|
||||||
if (!chapter || !chapter.show) {
|
if (!chapter || !chapter.show) {
|
||||||
redirect(303, `/dashboard/chapters`);
|
throw redirect(303, `/dashboard/chapters`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!chapter.puzzles.some((puzzle) => puzzle.id === parseInt(puzzleId)) ||
|
!chapter.puzzles.some((puzzle) => puzzle.id === parseInt(puzzleId)) ||
|
||||||
!chapter.puzzles.find((puzzle) => puzzle.id === parseInt(puzzleId))?.show
|
!chapter.puzzles.find((puzzle) => puzzle.id === parseInt(puzzleId))?.show
|
||||||
) {
|
) {
|
||||||
redirect(303, `/dashboard/chapters/${chapterId}`);
|
throw redirect(303, `/dashboard/chapters/${chapterId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = await fetch(`${API_URL}/puzzle/${puzzleId}`, {
|
res = await fetch(`${API_URL}/puzzle/${puzzleId}`, {
|
||||||
|
@ -44,13 +44,13 @@ export const load = (async ({ parent, fetch, cookies, params: { chapterId, puzzl
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
error(404, 'Puzzle not found');
|
throw error(404, 'Puzzle not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const puzzle = await res.json();
|
const puzzle = await res.json();
|
||||||
|
|
||||||
if (!puzzle) {
|
if (!puzzle) {
|
||||||
error(404, 'Puzzle not found');
|
throw error(404, 'Puzzle not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -62,6 +62,6 @@ export const load = (async ({ parent, fetch, cookies, params: { chapterId, puzzl
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
default: async ({ params }) => {
|
default: async ({ params }) => {
|
||||||
redirect(303, `/dashboard/chapters/${params.chapterId}/puzzle/${params.puzzleId}`);
|
throw redirect(303, `/dashboard/chapters/${params.chapterId}/puzzle/${params.puzzleId}`);
|
||||||
}
|
}
|
||||||
} satisfies Actions;
|
} satisfies Actions;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const load = (async ({ parent, fetch, cookies, params: { chapterId } }) =
|
||||||
await parent();
|
await parent();
|
||||||
|
|
||||||
if (!chapterId) {
|
if (!chapterId) {
|
||||||
redirect(303, '/dashboard');
|
throw redirect(303, '/dashboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
const session = cookies.get('session');
|
const session = cookies.get('session');
|
||||||
|
@ -22,13 +22,13 @@ export const load = (async ({ parent, fetch, cookies, params: { chapterId } }) =
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
redirect(303, '/dashboard');
|
throw redirect(303, '/dashboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
const leaderboard = (await res.json()) as LeaderboardEvent;
|
const leaderboard = (await res.json()) as LeaderboardEvent;
|
||||||
|
|
||||||
if (!leaderboard || !leaderboard.groups.length) {
|
if (!leaderboard || !leaderboard.groups.length) {
|
||||||
redirect(303, '/dashboard');
|
throw redirect(303, '/dashboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import Button from '$lib/components/ui/Button.svelte';
|
import Button from '$lib/components/ui/Button.svelte';
|
||||||
import Input from '$lib/components/ui/Input.svelte';
|
import Input from '$lib/components/ui/Input.svelte';
|
||||||
|
|
||||||
import plausible from '$lib/stores/plausible';
|
import plausible from '$lib/stores/Plausible';
|
||||||
import { addToast } from '$lib/components/Toaster.svelte';
|
import { addToast } from '$lib/components/Toaster.svelte';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
|
@ -6,7 +6,6 @@ import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
import { superValidate } from 'sveltekit-superforms/server';
|
import { superValidate } from 'sveltekit-superforms/server';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { zod } from 'sveltekit-superforms/adapters';
|
|
||||||
|
|
||||||
const forgotSchema = z.object({
|
const forgotSchema = z.object({
|
||||||
email: z
|
email: z
|
||||||
|
@ -44,9 +43,9 @@ const confirmationSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const load = (async ({ locals: { user } }) => {
|
export const load = (async ({ locals: { user } }) => {
|
||||||
if (user) redirect(303, '/dashboard');
|
if (user) throw redirect(303, '/dashboard');
|
||||||
|
|
||||||
const form = await superValidate(zod(forgotSchema));
|
const form = await superValidate(forgotSchema);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form
|
form
|
||||||
|
@ -55,7 +54,7 @@ export const load = (async ({ locals: { user } }) => {
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
forgot: async ({ request, cookies }) => {
|
forgot: async ({ request, cookies }) => {
|
||||||
const form = await superValidate(request, zod(forgotSchema));
|
const form = await superValidate(request, forgotSchema);
|
||||||
|
|
||||||
if (!form.valid) {
|
if (!form.valid) {
|
||||||
return fail(400, { form });
|
return fail(400, { form });
|
||||||
|
@ -78,6 +77,8 @@ export const actions = {
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(res);
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const token = res.headers.get('Authorization')?.split('Bearer ')[1];
|
const token = res.headers.get('Authorization')?.split('Bearer ')[1];
|
||||||
|
|
||||||
|
@ -86,21 +87,21 @@ export const actions = {
|
||||||
path: '/'
|
path: '/'
|
||||||
});
|
});
|
||||||
|
|
||||||
redirect(303, '/dashboard');
|
throw redirect(303, '/dashboard');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
form
|
form
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
form.errors.code = ['Code invalide ou expiré'];
|
form.errors.passwd = ['Code invalide ou expiré'];
|
||||||
|
|
||||||
return fail(400, {
|
return fail(400, {
|
||||||
form
|
form
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
confirmation: async ({ request, cookies }) => {
|
confirmation: async ({ request, cookies }) => {
|
||||||
const form = await superValidate(request, zod(confirmationSchema));
|
const form = await superValidate(request, confirmationSchema);
|
||||||
|
|
||||||
if (!form.valid) {
|
if (!form.valid) {
|
||||||
return fail(400, { form });
|
return fail(400, { form });
|
||||||
|
@ -124,7 +125,7 @@ export const actions = {
|
||||||
path: '/'
|
path: '/'
|
||||||
});
|
});
|
||||||
|
|
||||||
redirect(303, '/dashboard');
|
throw redirect(303, '/dashboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
form.errors.code = [`Une erreur s'est produite (${res.status} ${res.statusText})`];
|
form.errors.code = [`Une erreur s'est produite (${res.status} ${res.statusText})`];
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
submitting = false;
|
submitting = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -57,9 +58,7 @@
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="philipzcwbarlow@peerat.dev"
|
placeholder="philipzcwbarlow@peerat.dev"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
autocorrect="off"
|
|
||||||
required
|
required
|
||||||
aria-invalid={$errors.email ? 'true' : undefined}
|
|
||||||
/>
|
/>
|
||||||
{#if $errors.email}<span class="text-sm text-red-500">{$errors.email}</span>{/if}
|
{#if $errors.email}<span class="text-sm text-red-500">{$errors.email}</span>{/if}
|
||||||
|
|
||||||
|
@ -70,26 +69,12 @@
|
||||||
duration: 300
|
duration: 300
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<label for="passwd"> Nouveau Mot de passe </label>
|
<label for="passwd"> Mot de passe </label>
|
||||||
<Input
|
<Input name="passwd" placeholder="************" type="password" />
|
||||||
bind:value={$form.passwd}
|
|
||||||
name="passwd"
|
|
||||||
placeholder="************"
|
|
||||||
type="password"
|
|
||||||
required
|
|
||||||
aria-invalid={$errors.passwd ? 'true' : undefined}
|
|
||||||
/>
|
|
||||||
{#if $errors.passwd}<span class="text-sm text-red-500">{$errors.passwd}</span>{/if}
|
{#if $errors.passwd}<span class="text-sm text-red-500">{$errors.passwd}</span>{/if}
|
||||||
|
|
||||||
<label for="code"> Code </label>
|
<label for="code"> Code </label>
|
||||||
<Input
|
<Input name="code" placeholder="1234" type="text" />
|
||||||
bind:value={$form.code}
|
|
||||||
name="code"
|
|
||||||
placeholder="1234"
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
aria-invalid={$errors.code ? 'true' : undefined}
|
|
||||||
/>
|
|
||||||
{#if $errors.code}<span class="text-sm text-red-500">{$errors.code}</span>{/if}
|
{#if $errors.code}<span class="text-sm text-red-500">{$errors.code}</span>{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -107,9 +92,9 @@
|
||||||
</li>
|
</li>
|
||||||
{#if confirmation}
|
{#if confirmation}
|
||||||
<li>
|
<li>
|
||||||
<button formaction="?/register" class="text-highlight-secondary hover:text-brand">
|
<button formaction="?/register" class="text-highlight-secondary hover:text-brand"
|
||||||
Renvoyer le code
|
>Pas reçu ?</button
|
||||||
</button>
|
>
|
||||||
</li>
|
</li>
|
||||||
{/if}
|
{/if}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -9,5 +9,5 @@ export const load: ServerLoad = async ({ cookies, locals }) => {
|
||||||
|
|
||||||
locals.user = undefined;
|
locals.user = undefined;
|
||||||
|
|
||||||
redirect(303, '/');
|
throw redirect(303, '/');
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
import { API_URL } from '$env/static/private';
|
import { API_URL } from '$env/static/private';
|
||||||
|
|
||||||
import { fail, redirect, type Actions } from '@sveltejs/kit';
|
import { redirect, type Actions, fail } from '@sveltejs/kit';
|
||||||
|
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
import { zod } from 'sveltekit-superforms/adapters';
|
|
||||||
import { superValidate } from 'sveltekit-superforms/server';
|
import { superValidate } from 'sveltekit-superforms/server';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
|
||||||
export const load = (async ({ locals: { user } }) => {
|
|
||||||
if (user) redirect(303, '/dashboard');
|
|
||||||
|
|
||||||
const form = await superValidate(zod(schema));
|
|
||||||
|
|
||||||
return {
|
|
||||||
form
|
|
||||||
};
|
|
||||||
}) satisfies PageServerLoad;
|
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
pseudo: z.string().trim(),
|
pseudo: z.string().trim(),
|
||||||
passwd: z.string()
|
passwd: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const load = (async ({ locals: { user } }) => {
|
||||||
|
if (user) throw redirect(303, '/dashboard');
|
||||||
|
|
||||||
|
const form = await superValidate(schema);
|
||||||
|
|
||||||
|
return {
|
||||||
|
form
|
||||||
|
};
|
||||||
|
}) satisfies PageServerLoad;
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
default: async ({ request, cookies }) => {
|
default: async ({ request, cookies }) => {
|
||||||
const form = await superValidate(request, zod(schema));
|
const form = await superValidate(request, schema);
|
||||||
|
|
||||||
if (!form.valid) {
|
if (!form.valid) {
|
||||||
return fail(400, { form });
|
return fail(400, { form });
|
||||||
|
@ -42,12 +40,7 @@ export const actions = {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const token = res.headers.get('Authorization')?.split(' ')[1];
|
const token = res.headers.get('Authorization')?.split(' ')[1];
|
||||||
|
|
||||||
if (!token) {
|
if (!token) throw new Error('No token found');
|
||||||
|
|
||||||
form.errors.passwd = ["Une erreur est survenue, veuillez réessayer plus tard"];
|
|
||||||
|
|
||||||
return fail(500, { form });
|
|
||||||
}
|
|
||||||
|
|
||||||
cookies.set('session', token, {
|
cookies.set('session', token, {
|
||||||
path: '/'
|
path: '/'
|
||||||
|
|
|
@ -6,7 +6,6 @@ import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
import { superValidate } from 'sveltekit-superforms/server';
|
import { superValidate } from 'sveltekit-superforms/server';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { zod } from 'sveltekit-superforms/adapters';
|
|
||||||
|
|
||||||
const registerSchema = z.object({
|
const registerSchema = z.object({
|
||||||
email: z
|
email: z
|
||||||
|
@ -51,9 +50,9 @@ const confirmationSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const load = (async ({ locals: { user } }) => {
|
export const load = (async ({ locals: { user } }) => {
|
||||||
if (user) redirect(303, '/dashboard');
|
if (user) throw redirect(303, '/dashboard');
|
||||||
|
|
||||||
const form = await superValidate(zod(registerSchema));
|
const form = await superValidate(registerSchema);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form
|
form
|
||||||
|
@ -62,7 +61,7 @@ export const load = (async ({ locals: { user } }) => {
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
register: async ({ request }) => {
|
register: async ({ request }) => {
|
||||||
const form = await superValidate(request, zod(registerSchema));
|
const form = await superValidate(request, registerSchema);
|
||||||
|
|
||||||
if (!form.valid) {
|
if (!form.valid) {
|
||||||
return fail(400, { form });
|
return fail(400, { form });
|
||||||
|
@ -100,7 +99,7 @@ export const actions = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
confirmation: async ({ request, cookies }) => {
|
confirmation: async ({ request, cookies }) => {
|
||||||
const form = await superValidate(request, zod(confirmationSchema));
|
const form = await superValidate(request, confirmationSchema);
|
||||||
|
|
||||||
if (!form.valid) {
|
if (!form.valid) {
|
||||||
return fail(400, { form });
|
return fail(400, { form });
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Loader2 } from 'lucide-svelte';
|
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { superForm } from 'sveltekit-superforms/client';
|
import { superForm } from 'sveltekit-superforms/client';
|
||||||
|
import { Loader2 } from 'lucide-svelte';
|
||||||
|
|
||||||
import type { PageData, Snapshot } from './$types';
|
import type { PageData, Snapshot } from './$types';
|
||||||
|
|
||||||
import { addToast } from '$lib/components/Toaster.svelte';
|
|
||||||
import Button from '$lib/components/ui/Button.svelte';
|
import Button from '$lib/components/ui/Button.svelte';
|
||||||
import Input from '$lib/components/ui/Input.svelte';
|
import Input from '$lib/components/ui/Input.svelte';
|
||||||
|
import { addToast } from '$lib/components/Toaster.svelte';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
|
@ -63,7 +63,6 @@
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="philipzcwbarlow@peerat.dev"
|
placeholder="philipzcwbarlow@peerat.dev"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
autocorrect="off"
|
|
||||||
required
|
required
|
||||||
aria-invalid={$errors.email ? 'true' : undefined}
|
aria-invalid={$errors.email ? 'true' : undefined}
|
||||||
/>
|
/>
|
||||||
|
@ -76,7 +75,6 @@
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Philip"
|
placeholder="Philip"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
autocorrect="off"
|
|
||||||
required
|
required
|
||||||
aria-invalid={$errors.firstname ? 'true' : undefined}
|
aria-invalid={$errors.firstname ? 'true' : undefined}
|
||||||
/>
|
/>
|
||||||
|
@ -89,7 +87,6 @@
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Barlow"
|
placeholder="Barlow"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
autocorrect="off"
|
|
||||||
required
|
required
|
||||||
aria-invalid={$errors.lastname ? 'true' : undefined}
|
aria-invalid={$errors.lastname ? 'true' : undefined}
|
||||||
/>
|
/>
|
||||||
|
@ -102,7 +99,6 @@
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Cypher Wolf"
|
placeholder="Cypher Wolf"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
autocorrect="off"
|
|
||||||
required
|
required
|
||||||
aria-invalid={$errors.pseudo ? 'true' : undefined}
|
aria-invalid={$errors.pseudo ? 'true' : undefined}
|
||||||
/>
|
/>
|
||||||
|
@ -120,7 +116,6 @@
|
||||||
name="passwd"
|
name="passwd"
|
||||||
placeholder="************"
|
placeholder="************"
|
||||||
type="password"
|
type="password"
|
||||||
required
|
|
||||||
aria-invalid={$errors.passwd ? 'true' : undefined}
|
aria-invalid={$errors.passwd ? 'true' : undefined}
|
||||||
/>
|
/>
|
||||||
{#if $errors.passwd}<span class="text-sm text-red-500">{$errors.passwd}</span>{/if}
|
{#if $errors.passwd}<span class="text-sm text-red-500">{$errors.passwd}</span>{/if}
|
||||||
|
@ -130,7 +125,6 @@
|
||||||
name="code"
|
name="code"
|
||||||
placeholder="1234"
|
placeholder="1234"
|
||||||
type="text"
|
type="text"
|
||||||
required
|
|
||||||
aria-invalid={$errors.code ? 'true' : undefined}
|
aria-invalid={$errors.code ? 'true' : undefined}
|
||||||
/>
|
/>
|
||||||
{#if $errors.code}<span class="text-sm text-red-500">{$errors.code}</span>{/if}
|
{#if $errors.code}<span class="text-sm text-red-500">{$errors.code}</span>{/if}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { preprocessMeltUI } from '@melt-ui/pp';
|
import { preprocessMeltUI } from '@melt-ui/pp';
|
||||||
import adapter from '@sveltejs/adapter-node';
|
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
||||||
import sequence from 'svelte-sequential-preprocessor';
|
import sequence from 'svelte-sequential-preprocessor';
|
||||||
|
import adapter from '@sveltejs/adapter-node';
|
||||||
|
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||||
/** @type {import('@sveltejs/kit').Config}*/
|
/** @type {import('@sveltejs/kit').Config}*/
|
||||||
const config = {
|
const config = {
|
||||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||||
|
|
|
@ -5,8 +5,5 @@ export default defineConfig({
|
||||||
plugins: [sveltekit()],
|
plugins: [sveltekit()],
|
||||||
test: {
|
test: {
|
||||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||||
},
|
|
||||||
define: {
|
|
||||||
SUPERFORMS_LEGACY: true
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue