import React, { useState } from 'react'; import { Heart, Music, Mic, Users, Calendar, ClipboardList, Send, CheckCircle, Sparkles, MessageCircle, Trash2, Edit, X, CheckSquare, AlignLeft, Type, AlertTriangle } from 'lucide-react'; const WeddingSurveyForm = () => { // 1. 定義初始問卷結構 (Data-Driven) const initialSections = [ { id: 'basic', title: '基本資訊', icon: ClipboardList, questions: [ { id: 'b1', type: 'text', label: '新郎姓名' }, { id: 'b2', type: 'text', label: '新娘姓名' }, { id: 'b3', type: 'date', label: '婚禮日期' }, { id: 'b4', type: 'text', label: '婚禮舉行地點' } ] }, { id: 'style', title: '婚禮風格與氛圍', icon: Heart, questions: [ { id: 's1', type: 'checkbox', label: '您希望婚禮的整體氛圍是什麼樣的?(可複選)', options: ['優雅浪漫', '輕鬆幽默', '熱烈熱情', '正式莊重', '其他(請具體描述)'] }, { id: 's2', type: 'checkbox', label: '您希望主持人的風格是什麼樣的?(可複選)', options: ['輕鬆幽默,讓來賓開心', '正式莊重,尊重儀式感', '活潑熱情,讓氛圍更加熱烈', '輕快、自然,保持輕鬆的氛圍', '其他(請具體描述)'] }, { id: 's3', type: 'checkbox', label: '婚禮過程中,您希望主持人更多強調哪些方面?(可複選)', options: ['夫妻的愛情故事', '家庭與朋友的祝福', '婚禮儀式的莊重感', '互動遊戲或有趣的環節', '其他(請具體描述)'] }, { id: 's4', type: 'radio', label: '在婚禮上,您希望主持人如何與來賓互動?', options: ['輕鬆、隨和地與來賓互動', '鼓勵來賓參與某些環節', '保持較少互動,專注於主持', '其他(請具體描述)'] } ] }, { id: 'story', title: '新人的背景與故事', icon: Users, questions: [ { id: 'st1', type: 'textarea', label: '新郎與新娘的相識過程是什麼?' }, { id: 'st2', type: 'textarea', label: '彼此認為最浪漫的事' }, { id: 'st3', type: 'textarea', label: '交往多久? 工作、平常相處是遠距離嗎?' }, { id: 'st4', type: 'textarea', label: '這一年來大概多久見一次?' }, { id: 'st5', type: 'textarea', label: '如何維繫彼此的感情?' }, { id: 'st6', type: 'textarea', label: '如何確定對方就是對的人?' }, { id: 'st7', type: 'textarea', label: '用一個狀態形容 對方在自己心中的樣子' }, { id: 'st8', type: 'textarea', label: '對方為自己做過最浪慢的事' }, { id: 'st9', type: 'textarea', label: '有沒有特別的家庭成員或朋友,希望在婚禮中被提到或特別感謝?' }, { id: 'st10', type: 'textarea', label: '您希望在婚禮中有沒有特別的驚喜或互動環節?' }, { id: 'st11', type: 'textarea', label: '婚禮中是否有特別的元素(例如:文化、家庭傳統、特定歌曲或習俗)您希望強調?' } ] }, { id: 'flow', title: '婚禮儀式與流程', icon: Calendar, questions: [ { id: 'f1', type: 'checkbox', label: '婚禮中的主要儀式,您希望強調哪些?(可複選)', options: ['誓言交換', '交換戒指', '第一支舞', '乾杯儀式', '父母感謝', '其他(請具體描述)'] }, { id: 'f2', type: 'radio', label: '婚禮儀式結束後,您是否希望主持人帶領其他活動(如:晚宴、遊戲、表演等)?', options: ['是', '否', '不確定'] }, { id: 'f3', type: 'radio', label: '您希望婚禮的流程緊湊還是稍微輕鬆一些?', options: ['緊湊,按時完成每個環節', '輕鬆,給來賓更多自由交流的時間'] } ] }, { id: 'req', title: '婚禮主持的具體要求', icon: Mic, questions: [ { id: 'r1', type: 'checkbox', label: '您希望主持人在婚禮中使用哪些語言或語氣?(可複選)', options: ['輕鬆幽默,帶有笑點', '端莊正式,專注於儀式感', '感性、溫馨,注重情感表達', '其他(請具體描述)'] }, { id: 'r2', type: 'radio', label: '您是否希望主持人提前與您進行一對一的會議,了解婚禮的詳細安排?', options: ['是', '否', '無所謂'] }, { id: 'r3', type: 'textarea', label: '婚禮中是否有您希望避免的事情?' } ] }, { id: 'music', title: '婚禮的音樂與其他細節', icon: Music, questions: [ { id: 'm1', type: 'text', label: '有愛情主題曲嗎?' }, { id: 'm2', type: 'textarea', label: '平常都聽什麼歌?' }, { id: 'm3', type: 'textarea', label: '婚禮的歌單?' }, { id: 'm4', type: 'textarea', label: '您有沒有希望在婚禮中播放的特別影片或圖片?' }, { id: 'm5', type: 'textarea', label: '婚禮中是否有某些特定的主題或顏色,您希望主持人參考?' }, { id: 'm6', type: 'textarea', label: '您有沒有對婚禮流程中特定環節的時間長短有特別要求?' } ] }, { id: 'other', title: '其他建議與期望', icon: MessageCircle, questions: [ { id: 'o1', type: 'textarea', label: '對主持人有任何特殊的期望或要求嗎?' }, { id: 'o2', type: 'textarea', label: '是否有其他您認為非常重要的細節,主持人需要注意的地方?' } ] } ]; const [sections, setSections] = useState(initialSections); const [formData, setFormData] = useState({}); const [submitted, setSubmitted] = useState(false); const [isEditMode, setIsEditMode] = useState(false); // 編輯模式開關 const [confirmDelete, setConfirmDelete] = useState(null); // 用於確認刪除的狀態 {sIdx, qIdx} const [submitError, setSubmitError] = useState(false); // 提交錯誤提示 // --- 編輯功能 --- // 1. 觸發確認刪除彈窗 const startDeleteQuestion = (sectionIndex, questionIndex) => { // 儲存待刪除問題的索引,等待確認 setConfirmDelete({ sIdx: sectionIndex, qIdx: questionIndex }); }; // 2. 執行刪除 const handleConfirmDelete = () => { if (confirmDelete) { const { sIdx, qIdx } = confirmDelete; const newSections = [...sections]; // 確保深拷貝以觸發 React 更新 newSections[sIdx].questions = [...newSections[sIdx].questions]; newSections[sIdx].questions.splice(qIdx, 1); setSections(newSections); setConfirmDelete(null); // 關閉彈窗 } }; // 3. 取消刪除 const handleCancelDelete = () => { setConfirmDelete(null); // 關閉彈窗 }; const addQuestion = (sectionIndex, type) => { const newSections = [...sections]; const newId = `new_${Date.now()}`; let newQuestion = { id: newId, label: '請輸入問題標題...', type }; if (type === 'checkbox' || type === 'radio') { newQuestion.options = ['選項 1', '選項 2', '我想要補充...']; // 更改選項名稱 } // 確保深拷貝以觸發 React 更新 newSections[sectionIndex].questions = [...newSections[sectionIndex].questions, newQuestion]; setSections(newSections); }; const updateQuestionLabel = (sectionIndex, questionIndex, newLabel) => { const newSections = [...sections]; // 確保深拷貝以觸發 React 更新 newSections[sectionIndex].questions = [...newSections[sectionIndex].questions]; newSections[sectionIndex].questions[questionIndex].label = newLabel; setSections(newSections); }; // --- 填寫功能 --- const handleInputChange = (questionId, value) => { setFormData(prev => ({ ...prev, [questionId]: value })); }; const handleCheckboxChange = (questionId, option, checked) => { setFormData(prev => { const currentValues = prev[questionId] || []; // 處理「我想要補充」的特殊邏輯 const isOther = option.startsWith('其他') || option.startsWith('我想要補充'); const otherPrefix = '我想要補充: '; let newValues; if (checked) { if (isOther) { // 檢查是否已經有包含 '我想要補充:' 的值 const existingOther = currentValues.find(v => v.startsWith(otherPrefix) || v === option); if(existingOther) return prev; newValues = [...currentValues, option]; } else { newValues = [...currentValues, option]; } } else { // 取消選中 if (isOther) { // 移除所有以 '我想要補充' 或 '其他' 開頭的項目 newValues = currentValues.filter(v => !v.startsWith(otherPrefix) && !v.startsWith('其他')); } else { newValues = currentValues.filter(v => v !== option); } } return { ...prev, [questionId]: newValues }; }); }; const handleSubmit = (e) => { e.preventDefault(); if (isEditMode) { setSubmitError(true); setTimeout(() => setSubmitError(false), 3000); // 3秒後隱藏錯誤 return; } setSubmitted(true); setSubmitError(false); window.scrollTo({ top: 0, behavior: 'smooth' }); }; // --- 元件 --- const ChoiceGroup = ({ question, sectionIndex, questionIndex }) => { const currentValues = formData[question.id] || (question.type === 'checkbox' ? [] : ''); const isMultiple = question.type === 'checkbox'; return (
感謝您的填寫。如有需要,您可以重新編輯問卷結構。
親愛的新人您好,為了讓您的婚禮更加完美,請協助我們填寫以下問卷。
您確定要刪除「{getQuestionLabelToDelete()}」這個問題嗎?刪除後無法復原。