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:
@@ -4,6 +4,7 @@ import { useState, useEffect, use, useCallback } from "react";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {
|
import {
|
||||||
|
PencilIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
Trash2Icon,
|
Trash2Icon,
|
||||||
RefreshCwIcon,
|
RefreshCwIcon,
|
||||||
@@ -58,6 +59,7 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [autoRefresh, setAutoRefresh] = useState(false);
|
const [autoRefresh, setAutoRefresh] = useState(false);
|
||||||
|
const [editMode, setEditMode] = useState(false);
|
||||||
const [teams, setTeams] = useState<Team[]>([]);
|
const [teams, setTeams] = useState<Team[]>([]);
|
||||||
|
|
||||||
// Add widget dialog
|
// Add widget dialog
|
||||||
@@ -231,6 +233,15 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<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
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -249,10 +260,12 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
|
|||||||
<RefreshCwIcon className="h-4 w-4" />
|
<RefreshCwIcon className="h-4 w-4" />
|
||||||
Refresh
|
Refresh
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="sm" onClick={() => setAddOpen(true)} className="h-8 bg-primary shadow-sm">
|
{editMode && (
|
||||||
<PlusIcon className="h-4 w-4" />
|
<Button size="sm" onClick={() => setAddOpen(true)} className="h-8 bg-primary shadow-sm">
|
||||||
Add widget
|
<PlusIcon className="h-4 w-4" />
|
||||||
</Button>
|
Add widget
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</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">
|
<div className="flex h-full flex-col items-center justify-center gap-3">
|
||||||
<LayoutGridIcon className="h-10 w-10 text-muted-foreground/40" />
|
<LayoutGridIcon className="h-10 w-10 text-muted-foreground/40" />
|
||||||
<p className="text-sm text-muted-foreground">No widgets yet</p>
|
<p className="text-sm text-muted-foreground">No widgets yet</p>
|
||||||
<Button variant="outline" size="sm" onClick={() => setAddOpen(true)}>
|
{editMode ? (
|
||||||
<PlusIcon className="h-4 w-4" />
|
<Button variant="outline" size="sm" onClick={() => setAddOpen(true)}>
|
||||||
Add your first widget
|
<PlusIcon className="h-4 w-4" />
|
||||||
</Button>
|
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>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid auto-rows-[minmax(100px,auto)] grid-cols-6 gap-3 md:grid-cols-12 md:gap-4">
|
<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)}
|
style={widgetGridStyle(widget.position)}
|
||||||
>
|
>
|
||||||
{renderWidget(widget)}
|
{renderWidget(widget)}
|
||||||
<button
|
{editMode && (
|
||||||
type="button"
|
<button
|
||||||
onClick={() => handleDeleteWidget(widget.id)}
|
type="button"
|
||||||
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"
|
onClick={() => handleDeleteWidget(widget.id)}
|
||||||
title="Remove widget"
|
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>
|
<Trash2Icon className="h-3.5 w-3.5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user