Files
nobat724_front/components/layout/footer/index.js
T
hamedandClaude Opus 5 45f94743fd feat(footer): name the visitor's city in the search chip and link the chips
The first chip said "your city" on every domain even though each domain is
already scoped to one; it now carries that city's name, falling back to the
old wording on the root domain, which has no city. Both site chips link to
"/" — relative, so each domain lands on its own home page rather than
throwing the visitor onto another one — and the third is retitled to name
the product it points at.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 15:10:18 +03:30

179 lines
6.2 KiB
JavaScript

"use client";
import { footerL, footerR } from "@/constans";
import Logo from "@/app/component/Logo";
import Link from "next/link";
// Icons
import Linkedin from "../../icons/Linkedin";
import Telegram from "../../icons/Telegram";
import Whatsapp from "../../icons/Whatsapp";
import Instagram from "../../icons/Instagram";
import LocationF from "../../icons/LocationF";
import CalendarAddF from "../../icons/CalendarAddF";
import StethoscopeF from "../../icons/StethoscopeF";
import LogoNamad from "./LogoNamad";
import HeadMenu from "./menu/HeadMenu";
import ListMenu from "./menu/ListMenu";
import { useState } from "react";
import { isRootCity } from "@/lib/rootCity";
// روی دامنهٔ ریشه (nobat724.com) شهری در کار نیست، پس همان «شهر شما» می‌ماند؛
// روی دامنهٔ هر شهر، نام همان شهر می‌نشیند. لینک نسبی است تا هر دامنه به ریشهٔ
// خودش برود و کاربر بین دامنه‌ها پرت نشود.
const buildHead = (matchedCity) => {
const cityName = isRootCity(matchedCity) ? null : matchedCity?.name;
return [
{
icon: <LocationF />,
text: cityName ? `جستجوی پزشک در شهر ${cityName}` : "جستجوی پزشک در شهر شما",
link: "/",
},
{ icon: <CalendarAddF />, text: "نوبت گیری سریع و آسان", link: "/" },
{
icon: <StethoscopeF />,
text: "مدیریت کلینیک با کلینیک پرو",
link: "https://clinic-pro.ir/",
},
];
};
function buildSocialUrl(name, value) {
if (!value) return null;
if (/^https?:\/\//i.test(value)) return value;
const handle = value.replace(/^@/, "").replace(/^\+/, "");
switch (name) {
case "instagram":
return `https://instagram.com/${handle}`;
case "telegram":
return `https://t.me/${handle}`;
case "whatsapp":
// wa.me needs international format: 09xx… → 989xx…
return `https://wa.me/${handle.replace(/\D/g, "").replace(/^0/, "98")}`;
default:
return value;
}
}
function Footer({ matchedCity }) {
const socialMedias = [
{
icon: <Instagram />,
name: "instagram",
},
{
icon: <Telegram />,
name: "telegram",
},
{
icon: <Whatsapp />,
name: "whatsapp",
},
];
const [openMenu, setOpenMenu] = useState({
right: false,
left: false,
});
const changeMenu = (name) =>
setOpenMenu({ ...openMenu, [name]: !openMenu[name] });
return (
<div className="pb-[11px]">
<div className="flex items-center justify-evenly gap-[12px]">
{buildHead(matchedCity).map((item, idx) => (
<Link key={idx} href={item.link}>
<div
className="flex flex-col lg:flex-row items-center cursor-pointer justify-start gap-1 p-[6px] hover:transition-all transition-all duration-300 hover:duration-300 rounded-[8px] border-solid border border-[#EFEFEF] bg-[#F7F7F7] hover:bg-none hover:border-[#FDBD9F]"
>
{item.icon}
<p className="text-[#2F2F2F] text-center text-[12px] sm:text-[14px] md:text-[16px] font-medium">
{item.text}
</p>
</div>
</Link>
))}
</div>
<span className="h-px bg-[#D7D7D7] mb-[40px] mt-[48px] w-full block"></span>
<div
className="pb-[16px] sm:pb-[18px] md:pb-[19px] lg:pb-[21px] flex flex-col gap-[16px] lg:gap-0 lg:flex-row items-start justify-between"
>
{/* Right */}
<div className="w-full lg:w-fit flex gap-[12px] lg:gap-[30px] flex-col items-start">
{/* Icon */}
<Logo matchedCity={matchedCity} />
<p className="w-full lg:w-fit lg:max-w-[260px] text-[#616161] text-[14px] font-normal">
{matchedCity?.footer_description}
</p>
<div className="hidden lg:flex">
<LogoNamad />
</div>
</div>
{/* Center */}
<div className="w-full lg:w-fit">
<HeadMenu
title={footerR[0]}
isOpen={openMenu.right}
name="right"
changeMenu={changeMenu}
/>
<ListMenu list={footerR} isOpen={openMenu.right} />
</div>
<div className="w-full lg:w-fit">
<HeadMenu
title={footerL[0]}
isOpen={openMenu.left}
name="left"
changeMenu={changeMenu}
/>
<ListMenu list={footerL} isOpen={openMenu.left} />
</div>
{/* Left */}
<div className="w-full lg:w-fit flex flex-row lg:flex-col items-center lg:items-start justify-center gap-[32px]">
<p className="text-[#3B3B3B] after:!duration-500 w-fit text-[16px] after:hover:w-full after:transition-all after:hover:bg-[#F17732] font-bold pb-1.5 relative after:absolute after:right-0 after:h-0.5 after:bottom-0 after:w-0">
همراه با ما باشید:
</p>
<ul className="flex items-center gap-[8px] sm:gap-[11px] md:gap-[13px] lg:gap-[15px]">
{socialMedias.map((item, idx) => {
const url = buildSocialUrl(item.name, matchedCity?.social_media?.[item.name]);
return (
<li
key={idx}
className="p-2.5 bg-[#EAECFA] hover-rotate-icon cursor-pointer rounded-full w-fit"
>
{url ? (
<a
href={url}
target="_blank"
rel="noopener noreferrer"
className="min-h-fit"
aria-label={item.name}
>
{item.icon}
</a>
) : (
<span className="min-h-fit" role="img" aria-label={item.name}>
{item.icon}
</span>
)}
</li>
);
})}
</ul>
</div>
<div className="flex lg:hidden justify-center w-full mt-2">
<LogoNamad />
</div>
</div>
<p className="text-center text-[#7E7E7E] text-[12px] font-normal">
{matchedCity?.footerDisclaimer}
</p>
</div>
);
}
export default Footer;