| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- "use client";
- import React from "react";
- import { Loader2 } from "lucide-react";
- import ExplorerLoading from "@/components/explorer/states/ExplorerLoading";
- import ExplorerEmpty from "@/components/explorer/states/ExplorerEmpty";
- import ExplorerError from "@/components/explorer/states/ExplorerError";
- import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
- import { Button } from "@/components/ui/button";
- import {
- sortSearchItems,
- SEARCH_RESULTS_SORT,
- } from "@/lib/frontend/search/resultsSorting";
- import { useDebouncedVisibility } from "@/lib/frontend/hooks/useDebouncedVisibility";
- import SearchResultsToolbar from "@/components/search/SearchResultsToolbar";
- import SearchResultsTable from "@/components/search/SearchResultsTable";
- const LOADING_DELAY_MS = 300;
- export default function SearchResults({
- branch,
- status,
- items,
- total,
- error,
- onRetry,
- nextCursor,
- onLoadMore,
- isLoadingMore,
- loadMoreError,
- needsBranchSelection = false,
- }) {
- const [sortMode, setSortMode] = React.useState(SEARCH_RESULTS_SORT.RELEVANCE);
- const showLoadingUi = useDebouncedVisibility(status === "loading", {
- delayMs: LOADING_DELAY_MS,
- minVisibleMs: 0,
- });
- const sortedItems = React.useMemo(() => {
- return sortSearchItems(items, sortMode);
- }, [items, sortMode]);
- if (status === "idle") {
- if (needsBranchSelection) {
- return (
- <ExplorerEmpty
- title="Niederlassungen auswählen"
- description="Bitte wählen Sie mindestens eine Niederlassung aus, um die Suche zu starten."
- upHref={null}
- />
- );
- }
- return (
- <ExplorerEmpty
- title="Suche starten"
- description="Bitte geben Sie einen Suchbegriff ein und klicken Sie auf „Suchen“."
- upHref={null}
- />
- );
- }
- if (status === "error" && error) {
- // Validation errors are rendered in the SearchForm (near the inputs).
- if (error.kind === "validation") {
- return (
- <ExplorerEmpty
- title="Eingaben prüfen"
- description="Bitte prüfen Sie Ihre Filter oben."
- upHref={null}
- />
- );
- }
- return (
- <ExplorerError
- title={error.title}
- description={error.description}
- onRetry={onRetry}
- />
- );
- }
- // Debounced loading UI:
- // - If loading is very fast, do not show skeletons (prevents flicker).
- if (showLoadingUi) {
- return <ExplorerLoading variant="table" count={8} />;
- }
- if (status === "loading") {
- return <div className="h-16" aria-hidden="true" />;
- }
- const list = Array.isArray(sortedItems) ? sortedItems : [];
- if (list.length === 0) {
- return (
- <ExplorerEmpty
- title="Keine Treffer"
- description="Für Ihre Suche wurden keine Treffer gefunden."
- upHref={null}
- />
- );
- }
- return (
- <div className="space-y-4">
- <SearchResultsToolbar
- countLoaded={list.length}
- total={total}
- sortMode={sortMode}
- onSortModeChange={setSortMode}
- />
- <SearchResultsTable routeBranch={branch} items={list} />
- {loadMoreError ? (
- <Alert variant="destructive">
- <AlertTitle>{loadMoreError.title}</AlertTitle>
- <AlertDescription>{loadMoreError.description}</AlertDescription>
- </Alert>
- ) : null}
- {nextCursor ? (
- <div className="flex justify-center">
- <Button
- type="button"
- variant="outline"
- onClick={onLoadMore}
- disabled={isLoadingMore}
- title="Weitere Ergebnisse laden"
- >
- {isLoadingMore ? (
- <>
- <Loader2 className="h-4 w-4 animate-spin" />
- Lädt…
- </>
- ) : (
- "Mehr laden"
- )}
- </Button>
- </div>
- ) : null}
- </div>
- );
- }
|