import { useState, useEffect, useRef, useId } from "react"; import { useParams, useNavigate, useLocation, Link as RouterLink, } from "react-router-dom"; import { useQuery } from "@tanstack/react-query"; import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import IconButton from "@mui/material/IconButton"; import { useAlert } from "../context/AlertContext"; import { useAuth } from "../context/AuthContext"; import Forbidden from "../components/Forbidden"; import ItemPicker from "../components/warehouse/ItemPicker"; import { jsonQuery } from "../lib/apiAdapter"; import { warehouseIssueDetailOptions, warehouseLocationListOptions, type WarehouseLocation, } from "../lib/queries/warehouse"; import { projectListOptions, type Project } from "../lib/queries/projects"; import { useApiMutation } from "../lib/queries/mutations"; import { Button, Card, TextField, Select, Field, LoadingState, PageEnter, } from "../ui"; interface IssueForm { project_id: number | null; notes: string; } interface MovementItem { key: string; item_id: number | null; item_name?: string; quantity: number; unit_price: number; location_id: number | null; batch_id: number | null; reservation_id: number | null; notes: string | null; } interface Batch { id: number; quantity: number; unit_price: number; received_at: string; is_consumed: boolean; } interface BatchesResponse { batches: Batch[]; total_stock: number; reserved_quantity: number; available_quantity: number; } function parseDecimal(raw: string): number { const cleaned = raw.replace(/[eE+-]/g, ""); const n = Number(cleaned); return Number.isFinite(n) ? n : 0; } const BackIcon = ( ); const RemoveIcon = ( ); const PlusIcon = ( ); /** Inline batch dropdown: lists FIFO batches for an item, sets batch + unit price. */ function BatchSelect({ itemId, value, onChange, }: { itemId: number | null; value: number | null; onChange: (batchId: number, unitPrice: number) => void; }) { const { data: response } = useQuery({ queryKey: ["warehouse", "batches", itemId], queryFn: () => jsonQuery( `/api/admin/warehouse/items/${itemId}/batches`, ), enabled: !!itemId, }); const batches = response?.batches ?? []; return ( {response && response.reserved_quantity > 0 && ( Dostupné: {response.available_quantity} ks (z toho rezervováno:{" "} {response.reserved_quantity} ks) )} setForm((prev) => ({ ...prev, project_id: val === "" ? null : Number(val), })) } options={projectOptions} /> setForm((prev) => ({ ...prev, notes: e.target.value })) } placeholder="Volitelné poznámky" /> {/* Lines */} Položky {errors.items && ( {errors.items} )} {items.map((item, index) => ( updateItem(index, "item_id", id)} /> { updateItem(index, "batch_id", batchId); updateItem(index, "unit_price", unitPrice); }} /> updateItem(index, "quantity", parseDecimal(e.target.value)) } inputProps={{ min: 0, step: 0.001, inputMode: "decimal", pattern: "[0-9]+([\\.,][0-9]+)?", "aria-label": `Množství, řádek ${index + 1}`, }} placeholder="Množství" />