diff --git a/drizzle/schema.ts b/drizzle/schema.ts
new file mode 100644
index 0000000..8bcc296
--- /dev/null
+++ b/drizzle/schema.ts
@@ -0,0 +1,60 @@
+import { pgTable, foreignKey, unique, uuid, text, boolean, date } from "drizzle-orm/pg-core"
+ import { sql } from "drizzle-orm"
+
+
+
+export const groups = pgTable("groups", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ userId: uuid("user_id").references(() => users.id),
+ email: text("email").notNull(),
+ name: text("name").notNull(),
+},
+(table) => {
+ return {
+ groupsEmailUnique: unique("groups_email_unique").on(table.email),
+ }
+});
+
+export const sources = pgTable("sources", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ groupId: uuid("group_id").notNull().references(() => groups.id),
+ name: text("name").notNull(),
+ isConfirmed: boolean("is_confirmed").default(false).notNull(),
+});
+
+export const letters = pgTable("letters", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ sender: text("sender").notNull(),
+ content: text("content").notNull(),
+ groupId: uuid("group_id").notNull().references(() => groups.id),
+ dateCreated: date("date_created").defaultNow().notNull(),
+ senderEmail: text("sender_email").notNull(),
+ subject: text("subject").notNull(),
+});
+
+export const sessions = pgTable("sessions", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ userId: uuid("user_id").notNull(),
+ dateCreated: date("date_created").defaultNow().notNull(),
+});
+
+export const users = pgTable("users", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ name: text("name").notNull(),
+ email: text("email").notNull(),
+ hashedPassword: text("hashed_password").notNull(),
+ dateCreated: date("date_created").defaultNow().notNull(),
+},
+(table) => {
+ return {
+ usersEmailUnique: unique("users_email_unique").on(table.email),
+ }
+});
+
+export const pods = pgTable("pods", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ userId: uuid("user_id").references(() => users.id),
+ script: text("script").notNull(),
+ dateCreated: date("date_created").defaultNow().notNull(),
+ groupId: uuid("group_id").references(() => groups.id),
+});
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 9a2b881..eeff40d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,10 +15,13 @@
"drizzle-orm": "^0.30.1",
"formsnap": "^0.5.1",
"lucide-svelte": "^0.354.0",
+ "mode-watcher": "^0.2.2",
"pg": "^8.11.3",
+ "svelte-sonner": "^0.3.19",
"sveltekit-superforms": "^2.8.1",
"tailwind-merge": "^2.2.1",
"tailwind-variants": "^0.2.0",
+ "vaul-svelte": "^0.3.0",
"zod": "^3.22.4"
},
"devDependencies": {
@@ -3186,6 +3189,14 @@
"mkdirp": "bin/cmd.js"
}
},
+ "node_modules/mode-watcher": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-0.2.2.tgz",
+ "integrity": "sha512-QjkHQL9pXrr7Vb0P3WbOWAF8mv1Q6jEwUZ5GUyCnI9eEoXH234zuaOGChUF7ZQtjxwtmXDzKFSW/36TvLDg1/A==",
+ "peerDependencies": {
+ "svelte": "^4.0.0"
+ }
+ },
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
@@ -4474,6 +4485,14 @@
}
}
},
+ "node_modules/svelte-sonner": {
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/svelte-sonner/-/svelte-sonner-0.3.19.tgz",
+ "integrity": "sha512-jpPOgLtHwRaB6Vqo2dUQMv15/yUV/BQWTjKpEqQ11uqRSHKjAYUKZyGrHB2cQsGmyjR0JUzBD58btpgNqINQ/Q==",
+ "peerDependencies": {
+ "svelte": ">=3 <5"
+ }
+ },
"node_modules/sveltekit-superforms": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/sveltekit-superforms/-/sveltekit-superforms-2.8.1.tgz",
@@ -4896,6 +4915,63 @@
"node": ">= 0.10"
}
},
+ "node_modules/vaul-svelte": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/vaul-svelte/-/vaul-svelte-0.3.0.tgz",
+ "integrity": "sha512-+PBfKDWl+xfloe8Tm1G8x3TqbCiUWoyUedU2WC5iE3v6LOYPKo8FyEtzNC5ZqFVVnUKSKNg+4Fi73nuzMkT7JA==",
+ "dependencies": {
+ "bits-ui": "^0.16.0"
+ },
+ "peerDependencies": {
+ "svelte": "^4.0.0"
+ }
+ },
+ "node_modules/vaul-svelte/node_modules/@melt-ui/svelte": {
+ "version": "0.68.0",
+ "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.68.0.tgz",
+ "integrity": "sha512-/QvA98hnYEodZtHJ71+ocum/WWp30hVNt3F8uiZKnNYwZDaiQYjlyR9AaGKYcZLCe6R68op1mfCzc0kTzJilyA==",
+ "dependencies": {
+ "@floating-ui/core": "^1.3.1",
+ "@floating-ui/dom": "^1.4.5",
+ "@internationalized/date": "^3.5.0",
+ "dequal": "^2.0.3",
+ "focus-trap": "^7.5.2",
+ "nanoid": "^5.0.4"
+ },
+ "peerDependencies": {
+ "svelte": ">=3 <5"
+ }
+ },
+ "node_modules/vaul-svelte/node_modules/bits-ui": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.16.0.tgz",
+ "integrity": "sha512-HEkuVDyUG9dTWtKujKpdDsGOe9GRmuYOEF9yGbjVwNazxMQDQa9deUX8vM3ofGBWaJgr1cEu88p38kP5Z5gQ8w==",
+ "dependencies": {
+ "@internationalized/date": "^3.5.1",
+ "@melt-ui/svelte": "0.68.0",
+ "nanoid": "^5.0.4"
+ },
+ "peerDependencies": {
+ "svelte": "^4.0.0"
+ }
+ },
+ "node_modules/vaul-svelte/node_modules/nanoid": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.6.tgz",
+ "integrity": "sha512-rRq0eMHoGZxlvaFOUdK1Ev83Bd1IgzzR+WJ3IbDJ7QOSdAxYjlurSPqFs9s4lJg29RT6nPwizFtJhQS6V5xgiA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.js"
+ },
+ "engines": {
+ "node": "^18 || >=20"
+ }
+ },
"node_modules/vite": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.1.5.tgz",
diff --git a/package.json b/package.json
index 97b4e98..85d6aef 100644
--- a/package.json
+++ b/package.json
@@ -39,10 +39,13 @@
"drizzle-orm": "^0.30.1",
"formsnap": "^0.5.1",
"lucide-svelte": "^0.354.0",
+ "mode-watcher": "^0.2.2",
"pg": "^8.11.3",
+ "svelte-sonner": "^0.3.19",
"sveltekit-superforms": "^2.8.1",
"tailwind-merge": "^2.2.1",
"tailwind-variants": "^0.2.0",
+ "vaul-svelte": "^0.3.0",
"zod": "^3.22.4"
}
}
diff --git a/src/lib/components/organisms/create-group.svelte b/src/lib/components/organisms/create-group.svelte
new file mode 100644
index 0000000..7396846
--- /dev/null
+++ b/src/lib/components/organisms/create-group.svelte
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+ Group title
+ Set a memorable name for your group.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer-content.svelte b/src/lib/components/ui/drawer/drawer-content.svelte
new file mode 100644
index 0000000..a4e3d9a
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer-content.svelte
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer-description.svelte b/src/lib/components/ui/drawer/drawer-description.svelte
new file mode 100644
index 0000000..1f4c12b
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer-description.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer-footer.svelte b/src/lib/components/ui/drawer/drawer-footer.svelte
new file mode 100644
index 0000000..6685813
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer-footer.svelte
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer-header.svelte b/src/lib/components/ui/drawer/drawer-header.svelte
new file mode 100644
index 0000000..265f291
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer-header.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer-nested.svelte b/src/lib/components/ui/drawer/drawer-nested.svelte
new file mode 100644
index 0000000..79b68e3
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer-nested.svelte
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer-overlay.svelte b/src/lib/components/ui/drawer/drawer-overlay.svelte
new file mode 100644
index 0000000..f0b64d6
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer-overlay.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer-title.svelte b/src/lib/components/ui/drawer/drawer-title.svelte
new file mode 100644
index 0000000..fd0a02b
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer-title.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/drawer.svelte b/src/lib/components/ui/drawer/drawer.svelte
new file mode 100644
index 0000000..40eae5e
--- /dev/null
+++ b/src/lib/components/ui/drawer/drawer.svelte
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/drawer/index.ts b/src/lib/components/ui/drawer/index.ts
new file mode 100644
index 0000000..76932e3
--- /dev/null
+++ b/src/lib/components/ui/drawer/index.ts
@@ -0,0 +1,41 @@
+import { Drawer as DrawerPrimitive } from "vaul-svelte";
+
+import Root from "./drawer.svelte";
+import Content from "./drawer-content.svelte";
+import Description from "./drawer-description.svelte";
+import Overlay from "./drawer-overlay.svelte";
+import Footer from "./drawer-footer.svelte";
+import Header from "./drawer-header.svelte";
+import Title from "./drawer-title.svelte";
+import NestedRoot from "./drawer-nested.svelte";
+
+const Trigger = DrawerPrimitive.Trigger;
+const Portal = DrawerPrimitive.Portal;
+const Close = DrawerPrimitive.Close;
+
+export {
+ Root,
+ NestedRoot,
+ Content,
+ Description,
+ Overlay,
+ Footer,
+ Header,
+ Title,
+ Trigger,
+ Portal,
+ Close,
+
+ //
+ Root as Drawer,
+ NestedRoot as DrawerNestedRoot,
+ Content as DrawerContent,
+ Description as DrawerDescription,
+ Overlay as DrawerOverlay,
+ Footer as DrawerFooter,
+ Header as DrawerHeader,
+ Title as DrawerTitle,
+ Trigger as DrawerTrigger,
+ Portal as DrawerPortal,
+ Close as DrawerClose,
+};
diff --git a/src/lib/components/ui/sonner/index.ts b/src/lib/components/ui/sonner/index.ts
new file mode 100644
index 0000000..1ad9f4a
--- /dev/null
+++ b/src/lib/components/ui/sonner/index.ts
@@ -0,0 +1 @@
+export { default as Toaster } from "./sonner.svelte";
diff --git a/src/lib/components/ui/sonner/sonner.svelte b/src/lib/components/ui/sonner/sonner.svelte
new file mode 100644
index 0000000..7d5b2f1
--- /dev/null
+++ b/src/lib/components/ui/sonner/sonner.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/src/lib/db/schema.ts b/src/lib/db/schema.ts
index b14482f..b1becba 100644
--- a/src/lib/db/schema.ts
+++ b/src/lib/db/schema.ts
@@ -1,4 +1,4 @@
-import { date, pgTable, serial, text, uuid, varchar } from 'drizzle-orm/pg-core';
+import { boolean, date, pgTable, serial, text, uuid, varchar } from 'drizzle-orm/pg-core';
import { drizzle } from 'drizzle-orm/node-postgres';
export const usersTable = pgTable('users', {
@@ -13,6 +13,7 @@ export const podsTable = pgTable('pods', {
id: uuid('id').primaryKey().defaultRandom(),
user_id: uuid('user_id').references(() => usersTable.id),
script: text('script').notNull(),
+ groupId: uuid("group_id").references(() => groupsTable.id),
date_created: date('date_created').notNull().defaultNow()
});
@@ -20,4 +21,28 @@ export const sessionsTable = pgTable('sessions', {
id: uuid('id').primaryKey().defaultRandom(),
user_id: uuid('user_id').notNull(),
date_created: date('date_created').notNull().defaultNow()
-})
\ No newline at end of file
+})
+
+export const groupsTable = pgTable("groups", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ userId: uuid("user_id").references(() => usersTable.id),
+ email: text("email").notNull().unique(),
+ name: text("name").notNull(),
+});
+
+export const sourcesTable = pgTable("sources", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ groupId: uuid("group_id").notNull().references(() => groupsTable.id),
+ name: text("name").notNull(),
+ isConfirmed: boolean("is_confirmed").default(false).notNull(),
+});
+
+export const lettersTable = pgTable("letters", {
+ id: uuid("id").defaultRandom().primaryKey().notNull(),
+ sender: text("sender").notNull(),
+ content: text("content").notNull(),
+ groupId: uuid("group_id").notNull().references(() => groupsTable.id),
+ dateCreated: date("date_created").defaultNow().notNull(),
+ senderEmail: text("sender_email").notNull(),
+ subject: text("subject").notNull(),
+});
diff --git a/src/lib/services/auth.server.ts b/src/lib/services/auth.server.ts
index da23026..93de3af 100644
--- a/src/lib/services/auth.server.ts
+++ b/src/lib/services/auth.server.ts
@@ -12,7 +12,10 @@ export async function createSession(user_id: string) {
}
export async function validateSession(session_id: string) {
- const session = await db.select().from(sessionsTable).where(eq(sessionsTable.id, session_id)).leftJoin(usersTable, eq(usersTable.id, sessionsTable.user_id));
-
- return session[0].users;
+ try {
+ const session = await db.select().from(sessionsTable).where(eq(sessionsTable.id, session_id)).leftJoin(usersTable, eq(usersTable.id, sessionsTable.user_id));
+ return session[0].users;
+ } catch (e) {
+ return false;
+ }
}
\ No newline at end of file
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index c3fffca..86cd539 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,7 +1,10 @@
+
+
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index f2c2eb5..06dc57e 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -4,23 +4,23 @@
import { Button } from '$lib/components/ui/button';
import Player from '$lib/components/organisms/player.svelte';
import { onMount } from 'svelte';
- import { PlayIcon, Loader, Plus, MailIcon } from 'lucide-svelte';
+ import { PlayIcon, Loader, Plus, MailIcon, PlusIcon } from 'lucide-svelte';
+ import CreateGroup from '$lib/components/organisms/create-group.svelte';
let script = "";
let opened = false;
- let pods = [];
+ let groups = [];
+ let pods = []
onMount(async () => {
let res = await (await fetch("/")).json();
console.log(res);
script = res.script;
- res = await (await fetch("/api/pods")).json();
- console.log(res);
- pods = res.pods;
+ res = await (await fetch("/api/groups")).json();
+ groups = res.groups;
});
-
{#if opened}
@@ -41,16 +41,16 @@
{/each}
-
+