Files
wace_rps/frontend/components/material/InventoryHistoryDialog.tsx
T
hjjeong aacbb62ad8 자재관리 2메뉴 풀-CRUD + 액션 (자재리스트 + 불출의뢰서)
- 신규 테이블 5종 (운영 11133 → RPS 11134 DDL 1:1):
  inventory_mgmt / inventory_mgmt_in / inventory_mgmt_out /
  inventory_mgmt_out_master / inventory_mgmt_history
- 백엔드 /api/inventory-mng — 리스트·재고등록·자재이동·삭제·이력 +
  불출의뢰 생성·접수·자재불출(재고 차감)·삭제. 채번 Rfw-YYYY-seq.
- 프론트 /COMPANY_16/material/{list, issue-request} +
  StockRegister / MaterialMove / IssueRequestCreate /
  InventoryHistory / IssueDispatch 다이얼로그 5종.
- AdminPageRenderer 등록 + /material/ prefix.
2026-05-19 11:25:15 +09:00

102 lines
3.6 KiB
TypeScript

"use client";
// 자재관리 > 자재리스트 — 입출고 이력 다이얼로그
// wace 1:1: inventoryRequestHistoryPopUp.jsp
// 입고/이동/출고 UNION 결과 노출
import React, { useEffect, useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { X } from "lucide-react";
import { inventoryMngApi } from "@/lib/api/inventoryMng";
import { toast } from "sonner";
interface HistoryRow {
objid: string;
part_no: string;
part_name: string;
gubun: string;
qty: string;
location_name: string;
sub_location_name: string;
regdate: string;
writer_name: string;
}
interface Props {
open: boolean;
onClose: () => void;
parentObjid: string; // inventory_mgmt.objid
partLabel?: string;
}
export function InventoryHistoryDialog({ open, onClose, parentObjid, partLabel }: Props) {
const [rows, setRows] = useState<HistoryRow[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!open || !parentObjid) return;
setLoading(true);
(async () => {
try {
const data = await inventoryMngApi.history(parentObjid);
setRows(data as HistoryRow[]);
} catch (e: any) {
toast.error(e?.response?.data?.message ?? e?.message ?? "이력 조회 실패");
} finally {
setLoading(false);
}
})();
}, [open, parentObjid]);
return (
<Dialog open={open} onOpenChange={(v) => !v && onClose()}>
<DialogContent className="max-w-4xl">
<DialogHeader>
<DialogTitle> {partLabel ? `${partLabel}` : ""}</DialogTitle>
<DialogDescription> // .</DialogDescription>
</DialogHeader>
<div className="overflow-x-auto text-xs">
<table className="w-full border">
<thead className="bg-muted/50">
<tr>
<th className="border px-2 py-1"></th>
<th className="border px-2 py-1 text-right"></th>
<th className="border px-2 py-1">Location</th>
<th className="border px-2 py-1">Sub</th>
<th className="border px-2 py-1"></th>
<th className="border px-2 py-1"></th>
</tr>
</thead>
<tbody>
{loading && (
<tr><td colSpan={6} className="border px-2 py-3 text-center"> ...</td></tr>
)}
{!loading && rows.length === 0 && (
<tr><td colSpan={6} className="border px-2 py-3 text-center"> .</td></tr>
)}
{rows.map((r, i) => (
<tr key={i}>
<td className="border px-2 py-1">{r.gubun}</td>
<td className="border px-2 py-1 text-right">{r.qty || "0"}</td>
<td className="border px-2 py-1">{r.location_name}</td>
<td className="border px-2 py-1">{r.sub_location_name}</td>
<td className="border px-2 py-1">{r.writer_name}</td>
<td className="border px-2 py-1">{r.regdate?.toString().slice(0, 19).replace("T", " ")}</td>
</tr>
))}
</tbody>
</table>
</div>
<DialogFooter>
<Button size="sm" variant="ghost" onClick={onClose}>
<X className="h-3.5 w-3.5 mr-1" />
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}