268 lines
10 KiB
JavaScript
268 lines
10 KiB
JavaScript
import React, { useState, useRef, useEffect } from 'react'
|
|
import { Popconfirm, message } from 'antd'
|
|
import { DefaultModal } from '../../Components/Modal/DefaultModal'
|
|
import "../Styles/FaqSectionForm.scss"
|
|
|
|
const FaqSectionForm = () => {
|
|
const [question, setQuestion] = useState('')
|
|
const [answer, setAnswer] = useState('')
|
|
const [faqs, setFaqs] = useState([])
|
|
const [editingId, setEditingId] = useState(null)
|
|
const [isModalOpen, setIsModalOpen] = useState(false)
|
|
const [questionError, setQuestionError] = useState('')
|
|
const [answerError, setAnswerError] = useState('')
|
|
const questionInputRef = useRef(null)
|
|
|
|
// UUID generator fallback for browser compatibility
|
|
const generateUUID = () => {
|
|
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
return crypto.randomUUID()
|
|
}
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
const r = Math.random() * 16 | 0
|
|
const v = c === 'x' ? r : (r & 0x3 | 0x8)
|
|
return v.toString(16)
|
|
})
|
|
}
|
|
|
|
const openModal = () => {
|
|
setIsModalOpen(true)
|
|
}
|
|
|
|
const closeModal = () => {
|
|
setIsModalOpen(false)
|
|
handleClear()
|
|
}
|
|
|
|
const handleSave = () => {
|
|
let hasError = false
|
|
|
|
if (!question.trim()) {
|
|
setQuestionError('Question is required')
|
|
hasError = true
|
|
} else {
|
|
setQuestionError('')
|
|
}
|
|
|
|
if (!answer.trim()) {
|
|
setAnswerError('Answer is required')
|
|
hasError = true
|
|
} else {
|
|
setAnswerError('')
|
|
}
|
|
|
|
if (hasError) {
|
|
message.error('Please fix the highlighted fields')
|
|
return
|
|
}
|
|
|
|
const newFaq = {
|
|
id: editingId || generateUUID(),
|
|
question: question.trim(),
|
|
answer: answer.trim(),
|
|
isActive: true,
|
|
createdAt: new Date().toLocaleDateString('en-US')
|
|
}
|
|
|
|
if (editingId) {
|
|
setFaqs(prev => prev.map(faq => faq.id === editingId ? newFaq : faq))
|
|
setEditingId(null)
|
|
message.success('FAQ updated!')
|
|
} else {
|
|
setFaqs(prev => [...prev, newFaq])
|
|
message.success('FAQ added!')
|
|
}
|
|
|
|
closeModal()
|
|
}
|
|
|
|
const handleClear = () => {
|
|
setQuestion('')
|
|
setAnswer('')
|
|
setEditingId(null)
|
|
setQuestionError('')
|
|
setAnswerError('')
|
|
}
|
|
|
|
const handleEdit = (faq) => {
|
|
setQuestion(faq.question)
|
|
setAnswer(faq.answer)
|
|
setEditingId(faq.id)
|
|
openModal()
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (editingId && questionInputRef.current) {
|
|
questionInputRef.current.focus()
|
|
}
|
|
}, [editingId])
|
|
|
|
const handleDelete = (id) => {
|
|
setFaqs(prev => prev.filter(faq => faq.id !== id))
|
|
message.success('FAQ deleted')
|
|
}
|
|
|
|
const handleToggleStatus = (id) => {
|
|
setFaqs(prev => prev.map(faq =>
|
|
faq.id === id ? { ...faq, isActive: !faq.isActive } : faq
|
|
))
|
|
}
|
|
|
|
return (
|
|
<div className='faq-form-master'>
|
|
{/* Header Section */}
|
|
<div className='faq-form-header'>
|
|
<div className='faq-header-left'>
|
|
{/* <div className='faq-header-icon'>
|
|
<span>❓</span>
|
|
</div> */}
|
|
<div className='faq-header-content'>
|
|
<h2>FAQ Management</h2>
|
|
<p>Manage and organize your frequently asked questions.</p>
|
|
</div>
|
|
</div>
|
|
<button onClick={openModal} className='faq-create-btn'>
|
|
<span>+</span> Create FAQ
|
|
</button>
|
|
</div>
|
|
|
|
{/* Tab Navigation */}
|
|
<div className='faq-tab-navigation'>
|
|
<div className='faq-tab-buttons'>
|
|
<button className='faq-tab-btn faq-active'>
|
|
FAQs ({faqs.length})
|
|
</button>
|
|
<button className='faq-tab-btn'>
|
|
All Status
|
|
</button>
|
|
</div>
|
|
<div className='faq-tab-controls'>
|
|
<div className='faq-sort-dropdown'>
|
|
<select>
|
|
<option value="newest">Newest First</option>
|
|
<option value="oldest">Oldest First</option>
|
|
<option value="alphabetical">Alphabetical</option>
|
|
</select>
|
|
</div>
|
|
<div className='faq-view-toggle'>
|
|
<button className='faq-view-btn faq-active'>
|
|
<span>⊞</span>
|
|
</button>
|
|
<button className='faq-view-btn'>
|
|
<span>☰</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Content Area */}
|
|
{faqs.length > 0 ? (
|
|
<div className='faq-display'>
|
|
<div className='faq-grid'>
|
|
{faqs.map((faq, index) => (
|
|
<div key={faq.id} className={`faq-card ${!faq.isActive ? 'faq-inactive' : ''}`}>
|
|
<div className='faq-card-header'>
|
|
<h3>{faq.question}</h3>
|
|
<div className='faq-card-actions'>
|
|
<button className='faq-edit-btn' onClick={() => handleEdit(faq)}>Edit</button>
|
|
<Popconfirm
|
|
title="Delete FAQ"
|
|
description="Are you sure you want to delete this FAQ?"
|
|
onConfirm={() => handleDelete(faq.id)}
|
|
okText="Yes"
|
|
cancelText="No"
|
|
>
|
|
<button className='faq-delete-btn'>Delete</button>
|
|
</Popconfirm>
|
|
<button
|
|
className={`faq-status-btn ${faq.isActive ? 'faq-deactivate' : 'faq-activate'}`}
|
|
onClick={() => handleToggleStatus(faq.id)}
|
|
>
|
|
{faq.isActive ? 'Deactivate' : 'Activate'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div className='faq-card-content'>
|
|
<p><strong>Answer:</strong> {faq.answer}</p>
|
|
<p className='faq-created-date'>Created: {faq.createdAt}</p>
|
|
<p className={`faq-status ${faq.isActive ? 'faq-active' : 'faq-inactive'}`}>
|
|
Status: {faq.isActive ? 'Active' : 'Inactive'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className='faq-placeholder-content'>
|
|
<div className='faq-placeholder-icon'>
|
|
<span>❓</span>
|
|
</div>
|
|
<h2>No FAQs Found</h2>
|
|
<p>Get started by creating your first FAQ</p>
|
|
</div>
|
|
)}
|
|
|
|
{/* Modal */}
|
|
<DefaultModal
|
|
open={isModalOpen}
|
|
title={editingId ? 'Edit FAQ' : 'Create New FAQ'}
|
|
handleCancel={closeModal}
|
|
handleSubmit={handleSave}
|
|
buttonText={editingId ? 'Update FAQ' : 'Add FAQ'}
|
|
width={600}
|
|
destroyOnClose={true}
|
|
>
|
|
<div className='faq-form'>
|
|
<div className='faq-form-group'>
|
|
<label htmlFor='question'>Question</label>
|
|
<input
|
|
type='text'
|
|
id='question'
|
|
ref={questionInputRef}
|
|
value={question}
|
|
onChange={(e) => {
|
|
setQuestion(e.target.value)
|
|
if (questionError) setQuestionError('')
|
|
}}
|
|
placeholder='Enter FAQ question'
|
|
className={questionError ? 'error' : ''}
|
|
autoFocus
|
|
/>
|
|
{questionError && <span className='error-message'>{questionError}</span>}
|
|
</div>
|
|
|
|
<div className='faq-form-group'>
|
|
<label htmlFor='answer'>Answer</label>
|
|
<textarea
|
|
id='answer'
|
|
value={answer}
|
|
onChange={(e) => {
|
|
setAnswer(e.target.value)
|
|
if (answerError) setAnswerError('')
|
|
}}
|
|
placeholder='Enter FAQ answer'
|
|
className={answerError ? 'error' : ''}
|
|
rows='4'
|
|
/>
|
|
{answerError && <span className='error-message'>{answerError}</span>}
|
|
</div>
|
|
|
|
<div className='faq-form-actions'>
|
|
<button type='button' onClick={handleSave} className='faq-save-btn'>
|
|
{editingId ? 'Update' : 'Save'}
|
|
</button>
|
|
<button type='button' onClick={closeModal} className='faq-cancel-btn'>
|
|
Cancel
|
|
</button>
|
|
<button type='button' onClick={handleClear} className='faq-clear-btn'>
|
|
Clear
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</DefaultModal>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default FaqSectionForm |