129 lines
5.3 KiB
TypeScript
129 lines
5.3 KiB
TypeScript
import { type ComponentType } from 'react';
|
|
import {
|
|
YoutubeFilled,
|
|
InstagramFilled,
|
|
FacebookFilled,
|
|
GlobeFilled,
|
|
TiktokFilled,
|
|
} from '../icons/FilledIcons';
|
|
import { CHANNEL_OPTIONS, type StudioChannel, type ContentFormat } from '../../types/studio';
|
|
|
|
interface Props {
|
|
selectedChannel: StudioChannel | null;
|
|
selectedFormat: ContentFormat | null;
|
|
onChannelSelect: (ch: StudioChannel | null) => void;
|
|
onFormatSelect: (fmt: ContentFormat | null) => void;
|
|
}
|
|
|
|
const iconMap: Record<string, ComponentType<{ size?: number; className?: string }>> = {
|
|
youtube: YoutubeFilled,
|
|
instagram: InstagramFilled,
|
|
facebook: FacebookFilled,
|
|
globe: GlobeFilled,
|
|
tiktok: TiktokFilled,
|
|
};
|
|
|
|
export default function ChannelFormatStep({ selectedChannel, selectedFormat, onChannelSelect, onFormatSelect }: Props) {
|
|
const activeChannel = CHANNEL_OPTIONS.find(c => c.channel === selectedChannel);
|
|
|
|
return (
|
|
<div>
|
|
{/* Channel Selection */}
|
|
<div className="mb-10">
|
|
<h3 className="font-serif font-bold text-2xl text-[#0A1128] mb-2">채널 선택</h3>
|
|
<p className="text-sm text-slate-500 mb-6">콘텐츠를 게시할 채널을 선택하세요</p>
|
|
|
|
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-4">
|
|
{CHANNEL_OPTIONS.map(ch => {
|
|
const Icon = iconMap[ch.icon] ?? GlobeFilled;
|
|
const isSelected = selectedChannel === ch.channel;
|
|
|
|
return (
|
|
<button
|
|
key={ch.channel}
|
|
onClick={() => {
|
|
onChannelSelect(isSelected ? null : ch.channel);
|
|
onFormatSelect(null);
|
|
}}
|
|
className={`relative flex flex-col items-center gap-3 p-6 rounded-2xl border-2 transition-all ${
|
|
isSelected
|
|
? 'border-[#6C5CE7] bg-[#F3F0FF]/30 shadow-[3px_4px_12px_rgba(108,92,231,0.12)]'
|
|
: 'border-slate-100 bg-white shadow-[3px_4px_12px_rgba(0,0,0,0.06)] hover:border-[#D5CDF5]'
|
|
}`}
|
|
>
|
|
{isSelected && (
|
|
<div className="absolute top-3 right-3 w-5 h-5 rounded-full bg-[#6C5CE7] flex items-center justify-center">
|
|
<svg width="10" height="10" viewBox="0 0 14 14" fill="none">
|
|
<path d="M2 7L5.5 10.5L12 3.5" stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
</div>
|
|
)}
|
|
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${
|
|
isSelected ? 'bg-[#F3F0FF]' : 'bg-slate-50'
|
|
}`}>
|
|
<Icon size={24} className={isSelected ? 'text-[#6C5CE7]' : 'text-[#9B8AD4]'} />
|
|
</div>
|
|
<span className={`text-sm font-semibold ${
|
|
isSelected ? 'text-[#0A1128]' : 'text-slate-600'
|
|
}`}>
|
|
{ch.label}
|
|
</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Format Selection */}
|
|
{activeChannel && (
|
|
<div>
|
|
<h3 className="font-serif font-bold text-2xl text-[#0A1128] mb-2">포맷 선택</h3>
|
|
<p className="text-sm text-slate-500 mb-6">{activeChannel.label}에 적합한 콘텐츠 포맷을 선택하세요</p>
|
|
|
|
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4">
|
|
{activeChannel.formats.map(fmt => {
|
|
const isSelected = selectedFormat === fmt.key;
|
|
|
|
return (
|
|
<button
|
|
key={fmt.key}
|
|
onClick={() => onFormatSelect(isSelected ? null : fmt.key)}
|
|
className={`relative flex flex-col items-center gap-3 p-5 rounded-2xl border-2 transition-all ${
|
|
isSelected
|
|
? 'border-[#6C5CE7] bg-[#F3F0FF]/30 shadow-[3px_4px_12px_rgba(108,92,231,0.12)]'
|
|
: 'border-slate-100 bg-white shadow-[3px_4px_12px_rgba(0,0,0,0.06)] hover:border-[#D5CDF5]'
|
|
}`}
|
|
>
|
|
{isSelected && (
|
|
<div className="absolute top-3 right-3 w-5 h-5 rounded-full bg-[#6C5CE7] flex items-center justify-center">
|
|
<svg width="10" height="10" viewBox="0 0 14 14" fill="none">
|
|
<path d="M2 7L5.5 10.5L12 3.5" stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
</div>
|
|
)}
|
|
|
|
{/* Aspect ratio preview */}
|
|
<div className={`rounded-lg bg-slate-100 border border-slate-200 flex items-center justify-center ${
|
|
fmt.aspectRatio === '9:16' ? 'w-10 h-16' :
|
|
fmt.aspectRatio === '16:9' ? 'w-16 h-10' :
|
|
fmt.aspectRatio === '4:5' ? 'w-12 h-14' :
|
|
'w-12 h-12'
|
|
}`}>
|
|
<span className="text-xs text-slate-400 font-medium">{fmt.aspectRatio}</span>
|
|
</div>
|
|
|
|
<span className={`text-sm font-semibold ${
|
|
isSelected ? 'text-[#0A1128]' : 'text-slate-600'
|
|
}`}>
|
|
{fmt.label}
|
|
</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|