forked from UKSOURCE/hailearning.edu.vn
151 lines
6.8 KiB
TypeScript
151 lines
6.8 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
import Image from 'next/image';
|
|
import Link from 'next/link';
|
|
import headerData from './header.json';
|
|
|
|
interface SocialLink {
|
|
platform: string;
|
|
url: string;
|
|
icon: string;
|
|
}
|
|
|
|
interface MenuItem {
|
|
label: string;
|
|
href: string;
|
|
children?: MenuItem[];
|
|
}
|
|
|
|
interface OffcanvasProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const Offcanvas: React.FC<OffcanvasProps> = ({ isOpen, onClose }) => {
|
|
// Explicitly casting headerData to the expected structure
|
|
const data = headerData as {
|
|
top: {
|
|
socialLinks: SocialLink[];
|
|
};
|
|
offcanvas: {
|
|
description: string;
|
|
contactInfo: {
|
|
address: string;
|
|
email: string;
|
|
workingHours: string;
|
|
phone: string;
|
|
};
|
|
};
|
|
menu: MenuItem[];
|
|
};
|
|
|
|
const { offcanvas, top, menu } = data;
|
|
|
|
return (
|
|
<>
|
|
<div className="fix-area">
|
|
<div className={`offcanvas__info ${isOpen ? 'info-open' : ''}`}>
|
|
<div className="offcanvas__wrapper">
|
|
<div className="offcanvas__content">
|
|
<div className="offcanvas__top mb-5 d-flex justify-content-between align-items-center">
|
|
<div className="offcanvas__logo">
|
|
<Link href="/">
|
|
<Image
|
|
src="/assets/img/logo/black-logo.svg"
|
|
alt="logo-img"
|
|
width={150}
|
|
height={50}
|
|
priority
|
|
/>
|
|
</Link>
|
|
</div>
|
|
<div className="offcanvas__close">
|
|
<button onClick={onClose} aria-label="Close menu">
|
|
<i className="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<p className="text d-none d-xl-block">
|
|
{offcanvas.description}
|
|
</p>
|
|
|
|
{/* Mobile Menu Area */}
|
|
<div className="mobile-menu fix mb-3 d-xl-none">
|
|
<nav className="mean-nav">
|
|
<ul>
|
|
{menu.map((item: MenuItem, idx: number) => (
|
|
<li key={idx}>
|
|
<Link href={item.href} onClick={onClose}>
|
|
{item.label}
|
|
</Link>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
|
|
<div className="offcanvas__contact d-xl-block">
|
|
<h4 className="d-xl-block">Contact Info</h4>
|
|
<ul className="d-xl-block">
|
|
<li className="d-flex align-items-center">
|
|
<div className="offcanvas__contact-icon">
|
|
<i className="fal fa-map-marker-alt"></i>
|
|
</div>
|
|
<div className="offcanvas__contact-text">
|
|
<a target="_blank" href="#" rel="noopener noreferrer">
|
|
{offcanvas.contactInfo.address}
|
|
</a>
|
|
</div>
|
|
</li>
|
|
<li className="d-flex align-items-center">
|
|
<div className="offcanvas__contact-icon mr-15">
|
|
<i className="fal fa-envelope"></i>
|
|
</div>
|
|
<div className="offcanvas__contact-text">
|
|
<a href={`mailto:${offcanvas.contactInfo.email}`}>
|
|
<span>{offcanvas.contactInfo.email}</span>
|
|
</a>
|
|
</div>
|
|
</li>
|
|
<li className="d-flex align-items-center">
|
|
<div className="offcanvas__contact-icon mr-15">
|
|
<i className="fal fa-clock"></i>
|
|
</div>
|
|
<div className="offcanvas__contact-text">
|
|
<span>{offcanvas.contactInfo.workingHours}</span>
|
|
</div>
|
|
</li>
|
|
<li className="d-flex align-items-center">
|
|
<div className="offcanvas__contact-icon mr-15">
|
|
<i className="far fa-phone"></i>
|
|
</div>
|
|
<div className="offcanvas__contact-text">
|
|
<a href={`tel:${offcanvas.contactInfo.phone.replace(/\s/g, '')}`}>
|
|
{offcanvas.contactInfo.phone}
|
|
</a>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
<div className="social-icon d-flex align-items-center">
|
|
{top.socialLinks.map((social: SocialLink, idx: number) => (
|
|
<a key={idx} href={social.url} target="_blank" rel="noopener noreferrer">
|
|
<i className={social.icon}></i>
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={`offcanvas__overlay ${isOpen ? 'overlay-open' : ''}`}
|
|
onClick={onClose}
|
|
></div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Offcanvas;
|