feat: add edit mode toggle to dashboard page

- Edit/Done toggle button in header (pencil icon)
- Widget delete buttons only visible in edit mode
- Add widget button only visible in edit mode
- Empty state prompts to enter edit mode instead of adding directly
- Default is view mode — clean, no accidental deletes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Gjermund Høsøien Wiggen
2026-06-09 13:38:28 +02:00
parent 9938c7a7ad
commit 6ca8974eb9

View File

@@ -4,6 +4,7 @@ import { useState, useEffect, use, useCallback } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import {
PencilIcon,
PlusIcon,
Trash2Icon,
RefreshCwIcon,
@@ -58,6 +59,7 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [autoRefresh, setAutoRefresh] = useState(false);
const [editMode, setEditMode] = useState(false);
const [teams, setTeams] = useState<Team[]>([]);
// Add widget dialog
@@ -231,6 +233,15 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
</div>
</div>
<div className="flex items-center gap-2">
<Button
variant="outline"
size="sm"
onClick={() => setEditMode((v) => !v)}
className={cn("h-8 border-border/80", editMode ? "bg-primary/20 text-primary border-primary/40" : "bg-card/70")}
>
<PencilIcon className="h-4 w-4" />
{editMode ? "Done" : "Edit"}
</Button>
<Button
variant="outline"
size="sm"
@@ -249,10 +260,12 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
<RefreshCwIcon className="h-4 w-4" />
Refresh
</Button>
<Button size="sm" onClick={() => setAddOpen(true)} className="h-8 bg-primary shadow-sm">
<PlusIcon className="h-4 w-4" />
Add widget
</Button>
{editMode && (
<Button size="sm" onClick={() => setAddOpen(true)} className="h-8 bg-primary shadow-sm">
<PlusIcon className="h-4 w-4" />
Add widget
</Button>
)}
</div>
</div>
</header>
@@ -262,10 +275,17 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
<div className="flex h-full flex-col items-center justify-center gap-3">
<LayoutGridIcon className="h-10 w-10 text-muted-foreground/40" />
<p className="text-sm text-muted-foreground">No widgets yet</p>
<Button variant="outline" size="sm" onClick={() => setAddOpen(true)}>
<PlusIcon className="h-4 w-4" />
Add your first widget
</Button>
{editMode ? (
<Button variant="outline" size="sm" onClick={() => setAddOpen(true)}>
<PlusIcon className="h-4 w-4" />
Add your first widget
</Button>
) : (
<Button variant="outline" size="sm" onClick={() => setEditMode(true)}>
<PencilIcon className="h-4 w-4" />
Enter edit mode
</Button>
)}
</div>
) : (
<div className="grid auto-rows-[minmax(100px,auto)] grid-cols-6 gap-3 md:grid-cols-12 md:gap-4">
@@ -276,14 +296,16 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
style={widgetGridStyle(widget.position)}
>
{renderWidget(widget)}
<button
type="button"
onClick={() => handleDeleteWidget(widget.id)}
className="absolute right-2 top-2 hidden h-6 w-6 items-center justify-center rounded bg-destructive/90 text-destructive-foreground transition-opacity hover:bg-destructive group-hover:flex"
title="Remove widget"
>
<Trash2Icon className="h-3.5 w-3.5" />
</button>
{editMode && (
<button
type="button"
onClick={() => handleDeleteWidget(widget.id)}
className="absolute right-2 top-2 hidden h-6 w-6 items-center justify-center rounded bg-destructive/90 text-destructive-foreground transition-opacity hover:bg-destructive group-hover:flex"
title="Remove widget"
>
<Trash2Icon className="h-3.5 w-3.5" />
</button>
)}
</div>
))}
</div>