Files
starr-philproperties/src/modules/public/layouts/LandingLayout.jsx
T
2026-05-05 23:16:22 +08:00

201 lines
11 KiB
React

/***********************************************************************************************************************************************************************
* File Name: NavbarLayout.jsx
* Type of Program: Layout Route
* Description: A Layout router for Landing page.
* Module: Public User
* Author: lash0000
* Date Created: Oct. 10, 2025
***********************************************************************************************************************************************************************
* Change History:
* DATE AUTHOR LOG NUMBER DESCRIPTION
* Oct. 10, 2025 lash0000 001 Initial creation - STAR Phase 1 Project
***********************************************************************************************************************************************************************/
import { Fragment, useEffect, useRef } from 'react';
import { useTheme } from '@/contexts/ThemeContext';
import { NavLink, Link } from 'react-router-dom';
import { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger } from "@/components/ui/drawer"
import { Button } from '@/components/ui/button';
import { Toaster } from "@/components/ui/sonner"
import { RippleButton } from '@/components/custom/ripple-button';
import { Moon, Sun, Equal, Home, NotepadText, CircleUser, CroissantIcon, DoorOpen } from 'lucide-react';
import Footer from '../pages/LandingFooter';
function LandingLayout({ children }) {
const { theme, toggleTheme } = useTheme();
const drawerCloseRef = useRef(null);
useEffect(() => {
const handleResize = () => {
const isLargeScreen = window.matchMedia('(min-width: 1024px)').matches;
if (isLargeScreen && drawerCloseRef.current) {
drawerCloseRef.current.click();
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const scrollToId = (id) => {
const el = document.getElementById(id)
if (!el) return
const offset = 150
const top = el.getBoundingClientRect().top + window.scrollY - offset
window.scrollTo({ top, behavior: 'smooth' })
}
return (
<Fragment>
<nav className="fixed top-0 left-0 w-full h-fit flex items-center justify-between xs:px-6 lg:px-16 py-3 font-medium bg-background z-50 border">
<div className="inline-flex items-center space-x-2 text-card-foreground selection:bg-card-foreground selection:text-white dark:selection:bg-card-foreground dark:selection:text-black">
<div className="xs:w-32 lg:w-48">
<img src="/philpro-white.png" alt="" className="block dark:hidden w-auto" />
<img src="/philpro-dark.png" alt="" className="hidden dark:block w-auto" />
</div>
</div>
<div className='flex items-center'>
<div className="xs:hidden lg:block">
<div className="flex text-card-foreground selection:bg-card-foreground selection:text-white dark:selection:bg-card-foreground dark:selection:text-black gap-1.5">
<Button asChild variant="ghost" className="px-3">
<NavLink
to="."
onClick={() => scrollToId("home")}
className={({ isActive }) => `${isActive ? 'underline' : ''}`}
>
Home
</NavLink>
</Button>
<Button asChild variant="ghost" className="px-3">
<NavLink
to="."
onClick={() => scrollToId("about")}
className={({ isActive }) => ` ${isActive ? 'underline' : ''}`}
>
About
</NavLink>
</Button>
<Button asChild variant="ghost" className="px-3">
<NavLink
to="."
onClick={() => scrollToId("contacts")}
className={({ isActive }) => `${isActive ? 'underline' : ''}`}
>
Contacts
</NavLink>
</Button>
<Button asChild variant="ghost" className="px-3">
<NavLink
to="."
onClick={() => scrollToId("contacts")}
className={({ isActive }) => ` ${isActive ? 'underline' : ''}`}
>
FAQs
</NavLink>
</Button>
<Button className="dark:bg-blue-600 dark:text-white dark:hover:opacity-80" asChild>
<NavLink
to="/login"
onClick={() => scrollToId("contacts")}
className={({ isActive }) => `${isActive ? 'underline' : ''}`}
>
Sign in
</NavLink>
</Button>
<Button
variant="outline"
onClick={toggleTheme}
className="text-card-foreground cursor-pointer"
>
{theme === 'light' ? (<> <Moon /> Dark </>) : (<> <Sun /> Light </>)}
</Button>
</div>
</div>
<Drawer>
<Button
variant="outline"
onClick={toggleTheme}
className="mr-3 text-card-foreground cursor-pointer lg:hidden"
>
{theme === 'light' ? (<> <Moon /> Dark </>) : (<> <Sun /> Light </>)}
</Button>
<DrawerTrigger asChild>
<Button size="icon" className=" dark:bg-blue-500 dark:text-white lg:hidden">
<Equal />
</Button>
</DrawerTrigger>
<DrawerContent className="font-geist">
<DrawerHeader>
<DrawerTitle className="text-lg">
Made with {String.fromCodePoint('0x1f499')}
</DrawerTitle>
<DrawerDescription>Explore more.</DrawerDescription>
</DrawerHeader>
<div className="flex flex-col gap-2 p-4 font-medium text-sm">
<Link to="">
<RippleButton rippleColor="#ADD8E6" className="w-full justify-start text-card-foreground" onClick={() => drawerCloseRef.current?.click()}>
<div className='flex items-center space-x-3'>
<Home size={16} />
<label>Home</label>
</div>
</RippleButton>
</Link>
<Link to="">
<RippleButton rippleColor="#ADD8E6" className="w-full justify-start text-card-foreground" onClick={() => drawerCloseRef.current?.click()}>
<div className='flex items-center space-x-3'>
<NotepadText size={16} />
<label>About</label>
</div>
</RippleButton>
</Link>
<Link to="">
<RippleButton rippleColor="#ADD8E6" className="w-full justify-start text-card-foreground" onClick={() => drawerCloseRef.current?.click()}>
<div className='flex items-center space-x-3'>
<CircleUser size={16} />
<label>Contacts</label>
</div>
</RippleButton>
</Link>
<Link to="">
<RippleButton rippleColor="#ADD8E6" className="w-full justify-start text-card-foreground" onClick={() => drawerCloseRef.current?.click()}>
<div className='flex items-center space-x-3'>
<CroissantIcon size={16} />
<label>FAQs</label>
</div>
</RippleButton>
</Link>
<Link to="/login">
<RippleButton className="dark:bg-blue-500 dark:text-white w-full justify-start bg-primary text-primary-foreground" onClick={() => drawerCloseRef.current?.click()}>
<div className='flex items-center space-x-3'>
<DoorOpen size={16} />
<label>Sign in</label>
</div>
</RippleButton>
</Link>
</div>
<DrawerFooter>
<DrawerClose ref={drawerCloseRef} />
</DrawerFooter>
</DrawerContent>
</Drawer>
</div>
</nav>
<main id="main-page" className='pt-28'>
{children}
<Toaster position="top-center" />
</main>
{/* add footer */}
<Footer />
</Fragment>
);
}
export default LandingLayout;