refactor: 코드 정리 및 불필요한 로그 제거

- scheduleService.ts에서 스케줄 생성 로직을 간소화하고, 불필요한 줄바꿈을 제거하여 가독성을 향상시켰습니다.
- v2-sales-order-modal-layout.json에서 JSON 포맷을 정리하여 일관성을 유지했습니다.
- page.tsx, ScreenModal.tsx, ScreenDesigner.tsx, V2Input.tsx, V2Select.tsx, V2SelectConfigPanel.tsx, SimpleRepeaterTableComponent.tsx, ButtonPrimaryComponent.tsx, FileUploadComponent.tsx 등 여러 파일에서 디버깅 로그를 제거하여 코드의 깔끔함을 유지했습니다.
- 전반적으로 코드의 가독성을 높이고, 불필요한 로그를 제거하여 유지보수성을 개선했습니다.
This commit is contained in:
kjs
2026-02-05 17:35:13 +09:00
parent 34202be843
commit 73d05b991c
21 changed files with 1023 additions and 1478 deletions

View File

@@ -90,7 +90,7 @@ export function SimpleRepeaterTableComponent({
const newRowDefaults = componentConfig?.newRowDefaults || {};
const summaryConfig = componentConfig?.summaryConfig;
const maxHeight = componentConfig?.maxHeight || propMaxHeight || "240px";
// 🆕 컴포넌트 레벨의 저장 테이블 설정
const componentTargetTable = componentConfig?.targetTable || componentConfig?.saveTable;
const componentFkColumn = componentConfig?.fkColumn;
@@ -149,14 +149,11 @@ export function SimpleRepeaterTableComponent({
}
// API 호출
const response = await apiClient.post(
`/table-management/tables/${initialConfig.sourceTable}/data`,
{
search: filters,
page: 1,
size: 1000, // 대량 조회
}
);
const response = await apiClient.post(`/table-management/tables/${initialConfig.sourceTable}/data`, {
search: filters,
page: 1,
size: 1000, // 대량 조회
});
if (response.data.success && response.data.data?.data) {
const loadedData = response.data.data.data;
@@ -182,7 +179,7 @@ export function SimpleRepeaterTableComponent({
// 2. 조인 데이터 처리
const joinColumns = columns.filter(
(col) => col.sourceConfig?.type === "join" && col.sourceConfig.joinTable && col.sourceConfig.joinKey
(col) => col.sourceConfig?.type === "join" && col.sourceConfig.joinTable && col.sourceConfig.joinKey,
);
if (joinColumns.length > 0) {
@@ -208,25 +205,20 @@ export function SimpleRepeaterTableComponent({
const [tableName] = groupKey.split(":");
// 조인 키 값 수집 (중복 제거)
const keyValues = Array.from(new Set(
baseMappedData
.map((row: any) => row[key])
.filter((v: any) => v !== undefined && v !== null)
));
const keyValues = Array.from(
new Set(baseMappedData.map((row: any) => row[key]).filter((v: any) => v !== undefined && v !== null)),
);
if (keyValues.length === 0) return;
try {
// 조인 테이블 조회
// refKey(타겟 테이블 컬럼)로 검색
const response = await apiClient.post(
`/table-management/tables/${tableName}/data`,
{
search: { [refKey]: keyValues }, // { id: [1, 2, 3] }
page: 1,
size: 1000,
}
);
const response = await apiClient.post(`/table-management/tables/${tableName}/data`, {
search: { [refKey]: keyValues }, // { id: [1, 2, 3] }
page: 1,
size: 1000,
});
if (response.data.success && response.data.data?.data) {
const joinedRows = response.data.data.data;
@@ -251,7 +243,7 @@ export function SimpleRepeaterTableComponent({
console.error(`조인 실패 (${tableName}):`, error);
// 실패 시 무시하고 진행 (값은 undefined)
}
})
}),
);
}
@@ -296,7 +288,7 @@ export function SimpleRepeaterTableComponent({
// 🆕 컴포넌트 레벨의 targetTable이 설정되어 있으면 우선 사용
if (componentTargetTable) {
console.log("✅ [SimpleRepeaterTable] 컴포넌트 레벨 저장 테이블 사용:", componentTargetTable);
// 모든 행을 해당 테이블에 저장
const dataToSave = value.map((row: any) => {
// 메타데이터 필드 제외 (_, _rowIndex 등)
@@ -399,9 +391,12 @@ export function SimpleRepeaterTableComponent({
// 기존 onFormDataChange도 호출 (호환성)
if (onFormDataChange && columnName) {
// 테이블별 데이터를 통합하여 전달
onFormDataChange(columnName, Object.entries(dataByTable).flatMap(([table, rows]) =>
rows.map((row: any) => ({ ...row, _targetTable: table }))
));
onFormDataChange(
columnName,
Object.entries(dataByTable).flatMap(([table, rows]) =>
rows.map((row: any) => ({ ...row, _targetTable: table })),
),
);
}
};
@@ -543,24 +538,14 @@ export function SimpleRepeaterTableComponent({
if (!allowAdd || readOnly || value.length >= maxRows) return null;
return (
<Button
type="button"
variant="outline"
size="sm"
onClick={handleAddRow}
className="h-8 text-xs"
>
<Plus className="h-3.5 w-3.5 mr-1" />
<Button type="button" variant="outline" size="sm" onClick={handleAddRow} className="h-8 text-xs">
<Plus className="mr-1 h-3.5 w-3.5" />
{addButtonText}
</Button>
);
};
const renderCell = (
row: any,
column: SimpleRepeaterColumnConfig,
rowIndex: number
) => {
const renderCell = (row: any, column: SimpleRepeaterColumnConfig, rowIndex: number) => {
const cellValue = row[column.field];
// 계산 필드는 편집 불가
@@ -583,9 +568,7 @@ export function SimpleRepeaterTableComponent({
<Input
type="number"
value={cellValue || ""}
onChange={(e) =>
handleCellEdit(rowIndex, column.field, parseFloat(e.target.value) || 0)
}
onChange={(e) => handleCellEdit(rowIndex, column.field, parseFloat(e.target.value) || 0)}
className="h-7 text-xs"
/>
);
@@ -604,19 +587,19 @@ export function SimpleRepeaterTableComponent({
return (
<Select
value={cellValue || ""}
onValueChange={(newValue) =>
handleCellEdit(rowIndex, column.field, newValue)
}
onValueChange={(newValue) => handleCellEdit(rowIndex, column.field, newValue)}
>
<SelectTrigger className="h-7 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
{column.selectOptions?.filter((option) => option.value && option.value !== "").map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
{column.selectOptions
?.filter((option) => option.value && option.value !== "")
.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
);
@@ -636,11 +619,11 @@ export function SimpleRepeaterTableComponent({
// 로딩 중일 때
if (isLoading) {
return (
<div className={cn("border rounded-md overflow-hidden bg-background", className)}>
<div className={cn("bg-background overflow-hidden rounded-md border", className)}>
<div className="flex items-center justify-center py-12" style={{ minHeight: maxHeight }}>
<div className="text-center">
<Loader2 className="h-8 w-8 animate-spin text-primary mx-auto mb-2" />
<p className="text-sm text-muted-foreground"> ...</p>
<Loader2 className="text-primary mx-auto mb-2 h-8 w-8 animate-spin" />
<p className="text-muted-foreground text-sm"> ...</p>
</div>
</div>
</div>
@@ -650,14 +633,14 @@ export function SimpleRepeaterTableComponent({
// 에러 발생 시
if (loadError) {
return (
<div className={cn("border rounded-md overflow-hidden bg-background", className)}>
<div className={cn("bg-background overflow-hidden rounded-md border", className)}>
<div className="flex items-center justify-center py-12" style={{ minHeight: maxHeight }}>
<div className="text-center">
<div className="w-12 h-12 rounded-full bg-destructive/10 flex items-center justify-center mx-auto mb-2">
<X className="h-6 w-6 text-destructive" />
<div className="bg-destructive/10 mx-auto mb-2 flex h-12 w-12 items-center justify-center rounded-full">
<X className="text-destructive h-6 w-6" />
</div>
<p className="text-sm font-medium text-destructive mb-1"> </p>
<p className="text-xs text-muted-foreground">{loadError}</p>
<p className="text-destructive mb-1 text-sm font-medium"> </p>
<p className="text-muted-foreground text-xs">{loadError}</p>
</div>
</div>
</div>
@@ -668,30 +651,27 @@ export function SimpleRepeaterTableComponent({
const totalColumns = columns.length + (showRowNumber ? 1 : 0) + (allowDelete && !readOnly ? 1 : 0);
return (
<div className={cn("border rounded-md overflow-hidden bg-background", className)}>
<div className={cn("bg-background overflow-hidden rounded-md border", className)}>
{/* 상단 행 추가 버튼 */}
{allowAdd && addButtonPosition !== "bottom" && (
<div className="p-2 border-b bg-muted/50">
<div className="bg-muted/50 border-b p-2">
<AddRowButton />
</div>
)}
<div
className="overflow-x-auto overflow-y-auto"
style={{ maxHeight }}
>
<div className="overflow-x-auto overflow-y-auto" style={{ maxHeight }}>
<table className="w-full text-xs sm:text-sm">
<thead className="bg-muted sticky top-0 z-10">
<tr>
{showRowNumber && (
<th key="header-rownum" className="px-4 py-2 text-left font-medium text-muted-foreground w-12">
<th key="header-rownum" className="text-muted-foreground w-12 px-4 py-2 text-left font-medium">
#
</th>
)}
{columns.map((col) => (
<th
key={`header-${col.field}`}
className="px-4 py-2 text-left font-medium text-muted-foreground"
className="text-muted-foreground px-4 py-2 text-left font-medium"
style={{ width: col.width }}
>
{col.label}
@@ -699,7 +679,7 @@ export function SimpleRepeaterTableComponent({
</th>
))}
{!readOnly && allowDelete && (
<th key="header-delete" className="px-4 py-2 text-left font-medium text-muted-foreground w-20">
<th key="header-delete" className="text-muted-foreground w-20 px-4 py-2 text-left font-medium">
</th>
)}
@@ -708,11 +688,7 @@ export function SimpleRepeaterTableComponent({
<tbody className="bg-background">
{value.length === 0 ? (
<tr key="empty-row">
<td
key="empty-cell"
colSpan={totalColumns}
className="px-4 py-8 text-center text-muted-foreground"
>
<td key="empty-cell" colSpan={totalColumns} className="text-muted-foreground px-4 py-8 text-center">
{allowAdd ? (
<div className="flex flex-col items-center gap-2">
<span> </span>
@@ -725,9 +701,9 @@ export function SimpleRepeaterTableComponent({
</tr>
) : (
value.map((row, rowIndex) => (
<tr key={`row-${rowIndex}`} className="border-t hover:bg-accent/50">
<tr key={`row-${rowIndex}`} className="hover:bg-accent/50 border-t">
{showRowNumber && (
<td key={`rownum-${rowIndex}`} className="px-4 py-2 text-center text-muted-foreground">
<td key={`rownum-${rowIndex}`} className="text-muted-foreground px-4 py-2 text-center">
{rowIndex + 1}
</td>
)}
@@ -743,7 +719,7 @@ export function SimpleRepeaterTableComponent({
size="sm"
onClick={() => handleRowDelete(rowIndex)}
disabled={value.length <= minRows}
className="h-7 w-7 p-0 text-destructive hover:text-destructive disabled:opacity-50"
className="text-destructive hover:text-destructive h-7 w-7 p-0 disabled:opacity-50"
>
<Trash2 className="h-4 w-4" />
</Button>
@@ -758,35 +734,29 @@ export function SimpleRepeaterTableComponent({
{/* 합계 표시 */}
{summaryConfig?.enabled && summaryValues && (
<div className={cn(
"border-t bg-muted/30 p-3",
summaryConfig.position === "bottom-right" && "flex justify-end"
)}>
<div className={cn(
summaryConfig.position === "bottom-right" ? "w-auto min-w-[200px]" : "w-full"
)}>
<div
className={cn("bg-muted/30 border-t p-3", summaryConfig.position === "bottom-right" && "flex justify-end")}
>
<div className={cn(summaryConfig.position === "bottom-right" ? "w-auto min-w-[200px]" : "w-full")}>
{summaryConfig.title && (
<div className="text-xs font-medium text-muted-foreground mb-2">
{summaryConfig.title}
</div>
<div className="text-muted-foreground mb-2 text-xs font-medium">{summaryConfig.title}</div>
)}
<div className={cn(
"grid gap-2",
summaryConfig.position === "bottom-right" ? "grid-cols-1" : "grid-cols-2 sm:grid-cols-3 lg:grid-cols-4"
)}>
<div
className={cn(
"grid gap-2",
summaryConfig.position === "bottom-right" ? "grid-cols-1" : "grid-cols-2 sm:grid-cols-3 lg:grid-cols-4",
)}
>
{summaryConfig.fields.map((field) => (
<div
key={field.field}
className={cn(
"flex justify-between items-center px-3 py-1.5 rounded",
field.highlight ? "bg-primary/10 font-semibold" : "bg-background"
"flex items-center justify-between rounded px-3 py-1.5",
field.highlight ? "bg-primary/10 font-semibold" : "bg-background",
)}
>
<span className="text-xs text-muted-foreground">{field.label}</span>
<span className={cn(
"text-sm font-medium",
field.highlight && "text-primary"
)}>
<span className="text-muted-foreground text-xs">{field.label}</span>
<span className={cn("text-sm font-medium", field.highlight && "text-primary")}>
{formatSummaryValue(field, summaryValues[field.field] || 0)}
</span>
</div>
@@ -798,10 +768,10 @@ export function SimpleRepeaterTableComponent({
{/* 하단 행 추가 버튼 */}
{allowAdd && addButtonPosition !== "top" && value.length > 0 && (
<div className="p-2 border-t bg-muted/50 flex justify-between items-center">
<div className="bg-muted/50 flex items-center justify-between border-t p-2">
<AddRowButton />
{maxRows !== Infinity && (
<span className="text-xs text-muted-foreground">
<span className="text-muted-foreground text-xs">
{value.length} / {maxRows}
</span>
)}
@@ -810,4 +780,3 @@ export function SimpleRepeaterTableComponent({
</div>
);
}