개발관리>PART 등록·조회 + E-BOM 등록 검색 폼 select2-part 자동완성 (운영판 1:1)
3 페이지 검색 폼이 단순 Input + 품번/품명 LIKE 였음. 운영판 wace 는 class="select2-part" 자동완성 (initPartSelect2Ajax) + 한쪽 선택 시 다른 쪽 자동 채움. 수정 페이지 (모두 DevPartSelect 적용): - part-regist/page.tsx (M1 PART 등록 — wace partMngTempList.jsp) - part-search/page.tsx (M2 PART 조회 — wace partMngList.jsp) - ebom-regist/page.tsx (M3 E-BOM 등록 — wace structureList.jsp) 동작: - 품번/품명 양쪽 DevPartSelect (part_mng IS_LAST='1' 캐시) - 품번 선택 → 품명 자동 채움 (row.part_name) - 품명 선택 → 품번 자동 채움 (row.part_no) - setFilter 함수형 업데이트로 동시 setState 충돌 방지 ebom-search 와 동일 패턴 통일 — DevPartSelect 1개 컴포넌트로 4 페이지 공유. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import { DataGrid, DataGridColumn } from "@/components/common/DataGrid";
|
||||
import { CommCodeSelect } from "@/components/common/CommCodeSelect";
|
||||
import { devBomApi, BomReportListFilter, BomReportRow } from "@/lib/api/devBom";
|
||||
import { BomReportStatusDialog } from "@/components/development/BomReportStatusDialog";
|
||||
import { DevPartSelect } from "@/components/development/DevPartSelect";
|
||||
import { BomReportExcelImportDialog } from "@/components/development/BomReportExcelImportDialog";
|
||||
import { BomReportTreeDialog } from "@/components/development/BomReportTreeDialog";
|
||||
|
||||
@@ -135,19 +136,24 @@ export default function EbomRegistPage() {
|
||||
<option key={o.code} value={o.code}>{o.label}</option>)}
|
||||
</select>
|
||||
</Field>
|
||||
{/* wace structureList.jsp 1:1 — select2-part 자동완성 (양방향 동기) */}
|
||||
<Field label="품번">
|
||||
<Input
|
||||
value={filter.search_part_no ?? ""}
|
||||
onChange={(e) => setFilter({ ...filter, search_part_no: e.target.value })}
|
||||
placeholder="품번 LIKE"
|
||||
/>
|
||||
<DevPartSelect mode="partNo"
|
||||
value={filter.search_part_no ?? ""}
|
||||
onValueChange={(v, row) => setFilter((prev) => ({
|
||||
...prev,
|
||||
search_part_no: v,
|
||||
search_part_name: row?.part_name ?? prev.search_part_name,
|
||||
}))} />
|
||||
</Field>
|
||||
<Field label="품명">
|
||||
<Input
|
||||
value={filter.search_part_name ?? ""}
|
||||
onChange={(e) => setFilter({ ...filter, search_part_name: e.target.value })}
|
||||
placeholder="품명 LIKE"
|
||||
/>
|
||||
<DevPartSelect mode="partName"
|
||||
value={filter.search_part_name ?? ""}
|
||||
onValueChange={(v, row) => setFilter((prev) => ({
|
||||
...prev,
|
||||
search_part_name: v,
|
||||
search_part_no: row?.part_no ?? prev.search_part_no,
|
||||
}))} />
|
||||
</Field>
|
||||
</div>
|
||||
<div className="mt-3 flex items-center justify-between">
|
||||
|
||||
@@ -18,6 +18,7 @@ import { devPartApi, PartListFilter, PartRow } from "@/lib/api/devPart";
|
||||
import { PartFormDialog } from "@/components/development/PartFormDialog";
|
||||
import { PartDetailDialog } from "@/components/development/PartDetailDialog";
|
||||
import { PartExcelImportDialog } from "@/components/development/PartExcelImportDialog";
|
||||
import { DevPartSelect } from "@/components/development/DevPartSelect";
|
||||
|
||||
// wace 23셀 + 부속 (PARENT_PART_INFO/PARTNER_TITLE/Q_QTY)
|
||||
const GRID_COLUMNS: DataGridColumn[] = [
|
||||
@@ -157,21 +158,26 @@ export default function PartRegistPage() {
|
||||
{/* 검색폼 — wace partMngTempList.jsp 활성 2필드 */}
|
||||
<div className="border-b bg-card px-4 py-3">
|
||||
<div className="flex flex-wrap items-end gap-4">
|
||||
<div className="min-w-[200px]">
|
||||
{/* wace partMngTempList.jsp 1:1 — select2-part 자동완성 (양방향 동기) */}
|
||||
<div className="min-w-[220px]">
|
||||
<Label className="mb-1 block text-xs text-muted-foreground">품번</Label>
|
||||
<Input
|
||||
value={filter.search_part_no ?? ""}
|
||||
onChange={(e) => setFilter({ ...filter, search_part_no: e.target.value })}
|
||||
placeholder="품번 LIKE"
|
||||
/>
|
||||
<DevPartSelect mode="partNo"
|
||||
value={filter.search_part_no ?? ""}
|
||||
onValueChange={(v, row) => setFilter((prev) => ({
|
||||
...prev,
|
||||
search_part_no: v,
|
||||
search_part_name: row?.part_name ?? prev.search_part_name,
|
||||
}))} />
|
||||
</div>
|
||||
<div className="min-w-[200px]">
|
||||
<div className="min-w-[220px]">
|
||||
<Label className="mb-1 block text-xs text-muted-foreground">품명</Label>
|
||||
<Input
|
||||
value={filter.search_part_name ?? ""}
|
||||
onChange={(e) => setFilter({ ...filter, search_part_name: e.target.value })}
|
||||
placeholder="품명 LIKE"
|
||||
/>
|
||||
<DevPartSelect mode="partName"
|
||||
value={filter.search_part_name ?? ""}
|
||||
onValueChange={(v, row) => setFilter((prev) => ({
|
||||
...prev,
|
||||
search_part_name: v,
|
||||
search_part_no: row?.part_no ?? prev.search_part_no,
|
||||
}))} />
|
||||
</div>
|
||||
<div className="ml-auto flex items-end gap-2">
|
||||
<Button variant="outline" size="sm"
|
||||
|
||||
@@ -18,6 +18,7 @@ import { devPartApi, PartListFilter, PartRow } from "@/lib/api/devPart";
|
||||
import { PartFormDialog } from "@/components/development/PartFormDialog";
|
||||
import { PartDetailDialog } from "@/components/development/PartDetailDialog";
|
||||
import { PartExcelImportDialog } from "@/components/development/PartExcelImportDialog";
|
||||
import { DevPartSelect } from "@/components/development/DevPartSelect";
|
||||
|
||||
const GRID_COLUMNS: DataGridColumn[] = [
|
||||
{ key: "part_no", label: "품번", width: "w-[140px]", frozen: true },
|
||||
@@ -125,21 +126,26 @@ export default function PartSearchPage() {
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="border-b bg-card px-4 py-3">
|
||||
<div className="flex flex-wrap items-end gap-4">
|
||||
<div className="min-w-[200px]">
|
||||
{/* wace partMngList.jsp 1:1 — select2-part 자동완성 (양방향 동기) */}
|
||||
<div className="min-w-[220px]">
|
||||
<Label className="mb-1 block text-xs text-muted-foreground">품번</Label>
|
||||
<Input
|
||||
value={filter.search_part_no ?? ""}
|
||||
onChange={(e) => setFilter({ ...filter, search_part_no: e.target.value })}
|
||||
placeholder="품번 LIKE"
|
||||
/>
|
||||
<DevPartSelect mode="partNo"
|
||||
value={filter.search_part_no ?? ""}
|
||||
onValueChange={(v, row) => setFilter((prev) => ({
|
||||
...prev,
|
||||
search_part_no: v,
|
||||
search_part_name: row?.part_name ?? prev.search_part_name,
|
||||
}))} />
|
||||
</div>
|
||||
<div className="min-w-[200px]">
|
||||
<div className="min-w-[220px]">
|
||||
<Label className="mb-1 block text-xs text-muted-foreground">품명</Label>
|
||||
<Input
|
||||
value={filter.search_part_name ?? ""}
|
||||
onChange={(e) => setFilter({ ...filter, search_part_name: e.target.value })}
|
||||
placeholder="품명 LIKE"
|
||||
/>
|
||||
<DevPartSelect mode="partName"
|
||||
value={filter.search_part_name ?? ""}
|
||||
onValueChange={(v, row) => setFilter((prev) => ({
|
||||
...prev,
|
||||
search_part_name: v,
|
||||
search_part_no: row?.part_no ?? prev.search_part_no,
|
||||
}))} />
|
||||
</div>
|
||||
<div className="ml-auto flex items-end gap-2">
|
||||
<Button variant="outline" size="sm"
|
||||
|
||||
Reference in New Issue
Block a user