| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- "use client";
- import React from "react";
- import Link from "next/link";
- import { Eye, FolderOpen } from "lucide-react";
- import { dayPath } from "@/lib/frontend/routes";
- import { buildPdfUrl } from "@/lib/frontend/explorer/pdfUrl";
- import { formatSearchItemDateDe } from "@/lib/frontend/search/resultsSorting";
- import { Button } from "@/components/ui/button";
- import {
- Table,
- TableBody,
- TableCaption,
- TableCell,
- TableHead,
- TableHeader,
- TableRow,
- } from "@/components/ui/table";
- export default function SearchResultsTable({ routeBranch, scope, items }) {
- // NOTE:
- // - We intentionally keep the column set stable:
- // Branch | Date | File | Path | Actions
- // - For single-scope searches, all rows will show the same branch (routeBranch),
- // but the consistent layout improves scanability and avoids “column jumping”.
- const list = Array.isArray(items) ? items : [];
- return (
- <Table className="table-fixed">
- <TableCaption>
- Hinweis: PDFs werden in einem neuen Tab geöffnet.
- </TableCaption>
- <TableHeader>
- <TableRow>
- {/* Fixed-width columns keep the layout stable and prevent “action column drift”. */}
- <TableHead className="w-24">Niederlassung</TableHead>
- <TableHead className="w-28">Datum</TableHead>
- {/* Flexible columns: these must truncate to prevent horizontal scrolling. */}
- <TableHead>Datei</TableHead>
- <TableHead className="hidden md:table-cell">Pfad</TableHead>
- {/* Fixed actions column so buttons are always reachable without scrolling. */}
- <TableHead className="w-40 text-right">Aktionen</TableHead>
- </TableRow>
- </TableHeader>
- <TableBody>
- {list.map((it) => {
- const itemBranch = String(it?.branch || routeBranch);
- const year = String(it?.year || "");
- const month = String(it?.month || "");
- const day = String(it?.day || "");
- const filename = String(it?.filename || "");
- const relativePath = String(it?.relativePath || "");
- // Binary PDF endpoint: open in a new tab (do NOT fetch via apiClient).
- const pdfUrl = buildPdfUrl({
- branch: itemBranch,
- year,
- month,
- day,
- filename,
- });
- const dayHref = dayPath(itemBranch, year, month, day);
- // Stable key: relativePath is best; fallback is deterministic.
- const key =
- relativePath || `${itemBranch}/${year}/${month}/${day}/${filename}`;
- return (
- <TableRow key={key}>
- <TableCell className="w-24">
- <span className="text-sm">{itemBranch}</span>
- </TableCell>
- <TableCell className="w-28">
- <span className="text-sm">{formatSearchItemDateDe(it)}</span>
- </TableCell>
- {/* File column: must be shrinkable so truncate works in table-fixed layout. */}
- <TableCell className="min-w-0">
- <div className="min-w-0">
- <p className="truncate font-medium" title={filename}>
- {filename}
- </p>
- {/* Mobile: show path as secondary line instead of a dedicated column */}
- <p
- className="truncate text-xs text-muted-foreground md:hidden"
- title={relativePath}
- >
- {relativePath}
- </p>
- </div>
- </TableCell>
- {/* Path column (desktop): always truncate + title for full hover read. */}
- <TableCell className="hidden md:table-cell min-w-0">
- <span
- className="block max-w-full truncate text-xs text-muted-foreground"
- title={relativePath}
- >
- {relativePath}
- </span>
- </TableCell>
- {/* Actions: fixed-width column, buttons stacked to keep width small and stable. */}
- <TableCell className="w-40">
- <div className="flex gap-2">
- <Button
- variant="outline"
- size="sm"
- asChild
- className="w-36 justify-start"
- >
- <a
- href={pdfUrl}
- target="_blank"
- rel="noopener noreferrer"
- aria-label={`PDF öffnen: ${filename}`}
- title={`PDF öffnen: ${filename}`}
- >
- <Eye className="h-4 w-4" />
- Öffnen
- </a>
- </Button>
- <Button
- variant="outline"
- size="sm"
- asChild
- className="w-36 justify-start"
- >
- <Link href={dayHref} title="Zum Ordner">
- <FolderOpen className="h-4 w-4" />
- Zum Ordner
- </Link>
- </Button>
- </div>
- </TableCell>
- </TableRow>
- );
- })}
- </TableBody>
- </Table>
- );
- }
|