520 lines
22 KiB
JavaScript
520 lines
22 KiB
JavaScript
import React, { useState, useEffect, useCallback } from "react";
|
||
import { message } from "antd";
|
||
import { DefaultModal } from "../../Components/Modal/DefaultModal";
|
||
import "../Styles/FooterForm.scss";
|
||
import { getSession } from "../../Services/others.js";
|
||
import { getAdminPanel, postAdminPanel, putAdminPanel, deleteAdminPanel } from '../../features/AdminPanel/AdminPanel.js';
|
||
import { useDispatch } from 'react-redux';
|
||
import { Messages } from '../../Components/Notifications/Messages.jsx';
|
||
import { uploadImage } from "../../features/applications/bannerImage.js";
|
||
|
||
const FooterForm = ({ sectionKey = null }) => {
|
||
const dispatch = useDispatch();
|
||
const [footerData, setFooterData] = useState([]);
|
||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||
const [title, setTitle] = useState("");
|
||
const [description, setDescription] = useState("");
|
||
const [emailFields, setEmailFields] = useState([{ value: '', uniqueId: null }]);
|
||
const [phoneFields, setPhoneFields] = useState([{ value: '', uniqueId: null }]);
|
||
const [socialLink, setSocialLink] = useState("");
|
||
const [editingIndex, setEditingIndex] = useState(-1);
|
||
const [editData, setEditData] = useState(null);
|
||
const [titleError, setTitleError] = useState("");
|
||
const [descriptionError, setDescriptionError] = useState("");
|
||
const [messageData, setMessageData] = useState(null);
|
||
const [messageType, setMessageType] = useState(null);
|
||
const UserId = getSession('UserId') || 1;
|
||
|
||
useEffect(() => {
|
||
const getFooterData = async () => {
|
||
const res = await dispatch(getAdminPanel({ sectionName: sectionKey }))?.unwrap();
|
||
if (res?.data?.statusCode === 1) {
|
||
setFooterData(res?.data?.data);
|
||
} else {
|
||
setFooterData([]);
|
||
setMessageData(res?.data?.response);
|
||
setMessageType("error");
|
||
}
|
||
};
|
||
|
||
if (sectionKey) {
|
||
getFooterData();
|
||
}
|
||
}, [sectionKey, dispatch]);
|
||
|
||
const openModal = () => {
|
||
setIsModalOpen(true);
|
||
};
|
||
|
||
const closeModal = () => {
|
||
setIsModalOpen(false);
|
||
setTitle("");
|
||
setDescription("");
|
||
setEmailFields([{ value: '', uniqueId: null }]);
|
||
setPhoneFields([{ value: '', uniqueId: null }]);
|
||
setSocialLink("");
|
||
setEditingIndex(-1);
|
||
setEditData(null);
|
||
setTitleError("");
|
||
setDescriptionError("");
|
||
};
|
||
|
||
const handleClear = () => {
|
||
setTitle("");
|
||
setDescription("");
|
||
setEmailFields([{ value: '', uniqueId: null }]);
|
||
setPhoneFields([{ value: '', uniqueId: null }]);
|
||
setSocialLink("");
|
||
setTitleError("");
|
||
setDescriptionError("");
|
||
};
|
||
|
||
const addEmailField = () => {
|
||
setEmailFields([...emailFields, { value: '', uniqueId: null }]);
|
||
};
|
||
|
||
const removeEmailField = (index) => {
|
||
if (emailFields.length <= 1) return; // Don't remove if only one field
|
||
const updated = emailFields.filter((_, i) => i !== index);
|
||
setEmailFields(updated);
|
||
};
|
||
|
||
const updateEmailField = (index, value) => {
|
||
const updated = emailFields.map((email, i) => i === index ? { ...email, value } : email);
|
||
setEmailFields(updated);
|
||
};
|
||
|
||
const addPhoneField = () => {
|
||
setPhoneFields([...phoneFields, { value: '', uniqueId: null }]);
|
||
};
|
||
|
||
const removePhoneField = (index) => {
|
||
if (phoneFields.length <= 1) return; // Don't remove if only one field
|
||
const updated = phoneFields.filter((_, i) => i !== index);
|
||
setPhoneFields(updated);
|
||
};
|
||
|
||
const updatePhoneField = (index, value) => {
|
||
const updated = phoneFields.map((phone, i) => i === index ? { ...phone, value } : phone);
|
||
setPhoneFields(updated);
|
||
};
|
||
|
||
|
||
|
||
const handleSave = async () => {
|
||
let hasError = false;
|
||
|
||
if (!title.trim()) {
|
||
setTitleError("Title is required");
|
||
hasError = true;
|
||
} else setTitleError("");
|
||
|
||
if (!description.trim()) {
|
||
setDescriptionError("Description is required");
|
||
hasError = true;
|
||
} else setDescriptionError("");
|
||
|
||
if (hasError) {
|
||
message.error("Please fix the highlighted fields");
|
||
return;
|
||
}
|
||
|
||
// Build clean HomePageDetails array - only current form data
|
||
const homePageDetails = [];
|
||
|
||
// Add emails (only non-empty)
|
||
emailFields.forEach(email => {
|
||
if (email.value && email.value.trim()) {
|
||
homePageDetails.push({
|
||
DtlName: 'Email',
|
||
DtlDesc: email.value.trim(),
|
||
DtlHdr: '',
|
||
DtlImgUrl: '',
|
||
RStatus: 'A',
|
||
CreatedBy: UserId,
|
||
...(email.uniqueId && { UniqueId: email.uniqueId })
|
||
});
|
||
}
|
||
});
|
||
|
||
// Add phones (only non-empty)
|
||
phoneFields.forEach(phone => {
|
||
if (phone.value && phone.value.trim()) {
|
||
homePageDetails.push({
|
||
DtlName: 'Phone',
|
||
DtlHdr: phone.value.trim(),
|
||
DtlDesc: '',
|
||
DtlImgUrl: '',
|
||
RStatus: 'A',
|
||
CreatedBy: UserId,
|
||
...(phone.uniqueId && { UniqueId: phone.uniqueId })
|
||
});
|
||
}
|
||
});
|
||
|
||
// Check if data exists or if we're editing
|
||
const hasExistingData = footerData.length > 0;
|
||
const isEditing = editingIndex > -1 && editData;
|
||
const shouldUpdate = isEditing || hasExistingData;
|
||
|
||
const data = {
|
||
SectionName: sectionKey,
|
||
SectionHdr: title.trim(),
|
||
SectionDesc: description.trim(),
|
||
SectionImgUrl: '',
|
||
HomePageDetails: homePageDetails,
|
||
CreatedBy: UserId,
|
||
RStatus: 'A',
|
||
...(shouldUpdate
|
||
? { SectionId: editData?.SectionId || footerData[0]?.SectionId }
|
||
: {}),
|
||
};
|
||
|
||
console.log("API Request Data:", data);
|
||
console.log("Has Existing Data:", hasExistingData);
|
||
console.log("Is Editing:", isEditing);
|
||
console.log("Should Update:", shouldUpdate);
|
||
|
||
try {
|
||
const apiAction = shouldUpdate ? putAdminPanel : postAdminPanel;
|
||
console.log("API Action:", shouldUpdate ? "PUT" : "POST");
|
||
|
||
const res = await dispatch(apiAction(data))?.unwrap();
|
||
console.log(`${shouldUpdate ? "Put" : "Post"} response:`, res);
|
||
|
||
const success = res?.data?.statusCode === 1;
|
||
const messageText = shouldUpdate
|
||
? "Footer Updated Successfully"
|
||
: "Footer Added Successfully";
|
||
|
||
if (success) {
|
||
setMessageData(messageText);
|
||
setMessageType("success");
|
||
|
||
// Refresh data
|
||
const refreshRes = await dispatch(
|
||
getAdminPanel({ sectionName: sectionKey })
|
||
)?.unwrap();
|
||
if (refreshRes?.data?.statusCode === 1) {
|
||
setFooterData(refreshRes.data.data);
|
||
}
|
||
} else {
|
||
const errorMessage =
|
||
res?.response ||
|
||
res?.data?.response ||
|
||
res?.message ||
|
||
"Error saving footer";
|
||
console.log("API Error Response:", errorMessage);
|
||
setMessageData(errorMessage);
|
||
setMessageType("error");
|
||
}
|
||
} catch (error) {
|
||
console.error("API Error Details:", {
|
||
message: error?.message,
|
||
response: error?.response,
|
||
status: error?.response?.status,
|
||
data: error?.response?.data,
|
||
});
|
||
|
||
let errorMessage = "Network error occurred";
|
||
if (error?.response?.data?.message) {
|
||
errorMessage = error.response.data.message;
|
||
} else if (error?.response?.data?.response) {
|
||
errorMessage = error.response.data.response;
|
||
} else if (error?.message) {
|
||
errorMessage = error.message;
|
||
}
|
||
|
||
setMessageData(errorMessage);
|
||
setMessageType("error");
|
||
}
|
||
|
||
closeModal();
|
||
};
|
||
|
||
const handleEdit = (footer, index) => {
|
||
setTitle(footer.SectionHdr || "");
|
||
setDescription(footer.SectionDesc || "");
|
||
|
||
if (footer.HomePageDetails && footer.HomePageDetails.length > 0) {
|
||
const emails = footer.HomePageDetails.filter(d => d.DtlName === 'Email').map(d => ({
|
||
value: d.DtlDesc || '',
|
||
uniqueId: d.UniqueId || null
|
||
}));
|
||
const phones = footer.HomePageDetails.filter(d => d.DtlName === 'Phone').map(d => ({
|
||
value: d.DtlHdr || '',
|
||
uniqueId: d.UniqueId || null
|
||
}));
|
||
setEmailFields(emails.length > 0 ? emails : [{ value: '', uniqueId: null }]);
|
||
setPhoneFields(phones.length > 0 ? phones : [{ value: '', uniqueId: null }]);
|
||
} else {
|
||
setEmailFields([{ value: '', uniqueId: null }]);
|
||
setPhoneFields([{ value: '', uniqueId: null }]);
|
||
}
|
||
|
||
setEditingIndex(index);
|
||
setEditData(footer);
|
||
openModal();
|
||
};
|
||
|
||
const handleToggleActive = async (index) => {
|
||
const footer = footerData[index];
|
||
const newStatus = footer.RStatus === 'A' ? 'D' : 'A';
|
||
|
||
const deleteData = {
|
||
sectionId: footer.SectionId,
|
||
activeStatus: newStatus,
|
||
updatedBy: UserId
|
||
};
|
||
|
||
try {
|
||
const res = await dispatch(deleteAdminPanel(deleteData))?.unwrap();
|
||
|
||
if (res?.data?.statusCode === 1) {
|
||
setMessageData(`Footer ${newStatus === 'A' ? 'activated' : 'deactivated'} successfully`);
|
||
setMessageType('success');
|
||
|
||
const refreshRes = await dispatch(getAdminPanel({ sectionName: sectionKey }))?.unwrap();
|
||
if (refreshRes?.data?.statusCode === 1) {
|
||
setFooterData(refreshRes.data.data);
|
||
}
|
||
} else {
|
||
setMessageData('Error updating status');
|
||
setMessageType('error');
|
||
}
|
||
} catch (error) {
|
||
setMessageData('Network error occurred');
|
||
setMessageType('error');
|
||
}
|
||
};
|
||
|
||
const onComplete = useCallback(() => {
|
||
setMessageData(null);
|
||
setMessageType(null);
|
||
}, []);
|
||
|
||
return (
|
||
<div className="footer-form-master">
|
||
<Messages
|
||
messageType={messageType}
|
||
messageData={messageData}
|
||
onComplete={onComplete}
|
||
/>
|
||
|
||
{/* Header Section */}
|
||
<div className="footer-form-header">
|
||
<div className="footer-form-header-left">
|
||
<div className="footer-form-header-content">
|
||
<h2>Footer Management</h2>
|
||
<p>Manage and organize your footer content and settings.</p>
|
||
</div>
|
||
</div>
|
||
<button onClick={openModal} className="footer-form-create-btn">
|
||
<span>+</span> {footerData.length > 0 ? 'Edit Footer' : 'Create Footer'}
|
||
</button>
|
||
</div>
|
||
|
||
{/* Tab Navigation */}
|
||
<div className="footer-form-tab-navigation">
|
||
<div className="footer-form-tab-buttons">
|
||
<button className="footer-form-tab-btn footer-form-active">
|
||
Footer Sections ({footerData.length})
|
||
</button>
|
||
<button className="footer-form-tab-btn">All Status</button>
|
||
</div>
|
||
<div className="footer-form-tab-controls">
|
||
<div className="footer-form-sort-dropdown">
|
||
<select>
|
||
<option value="newest">Newest First</option>
|
||
<option value="oldest">Oldest First</option>
|
||
<option value="alphabetical">Alphabetical</option>
|
||
</select>
|
||
</div>
|
||
<div className="footer-form-view-toggle">
|
||
<button className="footer-form-view-btn footer-form-active">
|
||
<span>⊞</span>
|
||
</button>
|
||
<button className="footer-form-view-btn">
|
||
<span>☰</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Content Area */}
|
||
{footerData.length > 0 ? (
|
||
<div className="footer-form-display">
|
||
<div className="footer-form-grid">
|
||
{footerData.map((footer, index) => {
|
||
const detail = footer.HomePageDetails?.[0];
|
||
return (
|
||
<div key={footer.SectionId || index} className={`footer-form-card ${footer.RStatus?.trim() !== 'A' ? 'footer-form-inactive' : ''}`}>
|
||
<div className="footer-form-card-header">
|
||
<h3>{footer.SectionHdr}</h3>
|
||
</div>
|
||
<div className="footer-form-card-content">
|
||
<p><strong>Description:</strong> {footer.SectionDesc || "No description"}</p>
|
||
{footer.HomePageDetails && footer.HomePageDetails.length > 0 && (
|
||
<>
|
||
{footer.HomePageDetails.filter(d => d.DtlName === 'Email').length > 0 && (
|
||
<div className="footer-form-contact-section">
|
||
<p><strong>Emails:</strong></p>
|
||
{footer.HomePageDetails.filter(d => d.DtlName === 'Email').map((email, idx) => (
|
||
<div key={idx} className="footer-form-contact-info">
|
||
<span>{email.DtlDesc}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
{footer.HomePageDetails.filter(d => d.DtlName === 'Phone').length > 0 && (
|
||
<div className="footer-form-contact-section">
|
||
<p><strong>Phones:</strong></p>
|
||
{footer.HomePageDetails.filter(d => d.DtlName === 'Phone').map((phone, idx) => (
|
||
<div key={idx} className="footer-form-contact-info">
|
||
<span>{phone.DtlHdr}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</>
|
||
)}
|
||
<p className={`footer-form-status ${footer.RStatus?.trim() === 'A' ? 'footer-form-status-active' : 'footer-form-status-inactive'}`}>
|
||
Status: {footer.RStatus?.trim() === 'A' ? 'Active' : 'Inactive'}
|
||
</p>
|
||
</div>
|
||
<div className="footer-form-card-actions">
|
||
<button className="footer-form-edit-btn" onClick={() => handleEdit(footer, index)}>
|
||
Edit
|
||
</button>
|
||
<button
|
||
className={`footer-form-status-btn ${footer.RStatus?.trim() === 'A' ? 'footer-form-deactivate' : 'footer-form-activate'}`}
|
||
onClick={() => handleToggleActive(index)}
|
||
>
|
||
{footer.RStatus?.trim() === 'A' ? 'Deactivate' : 'Activate'}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="footer-form-placeholder-content">
|
||
<div className="footer-form-placeholder-icon">
|
||
<span>🦶</span>
|
||
</div>
|
||
<h2>No Footer Sections Found</h2>
|
||
<p>Get started by creating your first footer section</p>
|
||
</div>
|
||
)}
|
||
|
||
{/* Modal */}
|
||
<DefaultModal
|
||
open={isModalOpen}
|
||
title={editingIndex >= 0 ? "Edit Footer" : "Create New Footer"}
|
||
handleCancel={closeModal}
|
||
handleSubmit={handleSave}
|
||
buttonText={editingIndex > -1 ? "Update Footer" : "Add Footer"}
|
||
width={600}
|
||
destroyOnClose={true}
|
||
>
|
||
<div className="footer-form">
|
||
<div className="footer-form-group">
|
||
<label htmlFor="footerTitle">Title</label>
|
||
<input
|
||
type="text"
|
||
id="footerTitle"
|
||
value={title?.trim()}
|
||
onChange={(e) => {
|
||
setTitle(e.target.value);
|
||
if (titleError) setTitleError("");
|
||
}}
|
||
placeholder="Enter footer title"
|
||
className={titleError ? "footer-form-error" : ""}
|
||
autoFocus
|
||
/>
|
||
{titleError && <span className="footer-form-error-message">{titleError}</span>}
|
||
</div>
|
||
|
||
<div className="footer-form-group">
|
||
<label htmlFor="footerDescription">Description</label>
|
||
<input
|
||
type="text"
|
||
id="footerDescription"
|
||
value={description?.trim()}
|
||
onChange={(e) => {
|
||
setDescription(e.target.value);
|
||
if (descriptionError) setDescriptionError("");
|
||
}}
|
||
placeholder="Enter footer description"
|
||
className={descriptionError ? "footer-form-error" : ""}
|
||
/>
|
||
{descriptionError && <span className="footer-form-error-message">{descriptionError}</span>}
|
||
</div>
|
||
|
||
<div className="footer-form-group">
|
||
<label>Email Addresses</label>
|
||
{emailFields.map((email, index) => (
|
||
<div key={index} className="footer-form-field-group">
|
||
<div className="footer-form-inputs">
|
||
<input
|
||
type="email"
|
||
value={email.value}
|
||
onChange={(e) => updateEmailField(index, e.target.value)}
|
||
placeholder="Enter email address"
|
||
/>
|
||
<button type="button" onClick={() => removeEmailField(index)} className="footer-form-remove-btn">
|
||
×
|
||
</button>
|
||
</div>
|
||
</div>
|
||
))}
|
||
<button type="button" onClick={addEmailField} className="footer-form-add-btn">
|
||
+ Add Email
|
||
</button>
|
||
</div>
|
||
|
||
<div className="footer-form-group">
|
||
<label>Phone Numbers</label>
|
||
{phoneFields.map((phone, index) => (
|
||
<div key={index} className="footer-form-field-group">
|
||
<div className="footer-form-inputs">
|
||
<input
|
||
type="tel"
|
||
value={phone.value}
|
||
onChange={(e) => {
|
||
const value = e.target.value.replace(/[^0-9]/g, '').slice(0, 10);
|
||
updatePhoneField(index, value);
|
||
}}
|
||
placeholder="Enter 10-digit phone number"
|
||
maxLength={10}
|
||
/>
|
||
<button type="button" onClick={() => removePhoneField(index)} className="footer-form-remove-btn">
|
||
×
|
||
</button>
|
||
</div>
|
||
</div>
|
||
))}
|
||
<button type="button" onClick={addPhoneField} className="footer-form-add-btn">
|
||
+ Add Phone
|
||
</button>
|
||
</div>
|
||
|
||
<div className="footer-form-actions">
|
||
<button type="button" onClick={handleSave} className="footer-form-save-btn">
|
||
{editingIndex > -1 ? "Update" : "Save"}
|
||
</button>
|
||
<button type="button" onClick={closeModal} className="footer-form-cancel-btn">
|
||
Cancel
|
||
</button>
|
||
<button type="button" onClick={handleClear} className="footer-form-clear-btn">
|
||
Clear
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</DefaultModal>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default FooterForm; |