| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- "use client";
- import React from "react";
- import { Check, ChevronsUpDown } from "lucide-react";
- import { isValidBranchParam } from "@/lib/frontend/params";
- import { cn } from "@/lib/utils";
- 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 {
- Popover,
- PopoverContent,
- PopoverTrigger,
- } from "@/components/ui/popover";
- import {
- Command,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem,
- CommandList,
- } from "@/components/ui/command";
- function normalizeTypedBranch(value) {
- if (typeof value !== "string") return null;
- const s = value.trim().toUpperCase();
- return s ? s : null;
- }
- export default function SearchSingleBranchCombobox({
- branch,
- branchesStatus,
- availableBranches,
- onSingleBranchChange,
- isSubmitting,
- }) {
- const [open, setOpen] = React.useState(false);
- const [manual, setManual] = React.useState("");
- const listReady = branchesStatus === "ready";
- const listLoading = branchesStatus === "loading";
- const listError = branchesStatus === "error";
- const branchOptions = Array.isArray(availableBranches)
- ? availableBranches
- : [];
- const typed = normalizeTypedBranch(manual);
- const canApply = Boolean(typed && isValidBranchParam(typed));
- return (
- <div className="grid gap-2">
- <Label>Niederlassung</Label>
- <Popover open={open} onOpenChange={setOpen}>
- <PopoverTrigger asChild>
- <Button
- type="button"
- variant="outline"
- role="combobox"
- aria-expanded={open}
- disabled={isSubmitting}
- className="w-full justify-between sm:w-[18rem]"
- title="Niederlassung auswählen"
- >
- {branch}
- <ChevronsUpDown className="h-4 w-4 opacity-70" />
- </Button>
- </PopoverTrigger>
- <PopoverContent align="start" className="w-[18rem] p-0">
- {listReady ? (
- <Command>
- <CommandInput placeholder="Niederlassung suchen…" />
- <CommandList>
- <CommandEmpty>Keine Treffer.</CommandEmpty>
- <CommandGroup>
- {branchOptions.map((b) => {
- const id = String(b);
- const isActive = id === branch;
- return (
- <CommandItem
- key={id}
- value={id}
- onSelect={(value) => {
- if (typeof onSingleBranchChange !== "function")
- return;
- const next = normalizeTypedBranch(value);
- if (!next || !isValidBranchParam(next)) return;
- if (next !== branch) onSingleBranchChange(next);
- setOpen(false);
- }}
- >
- <Check
- className={cn(
- "mr-2 h-4 w-4",
- isActive ? "opacity-100" : "opacity-0"
- )}
- />
- {id}
- </CommandItem>
- );
- })}
- </CommandGroup>
- </CommandList>
- </Command>
- ) : listLoading ? (
- <div className="space-y-2 p-3">
- {Array.from({ length: 6 }).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>
- ) : (
- <div className="space-y-3 p-3">
- <p className="text-xs text-muted-foreground">
- Niederlassungen konnten nicht geladen werden. Sie können NLxx
- manuell eingeben.
- </p>
- <div className="flex gap-2">
- <Input
- value={manual}
- onChange={(e) => setManual(e.target.value)}
- onKeyDown={(e) => {
- if (e.key !== "Enter") return;
- if (!canApply) return;
- e.preventDefault();
- if (typeof onSingleBranchChange !== "function") return;
- onSingleBranchChange(typed);
- setManual("");
- setOpen(false);
- }}
- placeholder="z. B. NL17"
- disabled={isSubmitting}
- />
- <Button
- type="button"
- variant="outline"
- disabled={!canApply || isSubmitting}
- onClick={() => {
- if (!canApply) return;
- if (typeof onSingleBranchChange !== "function") return;
- onSingleBranchChange(typed);
- setManual("");
- setOpen(false);
- }}
- >
- Wechseln
- </Button>
- </div>
- </div>
- )}
- </PopoverContent>
- </Popover>
- </div>
- );
- }
|