This commit is contained in:
DDD1542
2026-03-17 21:50:37 +09:00
parent cfd7ee9fce
commit b293d184bb
8 changed files with 219 additions and 141 deletions

View File

@@ -76,18 +76,34 @@ export function ColumnDetailPanel({
if (!column) return null;
const refTableOpts = referenceTableOptions.length
? referenceTableOptions
: [
{ value: "none", label: "선택 안함" },
...tables.map((t) => ({
value: t.tableName,
label:
t.displayName && t.displayName !== t.tableName
? `${t.displayName} (${t.tableName})`
: t.tableName,
})),
];
const refTableOpts = useMemo(() => {
const hasKorean = (s: string) => /[가-힣]/.test(s);
const raw = referenceTableOptions.length
? [...referenceTableOptions]
: [
{ value: "none", label: "없음" },
...tables.map((t) => ({
value: t.tableName,
label:
t.displayName && t.displayName !== t.tableName
? `${t.displayName} (${t.tableName})`
: t.tableName,
})),
];
const noneOpt = raw.find((o) => o.value === "none");
const rest = raw.filter((o) => o.value !== "none");
rest.sort((a, b) => {
const aK = hasKorean(a.label);
const bK = hasKorean(b.label);
if (aK && !bK) return -1;
if (!aK && bK) return 1;
return a.label.localeCompare(b.label, "ko");
});
return noneOpt ? [noneOpt, ...rest] : rest;
}, [referenceTableOptions, tables]);
return (
<div className="flex h-full w-full flex-col border-l bg-card">
@@ -183,23 +199,33 @@ export function ColumnDetailPanel({
<CommandList className="max-h-[200px]">
<CommandEmpty className="py-2 text-center text-xs"> .</CommandEmpty>
<CommandGroup>
{refTableOpts.map((opt) => (
<CommandItem
key={opt.value}
value={`${opt.label} ${opt.value}`}
onSelect={() => {
onColumnChange("referenceTable", opt.value === "none" ? undefined : opt.value);
if (opt.value !== "none") onLoadReferenceColumns?.(opt.value);
setEntityTableOpen(false);
}}
className="text-xs"
>
<Check
className={cn("mr-2 h-3 w-3", column.referenceTable === opt.value ? "opacity-100" : "opacity-0")}
/>
{opt.label}
</CommandItem>
))}
{refTableOpts.map((opt) => {
const hasKorean = opt.value !== "none" && opt.label !== opt.value && !opt.label.startsWith(opt.value);
return (
<CommandItem
key={opt.value}
value={`${opt.label} ${opt.value}`}
onSelect={() => {
onColumnChange("referenceTable", opt.value === "none" ? undefined : opt.value);
if (opt.value !== "none") onLoadReferenceColumns?.(opt.value);
setEntityTableOpen(false);
}}
className="text-xs"
>
<Check
className={cn("mr-2 h-3 w-3", column.referenceTable === opt.value ? "opacity-100" : "opacity-0")}
/>
{hasKorean ? (
<div className="flex flex-col">
<span className="font-medium">{opt.label.replace(` (${opt.value})`, "")}</span>
<span className="text-[10px] text-muted-foreground">{opt.value}</span>
</div>
) : (
opt.label
)}
</CommandItem>
);
})}
</CommandGroup>
</CommandList>
</Command>
@@ -263,13 +289,14 @@ export function ColumnDetailPanel({
column.referenceColumn === refCol.columnName ? "opacity-100" : "opacity-0",
)}
/>
<div className="flex flex-col">
<span className="font-medium">
{refCol.displayName && refCol.displayName !== refCol.columnName
? `${refCol.displayName} (${refCol.columnName})`
: refCol.columnName}
</span>
</div>
{refCol.displayName && refCol.displayName !== refCol.columnName ? (
<div className="flex flex-col">
<span className="font-medium">{refCol.displayName}</span>
<span className="text-[10px] text-muted-foreground">{refCol.columnName}</span>
</div>
) : (
<span>{refCol.columnName}</span>
)}
</CommandItem>
))}
</CommandGroup>

View File

@@ -568,18 +568,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
);
}
if (!user) {
return (
<div className="flex h-screen items-center justify-center">
<div className="flex flex-col items-center">
<div className="border-primary mb-4 h-8 w-8 animate-spin rounded-full border-4 border-t-transparent"></div>
<p>...</p>
</div>
</div>
);
}
const uiMenus = convertMenuToUI(currentMenus, user as ExtendedUserInfo);
const uiMenus = user ? convertMenuToUI(currentMenus, user as ExtendedUserInfo) : [];
// 활성 탭에 해당하는 메뉴가 속한 부모 메뉴 자동 확장
useEffect(() => {
@@ -603,6 +592,17 @@ function AppLayoutInner({ children }: AppLayoutProps) {
}
}, [activeTab, uiMenus, isMenuActive, expandedMenus]);
if (!user) {
return (
<div className="flex h-screen items-center justify-center">
<div className="flex flex-col items-center">
<div className="border-primary mb-4 h-8 w-8 animate-spin rounded-full border-4 border-t-transparent"></div>
<p>...</p>
</div>
</div>
);
}
return (
<div className="bg-background flex h-screen flex-col">
{/* 모바일 헤더 */}

View File

@@ -493,8 +493,8 @@ export function TabBar() {
className={cn(
"group relative flex h-7 shrink-0 cursor-pointer items-center gap-0.5 rounded-t-md border border-b-0 px-3 select-none",
isActive
? "text-foreground z-10 -mb-px h-[30px] bg-white"
: "bg-muted/50 text-muted-foreground hover:bg-muted hover:text-foreground border-transparent",
? "text-primary z-10 -mb-px h-[30px] bg-primary/15 dark:bg-primary/20 border-primary/40 border-t-[3px] border-t-primary font-semibold"
: "bg-transparent text-muted-foreground hover:bg-muted/50 hover:text-foreground border-transparent",
)}
style={{
width: TAB_WIDTH,

View File

@@ -1552,16 +1552,22 @@ export const V2SplitPanelLayoutConfigPanel: React.FC<
/>
<SwitchRow
label="수정 버튼"
checked={config.rightPanel?.showEdit ?? false}
checked={(config.rightPanel?.showEdit ?? config.rightPanel?.editButton?.enabled) ?? false}
onCheckedChange={(checked) =>
updateRightPanel({ showEdit: checked })
updateRightPanel({
showEdit: checked,
editButton: { ...config.rightPanel?.editButton!, enabled: checked },
})
}
/>
<SwitchRow
label="삭제 버튼"
checked={config.rightPanel?.showDelete ?? false}
checked={(config.rightPanel?.showDelete ?? config.rightPanel?.deleteButton?.enabled) ?? false}
onCheckedChange={(checked) =>
updateRightPanel({ showDelete: checked })
updateRightPanel({
showDelete: checked,
deleteButton: { ...config.rightPanel?.deleteButton!, enabled: checked },
})
}
/>
</div>