Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions public/assets/icons/side-menu/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 23 additions & 16 deletions src/components/mobile/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client';

import { useRouter } from 'next/navigation';
import Sidebar from '@/components/mobile/SidebarMenu/index';
import { useState } from 'react';
import IconArrow from 'public/assets/icons/icon-arrow.svg';
import IconHamburger from 'public/assets/icons/icon-hamburger.svg';

Expand All @@ -11,28 +13,33 @@ interface HeaderProps {

export default function Header({ title, menu = false }: HeaderProps) {
const router = useRouter();
const [isSidebarOpen, setIsSidebarOpen] = useState(false);

return (
<section className="h-8.5 flex w-full items-center justify-between px-4 py-1.5">
<button
className="h-6 w-6 items-center justify-center"
type="button"
onClick={() => router.back()}
>
<IconArrow />
</button>
<div className="font-medium leading-6 text-black-primary">{title}</div>
{menu ? (
<>
<section className="h-8.5 flex w-full items-center justify-between px-4 py-1.5">
<button
className="h-6 w-6 items-center justify-center"
type="button"
onClick={() => console.log('사이드바 오픈!')}
onClick={() => router.back()}
>
<IconHamburger />
<IconArrow />
</button>
) : (
<div className="h-6 w-6" />
)}
</section>
<div className="font-medium leading-6 text-black-primary">{title}</div>
{menu ? (
<button
className="h-6 w-6 items-center justify-center"
type="button"
onClick={() => setIsSidebarOpen(true)}
>
<IconHamburger />
</button>
) : (
<div className="h-6 w-6" />
)}
</section>

<Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
</>
);
}
121 changes: 121 additions & 0 deletions src/components/mobile/SidebarMenu/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
'use client';

import { useEffect } from 'react';
import IconClose from 'public/assets/icons/side-menu/close.svg';
import IconRentalList from 'public/assets/icons/side-menu/rental-item-list.svg';
import IconRentalHistory from 'public/assets/icons/side-menu/rental-history.svg';
import IconUserAlarm from 'public/assets/icons/side-menu/user-alarm.svg';
import IconAdminDashboard from 'public/assets/icons/side-menu/admin-dashboard.svg';
import IconAdminAlarm from 'public/assets/icons/side-menu/admin-alarm.svg';
import IconLogout from 'public/assets/icons/side-menu/logout.svg';

interface SidebarProps {
isOpen: boolean;
onClose: () => void;
}

const menuItems = [
{ icon: IconRentalList, label: '복지 물품 목록', href: '/mobile/main' },
{ icon: IconRentalHistory, label: '대여기록', href: '/mobile/history' },
{ icon: IconUserAlarm, label: '알림', href: '/mobile/notification' },
];

const adminItems = [
{
icon: IconAdminDashboard,
label: '관리자 대시보드',
href: '/mobile/admin/dashboard',
},
{
icon: IconAdminAlarm,
label: '관리자 알림',
href: '/mobile/admin/notification',
},
];

const logoutItem = {
icon: IconLogout,
label: '로그아웃',
href: '/mobile/sign-in',
};

export default function Sidebar({ isOpen, onClose }: SidebarProps) {
return (
<>
{/* 오버레이 배경 */}
<div
className={`fixed inset-0 z-40 bg-black bg-opacity-50 transition-opacity ${
isOpen ? 'visible opacity-100' : 'invisible opacity-0'
}`}
onClick={onClose}
/>

{/* 사이드바 */}
<aside
className={`fixed right-0 top-0 z-50 h-full w-3/5 transform bg-white-primary transition-transform ${
isOpen ? 'translate-x-0' : 'translate-x-full'
}`}
>
<div className="flex items-center justify-end px-4 py-3">
<button type="button" onClick={onClose}>
<IconClose />
</button>
</div>
<nav className="p-5">
<div className="border-b border-gray-border pb-2 text-heading-4_M font-semibold text-black-primary">
메뉴
</div>

{/* 사용자 메뉴 */}
<ul className="text-body-2-normal_semi font-semibold text-black-primary">
{menuItems.map(({ icon: Icon, label, href }) => (
<li key={label}>
<a
href={href}
className="mt-3 flex items-center gap-3 rounded p-2 hover:bg-gray-100"
>
<Icon />
{label}
</a>
</li>
))}
</ul>

{/* 첫 번째 구분선 */}
<div className="my-5 border-t border-gray-border" />

{/* 관리자 메뉴 */}
<ul className="text-body-2-normal_semi font-semibold text-black-primary">
{adminItems.map(({ icon: Icon, label, href }) => (
<li key={label}>
<a
href={href}
className="mt-3 flex items-center gap-3 rounded p-2 hover:bg-gray-100"
>
<Icon />
{label}
</a>
</li>
))}
</ul>

{/* 두 번째 구분선 */}
<div className="my-5 border-t border-gray-border" />

{/* 로그아웃 버튼 */}
<ul className="text-body-2-normal_semi font-semibold text-black-primary">
<li key={logoutItem.label}>
<a
href={logoutItem.href}
className="mt-3 flex items-center gap-3 rounded p-2 hover:bg-gray-100"
>
<logoutItem.icon />
{logoutItem.label}
</a>
</li>
</ul>
</nav>
</aside>
</>
);
}
2 changes: 2 additions & 0 deletions src/components/mobile/layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client';

import React, { useEffect } from 'react';

interface MobileLayoutProps {
Expand Down