Files
GNX-WEB/gnx-react/app/policy/page.tsx
Iliyan Angelov dd8eb1c7aa update
2025-10-09 00:44:15 +03:00

400 lines
11 KiB
TypeScript

"use client";
import { useSearchParams } from 'next/navigation';
import Header from "@/components/shared/layout/header/Header";
import Footer from "@/components/shared/layout/footer/Footer";
import { Suspense } from 'react';
import { usePolicy } from '@/lib/hooks/usePolicy';
const PolicyContent = () => {
const searchParams = useSearchParams();
const typeParam = searchParams.get('type') || 'privacy';
const type = typeParam as 'privacy' | 'terms' | 'support';
const { data: policy, isLoading, error } = usePolicy(type);
if (isLoading) {
return (
<section className="policy-section section-padding">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-lg-10">
<div className="loading-state">
<div className="spinner"></div>
<p>Loading policy...</p>
</div>
</div>
</div>
</div>
<style jsx>{`
.policy-section {
background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
min-height: 100vh;
padding: 120px 0 80px;
}
.loading-state {
text-align: center;
padding: 4rem 2rem;
}
.spinner {
width: 50px;
height: 50px;
margin: 0 auto 1rem;
border: 4px solid #f3f3f3;
border-top: 4px solid #daa520;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-state p {
color: #64748b;
font-size: 1.1rem;
}
`}</style>
</section>
);
}
if (error || !policy) {
return (
<section className="policy-section section-padding">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-lg-10">
<div className="error-state">
<i className="fa-solid fa-exclamation-circle"></i>
<h2>Unable to Load Policy</h2>
<p>{error?.message || 'The requested policy could not be found.'}</p>
<a href="/support-center" className="btn btn-primary">Return to Support Center</a>
</div>
</div>
</div>
</div>
<style jsx>{`
.policy-section {
background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
min-height: 100vh;
padding: 120px 0 80px;
}
.error-state {
text-align: center;
padding: 4rem 2rem;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.error-state i {
font-size: 4rem;
color: #ef4444;
margin-bottom: 1rem;
}
.error-state h2 {
font-size: 2rem;
color: #1e293b;
margin-bottom: 1rem;
}
.error-state p {
color: #64748b;
font-size: 1.1rem;
margin-bottom: 2rem;
}
.btn-primary {
display: inline-block;
padding: 0.875rem 2rem;
background: linear-gradient(135deg, #daa520, #d4af37);
color: #0f172a;
text-decoration: none;
border-radius: 8px;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(218, 165, 32, 0.3);
}
`}</style>
</section>
);
}
return (
<section className="policy-section section-padding">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-lg-10">
{/* Policy Header */}
<div className="policy-header">
<h1 className="policy-title">{policy.title}</h1>
<div className="policy-meta">
<p className="policy-updated">
Last Updated: {new Date(policy.last_updated).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</p>
<p className="policy-version">Version {policy.version}</p>
<p className="policy-effective">
Effective Date: {new Date(policy.effective_date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</p>
</div>
{policy.description && (
<p className="policy-description">{policy.description}</p>
)}
</div>
{/* Policy Content */}
<div className="policy-content">
{policy.sections.map((section) => (
<div key={section.id} className="policy-section-item">
<h2 className="policy-heading">{section.heading}</h2>
<div className="policy-text" dangerouslySetInnerHTML={{
__html: section.content
// First, handle main sections with (a), (b), etc.
.replace(/\(a\)/g, '<br/><br/><strong>(a)</strong>')
.replace(/\(b\)/g, '<br/><br/><strong>(b)</strong>')
.replace(/\(c\)/g, '<br/><br/><strong>(c)</strong>')
.replace(/\(d\)/g, '<br/><br/><strong>(d)</strong>')
.replace(/\(e\)/g, '<br/><br/><strong>(e)</strong>')
.replace(/\(f\)/g, '<br/><br/><strong>(f)</strong>')
.replace(/\(g\)/g, '<br/><br/><strong>(g)</strong>')
.replace(/\(h\)/g, '<br/><br/><strong>(h)</strong>')
.replace(/\(i\)/g, '<br/><br/><strong>(i)</strong>')
.replace(/\(j\)/g, '<br/><br/><strong>(j)</strong>')
.replace(/\(k\)/g, '<br/><br/><strong>(k)</strong>')
.replace(/\(l\)/g, '<br/><br/><strong>(l)</strong>')
// Handle pipe separators for contact information
.replace(/ \| /g, '<br/><strong>')
.replace(/: /g, ':</strong> ')
// Handle semicolon with parenthesis
.replace(/; \(/g, ';<br/><br/>(')
// Add spacing after periods in long sentences
.replace(/\. ([A-Z])/g, '.<br/><br/>$1')
}} />
</div>
))}
</div>
{/* Contact Section */}
<div className="policy-footer">
<div className="contact-box">
<h3>Questions?</h3>
<p>If you have any questions about this policy, please don't hesitate to contact us.</p>
<a href="/contact-us" className="btn btn-primary">Contact Us</a>
</div>
</div>
</div>
</div>
</div>
<style jsx>{`
.policy-section {
background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
min-height: 100vh;
padding: 120px 0 80px;
}
.policy-header {
text-align: center;
margin-bottom: 3rem;
padding-bottom: 2rem;
border-bottom: 2px solid #e5e7eb;
}
.policy-title {
font-size: 2.5rem;
font-weight: 700;
color: #0f172a;
margin-bottom: 1rem;
}
.policy-meta {
display: flex;
justify-content: center;
gap: 2rem;
flex-wrap: wrap;
margin-bottom: 1rem;
}
.policy-meta p {
margin: 0;
}
.policy-updated,
.policy-version,
.policy-effective {
color: #64748b;
font-size: 0.95rem;
font-style: italic;
}
.policy-version {
color: #daa520;
font-weight: 600;
font-style: normal;
}
.policy-description {
color: #475569;
font-size: 1.1rem;
margin-top: 1rem;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.policy-content {
margin-bottom: 3rem;
}
.policy-section-item {
margin-bottom: 2.5rem;
padding: 2rem;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.policy-section-item:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
.policy-heading {
font-size: 1.5rem;
font-weight: 600;
color: #1e293b;
margin-bottom: 1rem;
}
.policy-text {
color: #475569;
font-size: 1rem;
line-height: 1.8;
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
.policy-text strong {
color: #1e293b;
font-weight: 600;
}
.policy-text :global(br) {
content: "";
display: block;
margin: 0.5rem 0;
}
.policy-footer {
margin-top: 4rem;
padding-top: 3rem;
border-top: 2px solid #e5e7eb;
}
.contact-box {
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
padding: 3rem;
border-radius: 12px;
text-align: center;
color: #ffffff;
}
.contact-box h3 {
font-size: 1.75rem;
margin-bottom: 1rem;
color: #ffffff;
}
.contact-box p {
font-size: 1.1rem;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 1.5rem;
}
.btn-primary {
display: inline-block;
padding: 0.875rem 2rem;
background: linear-gradient(135deg, #daa520, #d4af37);
color: #0f172a;
text-decoration: none;
border-radius: 8px;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(218, 165, 32, 0.3);
}
@media (max-width: 768px) {
.policy-section {
padding: 100px 0 60px;
}
.policy-title {
font-size: 2rem;
}
.policy-meta {
flex-direction: column;
gap: 0.5rem;
}
.policy-section-item {
padding: 1.5rem;
}
.policy-heading {
font-size: 1.25rem;
}
.contact-box {
padding: 2rem;
}
.contact-box h3 {
font-size: 1.5rem;
}
}
`}</style>
</section>
);
};
const PolicyPage = () => {
return (
<div className="tp-app">
<Header />
<main>
<Suspense fallback={<div>Loading...</div>}>
<PolicyContent />
</Suspense>
</main>
<Footer />
</div>
);
};
export default PolicyPage;