mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
201 lines
11 KiB
React
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;
|
|
|