ERP-node/frontend/lib/registry/components/screen-split-panel/ScreenSplitPanelConfigPanel...

352 lines
15 KiB
TypeScript

"use client";
import React, { useState, useEffect } from "react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { Settings, Layout, ArrowRight, Database, Loader2, Check, ChevronsUpDown } from "lucide-react";
import { screenApi } from "@/lib/api/screen";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { cn } from "@/lib/utils";
interface ScreenSplitPanelConfigPanelProps {
config: any;
onChange: (newConfig: any) => void;
}
export function ScreenSplitPanelConfigPanel({ config = {}, onChange }: ScreenSplitPanelConfigPanelProps) {
// 화면 목록 상태
const [screens, setScreens] = useState<any[]>([]);
const [isLoadingScreens, setIsLoadingScreens] = useState(true);
// Combobox 상태
const [leftOpen, setLeftOpen] = useState(false);
const [rightOpen, setRightOpen] = useState(false);
const [localConfig, setLocalConfig] = useState({
screenId: config.screenId || 0,
leftScreenId: config.leftScreenId || 0,
rightScreenId: config.rightScreenId || 0,
splitRatio: config.splitRatio || 50,
resizable: config.resizable ?? true,
buttonLabel: config.buttonLabel || "데이터 전달",
buttonPosition: config.buttonPosition || "center",
...config,
});
// config prop이 변경되면 localConfig 동기화
useEffect(() => {
console.log("🔄 [ScreenSplitPanelConfigPanel] config prop 변경 감지:", config);
setLocalConfig({
screenId: config.screenId || 0,
leftScreenId: config.leftScreenId || 0,
rightScreenId: config.rightScreenId || 0,
splitRatio: config.splitRatio || 50,
resizable: config.resizable ?? true,
buttonLabel: config.buttonLabel || "데이터 전달",
buttonPosition: config.buttonPosition || "center",
...config,
});
}, [config]);
// 화면 목록 로드
useEffect(() => {
const loadScreens = async () => {
try {
setIsLoadingScreens(true);
const response = await screenApi.getScreens({ page: 1, size: 1000 });
if (response.data) {
setScreens(response.data);
}
} catch (error) {
console.error("화면 목록 로드 실패:", error);
} finally {
setIsLoadingScreens(false);
}
};
loadScreens();
}, []);
const updateConfig = (key: string, value: any) => {
const newConfig = {
...localConfig,
[key]: value,
};
setLocalConfig(newConfig);
console.log("📝 [ScreenSplitPanelConfigPanel] 설정 변경:", {
key,
value,
newConfig,
hasOnChange: !!onChange,
});
// 변경 즉시 부모에게 전달
if (onChange) {
onChange(newConfig);
}
};
return (
<div className="space-y-4">
<Tabs defaultValue="layout" className="w-full">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="layout" className="gap-2">
<Layout className="h-4 w-4" />
</TabsTrigger>
<TabsTrigger value="screens" className="gap-2">
<Database className="h-4 w-4" />
</TabsTrigger>
</TabsList>
{/* 레이아웃 탭 */}
<TabsContent value="layout" className="space-y-4">
<Card>
<CardHeader>
<CardTitle className="text-base"> </CardTitle>
<CardDescription className="text-xs"> </CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<div className="flex items-center justify-between">
<Label htmlFor="splitRatio" className="text-xs">
(%)
</Label>
<span className="text-xs font-medium">{localConfig.splitRatio}%</span>
</div>
<Input
id="splitRatio"
type="range"
min="20"
max="80"
step="5"
value={localConfig.splitRatio}
onChange={(e) => updateConfig("splitRatio", parseInt(e.target.value))}
className="h-2"
/>
<div className="text-muted-foreground flex justify-between text-xs">
<span>20%</span>
<span>50%</span>
<span>80%</span>
</div>
</div>
<Separator />
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<Label htmlFor="resizable" className="text-xs font-medium">
</Label>
<p className="text-muted-foreground text-xs"> </p>
</div>
<Checkbox
id="resizable"
checked={localConfig.resizable}
onCheckedChange={(checked) => updateConfig("resizable", checked)}
/>
</div>
</CardContent>
</Card>
</TabsContent>
{/* 화면 설정 탭 */}
<TabsContent value="screens" className="space-y-4">
<Card>
<CardHeader>
<CardTitle className="text-base"> </CardTitle>
<CardDescription className="text-xs"> </CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{isLoadingScreens ? (
<div className="flex items-center justify-center py-8">
<Loader2 className="text-muted-foreground h-6 w-6 animate-spin" />
<span className="text-muted-foreground ml-2 text-xs"> ...</span>
</div>
) : (
<>
<div className="space-y-2">
<Label htmlFor="leftScreenId" className="text-xs">
()
</Label>
<Popover open={leftOpen} onOpenChange={setLeftOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={leftOpen}
className="h-9 w-full justify-between text-xs"
>
{localConfig.leftScreenId
? screens.find((s) => s.screenId === localConfig.leftScreenId)?.screenName || "화면 선택..."
: "화면 선택..."}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent
className="p-0"
style={{ width: "var(--radix-popover-trigger-width)" }}
align="start"
>
<Command>
<CommandInput placeholder="화면 검색..." className="text-xs" />
<CommandList>
<CommandEmpty className="text-xs"> .</CommandEmpty>
<CommandGroup>
{screens.map((screen) => (
<CommandItem
key={screen.screenId}
value={`${screen.screenName} ${screen.screenCode}`}
onSelect={() => {
updateConfig("leftScreenId", screen.screenId);
setLeftOpen(false);
}}
className="text-xs"
>
<Check
className={cn(
"mr-2 h-4 w-4",
localConfig.leftScreenId === screen.screenId ? "opacity-100" : "opacity-0",
)}
/>
<div className="flex flex-col">
<span className="font-medium">{screen.screenName}</span>
<span className="text-[10px] text-gray-500">{screen.screenCode}</span>
</div>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<p className="text-muted-foreground text-xs"> </p>
</div>
<Separator />
<div className="space-y-2">
<Label htmlFor="rightScreenId" className="text-xs">
()
</Label>
<Popover open={rightOpen} onOpenChange={setRightOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={rightOpen}
className="h-9 w-full justify-between text-xs"
>
{localConfig.rightScreenId
? screens.find((s) => s.screenId === localConfig.rightScreenId)?.screenName ||
"화면 선택..."
: "화면 선택..."}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent
className="p-0"
style={{ width: "var(--radix-popover-trigger-width)" }}
align="start"
>
<Command>
<CommandInput placeholder="화면 검색..." className="text-xs" />
<CommandList>
<CommandEmpty className="text-xs"> .</CommandEmpty>
<CommandGroup>
{screens.map((screen) => (
<CommandItem
key={screen.screenId}
value={`${screen.screenName} ${screen.screenCode}`}
onSelect={() => {
updateConfig("rightScreenId", screen.screenId);
setRightOpen(false);
}}
className="text-xs"
>
<Check
className={cn(
"mr-2 h-4 w-4",
localConfig.rightScreenId === screen.screenId ? "opacity-100" : "opacity-0",
)}
/>
<div className="flex flex-col">
<span className="font-medium">{screen.screenName}</span>
<span className="text-[10px] text-gray-500">{screen.screenCode}</span>
</div>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<p className="text-muted-foreground text-xs"> </p>
</div>
<div className="rounded-lg border border-amber-200 bg-amber-50 p-3 dark:border-amber-900 dark:bg-amber-950">
<p className="text-xs text-amber-800 dark:text-amber-200">
💡 <strong> :</strong> ,
"transferData" .
<br />
(), , .
</p>
</div>
</>
)}
</CardContent>
</Card>
</TabsContent>
</Tabs>
{/* 설정 요약 */}
<Card>
<CardHeader>
<CardTitle className="text-sm"> </CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-1 text-xs">
<div className="flex justify-between">
<span className="text-muted-foreground"> :</span>
<span className="font-medium">
{localConfig.leftScreenId
? screens.find((s) => s.screenId === localConfig.leftScreenId)?.screenName ||
`ID: ${localConfig.leftScreenId}`
: "미설정"}
</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"> :</span>
<span className="font-medium">
{localConfig.rightScreenId
? screens.find((s) => s.screenId === localConfig.rightScreenId)?.screenName ||
`ID: ${localConfig.rightScreenId}`
: "미설정"}
</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"> :</span>
<span className="font-medium">
{localConfig.splitRatio}% / {100 - localConfig.splitRatio}%
</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"> :</span>
<span className="font-medium">{localConfig.resizable ? "가능" : "불가능"}</span>
</div>
</div>
</CardContent>
</Card>
</div>
);
}