This commit is contained in:
Ondřej 2024-02-05 22:59:49 +01:00
parent 5ce272e7c8
commit 32226f7d0e
12 changed files with 2759 additions and 39 deletions

3
.gitignore vendored
View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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"
} }
} }

View 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");

View 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
View 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
View 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
View 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;
};

View file

@ -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">

View file

@ -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(),
}); });

View file

@ -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);
} }

View file

@ -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);
} }