ERP-node/frontend/lib/registry/components/v2-process-work-standard/components/InspectionStandardLookup.tsx

188 lines
6.4 KiB
TypeScript

"use client";
import React, { useState, useEffect, useCallback } from "react";
import { Search, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogFooter,
} from "@/components/ui/dialog";
import { apiClient } from "@/lib/api/client";
import { InspectionStandard } from "../types";
interface InspectionStandardLookupProps {
open: boolean;
onClose: () => void;
onSelect: (item: InspectionStandard) => void;
}
export function InspectionStandardLookup({
open,
onClose,
onSelect,
}: InspectionStandardLookupProps) {
const [data, setData] = useState<any[]>([]);
const [searchText, setSearchText] = useState("");
const [loading, setLoading] = useState(false);
const fetchData = useCallback(async () => {
setLoading(true);
try {
const search: Record<string, any> = {};
if (searchText.trim()) {
search.inspection_item = searchText.trim();
search.inspection_code = searchText.trim();
}
const params = new URLSearchParams({
page: "1",
size: "100",
enableEntityJoin: "true",
...(searchText.trim() ? { search: JSON.stringify(search) } : {}),
});
const res = await apiClient.get(
`/table-management/tables/inspection_standard/data-with-joins?${params}`
);
if (res.data?.success) {
const result = res.data.data;
setData(Array.isArray(result) ? result : result?.data || []);
}
} catch (err) {
console.error("검사기준 조회 실패", err);
} finally {
setLoading(false);
}
}, [searchText]);
useEffect(() => {
if (open) {
fetchData();
}
}, [open, fetchData]);
const handleSelect = (item: any) => {
onSelect({
id: item.id,
inspection_code: item.inspection_code || "",
inspection_item: item.inspection_item || item.inspection_criteria || "",
inspection_method: item.inspection_method || "",
unit: item.unit || "",
lower_limit: item.lower_limit || "",
upper_limit: item.upper_limit || "",
});
onClose();
};
return (
<Dialog open={open} onOpenChange={(v) => !v && onClose()}>
<DialogContent className="max-w-[95vw] sm:max-w-[700px]">
<DialogHeader>
<DialogTitle className="flex items-center gap-2 text-base sm:text-lg">
<Search className="h-5 w-5" />
</DialogTitle>
<DialogDescription className="text-xs sm:text-sm">
</DialogDescription>
</DialogHeader>
<div className="space-y-3">
<div className="flex gap-2">
<Input
placeholder="검사항목명 또는 검사코드로 검색..."
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && fetchData()}
className="h-9 text-sm"
/>
</div>
<div className="max-h-[400px] overflow-auto rounded border">
<table className="w-full text-sm">
<thead className="sticky top-0 bg-muted">
<tr className="border-b">
<th className="px-3 py-2 text-left font-medium text-muted-foreground">
</th>
<th className="px-3 py-2 text-left font-medium text-muted-foreground">
</th>
<th className="px-3 py-2 text-left font-medium text-muted-foreground">
</th>
<th className="px-3 py-2 text-center font-medium text-muted-foreground">
</th>
<th className="px-3 py-2 text-center font-medium text-muted-foreground">
</th>
<th className="px-3 py-2 text-center font-medium text-muted-foreground">
</th>
<th className="w-16 px-3 py-2 text-center font-medium text-muted-foreground">
</th>
</tr>
</thead>
<tbody>
{loading ? (
<tr>
<td colSpan={7} className="py-8 text-center text-muted-foreground">
...
</td>
</tr>
) : data.length === 0 ? (
<tr>
<td colSpan={7} className="py-8 text-center text-muted-foreground">
</td>
</tr>
) : (
data.map((item, idx) => (
<tr
key={item.id || idx}
className="border-b transition-colors hover:bg-muted/30"
>
<td className="px-3 py-2">{item.inspection_code || "-"}</td>
<td className="px-3 py-2">
{item.inspection_item || item.inspection_criteria || "-"}
</td>
<td className="px-3 py-2">{item.inspection_method || "-"}</td>
<td className="px-3 py-2 text-center">
{item.lower_limit || "-"}
</td>
<td className="px-3 py-2 text-center">
{item.upper_limit || "-"}
</td>
<td className="px-3 py-2 text-center">{item.unit || "-"}</td>
<td className="px-3 py-2 text-center">
<Button
size="sm"
className="h-7 px-3 text-xs"
onClick={() => handleSelect(item)}
>
</Button>
</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={onClose} className="h-8 text-xs sm:h-10 sm:text-sm">
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}