feat: initial commit

This commit is contained in:
2026-04-09 20:52:10 -03:00
commit 1a92cc6c11
86 changed files with 19533 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
import { MenuBurgerButton } from '@/ui/components/internal/header/mobile-header/utils/menu-burguer-button';
import ThemeToggle from '@/ui/components/internal/theme-toggle';
export type BaseMobileHeaderProps = {
active?: boolean;
onStateChange?: (value: boolean) => void;
};
export const BaseMobileHeader = ({
active,
onStateChange,
}: BaseMobileHeaderProps) => {
return (
<div className='flex items-center space-x-4'>
<ThemeToggle></ThemeToggle>
<MenuBurgerButton
state={active ?? false}
onStateChange={onStateChange}
/>
</div>
);
};

View File

@@ -0,0 +1,62 @@
'use client';
import { getSessionData } from '@/lib/session/session-storage';
import { BaseMobileHeader } from '@/ui/components/internal/header/mobile-header/base-mobile-header';
import { HeaderSlider } from '@/ui/components/internal/header/mobile-header/utils/header-slider';
import { UserButton } from '@/ui/components/internal/user-profile/user-profile-button';
import { useQuery } from '@tanstack/react-query';
import Link from 'next/link';
import { useState } from 'react';
export const DynamicMobileHeader = () => {
const { data: sessionData } = useQuery({
queryKey: ['sessionData'],
queryFn: async () => {
return await getSessionData();
},
});
const user = sessionData?.user;
const [isNavigationState, setNavigationState] = useState(false);
const links = [
{ href: '/home', label: 'Home', condition: true },
{ href: '/about', label: 'About', condition: true },
{ href: '/admin', label: 'Admin', condition: !!user },
];
const userButton = !!user ? <UserButton user={user} /> : <div />;
return (
<>
<BaseMobileHeader
active={isNavigationState}
onStateChange={(value: boolean) => setNavigationState(value)}
/>
<HeaderSlider
isOpen={isNavigationState}
onClose={() => setNavigationState(false)}
>
<div className='h-full flex flex-col items-center justify-center'>
<div className='h-2/3 flex flex-col items-start justify-around'>
{links
.filter((link) => link.condition)
.map((link) => (
<Link
key={link.href}
href={link.href}
className='text-xl font-normal transition-colors hover:font-bold hover:text-primary'
>
{link.label}
</Link>
))}
</div>
<div className='h-1/3 flex items-center space-x-4 mt-4'>
{userButton}
</div>
</div>
</HeaderSlider>
</>
);
};

View File

@@ -0,0 +1,5 @@
import { BaseMobileHeader } from '@/ui/components/internal/header/mobile-header/base-mobile-header';
export const StaticMobileHeader = () => {
return <BaseMobileHeader active={false} />;
};

View File

@@ -0,0 +1,29 @@
export const HeaderSlider = ({
children,
isOpen,
onClose,
}: Readonly<{
children: React.ReactNode;
isOpen: boolean;
onClose?: () => void;
}>) => {
const clickedOutside = () => {
if (onClose) onClose();
};
return (
<div
className={`absolute top-[8dvh] right-0 flex col w-full duration-300
${isOpen ? '' : 'delay-300 translate-x-[102vw]'}`}
>
<div
className={`page-height w-1/2 transition-all ease-in-out duration-300 ${
isOpen ? 'delay-300 bg-black/60' : 'bg-black/0'
}`}
onClick={clickedOutside}
/>
{/* Only slide the content panel */}
<div className={`bg-background page-height w-1/2`}>{children}</div>
</div>
);
};

View File

@@ -0,0 +1,41 @@
'use client';
type MenuBurgerButtonProps = {
state: boolean;
onStateChange?: (value: boolean) => void;
};
export const MenuBurgerButton = ({
state,
onStateChange,
}: MenuBurgerButtonProps) => {
state = state ?? false;
// This function is called when the button is clicked
const handleClick = () => {
if (onStateChange) onStateChange(!state);
};
return (
<div
className='flex flex-col md:hidden w-10 h-10 justify-center items-center cursor-pointer relative'
onClick={handleClick}
>
<span
className={`w-8 h-[4px] bg-primary rounded transition-all duration-200 ${
state ? 'opacity-0' : 'opacity-100'
}`}
/>
<span
className={`absolute w-8 h-[4px] bg-primary rounded transition-all duration-200 ${
state ? 'rotate-45' : '-translate-y-[10px]'
}`}
/>
<span
className={`absolute w-8 h-[4px] bg-primary rounded transition-all duration-200 ${
state ? '-rotate-45' : 'translate-y-[10px]'
}`}
/>
</div>
);
};