diff --git a/bun.lockb b/bun.lockb
index 1c9283a..e0f6621 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 7474fd1..ee6837c 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
"@tauri-apps/plugin-opener": "^2"
},
"devDependencies": {
- "@lucide/svelte": "^0.554.0",
+ "@internationalized/date": "^3.8.1",
+ "@lucide/svelte": "^0.544.0",
"@sveltejs/adapter-static": "^3.0.6",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
@@ -25,6 +26,7 @@
"@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.1.17",
"@tauri-apps/cli": "^2",
+ "bits-ui": "^2.11.0",
"clsx": "^2.1.1",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
diff --git a/src/lib/components/ui/dialog/dialog-close.svelte b/src/lib/components/ui/dialog/dialog-close.svelte
new file mode 100644
index 0000000..840b2f6
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-close.svelte
@@ -0,0 +1,7 @@
+
+
+
diff --git a/src/lib/components/ui/dialog/dialog-content.svelte b/src/lib/components/ui/dialog/dialog-content.svelte
new file mode 100644
index 0000000..9d7c7f5
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-content.svelte
@@ -0,0 +1,43 @@
+
+
+
+
+
+ {@render children?.()}
+ {#if showCloseButton}
+
+
+ Close
+
+ {/if}
+
+
diff --git a/src/lib/components/ui/dialog/dialog-description.svelte b/src/lib/components/ui/dialog/dialog-description.svelte
new file mode 100644
index 0000000..3845023
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-description.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/lib/components/ui/dialog/dialog-footer.svelte b/src/lib/components/ui/dialog/dialog-footer.svelte
new file mode 100644
index 0000000..e7ff446
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-footer.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/dialog/dialog-header.svelte b/src/lib/components/ui/dialog/dialog-header.svelte
new file mode 100644
index 0000000..4e5c447
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-header.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/dialog/dialog-overlay.svelte b/src/lib/components/ui/dialog/dialog-overlay.svelte
new file mode 100644
index 0000000..f81ad83
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-overlay.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/src/lib/components/ui/dialog/dialog-title.svelte b/src/lib/components/ui/dialog/dialog-title.svelte
new file mode 100644
index 0000000..067e55e
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-title.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/lib/components/ui/dialog/dialog-trigger.svelte b/src/lib/components/ui/dialog/dialog-trigger.svelte
new file mode 100644
index 0000000..9d1e801
--- /dev/null
+++ b/src/lib/components/ui/dialog/dialog-trigger.svelte
@@ -0,0 +1,7 @@
+
+
+
diff --git a/src/lib/components/ui/dialog/index.ts b/src/lib/components/ui/dialog/index.ts
new file mode 100644
index 0000000..dce1d9d
--- /dev/null
+++ b/src/lib/components/ui/dialog/index.ts
@@ -0,0 +1,37 @@
+import { Dialog as DialogPrimitive } from "bits-ui";
+
+import Title from "./dialog-title.svelte";
+import Footer from "./dialog-footer.svelte";
+import Header from "./dialog-header.svelte";
+import Overlay from "./dialog-overlay.svelte";
+import Content from "./dialog-content.svelte";
+import Description from "./dialog-description.svelte";
+import Trigger from "./dialog-trigger.svelte";
+import Close from "./dialog-close.svelte";
+
+const Root = DialogPrimitive.Root;
+const Portal = DialogPrimitive.Portal;
+
+export {
+ Root,
+ Title,
+ Portal,
+ Footer,
+ Header,
+ Trigger,
+ Overlay,
+ Content,
+ Description,
+ Close,
+ //
+ Root as Dialog,
+ Title as DialogTitle,
+ Portal as DialogPortal,
+ Footer as DialogFooter,
+ Header as DialogHeader,
+ Trigger as DialogTrigger,
+ Overlay as DialogOverlay,
+ Content as DialogContent,
+ Description as DialogDescription,
+ Close as DialogClose,
+};
diff --git a/src/lib/components/ui/input/index.ts b/src/lib/components/ui/input/index.ts
new file mode 100644
index 0000000..f47b6d3
--- /dev/null
+++ b/src/lib/components/ui/input/index.ts
@@ -0,0 +1,7 @@
+import Root from "./input.svelte";
+
+export {
+ Root,
+ //
+ Root as Input,
+};
diff --git a/src/lib/components/ui/input/input.svelte b/src/lib/components/ui/input/input.svelte
new file mode 100644
index 0000000..960167d
--- /dev/null
+++ b/src/lib/components/ui/input/input.svelte
@@ -0,0 +1,52 @@
+
+
+{#if type === "file"}
+
+{:else}
+
+{/if}
diff --git a/src/lib/components/ui/label/index.ts b/src/lib/components/ui/label/index.ts
new file mode 100644
index 0000000..8bfca0b
--- /dev/null
+++ b/src/lib/components/ui/label/index.ts
@@ -0,0 +1,7 @@
+import Root from "./label.svelte";
+
+export {
+ Root,
+ //
+ Root as Label,
+};
diff --git a/src/lib/components/ui/label/label.svelte b/src/lib/components/ui/label/label.svelte
new file mode 100644
index 0000000..d0afda3
--- /dev/null
+++ b/src/lib/components/ui/label/label.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/src/lib/services/workspaces.ts b/src/lib/services/workspaces.ts
index 7caf735..2b5ef30 100644
--- a/src/lib/services/workspaces.ts
+++ b/src/lib/services/workspaces.ts
@@ -1,33 +1,70 @@
import type { Workspace } from "$lib/types/workspace";
-let ws: Workspace[] = [
+const ws: Map = new Map([
+ [
+ "1",
{
- Id: "1",
- Name: "Test 1",
- Description: "This is a test description"
+ Id: "1",
+ Name: "Test 1",
+ Description: "This is a test description",
},
+ ],
+ [
+ "2",
{
- Id: "2",
- Name: "Test 2",
- Description: "This is a longer test description"
+ Id: "2",
+ Name: "Test 2",
+ Description: "This is a longer test description",
},
+ ],
+ [
+ "3",
{
- Id: "3",
- Name: "Test 3",
- Description: "This is a slightly longer test description"
+ Id: "3",
+ Name: "Test 3",
+ Description: "This is a slightly longer test description",
},
+ ],
+ [
+ "4",
{
- Id: "4",
- Name: "Test 4",
- Description: "This is an even slightly longer test description"
+ Id: "4",
+ Name: "Test 4",
+ Description: "This is an even slightly longer test description",
},
+ ],
+ [
+ "5",
{
- Id: "5",
- Name: "Test 5",
- Description: "This is a veryyyyyyyyyyyyyyyyyyyyyyyyyyy longggggggggggggggggggggggggggg test descriptionnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"
+ Id: "5",
+ Name: "Test 5",
+ Description:
+ "This is a veryyyyyyyyyyyyyyyyyyyyyyyyyyy longggggggggggggggggggggggggggg test descriptionnnnnnnnnnnnnnnnnnnnnnnnnnnnnn",
},
-]
+ ],
+]);
+
+function convert_to_list(ws: Map): Workspace[] {
+ return [...ws.values()];
+}
export async function get_workspaces(): Promise {
- return ws
-}
\ No newline at end of file
+ return convert_to_list(ws);
+}
+
+export async function update_workspace(workspace: Workspace): Promise {
+ let w = ws.get(workspace.Id);
+ if (w != undefined) {
+ w.Name = workspace.Name;
+ w.Description = workspace.Description;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+export async function create_workspace(workspace: Workspace): Promise {
+ workspace.Id = crypto.randomUUID();
+ ws.set(workspace.Id, workspace);
+ return true;
+}
diff --git a/src/routes/workspaces/+page.svelte b/src/routes/workspaces/+page.svelte
index 432e7cf..283ec5c 100644
--- a/src/routes/workspaces/+page.svelte
+++ b/src/routes/workspaces/+page.svelte
@@ -2,66 +2,177 @@
import * as Empty from "$lib/components/ui/empty/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import FolderCodeIcon from "@lucide/svelte/icons/folder-code";
- import { get_workspaces } from "$lib/services/workspaces";
+ import {
+ create_workspace,
+ get_workspaces,
+ update_workspace,
+ } from "$lib/services/workspaces";
import type { Workspace } from "$lib/types/workspace";
import * as Card from "$lib/components/ui/card/index";
+ import * as Dialog from "$lib/components/ui/dialog/index.js";
+ import { Input } from "$lib/components/ui/input/index.js";
+ import { Label } from "$lib/components/ui/label/index.js";
- let showPrompt = false;
- let workspaces: Workspace[] = [];
-
- get_workspaces().then((ws) => {
- if (ws.length == 0) {
- showPrompt = true;
- } else {
- workspaces = ws;
- }
+ $effect(() => {
+ get_workspaces().then((ws) => {
+ if (ws.length == 0) {
+ showPrompt = true;
+ } else {
+ console.log(ws);
+ workspaces = ws;
+ }
+ });
});
+
+ let showPrompt = $state(false);
+ let workspaces = $state([]);
+ let dialogOpen = $state(false);
+ let dialogMode = $state<"create" | "edit">("create");
+ let selectedWorkspace = $state(null);
+ let workspaceName = $state("");
+ let workspaceDescription = $state("");
+
+ function openCreateDialog() {
+ dialogMode = "create";
+ selectedWorkspace = null;
+ workspaceName = "";
+ workspaceDescription = "";
+ dialogOpen = true;
+ }
+
+ function openEditDialog(workspace: Workspace) {
+ dialogMode = "edit";
+ selectedWorkspace = workspace;
+ workspaceName = workspace.Name ?? "";
+ workspaceDescription = workspace.Description ?? "";
+ dialogOpen = true;
+ }
+
+ async function handleDialogSubmit() {
+ let success = false;
+ if (dialogMode === "create") {
+ const w: Workspace = {
+ // Id will be assigned in create_workspace
+ Id: "",
+ Name: workspaceName,
+ Description: workspaceDescription,
+ };
+ success = await create_workspace(w);
+ } else if (selectedWorkspace != null) {
+ const w: Workspace = {
+ Id: selectedWorkspace.Id,
+ Name: workspaceName,
+ Description: workspaceDescription,
+ };
+ success = await update_workspace(w);
+ }
+
+ if (success) {
+ const updated = await get_workspaces();
+ workspaces = updated;
+ showPrompt = updated.length === 0;
+ }
+
+ dialogOpen = false;
+ }
-{#if showPrompt}
-
-
-
-
-
- No Workspaces Yet
-
- You haven't created any Workspaces yet. Get started by creating your
- first project.
-
-
-
-
-
-
-
-
-{:else}
-
-
+ {#if showPrompt}
+
- {#each workspaces as workspace (workspace.Id)}
-
-
- {workspace.Name}
-
- {workspace.Description}
-
-
-
-
-
-
-
- {/each}
+
+
+
+
+ No Workspaces Yet
+
+ You haven't created any Workspaces yet. Get started by creating your
+ first project.
+
+
+
+
+
+
+
+
+ {:else}
+
+
+
Workspaces
+
+
+
+ {#each workspaces as workspace (workspace.Id)}
+
+
+ {workspace.Name}
+
+ {workspace.Description}
+
+
+
+
+
+
+
+ {/each}
+
-
-{/if}
+ {/if}
+
+
+
+
+ {dialogMode === "create" ? "Create workspace" : "Edit workspace"}
+
+
+ {#if dialogMode === "create"}
+ Create a new workspace. Fill in the details below and click create.
+ {:else}
+ Update your workspace details and click save.
+ {/if}
+
+
+
+
+