refactor: 설정 패널 UI 개선 - Collapsible로 정리
- 필드 그룹을 Collapsible로 변경하여 펼침/접힘 가능 - 항목 표시 설정도 Collapsible로 분리하여 깔끔하게 정리 - 그룹 제목에 displayItems 개수 표시 - 기본적으로 그룹은 펼쳐진 상태, 표시 설정은 접힌 상태 - ChevronDown/ChevronRight 아이콘으로 펼침 상태 표시 - 복잡한 설정을 단계적으로 볼 수 있어 가독성 대폭 향상
This commit is contained in:
parent
eef1451c5a
commit
def94c41f4
|
|
@ -7,7 +7,8 @@ import { Button } from "@/components/ui/button";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Plus, X } from "lucide-react";
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||||
|
import { Plus, X, ChevronDown, ChevronRight } from "lucide-react";
|
||||||
import { SelectedItemsDetailInputConfig, AdditionalFieldDefinition, FieldGroup, DisplayItem, DisplayItemType, EmptyBehavior, DisplayFieldFormat } from "./types";
|
import { SelectedItemsDetailInputConfig, AdditionalFieldDefinition, FieldGroup, DisplayItem, DisplayItemType, EmptyBehavior, DisplayFieldFormat } from "./types";
|
||||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@/components/ui/command";
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@/components/ui/command";
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||||
|
|
@ -46,6 +47,12 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
||||||
// 🆕 필드 그룹 상태
|
// 🆕 필드 그룹 상태
|
||||||
const [localFieldGroups, setLocalFieldGroups] = useState<FieldGroup[]>(config.fieldGroups || []);
|
const [localFieldGroups, setLocalFieldGroups] = useState<FieldGroup[]>(config.fieldGroups || []);
|
||||||
|
|
||||||
|
// 🆕 그룹별 펼침/접힘 상태
|
||||||
|
const [expandedGroups, setExpandedGroups] = useState<Record<string, boolean>>({});
|
||||||
|
|
||||||
|
// 🆕 그룹별 표시 항목 설정 펼침/접힘 상태
|
||||||
|
const [expandedDisplayItems, setExpandedDisplayItems] = useState<Record<string, boolean>>({});
|
||||||
|
|
||||||
// 🆕 원본 테이블 선택 상태
|
// 🆕 원본 테이블 선택 상태
|
||||||
const [sourceTableSelectOpen, setSourceTableSelectOpen] = useState(false);
|
const [sourceTableSelectOpen, setSourceTableSelectOpen] = useState(false);
|
||||||
const [sourceTableSearchValue, setSourceTableSearchValue] = useState("");
|
const [sourceTableSearchValue, setSourceTableSearchValue] = useState("");
|
||||||
|
|
@ -621,20 +628,40 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{localFieldGroups.map((group, index) => (
|
{localFieldGroups.map((group, index) => (
|
||||||
<Card key={group.id} className="border-2">
|
<Collapsible
|
||||||
<CardContent className="space-y-2 pt-3 sm:space-y-3 sm:pt-4">
|
key={group.id}
|
||||||
<div className="flex items-center justify-between">
|
open={expandedGroups[group.id] ?? true}
|
||||||
<span className="text-xs font-semibold text-gray-700 sm:text-sm">그룹 {index + 1}</span>
|
onOpenChange={(open) => setExpandedGroups(prev => ({ ...prev, [group.id]: open }))}
|
||||||
<Button
|
>
|
||||||
type="button"
|
<Card className="border-2">
|
||||||
variant="ghost"
|
<CardContent className="space-y-2 p-3 sm:space-y-3 sm:p-4">
|
||||||
size="icon"
|
<div className="flex items-center justify-between">
|
||||||
onClick={() => removeFieldGroup(group.id)}
|
<CollapsibleTrigger asChild>
|
||||||
className="h-6 w-6 text-red-500 hover:text-red-700 sm:h-7 sm:w-7"
|
<Button variant="ghost" size="sm" className="h-auto p-0 hover:bg-transparent">
|
||||||
>
|
<div className="flex items-center gap-2">
|
||||||
<X className="h-3 w-3 sm:h-4 sm:w-4" />
|
{expandedGroups[group.id] ?? true ? (
|
||||||
</Button>
|
<ChevronDown className="h-4 w-4" />
|
||||||
</div>
|
) : (
|
||||||
|
<ChevronRight className="h-4 w-4" />
|
||||||
|
)}
|
||||||
|
<span className="text-xs font-semibold sm:text-sm">
|
||||||
|
그룹 {index + 1}: {group.title || group.id}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => removeFieldGroup(group.id)}
|
||||||
|
className="h-6 w-6 text-red-500 hover:text-red-700 sm:h-7 sm:w-7"
|
||||||
|
>
|
||||||
|
<X className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CollapsibleContent className="space-y-2 sm:space-y-3">{/* 기존 그룹 설정 내용 */}
|
||||||
|
|
||||||
{/* 그룹 ID */}
|
{/* 그룹 ID */}
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
|
|
@ -682,10 +709,27 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 🆕 이 그룹의 항목 표시 설정 */}
|
{/* 🆕 이 그룹의 항목 표시 설정 */}
|
||||||
<div className="space-y-2 rounded-lg border-2 border-dashed border-primary/30 bg-primary/5 p-2">
|
<Collapsible
|
||||||
<div className="flex items-center justify-between">
|
open={expandedDisplayItems[group.id] ?? false}
|
||||||
<Label className="text-[10px] font-semibold sm:text-xs">항목 표시 설정</Label>
|
onOpenChange={(open) => setExpandedDisplayItems(prev => ({ ...prev, [group.id]: open }))}
|
||||||
<div className="flex gap-1">
|
>
|
||||||
|
<div className="space-y-2 rounded-lg border-2 border-dashed border-primary/30 bg-primary/5 p-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<CollapsibleTrigger asChild>
|
||||||
|
<Button variant="ghost" size="sm" className="h-auto p-0 hover:bg-transparent">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
{expandedDisplayItems[group.id] ? (
|
||||||
|
<ChevronDown className="h-3 w-3" />
|
||||||
|
) : (
|
||||||
|
<ChevronRight className="h-3 w-3" />
|
||||||
|
)}
|
||||||
|
<Label className="text-[10px] font-semibold sm:text-xs cursor-pointer">
|
||||||
|
항목 표시 설정 ({(group.displayItems || []).length}개)
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<div className="flex gap-1">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -719,11 +763,12 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-[9px] text-muted-foreground sm:text-[10px]">
|
<CollapsibleContent className="space-y-2">
|
||||||
이 그룹의 입력 항목이 추가되면 어떻게 표시될지 설정
|
<p className="text-[9px] text-muted-foreground sm:text-[10px]">
|
||||||
</p>
|
이 그룹의 입력 항목이 추가되면 어떻게 표시될지 설정
|
||||||
|
</p>
|
||||||
|
|
||||||
{(!group.displayItems || group.displayItems.length === 0) ? (
|
{(!group.displayItems || group.displayItems.length === 0) ? (
|
||||||
<div className="rounded border border-dashed p-2 text-center text-[10px] text-muted-foreground">
|
<div className="rounded border border-dashed p-2 text-center text-[10px] text-muted-foreground">
|
||||||
미설정 (모든 필드를 " / "로 구분하여 표시)
|
미설정 (모든 필드를 " / "로 구분하여 표시)
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -846,10 +891,15 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</CollapsibleContent>
|
||||||
</CardContent>
|
</div>
|
||||||
</Card>
|
</Collapsible>
|
||||||
|
|
||||||
|
</CollapsibleContent>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Collapsible>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue