aboutsummaryrefslogtreecommitdiff
path: root/fe/src/lib/forms
diff options
context:
space:
mode:
Diffstat (limited to 'fe/src/lib/forms')
-rw-r--r--fe/src/lib/forms/AddForm.svelte25
-rw-r--r--fe/src/lib/forms/LoginForm.svelte86
-rw-r--r--fe/src/lib/forms/PreferencesForm.svelte119
-rw-r--r--fe/src/lib/forms/index.ts10
4 files changed, 222 insertions, 18 deletions
diff --git a/fe/src/lib/forms/AddForm.svelte b/fe/src/lib/forms/AddForm.svelte
index f85cce6..bbc8356 100644
--- a/fe/src/lib/forms/AddForm.svelte
+++ b/fe/src/lib/forms/AddForm.svelte
@@ -11,21 +11,10 @@
11 const statistic: Statistic = newStatistic(); 11 const statistic: Statistic = newStatistic();
12 12
13 function newStatistic(): Statistic { 13 function newStatistic(): Statistic {
14 let now = new Date(), 14 let date = new Date().toString();
15 month,
16 day,
17 year;
18
19 month = `${now.getMonth() + 1}`;
20 day = `${now.getDate()}`;
21 year = now.getFullYear();
22 if (month.length < 2) month = "0" + month;
23 if (day.length < 2) day = "0" + day;
24
25 const date = [year, month, day].join("-");
26 15
27 return { 16 return {
28 user_id: $user!.uuid, 17 user_id: $user!.id,
29 date, 18 date,
30 quantity: 1 19 quantity: 1
31 }; 20 };
@@ -37,7 +26,7 @@
37 26
38 async function handleSubmitStat() 27 async function handleSubmitStat()
39 { 28 {
40 const { date, quantity } = statistic; 29 const { user_id, date, quantity } = statistic;
41 await fetch(apiURL("stats"), { 30 await fetch(apiURL("stats"), {
42 method: "POST", 31 method: "POST",
43 headers: { 32 headers: {
@@ -45,7 +34,7 @@
45 }, 34 },
46 body: JSON.stringify({ 35 body: JSON.stringify({
47 date: new Date(date), 36 date: new Date(date),
48 user_id: 2, 37 user_id,
49 quantity 38 quantity
50 }) 39 })
51 }); 40 });
@@ -54,12 +43,12 @@
54 43
55</script> 44</script>
56 45
57<dialog {open} on:submit={handleSubmitStat}> 46<dialog id="addForm" {open} on:submit={handleSubmitStat}>
58 <h2>Add Water</h2> 47 <h2>Add Water</h2>
59 <form method="dialog"> 48 <form method="dialog">
60 <div class="form input group"> 49 <div class="form input group">
61 <label for="date">Date:</label> 50 <label for="date">Date:</label>
62 <input bind:value={statistic.date} id="date" name="date" type="date" /> 51 <input bind:value={statistic.date} id="date" name="date" type="datetime-local" />
63 </div> 52 </div>
64 <div class="form input group"> 53 <div class="form input group">
65 <label for="quantity">Quantity:</label> 54 <label for="quantity">Quantity:</label>
@@ -75,4 +64,4 @@
75 <button on:click={closeDialog}>Cancel</button> 64 <button on:click={closeDialog}>Cancel</button>
76 <button type="submit">Submit</button> 65 <button type="submit">Submit</button>
77 </form> 66 </form>
78</dialog> \ No newline at end of file 67</dialog>
diff --git a/fe/src/lib/forms/LoginForm.svelte b/fe/src/lib/forms/LoginForm.svelte
new file mode 100644
index 0000000..88d4479
--- /dev/null
+++ b/fe/src/lib/forms/LoginForm.svelte
@@ -0,0 +1,86 @@
1<script lang="ts">
2 import { token, user, preferences } from "../../stores/auth";
3 import Card from "../Card.svelte";
4 import { apiURL } from "../../utils";
5
6 let credentials: CredentialObject = {
7 username: "",
8 password: "",
9 };
10
11 let error: string | null = null;
12
13 interface CredentialObject {
14 username: string;
15 password: string;
16 }
17
18 function prepareCredentials({
19 username,
20 password,
21 }: CredentialObject): string {
22 return btoa(`${username}:${password}`);
23 }
24
25 async function onSubmit(e: Event) {
26 if (!credentials.username || !credentials.password) {
27 error = "please enter your username and password";
28 return;
29 }
30 const auth = prepareCredentials(credentials);
31
32 const response = await fetch(apiURL("auth"), {
33 method: "POST",
34 headers: {
35 Authorization: `Basic ${auth}`,
36 },
37 });
38
39 if (response.status === 401) {
40 error = "Your username or password is wrong";
41 return;
42 }
43
44 if (response.ok) {
45 const {
46 token: apiToken,
47 user: userData,
48 preferences: userPreferences,
49 } = await response.json();
50 user.setUser(userData);
51 preferences.setPreference(userPreferences);
52 token.authenticate(apiToken);
53 }
54
55 error = null;
56 }
57</script>
58
59<Card>
60 <form class="form" on:submit|preventDefault={onSubmit}>
61 <div class="form input group">
62 <label for="username">Username</label>
63 <input
64 bind:value={credentials.username}
65 id="username"
66 name="username"
67 type="text"
68 autocomplete="username"
69 />
70 </div>
71 <div class="form input group">
72 <label for="password">Password</label>
73 <input
74 bind:value={credentials.password}
75 id="password"
76 name="password"
77 type="password"
78 autocomplete="current-password"
79 />
80 </div>
81 {#if error}
82 <p class="error">{error}</p>
83 {/if}
84 <button type="submit">Log in</button>
85 </form>
86</Card>
diff --git a/fe/src/lib/forms/PreferencesForm.svelte b/fe/src/lib/forms/PreferencesForm.svelte
new file mode 100644
index 0000000..79663d1
--- /dev/null
+++ b/fe/src/lib/forms/PreferencesForm.svelte
@@ -0,0 +1,119 @@
1<script lang="ts">
2 import { user, preferences, token } from "../../stores/auth";
3 import { createEventDispatcher, onDestroy, onMount } from "svelte";
4 import type { User } from "../../types";
5 import { apiURL } from "../../utils";
6
7 export let open: boolean;
8
9 let sizes: Array<any>;
10 let selectedSize: number = 1;
11 let color: string = "#000000";
12
13 const dispatch = createEventDispatcher();
14
15 const unsubscribe = preferences.subscribe(
16 (value: any) => {
17 if (value) {
18 color = value.color;
19 selectedSize = value.size_id;
20 }
21 },
22 );
23
24 function closeDialog() {
25 dispatch("close");
26 }
27
28 async function updateUserPreferences() {
29 const res = await fetch(apiURL("user/preferences"), {
30 method: "PATCH",
31 headers: {
32 Authorization: `Bearer ${$token}`,
33 },
34 body: JSON.stringify($preferences),
35 });
36 }
37
38 async function getUserPreferences() {
39 const res = await fetch(apiURL(`user/${($user as User)!.id}/preferences`),
40 {
41 method: "GET",
42 headers: {
43 Authorization: `Bearer ${$token}`,
44 },
45 },
46 );
47 const updatePreferences = await res.json();
48 preferences.set(updatePreferences);
49 }
50
51 async function onPreferencesSave(): Promise<void> {
52 preferences.update((value) => ({
53 ...value!,
54 size_id: selectedSize,
55 color: color,
56 }));
57
58 await updateUserPreferences();
59 await getUserPreferences();
60
61 dispatch("close");
62 }
63
64 onMount(() => {
65 fetch(apiURL("sizes"), {
66 method: "GET",
67 headers: {
68 Authorization: `Bearer ${$token}`,
69 },
70 })
71 .then((res) => res.json())
72 .then((val) => (sizes = val));
73 });
74
75 onDestroy(() => {
76 unsubscribe();
77 });
78</script>
79
80<dialog {open} on:submit|preventDefault={onPreferencesSave}>
81 <h2>User Preferences</h2>
82 <form method="dialog">
83 <div class="form input group">
84 <label for="color">Color</label>
85 <input
86 id="color"
87 name="color"
88 type="color"
89 bind:value={color}
90 />
91 </div>
92 <div class="form input group">
93 <label for="size">Bottle Size</label>
94 <select
95 bind:value={selectedSize}
96 >
97 {#if sizes}
98 {#each sizes as size}
99 <option value={size.id}>{size.size} {size.unit}</option>
100 {/each}
101 {/if}
102 </select>
103 </div>
104 <button on:click={closeDialog}>Cancel</button>
105 <button type="submit">Save</button>
106 </form>
107</dialog>
108
109<style>
110 /* dialog {
111 background: white;
112 color: black;
113 }
114
115 input[type="color"] {
116 width: 4em;
117 height: 4em;
118 } */
119</style>
diff --git a/fe/src/lib/forms/index.ts b/fe/src/lib/forms/index.ts
new file mode 100644
index 0000000..ac4e63b
--- /dev/null
+++ b/fe/src/lib/forms/index.ts
@@ -0,0 +1,10 @@
1import AddForm from "./AddForm.svelte";
2import LoginForm from "./LoginForm.svelte";
3import PreferencesForm from "./PreferencesForm.svelte";
4
5
6export {
7 AddForm,
8 LoginForm,
9 PreferencesForm
10}; \ No newline at end of file