diff --git a/src/components/Toaster.svelte b/src/components/Toaster.svelte
new file mode 100644
index 0000000..90c08fd
--- /dev/null
+++ b/src/components/Toaster.svelte
@@ -0,0 +1,51 @@
+
+
+
diff --git a/src/lib/fetch.ts b/src/lib/browserFetch.ts
similarity index 73%
rename from src/lib/fetch.ts
rename to src/lib/browserFetch.ts
index e76b05d..a395773 100644
--- a/src/lib/fetch.ts
+++ b/src/lib/browserFetch.ts
@@ -1,15 +1,10 @@
-export enum MaybeType {
- Ok = 'ok',
- Error = 'error'
-}
-
interface Some {
- type: MaybeType.Ok;
+ type: 'ok';
value: T;
}
interface None {
- type: MaybeType.Error;
+ type: 'error';
value: Error;
}
@@ -17,20 +12,19 @@ export type Maybe = Some | None;
export function some(value: T): Some {
return {
- type: MaybeType.Ok,
+ type: 'ok',
value
};
}
export function none(message: string): None {
return {
- type: MaybeType.Error,
+ type: 'error',
value: new Error(message)
};
}
interface FetchOptions {
- getBearerToken?: () => Promise;
shouldParse?: boolean;
}
@@ -40,14 +34,11 @@ export async function tryFetch(
options?: FetchOptions
): Promise> {
try {
- const token = options?.getBearerToken ? await options.getBearerToken() : null;
-
const response = await fetch(input, {
...init,
headers: {
...init?.headers,
- 'Content-Type': 'application/json',
- ...(token ? { Authorization: `Bearer ${token}` } : {})
+ 'Content-Type': 'application/json'
}
});
@@ -63,6 +54,7 @@ export async function tryFetch(
const rawText = await response.text();
return none(rawText);
} catch (error: unknown) {
+ console.error('Failed to fetch', error);
if (error instanceof Error) {
return none(error.message);
}
diff --git a/src/lib/icons.ts b/src/lib/icons.ts
index d1e15be..3eb5959 100644
--- a/src/lib/icons.ts
+++ b/src/lib/icons.ts
@@ -48,5 +48,11 @@ export const icons = {
},
users: {
path: 'M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z'
+ },
+ 'x-circle': {
+ path: 'm9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z'
+ },
+ 'x-mark': {
+ path: 'M6 18 18 6M6 6l12 12'
}
};
diff --git a/src/lib/state/toastMessages.svelte.ts b/src/lib/state/toastMessages.svelte.ts
new file mode 100644
index 0000000..92356e1
--- /dev/null
+++ b/src/lib/state/toastMessages.svelte.ts
@@ -0,0 +1,32 @@
+import { getContext, setContext } from 'svelte';
+import { nanoid } from 'nanoid';
+
+import { type ToastMessage } from '$lib/types';
+
+type ToastMessageWithId = ToastMessage & { id: string; isShown: boolean };
+
+export class ToastMessages {
+ messages: ToastMessageWithId[] = $state([]);
+
+ constructor() {}
+
+ addMessage(message: ToastMessage) {
+ const id = nanoid();
+
+ this.messages.push({
+ ...message,
+ id,
+ isShown: false
+ });
+ }
+}
+
+const ToastMessagesKey = Symbol('ToastMessages');
+
+export function setToastMessages() {
+ return setContext(ToastMessagesKey, new ToastMessages());
+}
+
+export function getToastMessages() {
+ return getContext>(ToastMessagesKey);
+}
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 85af10a..a22ace6 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -174,3 +174,8 @@ export type ToggleFriendShare = {
noteId: string;
selected: boolean;
};
+
+export type ToastMessage = {
+ message: string;
+ type: 'success' | 'error';
+};
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index bf83302..cbd414a 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,9 +1,13 @@
+
{@render children()}
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index b54dc87..2b3baa8 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -60,7 +60,7 @@