refactor(ux): consolidate BMAD skills, update design system, and clean up Prisma generated client
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { FlaskConical, Plus, X, ChevronDown, Trash2, Layout, MoreVertical } from 'lucide-react'
|
||||
import { FlaskConical, Plus, ChevronDown, Trash2, Layout } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { renameCanvas, deleteCanvas, createCanvas } from '@/app/actions/canvas-actions'
|
||||
import { useRouter } from 'next/navigation'
|
||||
@@ -25,7 +25,7 @@ interface LabHeaderProps {
|
||||
|
||||
export function LabHeader({ canvases, currentCanvasId, onCreateCanvas }: LabHeaderProps) {
|
||||
const router = useRouter()
|
||||
const { t } = useLanguage()
|
||||
const { t, language } = useLanguage()
|
||||
const [isPending, startTransition] = useTransition()
|
||||
const [isEditing, setIsEditing] = useState(false)
|
||||
|
||||
@@ -36,22 +36,21 @@ export function LabHeader({ canvases, currentCanvasId, onCreateCanvas }: LabHead
|
||||
setIsEditing(false)
|
||||
return
|
||||
}
|
||||
|
||||
startTransition(async () => {
|
||||
try {
|
||||
await renameCanvas(id, newName)
|
||||
toast.success(t('labHeader.renamed'))
|
||||
} catch (e) {
|
||||
toast.error(t('labHeader.renameError'))
|
||||
}
|
||||
setIsEditing(false)
|
||||
})
|
||||
|
||||
try {
|
||||
await renameCanvas(id, newName)
|
||||
toast.success(t('labHeader.renamed'))
|
||||
router.refresh()
|
||||
} catch (e) {
|
||||
toast.error(t('labHeader.renameError'))
|
||||
}
|
||||
setIsEditing(false)
|
||||
}
|
||||
|
||||
const handleCreate = async () => {
|
||||
startTransition(async () => {
|
||||
try {
|
||||
const newCanvas = await createCanvas()
|
||||
const newCanvas = await createCanvas(language)
|
||||
router.push(`/lab?id=${newCanvas.id}`)
|
||||
toast.success(t('labHeader.created'))
|
||||
} catch (e) {
|
||||
@@ -148,49 +147,44 @@ export function LabHeader({ canvases, currentCanvasId, onCreateCanvas }: LabHead
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{/* Inline Rename */}
|
||||
<div className="ms-2 flex items-center gap-2 group">
|
||||
{isEditing ? (
|
||||
<input
|
||||
autoFocus
|
||||
className="bg-muted px-3 py-1.5 rounded-lg text-sm font-medium focus:ring-2 focus:ring-primary/20 outline-none w-[200px]"
|
||||
defaultValue={currentCanvas?.name}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') handleRename(currentCanvas?.id!, e.currentTarget.value)
|
||||
if (e.key === 'Escape') setIsEditing(false)
|
||||
}}
|
||||
onBlur={(e) => handleRename(currentCanvas?.id!, e.target.value)}
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => setIsEditing(true)}
|
||||
className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<MoreVertical className="h-3 w-3 opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{/* Inline Rename — click on project name to edit */}
|
||||
{currentCanvas && (
|
||||
<div className="ms-2 flex items-center gap-2">
|
||||
{isEditing ? (
|
||||
<input
|
||||
autoFocus
|
||||
className="bg-muted px-3 py-1.5 rounded-lg text-sm font-medium focus:ring-2 focus:ring-primary/20 outline-none w-[200px]"
|
||||
defaultValue={currentCanvas.name}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') handleRename(currentCanvas.id, e.currentTarget.value)
|
||||
if (e.key === 'Escape') setIsEditing(false)
|
||||
}}
|
||||
onBlur={(e) => handleRename(currentCanvas.id, e.target.value)}
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => setIsEditing(true)}
|
||||
className="text-sm font-semibold text-foreground hover:text-primary transition-colors"
|
||||
title={t('labHeader.rename') || 'Rename'}
|
||||
>
|
||||
{currentCanvas.name}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
{currentCanvas && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => handleDelete(currentCanvas.id, currentCanvas.name)}
|
||||
className="text-muted-foreground hover:text-destructive hover:bg-destructive/5 rounded-xl transition-all"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={handleCreate}
|
||||
disabled={isPending}
|
||||
className="h-10 rounded-xl px-4 flex items-center gap-2 shadow-lg shadow-primary/20 hover:shadow-primary/30 active:scale-95 transition-all outline-none"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
{t('labHeader.new')}
|
||||
</Button>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user