diff --git a/package.json b/package.json index 5aa91a0..8efec83 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/kit": "^2.9.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", + "@types/bun": "^1.1.14", "autoprefixer": "^10.4.20", "eslint": "^9.7.0", "eslint-config-prettier": "^9.1.0", @@ -41,6 +42,7 @@ "prettier-plugin-tailwindcss": "^0.6.5", "prisma": "^6.0.1", "storybook": "^8.4.7", + "storybook-dark-mode": "^4.0.2", "svelte": "^5.0.0", "svelte-check": "^4.0.0", "tailwindcss": "^3.4.9", @@ -56,14 +58,14 @@ "@prisma/client": "6.0.1", "@supabase/supabase-js": "^2.47.6", "@tailwindcss/typography": "^0.5.15", - "@types/bun": "^1.1.14", + "dayjs": "^1.11.13", "graphql": "^16.9.0", "graphql-yoga": "^5.10.4", "lucia": "^3.2.2", "oslo": "^1.2.1", "pino": "^9.5.0", "pino-pretty": "^13.0.0", - "storybook-dark-mode": "^4.0.2", + "tailwind-merge": "^2.5.5", "zod": "^3.24.0" } } diff --git a/prisma/dev.db b/prisma/dev.db index 14dfc11..7886134 100644 Binary files a/prisma/dev.db and b/prisma/dev.db differ diff --git a/prisma/dev.db-journal b/prisma/dev.db-journal deleted file mode 100644 index be0024e..0000000 Binary files a/prisma/dev.db-journal and /dev/null differ diff --git a/prisma/migrations/20241211200947_add_timestamps/migration.sql b/prisma/migrations/20241211200947_add_timestamps/migration.sql new file mode 100644 index 0000000..d4aa687 --- /dev/null +++ b/prisma/migrations/20241211200947_add_timestamps/migration.sql @@ -0,0 +1,37 @@ +/* + Warnings: + + - Made the column `content` on table `Post` required. This step will fail if there are existing NULL values in that column. + - Made the column `name` on table `User` required. This step will fail if there are existing NULL values in that column. + +*/ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Post" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "published" BOOLEAN DEFAULT false, + "authorId" INTEGER NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); +INSERT INTO "new_Post" ("authorId", "content", "id", "published", "title") SELECT "authorId", "content", "id", "published", "title" FROM "Post"; +DROP TABLE "Post"; +ALTER TABLE "new_Post" RENAME TO "Post"; +CREATE TABLE "new_User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "email" TEXT, + "name" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP +); +INSERT INTO "new_User" ("email", "id", "name") SELECT "email", "id", "name" FROM "User"; +DROP TABLE "User"; +ALTER TABLE "new_User" RENAME TO "User"; +CREATE UNIQUE INDEX "User_id_key" ON "User"("id"); +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 4319ec7..509e867 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,10 +16,13 @@ datasource db { model User { id Int @id @default(autoincrement()) - email String @unique - name String? + email String? @unique + name String posts Post[] sessions Session[] + + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt } model Session { @@ -35,10 +38,12 @@ model Session { model Post { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) title String - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) + content String + published Boolean? @default(false) + author User @relation(fields: [authorId], references: [id]) authorId Int + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt } \ No newline at end of file diff --git a/src/app.css b/src/app.css index a31e444..414ab1e 100644 --- a/src/app.css +++ b/src/app.css @@ -1,3 +1,19 @@ @import 'tailwindcss/base'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities'; + +:root { + @apply text-slate-800; +} + +h1 { + @apply font-display text-4xl; +} + +h2 { + @apply font-display text-3xl; +} + +h3 { + @apply font-display text-2xl; +} \ No newline at end of file diff --git a/src/lib/components/Button.svelte b/src/lib/components/Button.svelte index 995f0a7..2c8737a 100644 --- a/src/lib/components/Button.svelte +++ b/src/lib/components/Button.svelte @@ -9,12 +9,12 @@ backgroundColor, primary = false }: { - type: HTMLButtonAttributes['type']; - onClick: () => void; + type?: HTMLButtonAttributes['type']; + onClick?: () => void; label: string; - size: 'small' | 'normal' | 'large'; - backgroundColor: string; - primary: boolean; + size?: 'small' | 'normal' | 'large'; + backgroundColor?: string; + primary?: boolean; } = $props(); @@ -31,7 +31,7 @@ \ No newline at end of file diff --git a/src/lib/components/Navbar.svelte b/src/lib/components/Navbar.svelte index 757b744..bb75025 100644 --- a/src/lib/components/Navbar.svelte +++ b/src/lib/components/Navbar.svelte @@ -18,7 +18,7 @@ \ No newline at end of file diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts new file mode 100644 index 0000000..614de2d --- /dev/null +++ b/src/routes/+page.server.ts @@ -0,0 +1,18 @@ +import { prisma } from '$lib/server/prisma'; + +export async function load(event) { + const userId = event.cookies.get('user'); + if (!userId && isNaN(Number(userId))) { + return { + authenticated: false + }; + } + const user = await prisma.user.findUnique({ + where: { + id: Number(userId) + } + }); + return { + authenticated: !!user + }; +} \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index fa25cf6..2a4c1a0 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -2,10 +2,10 @@ import { goto } from '$app/navigation'; import Loader from '$lib/components/Loader.svelte'; + let { data } = $props(); + $effect(() => { - const id = setTimeout(() => { - goto('/app'); - }, 1500); + const id = setTimeout(() => (data.authenticated ? goto('/app') : goto('/login')), 1500); return () => { clearTimeout(id); }; @@ -19,9 +19,6 @@ \ No newline at end of file diff --git a/src/routes/api/graphql/+server.ts b/src/routes/api/graphql/+server.ts index 72aab8c..c208143 100644 --- a/src/routes/api/graphql/+server.ts +++ b/src/routes/api/graphql/+server.ts @@ -1,3 +1,3 @@ -import { Yoga } from '$lib/yoga'; +import { Yoga } from '$lib/server/yoga'; export { Yoga as GET, Yoga as POST }; \ No newline at end of file diff --git a/src/routes/login/+page.server.ts b/src/routes/login/+page.server.ts new file mode 100644 index 0000000..5216540 --- /dev/null +++ b/src/routes/login/+page.server.ts @@ -0,0 +1,46 @@ +import { logger } from '$lib/server/logger'; +import { prisma } from '$lib/server/prisma'; +import { error, redirect, type Actions } from '@sveltejs/kit'; + +export const actions = { + login: async (event) => { + const form = await event.request.formData(); + if (!form.has('email')) { + return error(400, 'Email is a required form field!'); + } + const user = await prisma.user.findUnique({ + where: { + email: form.get('email') as string + } + }); + if (!user) { + logger.error('User not found! ${user}'); + return error(401); + } + event.cookies.set('user', String(user.id), { + path: '/', + maxAge: 120 + }); + redirect(302, '/'); + }, + register: async (event) => { + const form = await event.request.formData(); + if (!form.has('email') || !form.has('name')) { + return error(400); + } + const user = await prisma.user.create({ + data: { + email: form.get('email') as string, + name: form.get('name') as string + } + }); + if (!user) { + return error(500); + } + event.cookies.set('user', String(user.id), { + path: '/', + maxAge: 120 + }); + redirect(302, '/'); + } +} satisfies Actions; \ No newline at end of file diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte new file mode 100644 index 0000000..1eb8b77 --- /dev/null +++ b/src/routes/login/+page.svelte @@ -0,0 +1,49 @@ + + +
+

Hestia

+
+
+

{mode === 'login' ? 'Login' : 'Register'}

+ {#if mode === 'register'} +
+ +
+ {/if} + + +
+
+
+
+
+ + \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index 228b779..575e6fd 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -8,6 +8,15 @@ export default { extend: { fontFamily: { display: ['Baskervville SC'] + }, + animation: { + fade: 'fadeIn .5s ease-in-out' + }, + keyframes: { + fadeIn: { + from: { opacity: '0' }, + to: { opacity: '1' } + } } } },