'use client'; import { useRef } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrash, faUpload } from '@fortawesome/free-solid-svg-icons'; import type { AlertConfigItem } from '@/types/response/donation/alertConfig'; import { Checkbox } from '@/components/ui/checkbox'; import { POPUP_EFFECTS, TEXT_EFFECTS, FONT_OPTIONS, MATCH_TYPES } from '../constants'; import type { FormState, PendingFiles } from '../types'; import { ALERT_TITLE_MAX_LENGTH, ALERT_MESSAGE_MAX_LENGTH, ALERT_AMOUNT_MIN, ALERT_DELAY_MIN, ALERT_DELAY_MAX, ALERT_DELAY_STEP, ALERT_DURATION_MIN, ALERT_DURATION_MAX, ALERT_DURATION_STEP, FONT_SIZE_MIN, FONT_SIZE_MAX, COLOR_HEX_MAX_LENGTH } from '@/constants/donation'; type Props = { form: FormState; editingItem: AlertConfigItem|null; saving: boolean; pendingFiles: PendingFiles; onFileSelect: (file: File, type: 'image'|'sound') => void; onFormChange: (field: K, value: FormState[K]) => void; onSave: () => void; onCancel: () => void; }; export default function AlertFormPanel({ form, editingItem, saving, pendingFiles, onFileSelect, onFormChange, onSave, onCancel }: Props) { const imageInputRef = useRef(null); const soundInputRef = useRef(null); // ── 폰트 그룹 렌더러 ───────────────────────────── const renderFontGroup = ( label: string, prefix: string, familyField: 'nicknameFontFamily'|'amountFontFamily'|'messageFontFamily'|'templateFontFamily', sizeField: 'nicknameFontSize'|'amountFontSize'|'messageFontSize'|'templateFontSize', colorField: 'nicknameFontColor'|'amountFontColor'|'messageFontColor'|'templateFontColor', defaultSize: number ) => (
{label}
onFormChange(sizeField, parseInt(e.target.value) || defaultSize)} title='Font Size' />
onFormChange(colorField, e.target.value)} /> onFormChange(colorField, e.target.value)} maxLength={COLOR_HEX_MAX_LENGTH} title='Font Color' />
); return (
{/* ── 기본 설정 ────────────────────────────── */}

기본 설정

onFormChange('title', e.target.value)} placeholder="알림 제목 (선택)" maxLength={ALERT_TITLE_MAX_LENGTH} />
onFormChange('amount', parseInt(e.target.value) || 0)} />
{MATCH_TYPES.map(mt => ( ))}
onFormChange('message', e.target.value)} placeholder="{이름}님이 {금액}원을 후원했습니다!" maxLength={ALERT_MESSAGE_MAX_LENGTH} /> 사용 가능한 변수: {'{이름}'}, {'{금액}'}
onFormChange('playDelaySec', parseFloat(e.target.value) || 0)} />
onFormChange('displayDurationSec', parseFloat(e.target.value) || 0)} />
{/* ── 효과 ────────────────────────────────── */}

효과

{/* ── 폰트 ────────────────────────────────── */}

폰트

{renderFontGroup('이름', 'font-nickname', 'nicknameFontFamily', 'nicknameFontSize', 'nicknameFontColor', 24)} {renderFontGroup('금액', 'font-amount', 'amountFontFamily', 'amountFontSize', 'amountFontColor', 24)} {renderFontGroup('보낼 내용', 'font-message', 'messageFontFamily', 'messageFontSize', 'messageFontColor', 18)} {renderFontGroup('알림 문구', 'font-template', 'templateFontFamily', 'templateFontSize', 'templateFontColor', 24)}
{/* ── 미디어 ───────────────────────────────── */}

미디어

{/* 이미지 */}
{form.enableImage && (
{form.imageUrl && (
알림 이미지
)} { const file = e.target.files?.[0]; if (file) onFileSelect(file, 'image'); e.target.value = ''; }} title='이미지 첨부' /> {pendingFiles.image && ( {pendingFiles.image.name} )} JPG, PNG, GIF (최대 20MB)
)} {/* 사운드 */}
{form.enableSound && (
{form.soundUrl && (
)} { const file = e.target.files?.[0]; if (file) onFileSelect(file, 'sound'); e.target.value = ''; }} title='사운드 첨부' /> {pendingFiles.sound && ( {pendingFiles.sound.name} )} MP3, OGG, WAV, M4A (최대 50MB)
)}
{/* ── 하단 버튼 ────────────────────────────── */}
); }