feat: add item list mode configuration and screen code handling
- Introduced `itemListMode` to the process work standard configuration, allowing users to select between displaying all items or only registered items. - Added `screenCode` to automatically set the screen ID when in registered mode. - Updated the `ProcessWorkStandardComponent` to handle the new configuration and adjust item fetching logic accordingly. - Enhanced the `ProcessWorkStandardConfigPanel` to include a select input for item list mode, improving user experience and configurability. These changes aim to enhance the flexibility and usability of the process work standard component. Made-with: Cursor
This commit is contained in:
parent
bd08b341f0
commit
429f1ba6ee
|
|
@ -17,25 +17,37 @@ interface ProcessWorkStandardComponentProps {
|
|||
formData?: Record<string, any>;
|
||||
isPreview?: boolean;
|
||||
tableName?: string;
|
||||
screenId?: number | string;
|
||||
}
|
||||
|
||||
export function ProcessWorkStandardComponent({
|
||||
config: configProp,
|
||||
isPreview,
|
||||
screenId,
|
||||
}: ProcessWorkStandardComponentProps) {
|
||||
const resolvedConfig = useMemo(() => {
|
||||
const merged = {
|
||||
...configProp,
|
||||
};
|
||||
if (merged.itemListMode === "registered" && !merged.screenCode && screenId) {
|
||||
merged.screenCode = `screen_${screenId}`;
|
||||
}
|
||||
return merged;
|
||||
}, [configProp, screenId]);
|
||||
|
||||
const config: ProcessWorkStandardConfig = useMemo(
|
||||
() => ({
|
||||
...defaultConfig,
|
||||
...configProp,
|
||||
dataSource: { ...defaultConfig.dataSource, ...configProp?.dataSource },
|
||||
phases: configProp?.phases?.length
|
||||
? configProp.phases
|
||||
...resolvedConfig,
|
||||
dataSource: { ...defaultConfig.dataSource, ...resolvedConfig?.dataSource },
|
||||
phases: resolvedConfig?.phases?.length
|
||||
? resolvedConfig.phases
|
||||
: defaultConfig.phases,
|
||||
detailTypes: configProp?.detailTypes?.length
|
||||
? configProp.detailTypes
|
||||
detailTypes: resolvedConfig?.detailTypes?.length
|
||||
? resolvedConfig.detailTypes
|
||||
: defaultConfig.detailTypes,
|
||||
}),
|
||||
[configProp]
|
||||
[resolvedConfig]
|
||||
);
|
||||
|
||||
const {
|
||||
|
|
@ -46,7 +58,8 @@ export function ProcessWorkStandardComponent({
|
|||
selectedDetailsByPhase,
|
||||
selection,
|
||||
loading,
|
||||
fetchItems,
|
||||
isRegisteredMode,
|
||||
loadItems,
|
||||
selectItem,
|
||||
selectProcess,
|
||||
fetchWorkItemDetails,
|
||||
|
|
@ -112,8 +125,8 @@ export function ProcessWorkStandardComponent({
|
|||
);
|
||||
|
||||
const handleInit = useCallback(() => {
|
||||
fetchItems();
|
||||
}, [fetchItems]);
|
||||
loadItems();
|
||||
}, [loadItems]);
|
||||
|
||||
const splitRatio = config.splitRatio || 30;
|
||||
|
||||
|
|
@ -144,7 +157,7 @@ export function ProcessWorkStandardComponent({
|
|||
items={items}
|
||||
routings={routings}
|
||||
selection={selection}
|
||||
onSearch={(keyword) => fetchItems(keyword)}
|
||||
onSearch={(keyword) => loadItems(keyword)}
|
||||
onSelectItem={selectItem}
|
||||
onSelectProcess={selectProcess}
|
||||
onInit={handleInit}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
|
|||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { ProcessWorkStandardConfig, WorkPhaseDefinition, DetailTypeDefinition } from "./types";
|
||||
import { defaultConfig } from "./config";
|
||||
|
||||
|
|
@ -81,6 +82,30 @@ export function ProcessWorkStandardConfigPanel({
|
|||
<div className="space-y-5 p-4">
|
||||
<h3 className="text-sm font-semibold">공정 작업기준 설정</h3>
|
||||
|
||||
{/* 품목 목록 모드 */}
|
||||
<section className="space-y-3">
|
||||
<p className="text-xs font-medium text-muted-foreground">품목 목록 모드</p>
|
||||
<div>
|
||||
<Select
|
||||
value={config.itemListMode || "all"}
|
||||
onValueChange={(v) => update({ itemListMode: v as "all" | "registered" })}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">전체 품목</SelectItem>
|
||||
<SelectItem value="registered">등록 품목만</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="mt-1 text-[10px] text-muted-foreground">
|
||||
{config.itemListMode === "registered"
|
||||
? "품목별 라우팅 탭에서 등록한 품목만 표시됩니다. screenCode는 화면 ID 기준으로 자동 설정됩니다."
|
||||
: "모든 품목을 표시합니다."}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 데이터 소스 설정 */}
|
||||
<section className="space-y-3">
|
||||
<p className="text-xs font-medium text-muted-foreground">데이터 소스 설정</p>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export class ProcessWorkStandardRenderer extends AutoRegisteringComponentRendere
|
|||
static componentDefinition = V2ProcessWorkStandardDefinition;
|
||||
|
||||
render(): React.ReactElement {
|
||||
const { formData, isPreview, config, tableName } = this.props as Record<
|
||||
const { formData, isPreview, config, tableName, screenId } = this.props as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
|
|
@ -20,6 +20,7 @@ export class ProcessWorkStandardRenderer extends AutoRegisteringComponentRendere
|
|||
formData={formData as Record<string, unknown>}
|
||||
tableName={tableName as string}
|
||||
isPreview={isPreview as boolean}
|
||||
screenId={screenId as number | string}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,4 +31,6 @@ export const defaultConfig: ProcessWorkStandardConfig = {
|
|||
splitRatio: 30,
|
||||
leftPanelTitle: "품목 및 공정 선택",
|
||||
readonly: false,
|
||||
itemListMode: "all",
|
||||
screenCode: "",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ export function useProcessWorkStandard(config: ProcessWorkStandardConfig) {
|
|||
processName: null,
|
||||
});
|
||||
|
||||
// 품목 목록 조회
|
||||
const isRegisteredMode = config.itemListMode === "registered";
|
||||
|
||||
// 품목 목록 조회 (전체 모드)
|
||||
const fetchItems = useCallback(
|
||||
async (search?: string) => {
|
||||
try {
|
||||
|
|
@ -59,6 +61,53 @@ export function useProcessWorkStandard(config: ProcessWorkStandardConfig) {
|
|||
[config.dataSource]
|
||||
);
|
||||
|
||||
// 등록 품목 조회 (등록 모드)
|
||||
const fetchRegisteredItems = useCallback(
|
||||
async (search?: string) => {
|
||||
const screenCode = config.screenCode;
|
||||
if (!screenCode) {
|
||||
console.warn("screenCode가 설정되지 않았습니다");
|
||||
setItems([]);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setLoading(true);
|
||||
const ds = config.dataSource;
|
||||
const params = new URLSearchParams({
|
||||
tableName: ds.itemTable,
|
||||
nameColumn: ds.itemNameColumn,
|
||||
codeColumn: ds.itemCodeColumn,
|
||||
routingTable: ds.routingVersionTable,
|
||||
routingFkColumn: ds.routingFkColumn,
|
||||
...(search ? { search } : {}),
|
||||
});
|
||||
const res = await apiClient.get(
|
||||
`${API_BASE}/registered-items/${encodeURIComponent(screenCode)}?${params}`
|
||||
);
|
||||
if (res.data?.success) {
|
||||
setItems(res.data.data || []);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("등록 품목 조회 실패", err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[config.dataSource, config.screenCode]
|
||||
);
|
||||
|
||||
// 모드에 따라 적절한 함수 호출
|
||||
const loadItems = useCallback(
|
||||
async (search?: string) => {
|
||||
if (isRegisteredMode) {
|
||||
await fetchRegisteredItems(search);
|
||||
} else {
|
||||
await fetchItems(search);
|
||||
}
|
||||
},
|
||||
[isRegisteredMode, fetchItems, fetchRegisteredItems]
|
||||
);
|
||||
|
||||
// 라우팅 + 공정 조회
|
||||
const fetchRoutings = useCallback(
|
||||
async (itemCode: string) => {
|
||||
|
|
@ -340,7 +389,10 @@ export function useProcessWorkStandard(config: ProcessWorkStandardConfig) {
|
|||
selection,
|
||||
loading,
|
||||
saving,
|
||||
isRegisteredMode,
|
||||
fetchItems,
|
||||
fetchRegisteredItems,
|
||||
loadItems,
|
||||
selectItem,
|
||||
selectProcess,
|
||||
fetchWorkItems,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ export interface ProcessWorkStandardConfig {
|
|||
splitRatio?: number;
|
||||
leftPanelTitle?: string;
|
||||
readonly?: boolean;
|
||||
/** 품목 목록 모드: all=전체, registered=등록된 품목만 */
|
||||
itemListMode?: "all" | "registered";
|
||||
/** 등록 모드 시 화면 코드 (자동 설정됨) */
|
||||
screenCode?: string;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
|
|
@ -121,6 +125,7 @@ export interface ProcessWorkStandardComponentProps {
|
|||
formData?: Record<string, any>;
|
||||
isPreview?: boolean;
|
||||
tableName?: string;
|
||||
screenId?: number | string;
|
||||
}
|
||||
|
||||
// 선택 상태
|
||||
|
|
|
|||
Loading…
Reference in New Issue