| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- "use client";
- import React from "react";
- import { ChevronDown, Search } from "lucide-react";
- import { SEARCH_SCOPE } from "@/lib/frontend/search/urlState";
- import { Button } from "@/components/ui/button";
- import { Input } from "@/components/ui/input";
- import { Label } from "@/components/ui/label";
- import { Skeleton } from "@/components/ui/skeleton";
- import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuLabel,
- DropdownMenuRadioGroup,
- DropdownMenuRadioItem,
- DropdownMenuSeparator,
- DropdownMenuTrigger,
- } from "@/components/ui/dropdown-menu";
- const SCOPE_LABELS = Object.freeze({
- [SEARCH_SCOPE.SINGLE]: "Diese Niederlassung",
- [SEARCH_SCOPE.MULTI]: "Mehrere Niederlassungen",
- [SEARCH_SCOPE.ALL]: "Alle Niederlassungen",
- });
- export default function SearchForm({
- branch,
- qDraft,
- onQDraftChange,
- onSubmit,
- currentQuery,
- isSubmitting,
- isAdminDev,
- scope,
- onScopeChange,
- availableBranches,
- branchesStatus,
- selectedBranches,
- onToggleBranch,
- }) {
- const canSearch = typeof qDraft === "string" && qDraft.trim().length > 0;
- const scopeLabel = SCOPE_LABELS[scope] || "Unbekannt";
- return (
- <div className="space-y-4">
- <form
- onSubmit={(e) => {
- e.preventDefault();
- if (!canSearch) return;
- onSubmit();
- }}
- className="space-y-3"
- >
- <div className="grid gap-2">
- <Label htmlFor="q">Suchbegriff</Label>
- <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
- <Input
- id="q"
- name="q"
- value={qDraft}
- onChange={(e) => onQDraftChange(e.target.value)}
- placeholder="z. B. Bridgestone, Rechnung, Kundennummer…"
- disabled={isSubmitting}
- />
- <Button type="submit" disabled={!canSearch || isSubmitting}>
- <Search className="h-4 w-4" />
- Suchen
- </Button>
- </div>
- {currentQuery ? (
- <div className="text-xs text-muted-foreground">
- Aktuelle Suche:{" "}
- <span className="ml-1 rounded-md bg-muted px-2 py-1 text-xs text-muted-foreground">
- {currentQuery}
- </span>
- </div>
- ) : (
- <div className="text-xs text-muted-foreground">
- Tipp: Die Suche ist URL-basiert und kann als Link geteilt werden.
- </div>
- )}
- </div>
- {isAdminDev ? (
- <div className="grid gap-2">
- <Label>Suchbereich</Label>
- <div className="flex flex-wrap items-center gap-2">
- <DropdownMenu>
- <DropdownMenuTrigger asChild>
- <Button
- type="button"
- variant="outline"
- disabled={isSubmitting}
- title="Suchbereich auswählen"
- >
- {scopeLabel}
- <ChevronDown className="h-4 w-4" />
- </Button>
- </DropdownMenuTrigger>
- <DropdownMenuContent align="start" className="min-w-[16rem]">
- <DropdownMenuLabel>Suchbereich</DropdownMenuLabel>
- <DropdownMenuSeparator />
- <DropdownMenuRadioGroup
- value={scope}
- onValueChange={(value) => onScopeChange(value)}
- >
- <DropdownMenuRadioItem value={SEARCH_SCOPE.SINGLE}>
- Diese Niederlassung ({branch})
- </DropdownMenuRadioItem>
- <DropdownMenuRadioItem value={SEARCH_SCOPE.MULTI}>
- Mehrere Niederlassungen
- </DropdownMenuRadioItem>
- <DropdownMenuRadioItem value={SEARCH_SCOPE.ALL}>
- Alle Niederlassungen
- </DropdownMenuRadioItem>
- </DropdownMenuRadioGroup>
- </DropdownMenuContent>
- </DropdownMenu>
- {scope === SEARCH_SCOPE.SINGLE ? (
- <span className="text-xs text-muted-foreground">
- Aktiv: {branch}
- </span>
- ) : null}
- </div>
- </div>
- ) : null}
- </form>
- {isAdminDev && scope === SEARCH_SCOPE.MULTI ? (
- <div className="rounded-lg border bg-card p-4 text-card-foreground shadow-sm">
- <div className="space-y-2">
- <p className="text-sm font-medium">Niederlassungen auswählen</p>
- <p className="text-xs text-muted-foreground">
- Wählen Sie eine oder mehrere Niederlassungen. Die Suche wird nach
- jeder Änderung aktualisiert.
- </p>
- {branchesStatus === "loading" ? (
- <div className="grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4">
- {Array.from({ length: 8 }).map((_, i) => (
- <div key={i} className="flex items-center gap-2">
- <Skeleton className="h-4 w-4" />
- <Skeleton className="h-4 w-16" />
- </div>
- ))}
- </div>
- ) : branchesStatus === "error" ? (
- <p className="text-sm text-muted-foreground">
- Niederlassungen konnten nicht geladen werden.
- </p>
- ) : (
- <div className="grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4">
- {(Array.isArray(availableBranches)
- ? availableBranches
- : []
- ).map((b) => {
- const checked = Array.isArray(selectedBranches)
- ? selectedBranches.includes(b)
- : false;
- return (
- <label
- key={b}
- className="flex items-center gap-2 rounded-md px-2 py-1 hover:bg-muted/50"
- >
- <input
- type="checkbox"
- checked={checked}
- onChange={() => onToggleBranch(b)}
- disabled={isSubmitting}
- />
- <span className="text-sm">{b}</span>
- </label>
- );
- })}
- </div>
- )}
- </div>
- </div>
- ) : null}
- </div>
- );
- }
|