381 lines
13 KiB
JavaScript
381 lines
13 KiB
JavaScript
import React, { useState } from 'react'
|
|
import { Popconfirm } from 'antd'
|
|
import { useAdminPanel } from '../AdminPanelContext'
|
|
import { DefaultModal } from '../../Components/Modal/DefaultModal'
|
|
import "../Styles/OfferingsForm.scss"
|
|
|
|
const OfferingsForm = () => {
|
|
const { sectionData, updateSectionData } = useAdminPanel()
|
|
const ecosystemData = sectionData.EcosystemForm || []
|
|
const [isModalOpen, setIsModalOpen] = useState(false)
|
|
const [title, setTitle] = useState('')
|
|
const [posters, setPosters] = useState([{ id: 1, title: '', description: '', image: '' }])
|
|
const [editingIndex, setEditingIndex] = useState(-1)
|
|
const [titleError, setTitleError] = useState('')
|
|
const [posterErrors, setPosterErrors] = useState({})
|
|
|
|
const openModal = () => {
|
|
setIsModalOpen(true)
|
|
}
|
|
|
|
const closeModal = () => {
|
|
setIsModalOpen(false)
|
|
setTitle('')
|
|
setPosters([{ id: 1, title: '', description: '', image: '' }])
|
|
setEditingIndex(-1)
|
|
setTitleError('')
|
|
setPosterErrors({})
|
|
}
|
|
|
|
const handleClear = () => {
|
|
setTitle('')
|
|
setPosters([{ id: 1, title: '', description: '', image: '' }])
|
|
setTitleError('')
|
|
setPosterErrors({})
|
|
}
|
|
|
|
const addPoster = () => {
|
|
const newId = Math.max(...posters.map(p => p.id)) + 1
|
|
setPosters([...posters, { id: newId, title: '', description: '', image: '' }])
|
|
}
|
|
|
|
const removePoster = (id) => {
|
|
if (posters.length > 1) {
|
|
setPosters(posters.filter(p => p.id !== id))
|
|
const newErrors = { ...posterErrors }
|
|
delete newErrors[id]
|
|
setPosterErrors(newErrors)
|
|
}
|
|
}
|
|
|
|
const handlePosterChange = (id, field, value) => {
|
|
setPosters(posters.map(p => p.id === id ? { ...p, [field]: value } : p))
|
|
if (posterErrors[id]) {
|
|
const newErrors = { ...posterErrors }
|
|
delete newErrors[id]
|
|
setPosterErrors(newErrors)
|
|
}
|
|
}
|
|
|
|
const handleImageChange = (id, e) => {
|
|
const file = e.target.files[0]
|
|
if (file) {
|
|
const reader = new FileReader()
|
|
reader.onloadend = () => {
|
|
handlePosterChange(id, 'image', reader.result)
|
|
}
|
|
reader.readAsDataURL(file)
|
|
}
|
|
}
|
|
|
|
const handleSave = () => {
|
|
let hasError = false
|
|
const errors = {}
|
|
|
|
if (!title.trim()) {
|
|
setTitleError('Title is required')
|
|
hasError = true
|
|
} else {
|
|
setTitleError('')
|
|
}
|
|
|
|
posters.forEach(poster => {
|
|
if (!poster.title.trim()) {
|
|
errors[poster.id] = 'Poster title is required'
|
|
hasError = true
|
|
}
|
|
})
|
|
|
|
setPosterErrors(errors)
|
|
if (hasError) return
|
|
|
|
const newEcosystem = {
|
|
id: editingIndex >= 0 ? ecosystemData[editingIndex].id : Date.now(),
|
|
title: title.trim(),
|
|
posters: posters.map(p => ({
|
|
id: p.id,
|
|
title: p.title.trim(),
|
|
description: p.description.trim(),
|
|
image: p.image
|
|
})),
|
|
active: true,
|
|
createdAt: editingIndex >= 0 ? ecosystemData[editingIndex].createdAt : new Date().toLocaleDateString()
|
|
}
|
|
|
|
if (editingIndex >= 0) {
|
|
const updatedEcosystems = ecosystemData.map((ecosystem, index) => index === editingIndex ? newEcosystem : ecosystem)
|
|
updateSectionData('EcosystemForm', updatedEcosystems)
|
|
setEditingIndex(-1)
|
|
} else {
|
|
updateSectionData('EcosystemForm', [...ecosystemData, newEcosystem])
|
|
}
|
|
|
|
closeModal()
|
|
}
|
|
|
|
const handleDelete = (index) => {
|
|
const updatedEcosystems = ecosystemData.filter((_, i) => i !== index)
|
|
updateSectionData('EcosystemForm', updatedEcosystems)
|
|
}
|
|
|
|
const handleEdit = (index) => {
|
|
setTitle(ecosystemData[index].title)
|
|
if (ecosystemData[index].posters && ecosystemData[index].posters.length > 0) {
|
|
setPosters(ecosystemData[index].posters)
|
|
} else {
|
|
// Handle legacy data structure
|
|
setPosters([{
|
|
id: 1,
|
|
title: ecosystemData[index].posterTitle || '',
|
|
description: ecosystemData[index].posterDescription || '',
|
|
image: ecosystemData[index].posterImage || ''
|
|
}])
|
|
}
|
|
setEditingIndex(index)
|
|
openModal()
|
|
}
|
|
|
|
const handleToggleActive = (index) => {
|
|
const updated = [...ecosystemData]
|
|
updated[index].active = !updated[index].active
|
|
updateSectionData('EcosystemForm', updated)
|
|
}
|
|
|
|
return (
|
|
<div className='OfferingsFormMaster'>
|
|
{/* Header Section */}
|
|
<div className='ecosystem-form-header'>
|
|
<div className='ecosystem-header-left'>
|
|
{/* <div className='ecosystem-header-icon'>
|
|
<span>🌱</span>
|
|
</div> */}
|
|
<div className='ecosystem-header-content'>
|
|
<h2>Offerings Management</h2>
|
|
<p>Manage and organize your ecosystem content and settings.</p>
|
|
</div>
|
|
</div>
|
|
<button onClick={openModal} className='ecosystem-create-btn'>
|
|
<span>+</span> Create Ecosystem
|
|
</button>
|
|
</div>
|
|
|
|
{/* Tab Navigation */}
|
|
<div className='ecosystem-tab-navigation'>
|
|
<div className='ecosystem-tab-buttons'>
|
|
<button className='ecosystem-tab-btn ecosystem-active'>
|
|
Offerings ({ecosystemData.length})
|
|
</button>
|
|
<button className='ecosystem-tab-btn'>
|
|
All Status
|
|
</button>
|
|
</div>
|
|
<div className='ecosystem-tab-controls'>
|
|
<div className='ecosystem-sort-dropdown'>
|
|
<select>
|
|
<option value="newest">Newest First</option>
|
|
<option value="oldest">Oldest First</option>
|
|
<option value="alphabetical">Alphabetical</option>
|
|
</select>
|
|
</div>
|
|
<div className='ecosystem-view-toggle'>
|
|
<button className='ecosystem-view-btn ecosystem-active'>
|
|
<span>⊞</span>
|
|
</button>
|
|
<button className='ecosystem-view-btn'>
|
|
<span>☰</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Content Area */}
|
|
{ecosystemData.length > 0 ? (
|
|
<div className='ecosystem-display'>
|
|
<div className='ecosystem-grid'>
|
|
{ecosystemData.map((ecosystem, index) => (
|
|
<div key={ecosystem.id} className={`ecosystem-card ${!ecosystem.active ? 'ecosystem-inactive' : ''}`}>
|
|
<div className='ecosystem-card-header'>
|
|
<h3>{ecosystem.title}</h3>
|
|
<div className='ecosystem-card-actions'>
|
|
<button className='ecosystem-edit-btn' onClick={() => handleEdit(index)}>Edit</button>
|
|
<Popconfirm
|
|
title="Delete Ecosystem"
|
|
description="Are you sure you want to delete this ecosystem?"
|
|
onConfirm={() => handleDelete(index)}
|
|
okText="Yes"
|
|
cancelText="No"
|
|
>
|
|
<button className='ecosystem-delete-btn'>Delete</button>
|
|
</Popconfirm>
|
|
<button
|
|
className={`ecosystem-status-btn ${ecosystem.active ? 'ecosystem-deactivate' : 'ecosystem-activate'}`}
|
|
onClick={() => handleToggleActive(index)}
|
|
>
|
|
{ecosystem.active ? 'Deactivate' : 'Activate'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div className='ecosystem-card-content'>
|
|
{ecosystem.posters && ecosystem.posters.length > 0 ? (
|
|
<div className='ecosystem-posters'>
|
|
<strong>Posters ({ecosystem.posters.length}):</strong>
|
|
{ecosystem.posters.map(poster => (
|
|
<div key={poster.id} className='ecosystem-poster-item'>
|
|
{poster.image && (
|
|
<div className='ecosystem-poster-image'>
|
|
<img src={poster.image} alt={poster.title} />
|
|
</div>
|
|
)}
|
|
<div className='ecosystem-poster-content'>
|
|
<p><strong>{poster.title}</strong></p>
|
|
{poster.description && <p>{poster.description}</p>}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : (
|
|
// Legacy data structure support
|
|
<>
|
|
{ecosystem.posterImage && (
|
|
<div className='ecosystem-poster-image'>
|
|
<img src={ecosystem.posterImage} alt={ecosystem.posterTitle} />
|
|
</div>
|
|
)}
|
|
<p><strong>Poster Title:</strong> {ecosystem.posterTitle}</p>
|
|
<p><strong>Description:</strong> {ecosystem.posterDescription || 'No description'}</p>
|
|
</>
|
|
)}
|
|
<p className='ecosystem-created-date'>Created: {ecosystem.date || ecosystem.createdAt}</p>
|
|
<p className={`ecosystem-status ${ecosystem.active ? 'ecosystem-active' : 'ecosystem-inactive'}`}>
|
|
Status: {ecosystem.active ? 'Active' : 'Inactive'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className='ecosystem-placeholder-content'>
|
|
<div className='ecosystem-placeholder-icon'>
|
|
<span>🌱</span>
|
|
</div>
|
|
<h2>No Ecosystems Found</h2>
|
|
<p>Get started by creating your first ecosystem</p>
|
|
</div>
|
|
)}
|
|
|
|
{/* Modal */}
|
|
<DefaultModal
|
|
open={isModalOpen}
|
|
title={editingIndex >= 0 ? 'Edit Ecosystem' : 'Create New Ecosystem'}
|
|
handleCancel={closeModal}
|
|
handleSubmit={handleSave}
|
|
buttonText={editingIndex >= 0 ? 'Update Ecosystem' : 'Add Ecosystem'}
|
|
width={600}
|
|
destroyOnClose={true}
|
|
>
|
|
<div className='ecosystem-form'>
|
|
<div className='ecosystem-form-group'>
|
|
<label htmlFor='ecosystemTitle'>Title</label>
|
|
<input
|
|
type='text'
|
|
id='ecosystemTitle'
|
|
value={title}
|
|
onChange={(e) => {
|
|
setTitle(e.target.value)
|
|
if (titleError) setTitleError('')
|
|
}}
|
|
placeholder='Enter ecosystem title'
|
|
className={titleError ? 'error' : ''}
|
|
autoFocus
|
|
/>
|
|
{titleError && <span className='error-message'>{titleError}</span>}
|
|
</div>
|
|
|
|
<div className='posters-container'>
|
|
<div className='posters-header'>
|
|
<h3>Poster Sections</h3>
|
|
<p>Add multiple poster sections for your ecosystem</p>
|
|
</div>
|
|
|
|
{posters.map((poster, idx) => (
|
|
<div key={poster.id} className='poster-section'>
|
|
<div className='poster-section-header'>
|
|
<span>Poster {idx + 1}</span>
|
|
{posters.length > 1 && (
|
|
<button
|
|
type='button'
|
|
className='remove-poster-btn'
|
|
onClick={() => removePoster(poster.id)}
|
|
>
|
|
✕
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
<div className='ecosystem-form-group'>
|
|
<label>Poster Title</label>
|
|
<input
|
|
type='text'
|
|
value={poster.title}
|
|
onChange={(e) => handlePosterChange(poster.id, 'title', e.target.value)}
|
|
placeholder='Enter poster title'
|
|
className={posterErrors[poster.id] ? 'error' : ''}
|
|
/>
|
|
{posterErrors[poster.id] && <span className='error-message'>{posterErrors[poster.id]}</span>}
|
|
</div>
|
|
|
|
<div className='ecosystem-form-group'>
|
|
<label>Poster Description</label>
|
|
<textarea
|
|
value={poster.description}
|
|
onChange={(e) => handlePosterChange(poster.id, 'description', e.target.value)}
|
|
placeholder='Enter poster description'
|
|
rows='3'
|
|
/>
|
|
</div>
|
|
|
|
<div className='ecosystem-form-group'>
|
|
<label>Poster Image</label>
|
|
<input
|
|
type='file'
|
|
accept='image/*'
|
|
onChange={(e) => handleImageChange(poster.id, e)}
|
|
className='ecosystem-file-input'
|
|
/>
|
|
{poster.image && (
|
|
<div className='ecosystem-image-preview'>
|
|
<img src={poster.image} alt='Preview' />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
|
|
<button
|
|
type='button'
|
|
className='add-poster-btn'
|
|
onClick={addPoster}
|
|
>
|
|
+ Add More Poster
|
|
</button>
|
|
</div>
|
|
|
|
<div className='ecosystem-form-actions'>
|
|
<button type='button' onClick={handleSave} className='ecosystem-save-btn'>
|
|
{editingIndex >= 0 ? 'Update' : 'Save'}
|
|
</button>
|
|
<button type='button' onClick={closeModal} className='ecosystem-cancel-btn'>
|
|
Cancel
|
|
</button>
|
|
<button type='button' onClick={handleClear} className='ecosystem-clear-btn'>
|
|
Clear
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</DefaultModal>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default OfferingsForm |