Update website layout to include a redesigned footer section
Implement a new footer component in AppLayout.tsx and add translations for footer links and text in translations.ts. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 1fa9329f-0cec-4a2f-80e8-e26dbae3142e Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 183f5c8d-3782-49ac-b611-3d83bcfdd05b Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/4d696b13-86f2-4c9d-be0d-95b293430047/1fa9329f-0cec-4a2f-80e8-e26dbae3142e/GHSmanY Replit-Helium-Checkpoint-Created: true
This commit is contained in:
@@ -1,21 +1,142 @@
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
import { Link } from "wouter";
|
||||||
|
import { Phone, Apple, Play } from "lucide-react";
|
||||||
import { Header } from "./Header";
|
import { Header } from "./Header";
|
||||||
import ehsanLogo from "../../assets/ehsan-logo.png";
|
import { useLanguage } from "../../contexts/LanguageContext";
|
||||||
|
|
||||||
|
function XIcon({ className = "" }: { className?: string }) {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" className={className}>
|
||||||
|
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24h-6.66l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FooterLink {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
internal?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export function AppLayout({ children }: { children: ReactNode }) {
|
export function AppLayout({ children }: { children: ReactNode }) {
|
||||||
|
const { t } = useLanguage();
|
||||||
|
const f = t.footer;
|
||||||
|
|
||||||
|
const overviewLinks: FooterLink[] = [
|
||||||
|
{ label: f.overviewAbout, href: "/about", internal: true },
|
||||||
|
{ label: f.overviewCommittees, href: "/about/committees", internal: true },
|
||||||
|
{ label: f.overviewSms, href: "#" },
|
||||||
|
{ label: f.overviewSitemap, href: "#" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const supportLinks: FooterLink[] = [
|
||||||
|
{ label: f.supportComplaints, href: "#" },
|
||||||
|
{ label: f.supportSla, href: "#" },
|
||||||
|
{ label: f.supportFaq, href: "#" },
|
||||||
|
{ label: f.supportPrivacy, href: "#" },
|
||||||
|
{ label: f.supportAccessibility, href: "#" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const renderLink = (link: FooterLink) => {
|
||||||
|
const cls =
|
||||||
|
"text-sm text-white/80 transition-colors hover:text-white";
|
||||||
|
if (link.internal) {
|
||||||
|
return (
|
||||||
|
<Link key={link.label} href={link.href} className={cls}>
|
||||||
|
{link.label}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<a key={link.label} href={link.href} className={cls}>
|
||||||
|
{link.label}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-[100dvh] flex flex-col bg-background font-sans">
|
<div className="min-h-[100dvh] flex flex-col bg-background font-sans">
|
||||||
<Header />
|
<Header />
|
||||||
<main className="flex-1">
|
<main className="flex-1">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
<footer className="border-t bg-white mt-auto py-8">
|
<footer className="mt-auto bg-[#14573A] text-white">
|
||||||
<div className="container mx-auto px-4 flex flex-col items-center gap-3 text-center">
|
<div className="container mx-auto px-4 py-12">
|
||||||
<img src={ehsanLogo} alt="EHSAN" className="h-9 w-auto object-contain" />
|
<div className="grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
<p className="text-sm text-muted-foreground">
|
{/* Overview */}
|
||||||
EHSAN POC © {new Date().getFullYear()}
|
<nav aria-label={f.overviewTitle} className="flex flex-col items-center gap-4 text-center lg:items-start lg:text-start">
|
||||||
|
<h3 className="text-base font-bold">{f.overviewTitle}</h3>
|
||||||
|
<div className="flex flex-col gap-3">{overviewLinks.map(renderLink)}</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Support */}
|
||||||
|
<nav aria-label={f.supportTitle} className="flex flex-col items-center gap-4 text-center lg:items-start lg:text-start">
|
||||||
|
<h3 className="text-base font-bold">{f.supportTitle}</h3>
|
||||||
|
<div className="flex flex-col gap-3">{supportLinks.map(renderLink)}</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Contact + App download */}
|
||||||
|
<div className="flex flex-col items-center gap-6 text-center sm:col-span-2 lg:col-span-1 lg:items-start lg:text-start">
|
||||||
|
<div className="flex flex-col items-center gap-4 lg:items-start">
|
||||||
|
<h3 className="text-base font-bold">{f.contactTitle}</h3>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
aria-label={f.phoneLabel}
|
||||||
|
className="flex h-10 w-10 items-center justify-center rounded-full border border-white/40 text-white transition-colors hover:bg-white hover:text-[#14573A]"
|
||||||
|
>
|
||||||
|
<Phone className="h-4 w-4" aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
aria-label={f.xLabel}
|
||||||
|
className="flex h-10 w-10 items-center justify-center rounded-full border border-white/40 text-white transition-colors hover:bg-white hover:text-[#14573A]"
|
||||||
|
>
|
||||||
|
<XIcon className="h-3.5 w-3.5" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col items-center gap-4 lg:items-start">
|
||||||
|
<h3 className="text-base font-bold">{f.downloadTitle}</h3>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
aria-label={f.appStoreLabel}
|
||||||
|
className="flex h-10 w-10 items-center justify-center rounded-lg border border-white/40 text-white transition-colors hover:bg-white hover:text-[#14573A]"
|
||||||
|
>
|
||||||
|
<Apple className="h-5 w-5" aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
aria-label={f.googlePlayLabel}
|
||||||
|
className="flex h-10 w-10 items-center justify-center rounded-lg border border-white/40 text-white transition-colors hover:bg-white hover:text-[#14573A]"
|
||||||
|
>
|
||||||
|
<Play className="h-5 w-5" aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom bar */}
|
||||||
|
<div className="mt-10 flex flex-col items-center gap-6 border-t border-white/15 pt-6 sm:flex-row sm:justify-between">
|
||||||
|
<div className="flex items-center gap-6">
|
||||||
|
<div className="flex flex-col leading-tight">
|
||||||
|
<span className="text-lg font-extrabold tracking-wide">SDAIA</span>
|
||||||
|
<span className="text-[10px] text-white/70">{f.sdaiaSubtitle}</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-8 w-px bg-white/20" aria-hidden="true" />
|
||||||
|
<div className="flex flex-col leading-tight">
|
||||||
|
<span className="text-sm font-bold tracking-[0.2em]">{f.visionLine1}</span>
|
||||||
|
<span className="text-xl font-extrabold tracking-tight">{f.visionLine2}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-white/70">
|
||||||
|
{f.rights} © {new Date().getFullYear()}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -423,6 +423,29 @@ export const en = {
|
|||||||
failed: "Failed",
|
failed: "Failed",
|
||||||
noEntries: "No WhatsApp log entries yet.",
|
noEntries: "No WhatsApp log entries yet.",
|
||||||
},
|
},
|
||||||
|
footer: {
|
||||||
|
overviewTitle: "Overview",
|
||||||
|
overviewAbout: "About EHSAN",
|
||||||
|
overviewCommittees: "Committees",
|
||||||
|
overviewSms: "Donate by SMS",
|
||||||
|
overviewSitemap: "Sitemap",
|
||||||
|
supportTitle: "Support & Help",
|
||||||
|
supportComplaints: "Complaints",
|
||||||
|
supportSla: "Service Level Agreement",
|
||||||
|
supportFaq: "FAQ",
|
||||||
|
supportPrivacy: "Privacy Policy",
|
||||||
|
supportAccessibility: "Accessibility",
|
||||||
|
contactTitle: "Contact Us",
|
||||||
|
phoneLabel: "Call us",
|
||||||
|
xLabel: "EHSAN on X",
|
||||||
|
downloadTitle: "Download the EHSAN app",
|
||||||
|
appStoreLabel: "Download on the App Store",
|
||||||
|
googlePlayLabel: "Get it on Google Play",
|
||||||
|
sdaiaSubtitle: "Saudi Data & AI Authority",
|
||||||
|
visionLine1: "VISION",
|
||||||
|
visionLine2: "2030",
|
||||||
|
rights: "All rights reserved to EHSAN platform",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ar = {
|
export const ar = {
|
||||||
@@ -850,4 +873,27 @@ export const ar = {
|
|||||||
failed: "فشل",
|
failed: "فشل",
|
||||||
noEntries: "لا توجد سجلات واتساب بعد.",
|
noEntries: "لا توجد سجلات واتساب بعد.",
|
||||||
},
|
},
|
||||||
|
footer: {
|
||||||
|
overviewTitle: "نظرة عامة",
|
||||||
|
overviewAbout: "عن إحسان",
|
||||||
|
overviewCommittees: "اللجان",
|
||||||
|
overviewSms: "التبرع بالرسائل النصية",
|
||||||
|
overviewSitemap: "خريطة الموقع",
|
||||||
|
supportTitle: "الدعم والمساعدة",
|
||||||
|
supportComplaints: "استقبال الشكاوى",
|
||||||
|
supportSla: "اتفاقية مستوى الخدمة",
|
||||||
|
supportFaq: "الأسئلة الشائعة",
|
||||||
|
supportPrivacy: "سياسة الخصوصية",
|
||||||
|
supportAccessibility: "إمكانية الوصول",
|
||||||
|
contactTitle: "تواصل معنا",
|
||||||
|
phoneLabel: "اتصل بنا",
|
||||||
|
xLabel: "إحسان على منصة X",
|
||||||
|
downloadTitle: "حمل تطبيق إحسان",
|
||||||
|
appStoreLabel: "حمله من App Store",
|
||||||
|
googlePlayLabel: "احصل عليه من Google Play",
|
||||||
|
sdaiaSubtitle: "الهيئة السعودية للبيانات والذكاء الاصطناعي",
|
||||||
|
visionLine1: "رؤية",
|
||||||
|
visionLine2: "2030",
|
||||||
|
rights: "جميع الحقوق محفوظة لمنصة إحسان",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user