diff --git a/e2e/specs/create-project-flow.spec.ts b/e2e/specs/create-project-flow.spec.ts index 4978a86e..7025ab3b 100644 --- a/e2e/specs/create-project-flow.spec.ts +++ b/e2e/specs/create-project-flow.spec.ts @@ -1,8 +1,21 @@ +import { expect } from '@playwright/test' import { testWithUser as test } from './fixtures' +import { waitForHydration } from './util' -test.describe('create project', { tag: ['@foo-bar'] }, () => { +test.describe('create project', () => { test('projects', async ({ page }) => { + const projectName = 'My new project' + await page.goto('/projects') - // TODO add test + await waitForHydration(page) + + await page.getByTestId('create-project-modal-trigger').click() + + await page.getByTestId('create-project-name-input').fill(projectName) + await page.getByTestId('create-project-base-language-input').fill('en') + + await page.getByTestId('create-project-submit-button').click() + + await expect(page.getByTestId('project-card-name')).toHaveText(projectName) }) }) diff --git a/package.json b/package.json index 9b96a171..183ecc4a 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "better-sqlite3": "^10.0.0", "bits-ui": "^0.21.7", "clsx": "^2.1.1", + "date-fns": "^3.6.0", "formsnap": "^1.0.0", "jsonwebtoken": "^9.0.2", "kysely": "^0.27.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7691795..64cc9bfe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + date-fns: + specifier: ^3.6.0 + version: 3.6.0 formsnap: specifier: ^1.0.0 version: 1.0.1(svelte@4.2.18)(sveltekit-superforms@2.15.1(@sveltejs/kit@2.5.17(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)))(svelte@4.2.18)) @@ -1381,6 +1384,9 @@ packages: resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} engines: {node: '>= 0.4'} + date-fns@3.6.0: + resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} + dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} @@ -4973,6 +4979,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.1 + date-fns@3.6.0: {} + dateformat@4.6.3: {} dayjs@1.11.11: diff --git a/services/src/error/index.ts b/services/src/error/index.ts new file mode 100644 index 00000000..02dd394f --- /dev/null +++ b/services/src/error/index.ts @@ -0,0 +1,5 @@ +export class CreateProjectNameNotUniqueError extends Error { + constructor() { + super('Project name must be unique') + } +} diff --git a/services/src/kysely/migrations/2024-04-28T09_init.ts b/services/src/kysely/migrations/2024-04-28T09_init.ts index e8160db9..625f4df4 100644 --- a/services/src/kysely/migrations/2024-04-28T09_init.ts +++ b/services/src/kysely/migrations/2024-04-28T09_init.ts @@ -14,16 +14,21 @@ export async function up(db: Kysely): Promise { await createTableMigration(tx, 'projects') .addColumn('name', 'text', (col) => col.unique().notNull()) .addColumn('base_language', 'integer', (col) => - col.references('languages.id').onDelete('restrict').notNull() + col + .references('languages.id') + .onDelete('restrict') + .notNull() + .modifyEnd(sql`DEFERRABLE INITIALLY DEFERRED`) ) .execute() await createTableMigration(tx, 'languages') - .addColumn('code', 'text', (col) => col.unique().notNull()) + .addColumn('code', 'text', (col) => col.notNull()) .addColumn('fallback_language', 'integer', (col) => col.references('languages.id')) .addColumn('project_id', 'integer', (col) => - col.references('project.id').onDelete('cascade').notNull() + col.references('projects.id').onDelete('cascade').notNull() ) + .addUniqueConstraint('languages_code_project_id_unique', ['code', 'project_id']) .execute() await createTableMigration(tx, 'keys') @@ -60,7 +65,7 @@ export async function down(db: Kysely): Promise { await tx.schema.dropTable('projects_users').execute() await tx.schema.dropTable('translations').execute() await tx.schema.dropTable('keys').execute() - await tx.schema.dropTable('languages').execute() await tx.schema.dropTable('projects').execute() + await tx.schema.dropTable('languages').execute() }) } diff --git a/services/src/project/project-repository.integration.test.ts b/services/src/project/project-repository.integration.test.ts new file mode 100644 index 00000000..4145f8a4 --- /dev/null +++ b/services/src/project/project-repository.integration.test.ts @@ -0,0 +1,129 @@ +import { beforeEach, describe, expect, it } from 'vitest' +import { createProject, getAllProjects } from './project-repository' +import { runMigration } from '../db/database-migration-util' +import { db } from '../db/database' +import type { CreateProjectFormSchema, SelectableProject } from './project' +import type { Languages } from 'kysely-codegen' +import type { Selectable } from 'kysely' + +const projectCreationObject: CreateProjectFormSchema = { + name: 'Test Project', + base_language: 'en' +} + +beforeEach(async () => { + db.reset() + await runMigration() +}) + +describe('Project Repository', () => { + describe('createProject', () => { + it('should create a project with the correct attributes', async () => { + const createdProject = await createProject(projectCreationObject) + + const projects = await db.selectFrom('projects').selectAll().execute() + expect(projects).toHaveLength(1) + + const project = projects[0] as SelectableProject + + expect(project).toMatchObject({ + id: createdProject.id, + name: projectCreationObject.name, + base_language: createdProject.base_language + }) + + expect(project.id).toBeTypeOf('number') + }) + + it('should not allow creation of projects with duplicate names', async () => { + await createProject(projectCreationObject) + + await expect(createProject(projectCreationObject)).rejects.toThrow() + + const projects = await db.selectFrom('projects').selectAll().execute() + expect(projects).toHaveLength(1) + }) + + it('should create a base language for the project', async () => { + const createdProject = await createProject(projectCreationObject) + + const languages = await db.selectFrom('languages').selectAll().execute() + expect(languages).toHaveLength(1) + + const language = languages[0] as Selectable + + expect(language.project_id).toBe(createdProject.id) + expect(language.code).toBe(projectCreationObject.base_language) + }) + + it('should link the base language to the project', async () => { + const createdProject = await createProject(projectCreationObject) + + expect(createdProject.base_language).not.toBe(0) + + const language = await db + .selectFrom('languages') + .where('id', '==', createdProject.base_language) + .selectAll() + .executeTakeFirstOrThrow() + + expect(language.project_id).toBe(createdProject.id) + }) + + it('should allow creation of multiple projects with the same base language code', async () => { + const project1 = { name: 'Project 1', base_language: 'en' } + const project2 = { name: 'Project 2', base_language: 'en' } + + await createProject(project1) + await createProject(project2) + + const projects = await db.selectFrom('projects').selectAll().execute() + expect(projects).toHaveLength(2) + + const languages = await db.selectFrom('languages').selectAll().execute() + expect(languages).toHaveLength(2) + + const languageCodes = languages.map((language: Selectable) => language.code) + expect(languageCodes.filter((code) => code === 'en')).toHaveLength(2) + }) + }) + + describe('getAllProjects', () => { + it('should return an empty array when there are no projects', async () => { + const projects = await getAllProjects() + expect(projects).toHaveLength(0) + }) + + it('should return all created projects', async () => { + const project1 = { name: 'Project 1', base_language: 'en' } + const project2 = { name: 'Project 2', base_language: 'fr' } + + await createProject(project1) + await createProject(project2) + + const projects = await getAllProjects() + expect(projects).toHaveLength(2) + + const projectNames = projects.map((project: SelectableProject) => project.name) + expect(projectNames).toContain('Project 1') + expect(projectNames).toContain('Project 2') + }) + + it('should return projects with correct attributes', async () => { + const createdProject = await createProject(projectCreationObject) + + const projects = await getAllProjects() + expect(projects).toHaveLength(1) + + const project = projects[0] as SelectableProject + + expect(project).toMatchObject({ + id: createdProject.id, + name: projectCreationObject.name, + base_language: createdProject.base_language + }) + + expect(project.id).toBeTypeOf('number') + }) + }) +}) diff --git a/services/src/project/project-repository.ts b/services/src/project/project-repository.ts new file mode 100644 index 00000000..f7065bb5 --- /dev/null +++ b/services/src/project/project-repository.ts @@ -0,0 +1,31 @@ +import type { CreateProjectFormSchema, SelectableProject } from './project' +import { db } from '../db/database' + +export function createProject(project: CreateProjectFormSchema): Promise { + return db.transaction().execute(async (tx) => { + const tempProject = await tx + .insertInto('projects') + .values({ name: project.name, base_language: 0 }) + .returning('id') + .executeTakeFirstOrThrow(() => new Error('Error Creating Project')) + + const baseLanguage = await tx + .insertInto('languages') + .values({ code: project.base_language, project_id: tempProject.id }) + .returning('id') + .executeTakeFirstOrThrow(() => new Error('Error Creating Base Language')) + + const createdProject = await tx + .updateTable('projects') + .set({ base_language: baseLanguage.id }) + .where('id', '==', tempProject.id) + .returningAll() + .executeTakeFirstOrThrow(() => new Error('Error Updating Project')) + + return createdProject + }) +} + +export function getAllProjects(): Promise { + return db.selectFrom('projects').selectAll().execute() +} diff --git a/services/src/project/project-service.ts b/services/src/project/project-service.ts new file mode 100644 index 00000000..f2652f1c --- /dev/null +++ b/services/src/project/project-service.ts @@ -0,0 +1,24 @@ +import { CreateProjectNameNotUniqueError } from '../error' +import { type CreateProjectFormSchema } from './project' +import * as repository from './project-repository' +import { SqliteError } from 'better-sqlite3' + +export async function createProject(project: CreateProjectFormSchema) { + try { + return await repository.createProject(project) + } catch (e: unknown) { + if (e instanceof SqliteError && e.code === 'SQLITE_CONSTRAINT_UNIQUE') { + throw new CreateProjectNameNotUniqueError() + } + + throw new Error('Error Creating Project') + } +} + +export async function getAllProjects() { + try { + return await repository.getAllProjects() + } catch (e) { + throw new Error('Error Getting Projects') + } +} diff --git a/services/src/project/project-service.unit.test.ts b/services/src/project/project-service.unit.test.ts new file mode 100644 index 00000000..ca629c93 --- /dev/null +++ b/services/src/project/project-service.unit.test.ts @@ -0,0 +1,86 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { createProject, getAllProjects } from './project-service' +import * as repository from './project-repository' +import type { CreateProjectFormSchema } from './project' +import { CreateProjectNameNotUniqueError } from '../error' +import { SqliteError } from 'better-sqlite3' + +vi.mock('./project-repository', () => ({ + createProject: vi.fn(), + getAllProjects: vi.fn() +})) + +const projectCreationObject: CreateProjectFormSchema = { + name: 'Test Project', + base_language: 'en' +} + +const mockSelectableProject = { + id: 1, + name: 'Test Project', + base_language: 1, + created_at: new Date().toISOString(), + updated_at: new Date().toISOString() +} + +beforeEach(() => { + vi.resetAllMocks() +}) + +describe('Project Service', () => { + describe('createProject', () => { + it('should call the repository to create a project', async () => { + vi.mocked(repository.createProject).mockResolvedValue(mockSelectableProject) + + const project = await createProject(projectCreationObject) + + expect(repository.createProject).toHaveBeenCalledWith(projectCreationObject) + expect(project).toEqual(mockSelectableProject) + }) + + it('should throw an error if the repository throws an error', async () => { + vi.mocked(repository.createProject).mockRejectedValue(new Error('Repository error')) + + await expect(createProject(projectCreationObject)).rejects.toThrow('Error Creating Project') + }) + + it('should throw a CreateProjectNameNotUniqueError if the repository throws a SQLITE_CONSTRAINT_UNIQUE error', async () => { + const sqliteError = new SqliteError( + 'SQLITE_CONSTRAINT_UNIQUE: UNIQUE constraint failed: projects.name', + 'SQLITE_CONSTRAINT_UNIQUE' + ) + vi.mocked(repository.createProject).mockRejectedValue(sqliteError) + + await expect(createProject(projectCreationObject)).rejects.toThrow( + new CreateProjectNameNotUniqueError() + ) + }) + }) + + describe('getAllProjects', () => { + it('should call the repository to get all projects', async () => { + const mockProjects = [mockSelectableProject] + vi.mocked(repository.getAllProjects).mockResolvedValue(mockProjects) + + const projects = await getAllProjects() + + expect(repository.getAllProjects).toHaveBeenCalled() + expect(projects).toEqual(mockProjects) + }) + + it('should return an empty array when there are no projects', async () => { + vi.mocked(repository.getAllProjects).mockResolvedValue([]) + + const projects = await getAllProjects() + + expect(repository.getAllProjects).toHaveBeenCalled() + expect(projects).toEqual([]) + }) + + it('should throw an error if the repository throws an error', async () => { + vi.mocked(repository.getAllProjects).mockRejectedValue(new Error('Repository error')) + + await expect(getAllProjects()).rejects.toThrow('Error Getting Projects') + }) + }) +}) diff --git a/services/src/project/project.ts b/services/src/project/project.ts new file mode 100644 index 00000000..57b99836 --- /dev/null +++ b/services/src/project/project.ts @@ -0,0 +1,20 @@ +import type { Insertable, Selectable } from 'kysely' +import type { Projects } from 'kysely-codegen' +import { z } from 'zod' + +export type ProjectCreationParams = Insertable> +export type Project = SelectableProject + +export type SelectableProject = Selectable +export type InsertableProject = Insertable + +export const createProjectSchema = z.object({ + name: z + .string({ required_error: 'Project name is required' }) + .min(1, 'Project name must have at least one character'), + base_language: z + .string({ required_error: 'Base language is required' }) + .min(1, 'Base language must have at least one character') +}) + +export type CreateProjectFormSchema = z.infer diff --git a/src/routes/(auth)/login/login-form.svelte b/src/components/container/auth/login-form.svelte similarity index 100% rename from src/routes/(auth)/login/login-form.svelte rename to src/components/container/auth/login-form.svelte diff --git a/src/routes/(auth)/signup/schema.ts b/src/components/container/auth/schema.ts similarity index 83% rename from src/routes/(auth)/signup/schema.ts rename to src/components/container/auth/schema.ts index 25a41441..2124f0d1 100644 --- a/src/routes/(auth)/signup/schema.ts +++ b/src/components/container/auth/schema.ts @@ -1,5 +1,12 @@ import { z } from 'zod' +export const loginSchema = z.object({ + email: z.string().email(), + password: z.string() +}) + +export type LoginFormSchema = typeof loginSchema + export const signupSchema = z .object({ email: z @@ -17,5 +24,3 @@ export const signupSchema = z message: "Passwords don't match", path: ['confirmPassword'] }) - -export type SignupFormSchema = typeof signupSchema diff --git a/src/routes/(auth)/signup/signup-form.svelte b/src/components/container/auth/signup-form.svelte similarity index 96% rename from src/routes/(auth)/signup/signup-form.svelte rename to src/components/container/auth/signup-form.svelte index 1ec65841..900b6417 100644 --- a/src/routes/(auth)/signup/signup-form.svelte +++ b/src/components/container/auth/signup-form.svelte @@ -2,14 +2,14 @@ import * as Form from '$components/ui/form' import { Input } from '$components/ui/input' import { Checkbox } from '$components/ui/checkbox' - import { type SignupFormSchema, signupSchema } from './schema' + import { signupSchema } from '$components/container/auth/schema' import { type Infer, type SuperValidated, superForm } from 'sveltekit-superforms' import { zodClient } from 'sveltekit-superforms/adapters' import { page } from '$app/stores' import { toast } from 'svelte-sonner' import { goto } from '$app/navigation' - export let data: SuperValidated> + export let data: SuperValidated> const form = superForm(data, { validators: zodClient(signupSchema), diff --git a/src/components/container/projects/create-project-schema.ts b/src/components/container/projects/create-project-schema.ts new file mode 100644 index 00000000..b47cf002 --- /dev/null +++ b/src/components/container/projects/create-project-schema.ts @@ -0,0 +1,10 @@ +import { z } from 'zod' + +export const createProjectSchema = z.object({ + name: z + .string({ required_error: 'Project name is required' }) + .min(1, 'Project name must have at least one character'), + base_language: z + .string({ required_error: 'Base language is required' }) + .min(1, 'Base language must have at least one character') +}) diff --git a/src/components/container/projects/create-project.svelte b/src/components/container/projects/create-project.svelte new file mode 100644 index 00000000..6919e43f --- /dev/null +++ b/src/components/container/projects/create-project.svelte @@ -0,0 +1,79 @@ + + + + + + Create Project + + +
+ + New Project + + Create a new project and start translating your application. + + +
+ + + Name + + + + + + + Base Language + + + + +
+ + Create Project + +
+
+
diff --git a/src/components/container/projects/project-card.svelte b/src/components/container/projects/project-card.svelte new file mode 100644 index 00000000..60b50839 --- /dev/null +++ b/src/components/container/projects/project-card.svelte @@ -0,0 +1,41 @@ + + + + + +
+ + {project.name} + + +
+
+ +
+
+
+
+
+ + Last updated: {formatDistanceToNow(project.updated_at + 'Z', { + addSuffix: true + })} + +
+
diff --git a/src/components/container/projects/project-cards-layout.svelte b/src/components/container/projects/project-cards-layout.svelte new file mode 100644 index 00000000..8f241e18 --- /dev/null +++ b/src/components/container/projects/project-cards-layout.svelte @@ -0,0 +1,29 @@ + + +
+ {#each projects as project} + + {/each} +
+ +{#if projects.length === 0} +
+
+

You have no projects

+

+ You can start translating as soon as you add a project +

+
+
+{/if} + + diff --git a/src/components/layout/main-content/header.svelte b/src/components/layout/main-content/header.svelte new file mode 100644 index 00000000..5f2bdf16 --- /dev/null +++ b/src/components/layout/main-content/header.svelte @@ -0,0 +1,8 @@ + + +
+

{title}

+ +
diff --git a/src/components/layout/main-content/index.ts b/src/components/layout/main-content/index.ts new file mode 100644 index 00000000..4ea24cff --- /dev/null +++ b/src/components/layout/main-content/index.ts @@ -0,0 +1,4 @@ +import MainContent from './main-content.svelte' +import MainContentHeader from './header.svelte' + +export { MainContent, MainContentHeader } diff --git a/src/components/layout/main-content/main-content.svelte b/src/components/layout/main-content/main-content.svelte new file mode 100644 index 00000000..5bd2dbbc --- /dev/null +++ b/src/components/layout/main-content/main-content.svelte @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/components/sidebar/index.ts b/src/components/layout/sidebar/index.ts similarity index 100% rename from src/components/sidebar/index.ts rename to src/components/layout/sidebar/index.ts diff --git a/src/components/sidebar/sidebar.svelte b/src/components/layout/sidebar/sidebar.svelte similarity index 100% rename from src/components/sidebar/sidebar.svelte rename to src/components/layout/sidebar/sidebar.svelte diff --git a/src/components/ui/dialog/dialog-content.svelte b/src/components/ui/dialog/dialog-content.svelte new file mode 100644 index 00000000..53640e09 --- /dev/null +++ b/src/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,36 @@ + + + + + + + + + Close + + + diff --git a/src/components/ui/dialog/dialog-description.svelte b/src/components/ui/dialog/dialog-description.svelte new file mode 100644 index 00000000..49dca809 --- /dev/null +++ b/src/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/components/ui/dialog/dialog-footer.svelte b/src/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 00000000..6481771b --- /dev/null +++ b/src/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,16 @@ + + +
+ +
diff --git a/src/components/ui/dialog/dialog-header.svelte b/src/components/ui/dialog/dialog-header.svelte new file mode 100644 index 00000000..11826bef --- /dev/null +++ b/src/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,13 @@ + + +
+ +
diff --git a/src/components/ui/dialog/dialog-overlay.svelte b/src/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 00000000..78bdbdb3 --- /dev/null +++ b/src/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/components/ui/dialog/dialog-portal.svelte b/src/components/ui/dialog/dialog-portal.svelte new file mode 100644 index 00000000..1ad7eb9d --- /dev/null +++ b/src/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,8 @@ + + + + + diff --git a/src/components/ui/dialog/dialog-title.svelte b/src/components/ui/dialog/dialog-title.svelte new file mode 100644 index 00000000..c2a2db60 --- /dev/null +++ b/src/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/components/ui/dialog/index.ts b/src/components/ui/dialog/index.ts new file mode 100644 index 00000000..8989ed80 --- /dev/null +++ b/src/components/ui/dialog/index.ts @@ -0,0 +1,36 @@ +import { Dialog as DialogPrimitive } from 'bits-ui' +import Title from './dialog-title.svelte' +import Portal from './dialog-portal.svelte' +import Footer from './dialog-footer.svelte' +import Header from './dialog-header.svelte' +import Overlay from './dialog-overlay.svelte' +import Content from './dialog-content.svelte' +import Description from './dialog-description.svelte' + +const Root = DialogPrimitive.Root +const Trigger = DialogPrimitive.Trigger +const Close = DialogPrimitive.Close + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose +} diff --git a/src/components/ui/popover/index.ts b/src/components/ui/popover/index.ts new file mode 100644 index 00000000..4ffbcda7 --- /dev/null +++ b/src/components/ui/popover/index.ts @@ -0,0 +1,18 @@ +import { Popover as PopoverPrimitive } from 'bits-ui' +import Content from './popover-content.svelte' + +const Root = PopoverPrimitive.Root +const Trigger = PopoverPrimitive.Trigger +const Close = PopoverPrimitive.Close + +export { + Root, + Content, + Trigger, + Close, + // + Root as Popover, + Content as PopoverContent, + Trigger as PopoverTrigger, + Close as PopoverClose +} diff --git a/src/components/ui/popover/popover-content.svelte b/src/components/ui/popover/popover-content.svelte new file mode 100644 index 00000000..7579150a --- /dev/null +++ b/src/components/ui/popover/popover-content.svelte @@ -0,0 +1,22 @@ + + + + + diff --git a/src/routes/(auth)/login/+page.server.ts b/src/routes/(auth)/login/+page.server.ts index 6b96a5f2..db641239 100644 --- a/src/routes/(auth)/login/+page.server.ts +++ b/src/routes/(auth)/login/+page.server.ts @@ -1,6 +1,6 @@ import type { Actions, PageServerLoad } from './$types' import { message, superValidate } from 'sveltekit-superforms' -import { loginSchema } from './schema' +import { loginSchema } from '$components/container/auth/schema' import { zod } from 'sveltekit-superforms/adapters' import { login } from 'services/user/user-auth-service' import { TOKEN_NAME, TOKEN_PREFIX } from 'services/auth/token' diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index da92bddb..6ee1b75d 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -1,6 +1,6 @@ diff --git a/src/routes/(auth)/login/schema.ts b/src/routes/(auth)/login/schema.ts deleted file mode 100644 index d2583ee5..00000000 --- a/src/routes/(auth)/login/schema.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { z } from 'zod' - -export const loginSchema = z.object({ - email: z.string().email(), - password: z.string() -}) - -export type LoginFormSchema = typeof loginSchema diff --git a/src/routes/(auth)/signup/+page.server.ts b/src/routes/(auth)/signup/+page.server.ts index 3b178c08..6557ed24 100644 --- a/src/routes/(auth)/signup/+page.server.ts +++ b/src/routes/(auth)/signup/+page.server.ts @@ -1,6 +1,6 @@ -import type { PageServerLoad } from './$types' +import type { Actions, PageServerLoad } from './$types' import { message, superValidate } from 'sveltekit-superforms' -import { signupSchema } from './schema' +import { signupSchema } from '$components/container/auth/schema' import { zod } from 'sveltekit-superforms/adapters' import { register } from 'services/user/user-auth-service' import { redirect } from '@sveltejs/kit' @@ -15,8 +15,7 @@ export const load: PageServerLoad = async (event) => { } } -/** @type {import('./$types').Actions} */ -export const actions = { +export const actions: Actions = { default: async ({ request }) => { const form = await superValidate(request, zod(signupSchema)) diff --git a/src/routes/(auth)/signup/+page.svelte b/src/routes/(auth)/signup/+page.svelte index 0d97e41b..3fb7a03b 100644 --- a/src/routes/(auth)/signup/+page.svelte +++ b/src/routes/(auth)/signup/+page.svelte @@ -1,6 +1,6 @@ diff --git a/src/routes/(authenticated)/+layout.svelte b/src/routes/(authenticated)/+layout.svelte index 9130cc4f..90828c49 100644 --- a/src/routes/(authenticated)/+layout.svelte +++ b/src/routes/(authenticated)/+layout.svelte @@ -1,5 +1,5 @@ + + + + + + + diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b3b38ee2..dee0a318 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -4,7 +4,7 @@ import { browser } from '$app/environment' -
+