diff --git a/frontend/components/v2/config-panels/V2MediaConfigPanel.tsx b/frontend/components/v2/config-panels/V2MediaConfigPanel.tsx index eaf643ce..1a13de92 100644 --- a/frontend/components/v2/config-panels/V2MediaConfigPanel.tsx +++ b/frontend/components/v2/config-panels/V2MediaConfigPanel.tsx @@ -2,14 +2,54 @@ /** * V2Media 설정 패널 - * 통합 미디어 컴포넌트의 세부 설정을 관리합니다. + * 토스식 단계별 UX: 미디어 타입 카드 선택 -> 기본 설정 -> 타입별 설정 -> 고급 설정(접힘) */ -import React from "react"; -import { Label } from "@/components/ui/label"; +import React, { useState } from "react"; import { Input } from "@/components/ui/input"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Checkbox } from "@/components/ui/checkbox"; +import { Switch } from "@/components/ui/switch"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@/components/ui/collapsible"; +import { + FileText, + Image, + Video, + Music, + Settings, + ChevronDown, +} from "lucide-react"; +import { cn } from "@/lib/utils"; + +// ─── 미디어 타입 카드 정의 ─── +const MEDIA_TYPE_CARDS = [ + { + value: "file", + icon: FileText, + title: "파일", + description: "일반 파일을 업로드해요", + }, + { + value: "image", + icon: Image, + title: "이미지", + description: "사진이나 그림을 올려요", + }, + { + value: "video", + icon: Video, + title: "비디오", + description: "동영상을 업로드해요", + }, + { + value: "audio", + icon: Music, + title: "오디오", + description: "음악이나 녹음을 올려요", + }, +] as const; interface V2MediaConfigPanelProps { config: Record; @@ -20,133 +60,150 @@ export const V2MediaConfigPanel: React.FC = ({ config, onChange, }) => { + const [advancedOpen, setAdvancedOpen] = useState(false); + const updateConfig = (field: string, value: any) => { onChange({ ...config, [field]: value }); }; + const currentMediaType = config.mediaType || config.type || "image"; + const isImageType = currentMediaType === "image"; + const isPlayerType = currentMediaType === "video" || currentMediaType === "audio"; + return ( -
- {/* MEDIA TYPE 섹션 */} -
-

MEDIA TYPE

-
- 미디어 타입 -
- -
+
+ {/* ─── 1단계: 미디어 타입 선택 (카드) ─── */} +
+

어떤 미디어를 업로드하나요?

+
+ {MEDIA_TYPE_CARDS.map((card) => { + const Icon = card.icon; + const isSelected = currentMediaType === card.value; + return ( + + ); + })}
- {/* FILE SETTINGS 섹션 */} -
-

FILE SETTINGS

+ {/* ─── 2단계: 기본 설정 ─── */} +
+ 파일 설정 +
- 허용 파일 형식 -
- updateConfig("accept", e.target.value)} - placeholder=".jpg,.png,.pdf" - className="h-7 text-xs" - /> -
-
-
- 최대 크기 (MB) -
- updateConfig("maxSize", e.target.value ? Number(e.target.value) : undefined)} - placeholder="10" - min="1" - className="h-7 text-xs" - /> -
-
-
- 최대 파일 수 -
- updateConfig("maxFiles", e.target.value ? Number(e.target.value) : undefined)} - placeholder="제한 없음" - min="1" - className="h-7 text-xs" - /> -
+ 허용 형식 + updateConfig("accept", e.target.value)} + placeholder=".jpg,.png,.pdf" + className="h-8 w-[180px] text-sm" + />
- {/* OPTIONS 섹션 */} -
-

OPTIONS

-
- 다중 파일 업로드 - +
+
+

여러 파일 업로드

+

+ 한 번에 여러 파일을 선택할 수 있어요 +

+
+ updateConfig("multiple", checked)} />
-
- 미리보기 표시 - +
+

미리보기

+

+ 업로드한 파일의 미리보기가 표시돼요 +

+
+ updateConfig("preview", checked)} />
-
- 드래그 앤 드롭 - +
+

드래그 앤 드롭

+

+ 파일을 끌어다 놓아서 업로드할 수 있어요 +

+
+ updateConfig("dragDrop", checked)} />
- {/* IMAGE SETTINGS 섹션 - 이미지 타입 전용 */} - {config.mediaType === "image" && ( -
-

IMAGE SETTINGS

-
-
- - updateConfig("maxWidth", e.target.value ? Number(e.target.value) : undefined)} - placeholder="자동" - className="h-7 text-xs" - /> + {/* ─── 4단계: 타입별 설정 ─── */} + + {/* 이미지 타입: 크기 제한 + 자르기 */} + {isImageType && ( +
+
+
+ + 이미지 설정
-
- - updateConfig("maxHeight", e.target.value ? Number(e.target.value) : undefined)} - placeholder="자동" - className="h-7 text-xs" - /> + +
+
+ 최대 너비 (px) + updateConfig("maxWidth", e.target.value ? Number(e.target.value) : undefined)} + placeholder="자동" + className="mt-1 h-8 text-sm" + /> +
+
+ 최대 높이 (px) + updateConfig("maxHeight", e.target.value ? Number(e.target.value) : undefined)} + placeholder="자동" + className="mt-1 h-8 text-sm" + /> +
-
- 자르기 기능 - +
+

자르기 기능

+

+ 이미지를 원하는 크기로 잘라서 올릴 수 있어요 +

+
+ updateConfig("crop", checked)} /> @@ -154,33 +211,108 @@ export const V2MediaConfigPanel: React.FC = ({
)} - {/* PLAYER SETTINGS 섹션 - 비디오/오디오 전용 */} - {(config.mediaType === "video" || config.mediaType === "audio") && ( -
-

PLAYER SETTINGS

-
- 자동 재생 - +
+
+ {currentMediaType === "video" ? ( +
+
+ +
+
+

자동 재생

+

+ 페이지를 열면 자동으로 재생돼요 +

+
+ updateConfig("autoplay", checked)} />
-
- 컨트롤 표시 - +
+

컨트롤 표시

+

+ 재생, 정지, 볼륨 등 조작 버튼이 보여요 +

+
+ updateConfig("controls", checked)} />
-
- 반복 재생 - +
+

반복 재생

+

+ 끝나면 처음부터 다시 재생해요 +

+
+ updateConfig("loop", checked)} />
)} + + {/* ─── 5단계: 고급 설정 (기본 접혀있음) ─── */} + + + + + +
+
+ 최대 크기 (MB) + updateConfig("maxSize", e.target.value ? Number(e.target.value) : undefined)} + placeholder="10" + min="1" + className="h-8 w-[180px] text-sm" + /> +
+ +
+ 최대 파일 수 + updateConfig("maxFiles", e.target.value ? Number(e.target.value) : undefined)} + placeholder="제한 없음" + min="1" + className="h-8 w-[180px] text-sm" + /> +
+
+
+
); };