diff --git a/src/admin/pages/WarehouseIssueForm.tsx b/src/admin/pages/WarehouseIssueForm.tsx index 11b469e..a4035fb 100644 --- a/src/admin/pages/WarehouseIssueForm.tsx +++ b/src/admin/pages/WarehouseIssueForm.tsx @@ -1,24 +1,163 @@ import { useState, useEffect, useRef, useId } from "react"; -import { useParams, useNavigate, useLocation, Link } from "react-router-dom"; +import { + useParams, + useNavigate, + useLocation, + Link as RouterLink, +} from "react-router-dom"; import { useQuery } from "@tanstack/react-query"; +import { motion } from "framer-motion"; +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 { motion } from "framer-motion"; -import FormField from "../components/FormField"; -import WarehouseMovementTable, { - type MovementItem, -} from "../components/warehouse/WarehouseMovementTable"; +import ItemPicker from "../components/warehouse/ItemPicker"; -import { warehouseIssueDetailOptions } from "../lib/queries/warehouse"; +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 } 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: - e.target.value === "" ? null : Number(e.target.value), - })) - } - className="admin-form-select" - > - - {projects.map((p: Project) => ( - - ))} - - {errors.project_id && ( -
{errors.project_id}
- )} - - -