Add db
This commit is contained in:
parent
5ce272e7c8
commit
32226f7d0e
12 changed files with 2759 additions and 39 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -19,3 +19,6 @@ pnpm-debug.log*
|
||||||
|
|
||||||
# macOS-specific files
|
# macOS-specific files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
db.sqlite
|
||||||
|
db.sqlite-journal
|
||||||
|
|
2654
package-lock.json
generated
2654
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -14,8 +14,15 @@
|
||||||
"@astrojs/node": "^8.2.0",
|
"@astrojs/node": "^8.2.0",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"astro": "^4.3.2",
|
"astro": "^4.3.2",
|
||||||
|
"better-sqlite3": "^9.4.0",
|
||||||
|
"kysely": "^0.27.2",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/better-sqlite3": "^7.6.9",
|
||||||
|
"prisma": "^5.9.1",
|
||||||
|
"prisma-kysely": "^1.7.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
prisma/migrations/20240205181524_init/migration.sql
Normal file
20
prisma/migrations/20240205181524_init/migration.sql
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Letter" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"created" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"firstName" TEXT NOT NULL,
|
||||||
|
"lastName" TEXT NOT NULL,
|
||||||
|
"email" TEXT NOT NULL,
|
||||||
|
"phone" TEXT,
|
||||||
|
"variant" TEXT NOT NULL,
|
||||||
|
"gender" TEXT,
|
||||||
|
"branch" TEXT NOT NULL,
|
||||||
|
"message" TEXT NOT NULL,
|
||||||
|
"subscribed" BOOLEAN NOT NULL,
|
||||||
|
"confirmationToken" TEXT NOT NULL,
|
||||||
|
"confirmed" BOOLEAN NOT NULL DEFAULT false
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Letter_email_key" ON "Letter"("email");
|
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Please do not edit this file manually
|
||||||
|
# It should be added in your version-control system (i.e. Git)
|
||||||
|
provider = "sqlite"
|
29
prisma/schema.prisma
Normal file
29
prisma/schema.prisma
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlite"
|
||||||
|
url = "file:../db.sqlite"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator kysely {
|
||||||
|
provider = "prisma-kysely"
|
||||||
|
output = "../src/db"
|
||||||
|
fileName = "types.ts"
|
||||||
|
}
|
||||||
|
|
||||||
|
model Letter {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
created DateTime @default(now())
|
||||||
|
updated DateTime @default(now())
|
||||||
|
firstName String
|
||||||
|
lastName String
|
||||||
|
email String @unique
|
||||||
|
phone String?
|
||||||
|
|
||||||
|
variant String
|
||||||
|
gender String?
|
||||||
|
branch String
|
||||||
|
message String
|
||||||
|
subscribed Boolean
|
||||||
|
|
||||||
|
confirmationToken String
|
||||||
|
confirmed Boolean @default(false)
|
||||||
|
}
|
12
src/db/index.ts
Normal file
12
src/db/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Kysely, SqliteDialect } from "kysely";
|
||||||
|
import SQLite from "better-sqlite3";
|
||||||
|
import type { DB } from "./types";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
const dialect = new SqliteDialect({
|
||||||
|
database: new SQLite(join(process.cwd(), "db.sqlite")),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const db = new Kysely<DB>({
|
||||||
|
dialect,
|
||||||
|
});
|
25
src/db/types.ts
Normal file
25
src/db/types.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import type { ColumnType } from "kysely";
|
||||||
|
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
||||||
|
? ColumnType<S, I | undefined, U>
|
||||||
|
: ColumnType<T, T | undefined, T>;
|
||||||
|
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
||||||
|
|
||||||
|
export type Letter = {
|
||||||
|
id: Generated<number>;
|
||||||
|
created: Generated<string>;
|
||||||
|
updated: Generated<string>;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
email: string;
|
||||||
|
phone: string | null;
|
||||||
|
variant: string;
|
||||||
|
gender: string | null;
|
||||||
|
branch: string;
|
||||||
|
message: string;
|
||||||
|
subscribed: number;
|
||||||
|
confirmationToken: string;
|
||||||
|
confirmed: Generated<number>;
|
||||||
|
};
|
||||||
|
export type DB = {
|
||||||
|
Letter: Letter;
|
||||||
|
};
|
|
@ -91,7 +91,7 @@ const result = letterOptionsSchema.safeParse(options);
|
||||||
zpracováním osobních údajů
|
zpracováním osobních údajů
|
||||||
</a>.
|
</a>.
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
<Checkbox name="subscribe">
|
<Checkbox name="subscribed">
|
||||||
Chci zaslat report o EPH a další informace o aktivitách EPH v ČR
|
Chci zaslat report o EPH a další informace o aktivitách EPH v ČR
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
<Button type="submit">
|
<Button type="submit">
|
||||||
|
|
|
@ -10,6 +10,7 @@ export const letterFormSchema = z.object({
|
||||||
gender: z.string().default("g"),
|
gender: z.string().default("g"),
|
||||||
branch: z.string(),
|
branch: z.string(),
|
||||||
message: z.string().min(1),
|
message: z.string().min(1),
|
||||||
|
|
||||||
subscribed: z.boolean(),
|
subscribed: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,13 @@ export const prerender = false;
|
||||||
if (Astro.request.method === "POST") {
|
if (Astro.request.method === "POST") {
|
||||||
const formData = await Astro.request.formData();
|
const formData = await Astro.request.formData();
|
||||||
const data = Object.fromEntries(formData.entries());
|
const data = Object.fromEntries(formData.entries());
|
||||||
const result = await letterFormSchema.safeParseAsync(data);
|
const result = await letterFormSchema.safeParseAsync({
|
||||||
|
...data,
|
||||||
|
subscribed: formData.has("subscribed"),
|
||||||
|
});
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
createLetter(lang, result.data);
|
await createLetter(lang, result.data);
|
||||||
return Astro.redirect(`/${lang}/letter-sent`, 303);
|
return Astro.redirect(`/${lang}/letter-sent`, 303);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
src/tasks.ts
35
src/tasks.ts
|
@ -1,7 +1,40 @@
|
||||||
|
import { db } from "./db";
|
||||||
import type { Lang } from "./lang";
|
import type { Lang } from "./lang";
|
||||||
import type { LetterForm } from "./letter/schema";
|
import type { LetterForm } from "./letter/schema";
|
||||||
|
import { generateToken } from "./utils";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
export async function createLetter(lang: Lang, letterForm: LetterForm) {
|
export async function createLetter(lang: Lang, letterForm: LetterForm) {
|
||||||
// TODO
|
|
||||||
console.log(lang, letterForm);
|
console.log(lang, letterForm);
|
||||||
|
|
||||||
|
// const existingLetter = await db
|
||||||
|
// .selectFrom("Letter")
|
||||||
|
// .where("email", "=", letterForm.email)
|
||||||
|
// .select("id")
|
||||||
|
// .execute();
|
||||||
|
|
||||||
|
// if (existingLetter.length > 0) {
|
||||||
|
// throw new Error("Exists");
|
||||||
|
// }
|
||||||
|
|
||||||
|
const confirmationToken = generateToken(32);
|
||||||
|
const result = await db
|
||||||
|
.insertInto("Letter")
|
||||||
|
.values({
|
||||||
|
...letterForm,
|
||||||
|
confirmationToken,
|
||||||
|
subscribed: Number(letterForm.subscribed),
|
||||||
|
})
|
||||||
|
.executeTakeFirst();
|
||||||
|
|
||||||
|
if (!result.insertId) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
await sendConfirmationEmail(lang, result.insertId.toString(), confirmationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendConfirmationEmail(lang: Lang, id: string, token: string) {
|
||||||
|
const confirmationUrl = join(import.meta.env.BASE_URL, lang, "confirm", id, token);
|
||||||
|
console.log("Confirmation link: ", confirmationUrl);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue