Files
sanaz-goodarzi/components/shell.js
T
2026-09-15 20:37:49 +03:30

47 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useEffect, useRef, useState } from 'react';
import { Menu, X, ArrowUpLeft, Instagram, Mail, ArrowUp } from 'lucide-react';
import { navigation, offices, phones, emails, instagram } from '../lib/content';
import AccountMenu from './account-menu';
export function Brand({branding={},dark=false}) {const src=(dark?branding.logoDarkUrl:branding.logoUrl)||branding.logoUrl||'/Logo.png';return <span className="brand"><img className="brand-logo" src={src} alt="لوگوی ساناز گودرزی" width="462" height="473"/><span className="brand-wordmark"><span className="brand-name">ساناز گودرزی<span className="brand-dot">.</span></span><span className="brand-caption" dir="ltr">ARCHITECTURE & INTERIOR DESIGN</span></span></span>}
export function Header({branding={}}) {
const path=usePathname(); const [open,setOpen]=useState(false); const dialog=useRef(null); const trigger=useRef(null);
useEffect(() => {
const panel = dialog.current;
if (!open && !panel.open) return;
const previousOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
if (open && !panel.open) panel.showModal();
panel.dataset.phase = open ? 'opening' : 'closing';
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const animation = panel.animate(
open
? [{ transform: 'translateX(100%)', opacity: .4 }, { transform: 'translateX(0)', opacity: 1 }]
: [{ transform: 'translateX(0)', opacity: 1 }, { transform: 'translateX(100%)', opacity: 0 }],
{ duration: reduced ? 0 : open ? 440 : 260, easing: 'cubic-bezier(.22,1,.36,1)', fill: 'both' }
);
animation.finished.then(() => {
if (!open) {
panel.close();
document.body.style.overflow = previousOverflow;
trigger.current?.focus();
}
}).catch(() => {});
return () => {
animation.cancel();
document.body.style.overflow = previousOverflow;
};
}, [open]);
return <><header className={`site-header ${path==='/'?'over-hero':''}`}><div className="header-inner"><Link href="/" aria-label="گروه معماری ساناز گودرزی، صفحهٔ اصلی"><Brand branding={branding}/></Link><nav className="desktop-nav" aria-label="ناوبری اصلی">{navigation.map(([href,label])=><Link key={href} href={href} aria-current={path===href?'page':undefined}>{label}</Link>)}</nav><div className="header-actions"><AccountMenu/><button ref={trigger} className="menu-button" onClick={()=>setOpen(true)} aria-label="باز کردن منو" aria-expanded={open} aria-controls="mobile-menu"><Menu/></button></div></div></header><dialog id="mobile-menu" className="mobile-menu" ref={dialog} onCancel={event=>{event.preventDefault();setOpen(false)}} onClick={e=>{if(e.target===dialog.current)setOpen(false)}}><div className="menu-top"><Brand branding={branding} dark/><button className="icon-button" aria-label="بستن منو" onClick={()=>setOpen(false)}><X/></button></div><nav aria-label="منوی موبایل">{navigation.map(([href,label],i)=><Link onClick={()=>setOpen(false)} key={href} href={href} aria-current={path===href?'page':undefined}><small>{String(i+1).padStart(2,'0')}</small>{label}<ArrowUpLeft/></Link>)}</nav><a href={`tel:${phones[0].value}`} className="menu-phone" dir="ltr">{phones[0].label}</a></dialog></>;
}
export function Footer({branding={}}) {
const pathname = usePathname();
if (pathname === '/') return null;
return <footer className="site-footer"><div className="reference-footer-main">
<div className="reference-footer-intro"><Link href="/"><Brand branding={branding} dark/></Link><p>این مجموعه در راستای رسیدن به اهداف بزرگ خود در حال وسعت بخشیدن به آتلیه‌های معماری خود می‌باشد.<br/>و در همین راستا در حال تلاش برای طراحی و ساخت بناهای عظیم معماری در این مرزوبوم و خارج از آن می‌باشد و با برنامه‌ریزی و اجرای طرح‌واره‌های هدفمند گام بزرگی را در این مسیر نهاده که به‌زودی همگان شاهد آن خواهیم بود.</p></div>
<div className="reference-footer-details"><div className="footer-contact"><h3>با ما در ارتباط باشید</h3>{phones.map(phone=><a key={phone.value} href={`tel:${phone.value}`} dir="ltr">{phone.label}</a>)}{emails.map(email=><a className="email" key={email} href={`mailto:${email}`} dir="ltr">{email}</a>)}<div className="social-links"><a href={instagram} target="_blank" rel="noreferrer" aria-label="اینستاگرام ساناز گودرزی"><Instagram size={20}/></a><a href={`mailto:${emails[0]}`} aria-label="ارسال ایمیل"><Mail size={20}/></a></div></div>
<div className="footer-offices"><h3>نشانی ما</h3>{offices.map(office=><p key={office.city}>{office.city} — {office.address}{office.latin&&<span dir="ltr">{office.latin}</span>}</p>)}</div></div>
</div><nav className="reference-footer-nav" aria-label="پیوندهای پایین صفحه">{navigation.map(([href,label])=><Link key={href} href={href}>{label}</Link>)}</nav><div className="footer-bottom"><div className="container footer-bottom-bar"><span>گروه معماری ساناز گودرزی</span><a href="https://meshkee.com" target="_blank" rel="noopener noreferrer" dir="ltr" className="meshkee-credit"><span className="meshkee-credit__frame" aria-hidden="true"><i/><i/><i/><i/></span><img src="/meshkee-logo.png" alt="Meshkee" width="42" height="42"/><span className="meshkee-credit__text"><span>Designed And Developed By</span><strong>Meshkee E-Commerce Team</strong></span></a><a className="back-top" href="#main" aria-label="بازگشت به بالای صفحه"><ArrowUp size={18}/></a></div></div></footer>}