From 411a9a5f1cdb4b52c65f4a1344c9be7694d130d7 Mon Sep 17 00:00:00 2001 From: Pulkit Garg Date: Wed, 25 Jun 2025 10:26:29 +0530 Subject: [PATCH] feature: add project name editing functionality --- apps/web/src/components/editor-header.tsx | 17 +-- .../components/editor/project-name-editor.tsx | 110 ++++++++++++++++++ apps/web/src/stores/project-store.ts | 13 +++ 3 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 apps/web/src/components/editor/project-name-editor.tsx diff --git a/apps/web/src/components/editor-header.tsx b/apps/web/src/components/editor-header.tsx index c6cecbe..6f9f0b2 100644 --- a/apps/web/src/components/editor-header.tsx +++ b/apps/web/src/components/editor-header.tsx @@ -6,6 +6,7 @@ import { ChevronLeft, Download } from "lucide-react"; import { useProjectStore } from "@/stores/project-store"; import { useTimelineStore } from "@/stores/timeline-store"; import { HeaderBase } from "./header-base"; +import { ProjectNameEditor } from "./editor/project-name-editor"; export function EditorHeader() { const { activeProject } = useProjectStore(); @@ -24,13 +25,15 @@ export function EditorHeader() { }; const leftContent = ( - - - {activeProject?.name || "Loading..."} - +
+ + + + +
); const centerContent = ( diff --git a/apps/web/src/components/editor/project-name-editor.tsx b/apps/web/src/components/editor/project-name-editor.tsx new file mode 100644 index 0000000..aa0141a --- /dev/null +++ b/apps/web/src/components/editor/project-name-editor.tsx @@ -0,0 +1,110 @@ +"use client"; + +import { useState, useRef, useEffect } from "react"; +import { Input } from "../ui/input"; +import { useProjectStore } from "@/stores/project-store"; +import { Edit2, Check, X } from "lucide-react"; +import { Button } from "../ui/button"; + +interface ProjectNameEditorProps { + className?: string; +} + +export function ProjectNameEditor({ className }: ProjectNameEditorProps) { + const { activeProject, updateProjectName } = useProjectStore(); + const [isEditing, setIsEditing] = useState(false); + const [editValue, setEditValue] = useState(""); + const inputRef = useRef(null); + + useEffect(() => { + if (activeProject) { + setEditValue(activeProject.name); + } + }, [activeProject]); + + useEffect(() => { + if (isEditing && inputRef.current) { + inputRef.current.focus(); + inputRef.current.select(); + } + }, [isEditing]); + + const handleStartEdit = () => { + if (activeProject) { + setEditValue(activeProject.name); + setIsEditing(true); + } + }; + + const handleSave = () => { + if (editValue.trim()) { + updateProjectName(editValue.trim()); + setIsEditing(false); + } + }; + + const handleCancel = () => { + if (activeProject) { + setEditValue(activeProject.name); + } + setIsEditing(false); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + handleSave(); + } else if (e.key === "Escape") { + handleCancel(); + } + }; + + if (!activeProject) { + return Loading...; + } + + if (isEditing) { + return ( +
+ setEditValue(e.target.value)} + onKeyDown={handleKeyDown} + className="h-7 text-sm px-3 py-1 min-w-[200px]" + size={1} + /> + + +
+ ); + } + + return ( +
+ {activeProject.name} + +
+ ); +} \ No newline at end of file diff --git a/apps/web/src/stores/project-store.ts b/apps/web/src/stores/project-store.ts index 734c07e..0d0812c 100644 --- a/apps/web/src/stores/project-store.ts +++ b/apps/web/src/stores/project-store.ts @@ -7,6 +7,7 @@ interface ProjectStore { // Actions createNewProject: (name: string) => void; closeProject: () => void; + updateProjectName: (name: string) => void; } export const useProjectStore = create((set) => ({ @@ -25,4 +26,16 @@ export const useProjectStore = create((set) => ({ closeProject: () => { set({ activeProject: null }); }, + + updateProjectName: (name: string) => { + set((state) => ({ + activeProject: state.activeProject + ? { + ...state.activeProject, + name, + updatedAt: new Date(), + } + : null, + })); + }, }));