updates
This commit is contained in:
@@ -18,7 +18,10 @@ import {
|
||||
Check,
|
||||
XCircle,
|
||||
Award,
|
||||
Shield
|
||||
Shield,
|
||||
RefreshCw,
|
||||
Accessibility,
|
||||
HelpCircle
|
||||
} from 'lucide-react';
|
||||
import { pageContentService, PageContent, PageType, UpdatePageContentData, bannerService, Banner } from '../../services/api';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -26,7 +29,7 @@ import Loading from '../../components/common/Loading';
|
||||
import { ConfirmationDialog } from '../../components/common';
|
||||
import IconPicker from '../../components/admin/IconPicker';
|
||||
|
||||
type ContentTab = 'overview' | 'home' | 'contact' | 'about' | 'footer' | 'seo';
|
||||
type ContentTab = 'overview' | 'home' | 'contact' | 'about' | 'footer' | 'seo' | 'privacy' | 'terms' | 'refunds' | 'cancellation' | 'accessibility' | 'faq';
|
||||
|
||||
const PageContentDashboard: React.FC = () => {
|
||||
const [activeTab, setActiveTab] = useState<ContentTab>('overview');
|
||||
@@ -38,6 +41,12 @@ const PageContentDashboard: React.FC = () => {
|
||||
about: null,
|
||||
footer: null,
|
||||
seo: null,
|
||||
privacy: null,
|
||||
terms: null,
|
||||
refunds: null,
|
||||
cancellation: null,
|
||||
accessibility: null,
|
||||
faq: null,
|
||||
});
|
||||
|
||||
// Form states for each page
|
||||
@@ -46,6 +55,12 @@ const PageContentDashboard: React.FC = () => {
|
||||
const [aboutData, setAboutData] = useState<UpdatePageContentData>({});
|
||||
const [footerData, setFooterData] = useState<UpdatePageContentData>({});
|
||||
const [seoData, setSeoData] = useState<UpdatePageContentData>({});
|
||||
const [privacyData, setPrivacyData] = useState<UpdatePageContentData>({ is_active: true });
|
||||
const [termsData, setTermsData] = useState<UpdatePageContentData>({ is_active: true });
|
||||
const [refundsData, setRefundsData] = useState<UpdatePageContentData>({ is_active: true });
|
||||
const [cancellationData, setCancellationData] = useState<UpdatePageContentData>({ is_active: true });
|
||||
const [accessibilityData, setAccessibilityData] = useState<UpdatePageContentData>({ is_active: true });
|
||||
const [faqData, setFaqData] = useState<UpdatePageContentData>({ is_active: true });
|
||||
|
||||
// Banner management state
|
||||
const [banners, setBanners] = useState<Banner[]>([]);
|
||||
@@ -88,6 +103,12 @@ const PageContentDashboard: React.FC = () => {
|
||||
about: null,
|
||||
footer: null,
|
||||
seo: null,
|
||||
privacy: null,
|
||||
terms: null,
|
||||
refunds: null,
|
||||
cancellation: null,
|
||||
accessibility: null,
|
||||
faq: null,
|
||||
};
|
||||
|
||||
contents.forEach((content) => {
|
||||
@@ -241,6 +262,84 @@ const PageContentDashboard: React.FC = () => {
|
||||
canonical_url: contents.seo.canonical_url || '',
|
||||
});
|
||||
}
|
||||
|
||||
// Privacy
|
||||
if (contents.privacy) {
|
||||
setPrivacyData({
|
||||
title: contents.privacy.title || '',
|
||||
subtitle: contents.privacy.subtitle || '',
|
||||
description: contents.privacy.description || '',
|
||||
content: contents.privacy.content || '',
|
||||
meta_title: contents.privacy.meta_title || '',
|
||||
meta_description: contents.privacy.meta_description || '',
|
||||
is_active: contents.privacy.is_active ?? true,
|
||||
});
|
||||
}
|
||||
|
||||
// Terms
|
||||
if (contents.terms) {
|
||||
setTermsData({
|
||||
title: contents.terms.title || '',
|
||||
subtitle: contents.terms.subtitle || '',
|
||||
description: contents.terms.description || '',
|
||||
content: contents.terms.content || '',
|
||||
meta_title: contents.terms.meta_title || '',
|
||||
meta_description: contents.terms.meta_description || '',
|
||||
is_active: contents.terms.is_active ?? true,
|
||||
});
|
||||
}
|
||||
|
||||
// Refunds
|
||||
if (contents.refunds) {
|
||||
setRefundsData({
|
||||
title: contents.refunds.title || '',
|
||||
subtitle: contents.refunds.subtitle || '',
|
||||
description: contents.refunds.description || '',
|
||||
content: contents.refunds.content || '',
|
||||
meta_title: contents.refunds.meta_title || '',
|
||||
meta_description: contents.refunds.meta_description || '',
|
||||
is_active: contents.refunds.is_active ?? true,
|
||||
});
|
||||
}
|
||||
|
||||
// Cancellation
|
||||
if (contents.cancellation) {
|
||||
setCancellationData({
|
||||
title: contents.cancellation.title || '',
|
||||
subtitle: contents.cancellation.subtitle || '',
|
||||
description: contents.cancellation.description || '',
|
||||
content: contents.cancellation.content || '',
|
||||
meta_title: contents.cancellation.meta_title || '',
|
||||
meta_description: contents.cancellation.meta_description || '',
|
||||
is_active: contents.cancellation.is_active ?? true,
|
||||
});
|
||||
}
|
||||
|
||||
// Accessibility
|
||||
if (contents.accessibility) {
|
||||
setAccessibilityData({
|
||||
title: contents.accessibility.title || '',
|
||||
subtitle: contents.accessibility.subtitle || '',
|
||||
description: contents.accessibility.description || '',
|
||||
content: contents.accessibility.content || '',
|
||||
meta_title: contents.accessibility.meta_title || '',
|
||||
meta_description: contents.accessibility.meta_description || '',
|
||||
is_active: contents.accessibility.is_active ?? true,
|
||||
});
|
||||
}
|
||||
|
||||
// FAQ
|
||||
if (contents.faq) {
|
||||
setFaqData({
|
||||
title: contents.faq.title || '',
|
||||
subtitle: contents.faq.subtitle || '',
|
||||
description: contents.faq.description || '',
|
||||
content: contents.faq.content || '',
|
||||
meta_title: contents.faq.meta_title || '',
|
||||
meta_description: contents.faq.meta_description || '',
|
||||
is_active: contents.faq.is_active ?? true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = async (pageType: PageType, data: UpdatePageContentData) => {
|
||||
@@ -449,6 +548,12 @@ const PageContentDashboard: React.FC = () => {
|
||||
{ id: 'home' as ContentTab, label: 'Home', icon: Home },
|
||||
{ id: 'contact' as ContentTab, label: 'Contact', icon: Mail },
|
||||
{ id: 'about' as ContentTab, label: 'About', icon: Info },
|
||||
{ id: 'privacy' as ContentTab, label: 'Privacy', icon: Shield },
|
||||
{ id: 'terms' as ContentTab, label: 'Terms', icon: FileText },
|
||||
{ id: 'refunds' as ContentTab, label: 'Refunds', icon: RefreshCw },
|
||||
{ id: 'cancellation' as ContentTab, label: 'Cancellation', icon: XCircle },
|
||||
{ id: 'accessibility' as ContentTab, label: 'Accessibility', icon: Accessibility },
|
||||
{ id: 'faq' as ContentTab, label: 'FAQ', icon: HelpCircle },
|
||||
{ id: 'footer' as ContentTab, label: 'Footer', icon: FileText },
|
||||
{ id: 'seo' as ContentTab, label: 'SEO', icon: Search },
|
||||
];
|
||||
@@ -528,6 +633,12 @@ const PageContentDashboard: React.FC = () => {
|
||||
{ id: 'home' as PageType, label: 'Home Page', icon: Home, color: 'blue', description: 'Manage hero section, featured content' },
|
||||
{ id: 'contact' as PageType, label: 'Contact Page', icon: Mail, color: 'green', description: 'Manage contact information and form' },
|
||||
{ id: 'about' as PageType, label: 'About Page', icon: Info, color: 'amber', description: 'Manage story, values, and features' },
|
||||
{ id: 'privacy' as PageType, label: 'Privacy Policy', icon: Shield, color: 'red', description: 'Manage privacy policy content' },
|
||||
{ id: 'terms' as PageType, label: 'Terms & Conditions', icon: FileText, color: 'teal', description: 'Manage terms and conditions' },
|
||||
{ id: 'refunds' as PageType, label: 'Refunds Policy', icon: RefreshCw, color: 'orange', description: 'Manage refunds policy content' },
|
||||
{ id: 'cancellation' as PageType, label: 'Cancellation Policy', icon: XCircle, color: 'pink', description: 'Manage cancellation policy content' },
|
||||
{ id: 'accessibility' as PageType, label: 'Accessibility', icon: Accessibility, color: 'cyan', description: 'Manage accessibility information' },
|
||||
{ id: 'faq' as PageType, label: 'FAQ', icon: HelpCircle, color: 'violet', description: 'Manage frequently asked questions' },
|
||||
{ id: 'footer' as PageType, label: 'Footer', icon: FileText, color: 'purple', description: 'Manage footer links and social media' },
|
||||
{ id: 'seo' as PageType, label: 'SEO Settings', icon: Search, color: 'indigo', description: 'Manage meta tags and SEO optimization' },
|
||||
].map((page) => {
|
||||
@@ -542,6 +653,9 @@ const PageContentDashboard: React.FC = () => {
|
||||
page.color === 'green' ? 'border-green-100/50 hover:border-green-300/60' :
|
||||
page.color === 'amber' ? 'border-amber-100/50 hover:border-amber-300/60' :
|
||||
page.color === 'purple' ? 'border-purple-100/50 hover:border-purple-300/60' :
|
||||
page.color === 'red' ? 'border-red-100/50 hover:border-red-300/60' :
|
||||
page.color === 'teal' ? 'border-teal-100/50 hover:border-teal-300/60' :
|
||||
page.color === 'orange' ? 'border-orange-100/50 hover:border-orange-300/60' :
|
||||
'border-indigo-100/50 hover:border-indigo-300/60'
|
||||
}`}
|
||||
>
|
||||
@@ -550,6 +664,9 @@ const PageContentDashboard: React.FC = () => {
|
||||
page.color === 'green' ? 'from-green-400' :
|
||||
page.color === 'amber' ? 'from-amber-400' :
|
||||
page.color === 'purple' ? 'from-purple-400' :
|
||||
page.color === 'red' ? 'from-red-400' :
|
||||
page.color === 'teal' ? 'from-teal-400' :
|
||||
page.color === 'orange' ? 'from-orange-400' :
|
||||
'from-indigo-400'
|
||||
}`}></div>
|
||||
<div className="relative space-y-5">
|
||||
@@ -560,6 +677,9 @@ const PageContentDashboard: React.FC = () => {
|
||||
page.color === 'green' ? 'bg-gradient-to-br from-green-500 to-green-600 border-green-400/50' :
|
||||
page.color === 'amber' ? 'bg-gradient-to-br from-amber-500 to-amber-600 border-amber-400/50' :
|
||||
page.color === 'purple' ? 'bg-gradient-to-br from-purple-500 to-purple-600 border-purple-400/50' :
|
||||
page.color === 'red' ? 'bg-gradient-to-br from-red-500 to-red-600 border-red-400/50' :
|
||||
page.color === 'teal' ? 'bg-gradient-to-br from-teal-500 to-teal-600 border-teal-400/50' :
|
||||
page.color === 'orange' ? 'bg-gradient-to-br from-orange-500 to-orange-600 border-orange-400/50' :
|
||||
'bg-gradient-to-br from-indigo-500 to-indigo-600 border-indigo-400/50'
|
||||
}`}>
|
||||
<Icon className="w-6 h-6 text-white" />
|
||||
@@ -568,6 +688,9 @@ const PageContentDashboard: React.FC = () => {
|
||||
<h3 className="font-bold text-gray-900 text-xl mb-1">{page.label}</h3>
|
||||
<div className={`h-1 w-12 rounded-full ${
|
||||
page.color === 'blue' ? 'bg-gradient-to-r from-blue-500 to-blue-600' :
|
||||
page.color === 'red' ? 'bg-gradient-to-r from-red-500 to-red-600' :
|
||||
page.color === 'teal' ? 'bg-gradient-to-r from-teal-500 to-teal-600' :
|
||||
page.color === 'orange' ? 'bg-gradient-to-r from-orange-500 to-orange-600' :
|
||||
page.color === 'green' ? 'bg-gradient-to-r from-green-500 to-green-600' :
|
||||
page.color === 'amber' ? 'bg-gradient-to-r from-amber-500 to-amber-600' :
|
||||
page.color === 'purple' ? 'bg-gradient-to-r from-purple-500 to-purple-600' :
|
||||
@@ -3607,6 +3730,570 @@ const PageContentDashboard: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Privacy Tab */}
|
||||
{activeTab === 'privacy' && (
|
||||
<div className="space-y-8">
|
||||
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900">Privacy Policy Content</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-sm font-medium text-gray-700">Enable Page</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setPrivacyData({ ...privacyData, is_active: !privacyData.is_active })}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 ${
|
||||
(privacyData.is_active ?? true) ? 'bg-purple-600' : 'bg-gray-300'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
(privacyData.is_active ?? true) ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={privacyData.title || ''}
|
||||
onChange={(e) => setPrivacyData({ ...privacyData, title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Privacy Policy"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Subtitle</label>
|
||||
<input
|
||||
type="text"
|
||||
value={privacyData.subtitle || ''}
|
||||
onChange={(e) => setPrivacyData({ ...privacyData, subtitle: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Your privacy is important to us"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Content (HTML)</label>
|
||||
<textarea
|
||||
value={privacyData.content || ''}
|
||||
onChange={(e) => setPrivacyData({ ...privacyData, content: e.target.value })}
|
||||
rows={20}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 font-mono text-sm"
|
||||
placeholder="Enter HTML content for privacy policy..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-gray-200 pt-6">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-4">SEO Settings</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={privacyData.meta_title || ''}
|
||||
onChange={(e) => setPrivacyData({ ...privacyData, meta_title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Description</label>
|
||||
<textarea
|
||||
value={privacyData.meta_description || ''}
|
||||
onChange={(e) => setPrivacyData({ ...privacyData, meta_description: e.target.value })}
|
||||
rows={3}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end pt-4 border-t border-gray-200">
|
||||
<button
|
||||
onClick={() => handleSave('privacy', privacyData)}
|
||||
disabled={saving}
|
||||
className="px-8 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-xl font-semibold hover:from-purple-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
>
|
||||
<Save className="w-5 h-5" />
|
||||
{saving ? 'Saving...' : 'Save Privacy Policy'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Terms Tab */}
|
||||
{activeTab === 'terms' && (
|
||||
<div className="space-y-8">
|
||||
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900 mb-6">Terms & Conditions Content</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={termsData.title || ''}
|
||||
onChange={(e) => setTermsData({ ...termsData, title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Terms & Conditions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Subtitle</label>
|
||||
<input
|
||||
type="text"
|
||||
value={termsData.subtitle || ''}
|
||||
onChange={(e) => setTermsData({ ...termsData, subtitle: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Please read these terms carefully"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Content (HTML)</label>
|
||||
<textarea
|
||||
value={termsData.content || ''}
|
||||
onChange={(e) => setTermsData({ ...termsData, content: e.target.value })}
|
||||
rows={20}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 font-mono text-sm"
|
||||
placeholder="Enter HTML content for terms & conditions..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-gray-200 pt-6">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-4">SEO Settings</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={termsData.meta_title || ''}
|
||||
onChange={(e) => setTermsData({ ...termsData, meta_title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Description</label>
|
||||
<textarea
|
||||
value={termsData.meta_description || ''}
|
||||
onChange={(e) => setTermsData({ ...termsData, meta_description: e.target.value })}
|
||||
rows={3}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end pt-4 border-t border-gray-200">
|
||||
<button
|
||||
onClick={() => handleSave('terms', termsData)}
|
||||
disabled={saving}
|
||||
className="px-8 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-xl font-semibold hover:from-purple-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
>
|
||||
<Save className="w-5 h-5" />
|
||||
{saving ? 'Saving...' : 'Save Terms & Conditions'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Refunds Tab */}
|
||||
{activeTab === 'refunds' && (
|
||||
<div className="space-y-8">
|
||||
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900">Refunds Policy Content</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-sm font-medium text-gray-700">Enable Page</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setRefundsData({ ...refundsData, is_active: !refundsData.is_active })}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 ${
|
||||
(refundsData.is_active ?? true) ? 'bg-purple-600' : 'bg-gray-300'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
(refundsData.is_active ?? true) ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={refundsData.title || ''}
|
||||
onChange={(e) => setRefundsData({ ...refundsData, title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Refunds Policy"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Subtitle</label>
|
||||
<input
|
||||
type="text"
|
||||
value={refundsData.subtitle || ''}
|
||||
onChange={(e) => setRefundsData({ ...refundsData, subtitle: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Our commitment to fair refunds"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Content (HTML)</label>
|
||||
<textarea
|
||||
value={refundsData.content || ''}
|
||||
onChange={(e) => setRefundsData({ ...refundsData, content: e.target.value })}
|
||||
rows={20}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 font-mono text-sm"
|
||||
placeholder="Enter HTML content for refunds policy..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-gray-200 pt-6">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-4">SEO Settings</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={refundsData.meta_title || ''}
|
||||
onChange={(e) => setRefundsData({ ...refundsData, meta_title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Description</label>
|
||||
<textarea
|
||||
value={refundsData.meta_description || ''}
|
||||
onChange={(e) => setRefundsData({ ...refundsData, meta_description: e.target.value })}
|
||||
rows={3}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end pt-4 border-t border-gray-200">
|
||||
<button
|
||||
onClick={() => handleSave('refunds', refundsData)}
|
||||
disabled={saving}
|
||||
className="px-8 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-xl font-semibold hover:from-purple-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
>
|
||||
<Save className="w-5 h-5" />
|
||||
{saving ? 'Saving...' : 'Save Refunds Policy'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Cancellation Tab */}
|
||||
{activeTab === 'cancellation' && (
|
||||
<div className="space-y-8">
|
||||
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900">Cancellation Policy Content</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-sm font-medium text-gray-700">Enable Page</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setCancellationData({ ...cancellationData, is_active: !cancellationData.is_active })}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 ${
|
||||
(cancellationData.is_active ?? true) ? 'bg-purple-600' : 'bg-gray-300'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
(cancellationData.is_active ?? true) ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={cancellationData.title || ''}
|
||||
onChange={(e) => setCancellationData({ ...cancellationData, title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Cancellation Policy"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Subtitle</label>
|
||||
<input
|
||||
type="text"
|
||||
value={cancellationData.subtitle || ''}
|
||||
onChange={(e) => setCancellationData({ ...cancellationData, subtitle: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Flexible cancellation options for your peace of mind"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Content (HTML)</label>
|
||||
<textarea
|
||||
value={cancellationData.content || ''}
|
||||
onChange={(e) => setCancellationData({ ...cancellationData, content: e.target.value })}
|
||||
rows={20}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 font-mono text-sm"
|
||||
placeholder="Enter HTML content for cancellation policy..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={cancellationData.meta_title || ''}
|
||||
onChange={(e) => setCancellationData({ ...cancellationData, meta_title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Cancellation Policy - Luxury Hotel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Description</label>
|
||||
<textarea
|
||||
value={cancellationData.meta_description || ''}
|
||||
onChange={(e) => setCancellationData({ ...cancellationData, meta_description: e.target.value })}
|
||||
rows={3}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Review our cancellation policy..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 pt-6 border-t border-gray-200">
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={() => handleSave('cancellation', cancellationData)}
|
||||
disabled={saving}
|
||||
className="px-8 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-xl font-semibold hover:from-purple-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
>
|
||||
<Save className="w-5 h-5" />
|
||||
{saving ? 'Saving...' : 'Save Cancellation Policy'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Accessibility Tab */}
|
||||
{activeTab === 'accessibility' && (
|
||||
<div className="space-y-8">
|
||||
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900">Accessibility Content</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-sm font-medium text-gray-700">Enable Page</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAccessibilityData({ ...accessibilityData, is_active: !accessibilityData.is_active })}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 ${
|
||||
(accessibilityData.is_active ?? true) ? 'bg-purple-600' : 'bg-gray-300'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
(accessibilityData.is_active ?? true) ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={accessibilityData.title || ''}
|
||||
onChange={(e) => setAccessibilityData({ ...accessibilityData, title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Accessibility"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Subtitle</label>
|
||||
<input
|
||||
type="text"
|
||||
value={accessibilityData.subtitle || ''}
|
||||
onChange={(e) => setAccessibilityData({ ...accessibilityData, subtitle: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Committed to providing an inclusive experience for all guests"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Content (HTML)</label>
|
||||
<textarea
|
||||
value={accessibilityData.content || ''}
|
||||
onChange={(e) => setAccessibilityData({ ...accessibilityData, content: e.target.value })}
|
||||
rows={20}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 font-mono text-sm"
|
||||
placeholder="Enter HTML content for accessibility page..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={accessibilityData.meta_title || ''}
|
||||
onChange={(e) => setAccessibilityData({ ...accessibilityData, meta_title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Accessibility - Luxury Hotel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Description</label>
|
||||
<textarea
|
||||
value={accessibilityData.meta_description || ''}
|
||||
onChange={(e) => setAccessibilityData({ ...accessibilityData, meta_description: e.target.value })}
|
||||
rows={3}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Discover our commitment to accessibility..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 pt-6 border-t border-gray-200">
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={() => handleSave('accessibility', accessibilityData)}
|
||||
disabled={saving}
|
||||
className="px-8 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-xl font-semibold hover:from-purple-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
>
|
||||
<Save className="w-5 h-5" />
|
||||
{saving ? 'Saving...' : 'Save Accessibility Content'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* FAQ Tab */}
|
||||
{activeTab === 'faq' && (
|
||||
<div className="space-y-8">
|
||||
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900">FAQ Content</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-sm font-medium text-gray-700">Enable Page</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setFaqData({ ...faqData, is_active: !faqData.is_active })}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 ${
|
||||
(faqData.is_active ?? true) ? 'bg-purple-600' : 'bg-gray-300'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
(faqData.is_active ?? true) ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={faqData.title || ''}
|
||||
onChange={(e) => setFaqData({ ...faqData, title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Frequently Asked Questions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Subtitle</label>
|
||||
<input
|
||||
type="text"
|
||||
value={faqData.subtitle || ''}
|
||||
onChange={(e) => setFaqData({ ...faqData, subtitle: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Find answers to common questions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Content (HTML)</label>
|
||||
<textarea
|
||||
value={faqData.content || ''}
|
||||
onChange={(e) => setFaqData({ ...faqData, content: e.target.value })}
|
||||
rows={20}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 font-mono text-sm"
|
||||
placeholder="Enter HTML content for FAQ page..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Title</label>
|
||||
<input
|
||||
type="text"
|
||||
value={faqData.meta_title || ''}
|
||||
onChange={(e) => setFaqData({ ...faqData, meta_title: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="FAQ - Luxury Hotel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2">Meta Description</label>
|
||||
<textarea
|
||||
value={faqData.meta_description || ''}
|
||||
onChange={(e) => setFaqData({ ...faqData, meta_description: e.target.value })}
|
||||
rows={3}
|
||||
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200"
|
||||
placeholder="Find answers to common questions..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 pt-6 border-t border-gray-200">
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={() => handleSave('faq', faqData)}
|
||||
disabled={saving}
|
||||
className="px-8 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-xl font-semibold hover:from-purple-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
>
|
||||
<Save className="w-5 h-5" />
|
||||
{saving ? 'Saving...' : 'Save FAQ Content'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* SEO Tab */}
|
||||
{activeTab === 'seo' && (
|
||||
<div className="space-y-8">
|
||||
|
||||
Reference in New Issue
Block a user