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} + + +
+
+ + +
+
+ + +
+ + + +
+
+