Files
wace_rps/frontend/components/project/ProjectInfoDialog.tsx
T
hjjeong 7c4817b045 진행관리 P1.5 재작업 — PROJECT_NO 셀 클릭 시 프로젝트 정보 다이얼로그
· wace fn_openSaleRegPopup(PROJECT_NO, "detail") 의도 재해석 — read-only 상세 조회 모드
· 행 전체 클릭(onRowClick) → PROJECT_NO 컬럼 셀 클릭(cellClick)으로 좁힘 (wace 1:1)
· 판매관리 페이지 라우팅 폐기 → ProjectInfoDialog 신설 (같은 탭, list row 직접 사용, 추가 API 호출 0)
· 표시 항목: 프로젝트번호/영업번호/주문유형/제품구분/국내해외/고객사/유무상/품번/품명/S/N/수주수량/접수일/요청납기/발주일/프로젝트명/작성자
· 영업관리 변경 롤백 (SaleListFilter.project_no, useSearchParams 자동 선택, 초기화 핸들러)
· 01-progress / 01-progress-verify 문서 갱신

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:06:01 +09:00

74 lines
3.1 KiB
TypeScript

"use client";
// 진행관리 PROJECT_NO 셀 클릭 시 표시되는 프로젝트 정보 다이얼로그 (read-only).
// wace `fn_openSaleRegPopup(PROJECT_NO, "detail")` 대응 — 새 창 대신 같은 탭 내 다이얼로그.
// list SQL 응답(ProgressRow)에 필요 데이터가 모두 포함돼 있어 별도 detail API 호출 불필요.
import React from "react";
import { Button } from "@/components/ui/button";
import {
Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle,
} from "@/components/ui/dialog";
import { ProgressRow } from "@/lib/api/projectMgmt";
interface Props {
open: boolean;
onOpenChange: (open: boolean) => void;
row: ProgressRow | null;
}
const fmtQty = (v: unknown) => {
if (v == null || v === "") return "";
const n = Number(String(v).replace(/,/g, ""));
return isNaN(n) ? String(v) : n.toLocaleString();
};
export function ProjectInfoDialog({ open, onOpenChange, row }: Props) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-xl">
<DialogHeader>
<DialogTitle> </DialogTitle>
</DialogHeader>
{row ? (
<div className="grid grid-cols-[120px_1fr] gap-y-2 gap-x-3 text-sm py-2">
<Label></Label><Value>{row.project_no}</Value>
<Label></Label><Value>{row.contract_no}</Value>
<Label></Label><Value>{row.category_name}</Value>
<Label></Label><Value>{row.product_name}</Value>
<Label>/</Label><Value>{row.area_name}</Value>
<Label></Label><Value>{row.customer_name}</Value>
<Label>/</Label><Value>{row.free_of_charge}</Value>
<Label></Label><Value>{row.product_item_code}</Value>
<Label></Label><Value>{row.product_item_name}</Value>
<Label>S/N</Label><Value>{row.serial_no}</Value>
<Label></Label><Value className="text-right">{fmtQty(row.contract_qty)}</Value>
<Label></Label><Value>{row.reg_date}</Value>
<Label></Label><Value>{row.req_del_date}</Value>
<Label></Label><Value>{row.order_date}</Value>
<Label></Label><Value>{row.project_name ?? ""}</Value>
<Label></Label><Value>{row.writer_name}</Value>
</div>
) : null}
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}></Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
function Label({ children }: { children: React.ReactNode }) {
return <div className="text-right text-xs text-muted-foreground self-center">{children}</div>;
}
function Value({ children, className }: { children: React.ReactNode; className?: string }) {
const empty = children == null || children === "";
return (
<div className={`min-h-7 px-2 py-1 rounded bg-muted/40 text-sm ${className ?? ""}`}>
{empty ? <span className="text-muted-foreground/60">-</span> : children}
</div>
);
}