Skip to content

Commit db46dac

Browse files
committed
feat: implement waitlist submission functionality in ChatIntroduction component with validation and user feedback
1 parent fbd1f45 commit db46dac

File tree

4 files changed

+125
-2
lines changed

4 files changed

+125
-2
lines changed

src/lib/components/chat/ChatIntroduction.svelte

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,54 @@
2222
let email = $state(user?.email || "");
2323
let phone = $state("");
2424
let kordamine = $state("");
25+
let isSubmitting = $state(false);
26+
let submitMessage = $state("");
27+
let submitError = $state("");
2528
const options = ["1 kord", "2 korda", "3 korda", "4 korda", "5 korda"];
29+
30+
async function handleSubmit() {
31+
// Reset messages
32+
submitMessage = "";
33+
submitError = "";
34+
35+
// Validate form
36+
if (!email || !phone || !kordamine) {
37+
submitError = "Palun täida kõik väljad";
38+
return;
39+
}
40+
41+
isSubmitting = true;
42+
43+
try {
44+
const response = await fetch("/api/waitlist", {
45+
method: "POST",
46+
headers: {
47+
"Content-Type": "application/json",
48+
},
49+
body: JSON.stringify({
50+
email,
51+
phone,
52+
repetition: kordamine,
53+
}),
54+
});
55+
56+
const data = await response.json();
57+
58+
if (response.ok) {
59+
submitMessage = "Täname! Oled edukalt ootejärjekorda lisatud.";
60+
// Reset form
61+
email = "";
62+
phone = "";
63+
kordamine = "";
64+
} else {
65+
submitError = data.error || "Viga andmete salvestamisel";
66+
}
67+
} catch (error) {
68+
submitError = "Viga andmete saatmisel. Palun proovi uuesti.";
69+
} finally {
70+
isSubmitting = false;
71+
}
72+
}
2673
</script>
2774

2875
<div class="my-auto flex flex-col">
@@ -229,9 +276,12 @@
229276

230277
<!-- Submit Button -->
231278
<button
232-
class="flex w-full items-center justify-center gap-2 rounded-md bg-[#306FC7] py-3 font-semibold text-white hover:bg-blue-700"
279+
type="button"
280+
onclick={handleSubmit}
281+
disabled={isSubmitting}
282+
class="flex w-full items-center justify-center gap-2 rounded-md bg-[#306FC7] py-3 font-semibold text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50"
233283
>
234-
Esita
284+
{isSubmitting ? "Saadan..." : "Esita"}
235285
<svg
236286
class="h-5 w-5"
237287
fill="none"
@@ -242,6 +292,19 @@
242292
<path stroke-linecap="round" stroke-linejoin="round" d="M17 8l4 4m0 0l-4 4m4-4H3" />
243293
</svg>
244294
</button>
295+
296+
<!-- Success/Error Messages -->
297+
{#if submitMessage}
298+
<div class="mt-3 rounded-md border border-green-400 bg-green-100 p-3 text-green-700">
299+
{submitMessage}
300+
</div>
301+
{/if}
302+
303+
{#if submitError}
304+
<div class="mt-3 rounded-md border border-red-400 bg-red-100 p-3 text-red-700">
305+
{submitError}
306+
</div>
307+
{/if}
245308
</div>
246309
</div>
247310
</div>

src/lib/server/database.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { MigrationResult } from "$lib/types/MigrationResult";
1313
import type { Semaphore } from "$lib/types/Semaphore";
1414
import type { AssistantStats } from "$lib/types/AssistantStats";
1515
import type { CommunityToolDB } from "$lib/types/Tool";
16+
import type { Waitlist } from "$lib/types/Waitlist";
1617
import { MongoMemoryServer } from "mongodb-memory-server";
1718
import { logger } from "$lib/server/logger";
1819
import { building } from "$app/environment";
@@ -132,6 +133,7 @@ export class Database {
132133
const tokenCaches = db.collection<TokenCache>("tokens");
133134
const tools = db.collection<CommunityToolDB>("tools");
134135
const configCollection = db.collection<ConfigKey>("config");
136+
const waitlist = db.collection<Waitlist>("waitlist");
135137

136138
return {
137139
conversations,
@@ -151,6 +153,7 @@ export class Database {
151153
tokenCaches,
152154
tools,
153155
config: configCollection,
156+
waitlist,
154157
};
155158
}
156159

@@ -175,6 +178,7 @@ export class Database {
175178
tokenCaches,
176179
tools,
177180
config,
181+
waitlist,
178182
} = this.getCollections();
179183

180184
conversations
@@ -290,6 +294,8 @@ export class Database {
290294
.catch((e) => logger.error(e));
291295

292296
config.createIndex({ key: 1 }, { unique: true }).catch((e) => logger.error(e));
297+
waitlist.createIndex({ email: 1 }, { unique: true }).catch((e) => logger.error(e));
298+
waitlist.createIndex({ createdAt: 1 }).catch((e) => logger.error(e));
293299
}
294300
}
295301

src/lib/types/Waitlist.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { ObjectId } from "mongodb";
2+
import type { Timestamps } from "./Timestamps";
3+
4+
export interface Waitlist extends Timestamps {
5+
_id: ObjectId;
6+
email: string;
7+
phone: string;
8+
repetition: string;
9+
}

src/routes/api/waitlist/+server.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { collections } from "$lib/server/database";
2+
import { json } from "@sveltejs/kit";
3+
import type { RequestHandler } from "./$types";
4+
import { ObjectId } from "mongodb";
5+
6+
export const POST: RequestHandler = async ({ request }) => {
7+
try {
8+
const { email, phone, repetition } = await request.json();
9+
10+
// Validate input
11+
if (!email || !phone || !repetition) {
12+
return json({ error: "Email, phone, and repetition are required" }, { status: 400 });
13+
}
14+
15+
// Validate email format
16+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
17+
if (!emailRegex.test(email)) {
18+
return json({ error: "Invalid email format" }, { status: 400 });
19+
}
20+
21+
// Check if email already exists
22+
const existingEntry = await collections.waitlist.findOne({ email });
23+
if (existingEntry) {
24+
return json({ error: "Email already registered" }, { status: 409 });
25+
}
26+
27+
// Insert new waitlist entry
28+
const now = new Date();
29+
const waitlistEntry = {
30+
_id: new ObjectId(),
31+
email,
32+
phone,
33+
repetition,
34+
createdAt: now,
35+
updatedAt: now,
36+
};
37+
38+
await collections.waitlist.insertOne(waitlistEntry);
39+
40+
return json({ success: true, message: "Successfully added to waitlist" });
41+
} catch (error) {
42+
console.error("Error adding to waitlist:", error);
43+
return json({ error: "Internal server error" }, { status: 500 });
44+
}
45+
};

0 commit comments

Comments
 (0)