feat: Phase B — interactive dashboard, breadcrumbs, clickable navigation
- Breadcrumb component: reusable nav with items array (label+href)
- DeadlineTrafficLights: buttons → Links to /fristen?status={filter}
- CaseOverviewGrid: static metrics → clickable Links to /cases?status={filter}
- UpcomingTimeline: items → clickable Links to /fristen/{id} or /termine/{id}
with case number links and hover chevron
- QuickActions: swap CalDAV Sync for "Neuer Termin" → /termine/neu,
fix "Frist eintragen" → /fristen/neu
- AISummaryCard: add RefreshCw button with spinning animation
- RecentActivityList: new component showing recent case events
- DeadlineList: accept initialStatus prop, add this_week/ok filters
- fristen/page.tsx: read searchParams.status for initial filter
- Add breadcrumbs to dashboard, fristen, cases, termine pages
- Add RecentActivity type, update DashboardData type
This commit is contained in:
@@ -10,7 +10,14 @@ import { toast } from "sonner";
|
||||
import { useState, useMemo } from "react";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
|
||||
type StatusFilter = "all" | "pending" | "completed" | "overdue";
|
||||
type StatusFilter = "all" | "pending" | "completed" | "overdue" | "this_week" | "ok";
|
||||
|
||||
function mapUrlStatus(status?: string): StatusFilter {
|
||||
if (status === "overdue") return "overdue";
|
||||
if (status === "this_week") return "this_week";
|
||||
if (status === "ok") return "ok";
|
||||
return "all";
|
||||
}
|
||||
|
||||
function getUrgency(deadline: Deadline): "red" | "amber" | "green" {
|
||||
if (deadline.status === "completed") return "green";
|
||||
@@ -47,9 +54,15 @@ const urgencyConfig = {
|
||||
const selectClass =
|
||||
"rounded-md border border-neutral-200 bg-white px-2.5 py-1 text-sm text-neutral-700 transition-colors focus:border-neutral-400 focus:ring-1 focus:ring-neutral-400 outline-none";
|
||||
|
||||
export function DeadlineList() {
|
||||
interface Props {
|
||||
initialStatus?: string;
|
||||
}
|
||||
|
||||
export function DeadlineList({ initialStatus }: Props) {
|
||||
const queryClient = useQueryClient();
|
||||
const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
|
||||
const [statusFilter, setStatusFilter] = useState<StatusFilter>(
|
||||
mapUrlStatus(initialStatus),
|
||||
);
|
||||
const [caseFilter, setCaseFilter] = useState<string>("all");
|
||||
|
||||
const { data: deadlines, isLoading } = useQuery({
|
||||
@@ -90,6 +103,18 @@ export function DeadlineList() {
|
||||
if (d.status === "completed") return false;
|
||||
if (!isPast(parseISO(d.due_date))) return false;
|
||||
}
|
||||
if (statusFilter === "this_week") {
|
||||
if (d.status === "completed") return false;
|
||||
const due = parseISO(d.due_date);
|
||||
if (isPast(due)) return false;
|
||||
if (!isThisWeek(due, { weekStartsOn: 1 })) return false;
|
||||
}
|
||||
if (statusFilter === "ok") {
|
||||
if (d.status === "completed") return false;
|
||||
const due = parseISO(d.due_date);
|
||||
if (isPast(due)) return false;
|
||||
if (isThisWeek(due, { weekStartsOn: 1 })) return false;
|
||||
}
|
||||
if (caseFilter !== "all" && d.case_id !== caseFilter) return false;
|
||||
return true;
|
||||
});
|
||||
@@ -144,10 +169,10 @@ export function DeadlineList() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() =>
|
||||
setStatusFilter(statusFilter === "pending" ? "all" : "pending")
|
||||
setStatusFilter(statusFilter === "this_week" ? "all" : "this_week")
|
||||
}
|
||||
className={`rounded-lg border p-3 text-left transition-all ${
|
||||
statusFilter === "pending"
|
||||
statusFilter === "this_week"
|
||||
? "border-amber-300 bg-amber-50 ring-1 ring-amber-200"
|
||||
: "border-neutral-200 bg-white hover:bg-neutral-50"
|
||||
}`}
|
||||
@@ -158,9 +183,11 @@ export function DeadlineList() {
|
||||
<div className="text-xs text-neutral-500">Diese Woche</div>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setStatusFilter("all")}
|
||||
onClick={() =>
|
||||
setStatusFilter(statusFilter === "ok" ? "all" : "ok")
|
||||
}
|
||||
className={`rounded-lg border p-3 text-left transition-all ${
|
||||
statusFilter === "all"
|
||||
statusFilter === "ok"
|
||||
? "border-green-300 bg-green-50 ring-1 ring-green-200"
|
||||
: "border-neutral-200 bg-white hover:bg-neutral-50"
|
||||
}`}
|
||||
@@ -187,6 +214,8 @@ export function DeadlineList() {
|
||||
<option value="pending">Offen</option>
|
||||
<option value="completed">Erledigt</option>
|
||||
<option value="overdue">Überfällig</option>
|
||||
<option value="this_week">Diese Woche</option>
|
||||
<option value="ok">Im Zeitplan</option>
|
||||
</select>
|
||||
{Array.isArray(cases) && cases.length > 0 && (
|
||||
<select
|
||||
|
||||
Reference in New Issue
Block a user