|
|
@@ -0,0 +1,165 @@
|
|
|
+"use client";
|
|
|
+
|
|
|
+import React from "react";
|
|
|
+import Link from "next/link";
|
|
|
+
|
|
|
+import {
|
|
|
+ Breadcrumb,
|
|
|
+ BreadcrumbItem,
|
|
|
+ BreadcrumbLink,
|
|
|
+ BreadcrumbList,
|
|
|
+ BreadcrumbPage,
|
|
|
+ BreadcrumbSeparator,
|
|
|
+} from "@/components/ui/breadcrumb";
|
|
|
+
|
|
|
+import { yearPath, monthPath } from "@/lib/frontend/routes";
|
|
|
+import { formatMonthLabel } from "@/lib/frontend/explorer/formatters";
|
|
|
+import {
|
|
|
+ buildExplorerDropdownItems,
|
|
|
+ buildBranchCrumbHref,
|
|
|
+} from "@/lib/frontend/explorer/breadcrumbDropdowns";
|
|
|
+
|
|
|
+import SegmentDropdown from "@/components/explorer/breadcrumbs/SegmentDropdown";
|
|
|
+
|
|
|
+/**
|
|
|
+ * ExplorerBreadcrumbs
|
|
|
+ *
|
|
|
+ * Breadcrumb navigation for the Explorer drill-down using shadcn/ui Breadcrumb.
|
|
|
+ * Optional dropdowns allow switching between existing years/months/days.
|
|
|
+ *
|
|
|
+ * UX rules:
|
|
|
+ * - All user-facing strings must be German.
|
|
|
+ * - Dropdowns are only rendered when options are available (non-empty lists).
|
|
|
+ *
|
|
|
+ * @param {{
|
|
|
+ * branch: string,
|
|
|
+ * year?: string|null,
|
|
|
+ * month?: string|null,
|
|
|
+ * day?: string|null,
|
|
|
+ * yearOptions?: string[]|null,
|
|
|
+ * monthOptions?: string[]|null,
|
|
|
+ * dayOptions?: string[]|null
|
|
|
+ * }} props
|
|
|
+ */
|
|
|
+export default function ExplorerBreadcrumbs({
|
|
|
+ branch,
|
|
|
+ year = null,
|
|
|
+ month = null,
|
|
|
+ day = null,
|
|
|
+ yearOptions = null,
|
|
|
+ monthOptions = null,
|
|
|
+ dayOptions = null,
|
|
|
+}) {
|
|
|
+ const { yearItems, monthItems, dayItems } = buildExplorerDropdownItems({
|
|
|
+ branch,
|
|
|
+ year,
|
|
|
+ month,
|
|
|
+ day,
|
|
|
+ yearOptions,
|
|
|
+ monthOptions,
|
|
|
+ dayOptions,
|
|
|
+ });
|
|
|
+
|
|
|
+ const showYear = Boolean(year);
|
|
|
+ const showMonth = Boolean(year && month);
|
|
|
+ const showDay = Boolean(year && month && day);
|
|
|
+
|
|
|
+ const isBranchCurrent = !year;
|
|
|
+ const isYearCurrent = Boolean(year && !month);
|
|
|
+ const isMonthCurrent = Boolean(year && month && !day);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Breadcrumb>
|
|
|
+ <BreadcrumbList>
|
|
|
+ {/* Branch */}
|
|
|
+ <BreadcrumbItem>
|
|
|
+ {isBranchCurrent ? (
|
|
|
+ <BreadcrumbPage>{branch}</BreadcrumbPage>
|
|
|
+ ) : (
|
|
|
+ <BreadcrumbLink asChild>
|
|
|
+ <Link href={buildBranchCrumbHref(branch)}>{branch}</Link>
|
|
|
+ </BreadcrumbLink>
|
|
|
+ )}
|
|
|
+ </BreadcrumbItem>
|
|
|
+
|
|
|
+ {/* Year */}
|
|
|
+ {showYear ? (
|
|
|
+ <>
|
|
|
+ <BreadcrumbSeparator />
|
|
|
+ <BreadcrumbItem>
|
|
|
+ <div className="flex items-center">
|
|
|
+ {isYearCurrent ? (
|
|
|
+ <BreadcrumbPage>{year}</BreadcrumbPage>
|
|
|
+ ) : (
|
|
|
+ <BreadcrumbLink asChild>
|
|
|
+ <Link href={yearPath(branch, year)}>{year}</Link>
|
|
|
+ </BreadcrumbLink>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {yearItems ? (
|
|
|
+ <SegmentDropdown
|
|
|
+ items={yearItems}
|
|
|
+ currentValue={year}
|
|
|
+ menuLabel="Jahr wechseln"
|
|
|
+ triggerAriaLabel="Jahr auswählen"
|
|
|
+ />
|
|
|
+ ) : null}
|
|
|
+ </div>
|
|
|
+ </BreadcrumbItem>
|
|
|
+ </>
|
|
|
+ ) : null}
|
|
|
+
|
|
|
+ {/* Month */}
|
|
|
+ {showMonth ? (
|
|
|
+ <>
|
|
|
+ <BreadcrumbSeparator />
|
|
|
+ <BreadcrumbItem>
|
|
|
+ <div className="flex items-center">
|
|
|
+ {isMonthCurrent ? (
|
|
|
+ <BreadcrumbPage>{formatMonthLabel(month)}</BreadcrumbPage>
|
|
|
+ ) : (
|
|
|
+ <BreadcrumbLink asChild>
|
|
|
+ <Link href={monthPath(branch, year, month)}>
|
|
|
+ {formatMonthLabel(month)}
|
|
|
+ </Link>
|
|
|
+ </BreadcrumbLink>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {monthItems ? (
|
|
|
+ <SegmentDropdown
|
|
|
+ items={monthItems}
|
|
|
+ currentValue={month}
|
|
|
+ menuLabel="Monat wechseln"
|
|
|
+ triggerAriaLabel="Monat auswählen"
|
|
|
+ />
|
|
|
+ ) : null}
|
|
|
+ </div>
|
|
|
+ </BreadcrumbItem>
|
|
|
+ </>
|
|
|
+ ) : null}
|
|
|
+
|
|
|
+ {/* Day */}
|
|
|
+ {showDay ? (
|
|
|
+ <>
|
|
|
+ <BreadcrumbSeparator />
|
|
|
+ <BreadcrumbItem>
|
|
|
+ <div className="flex items-center">
|
|
|
+ {/* Day is always current on the leaf route */}
|
|
|
+ <BreadcrumbPage>{day}</BreadcrumbPage>
|
|
|
+
|
|
|
+ {dayItems ? (
|
|
|
+ <SegmentDropdown
|
|
|
+ items={dayItems}
|
|
|
+ currentValue={day}
|
|
|
+ menuLabel="Tag wechseln"
|
|
|
+ triggerAriaLabel="Tag auswählen"
|
|
|
+ />
|
|
|
+ ) : null}
|
|
|
+ </div>
|
|
|
+ </BreadcrumbItem>
|
|
|
+ </>
|
|
|
+ ) : null}
|
|
|
+ </BreadcrumbList>
|
|
|
+ </Breadcrumb>
|
|
|
+ );
|
|
|
+}
|