diff --git a/app/(app)/canvas/[canvasId]/page.tsx b/app/(app)/canvas/[canvasId]/page.tsx index b987d52..1864148 100644 --- a/app/(app)/canvas/[canvasId]/page.tsx +++ b/app/(app)/canvas/[canvasId]/page.tsx @@ -1,7 +1,7 @@ import { notFound, redirect } from "next/navigation"; import Canvas from "@/components/canvas/canvas"; -import CanvasToolbar from "@/components/canvas/canvas-toolbar"; +import CanvasSidebar from "@/components/canvas/canvas-sidebar"; import { api } from "@/convex/_generated/api"; import type { Id } from "@/convex/_generated/dataModel"; import { fetchAuthQuery, isAuthenticated } from "@/lib/auth-server"; @@ -48,9 +48,11 @@ export default async function CanvasPage({ } return ( -
- - +
+ +
+ +
); } diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index 03d907c..daa49a4 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -340,7 +340,7 @@ export default function DashboardPage() { + )}
- )} + + {isUploading ? ( +
+
+
+ Wird hochgeladen... +
+
+ ) : data.url ? ( +
+ {data.filename +
+ ) : ( +
+ πŸ“ + Klicken oder hierhin ziehen + PNG, JPG, WebP +
+ )} + + {data.filename && data.url && ( +

+ {data.filename} +

+ )} +
+ + + ); diff --git a/components/canvas/nodes/note-node.tsx b/components/canvas/nodes/note-node.tsx index 952fc46..f4e1006 100644 --- a/components/canvas/nodes/note-node.tsx +++ b/components/canvas/nodes/note-node.tsx @@ -1,20 +1,83 @@ "use client"; -import { type Node, type NodeProps } from "@xyflow/react"; - +import { useState, useCallback, useEffect } from "react"; +import { type NodeProps, type Node } from "@xyflow/react"; +import { useMutation } from "convex/react"; +import { api } from "@/convex/_generated/api"; +import type { Id } from "@/convex/_generated/dataModel"; +import { useDebouncedCallback } from "@/hooks/use-debounced-callback"; import BaseNodeWrapper from "./base-node-wrapper"; -export type NoteNodeData = { +type NoteNodeData = { content?: string; + _status?: string; + _statusMessage?: string; }; export type NoteNode = Node; -export default function NoteNode({ data, selected }: NodeProps) { +export default function NoteNode({ id, data, selected }: NodeProps) { + const updateData = useMutation(api.nodes.updateData); + const [content, setContent] = useState(data.content ?? ""); + const [isEditing, setIsEditing] = useState(false); + + useEffect(() => { + if (!isEditing) { + setContent(data.content ?? ""); + } + }, [data.content, isEditing]); + + const saveContent = useDebouncedCallback( + (newContent: string) => { + updateData({ + nodeId: id as Id<"nodes">, + data: { + ...data, + content: newContent, + _status: undefined, + _statusMessage: undefined, + }, + }); + }, + 500, + ); + + const handleChange = useCallback( + (e: React.ChangeEvent) => { + const newContent = e.target.value; + setContent(newContent); + saveContent(newContent); + }, + [saveContent], + ); + return ( -
Notiz
-

{data.content || "Leere Notiz"}

+
+ πŸ“Œ Notiz +
+ {isEditing ? ( +