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
30 changes: 24 additions & 6 deletions src/app/mobile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
'use client';

import MobileLayout from '@/components/mobile/layout';
import Header from '@/components/mobile/Header';
import Dropdown from '@/components/mobile/Dropdown';
import useDropdown from '@/hooks/useDropdown';

export default function Mobile() {
const dropdownActions = [
{ title: '전체', func: () => console.log('전체') },
{ title: '대여 신청', func: () => console.log('대여 신청') },
{ title: '반납 신청', func: () => console.log('반납 신청') },
];

const { showDropdown, hideDropdown, isDropdownVisible } = useDropdown();

return (
<MobileLayout>
{/* <div className="w-full bg-main-primary">
<h1>국민대학교 소프트웨어융합대학</h1>
<p className="text-3xl font-bold">복지물품 대여 시스템</p>
</div> */}
<Header title="관리자 대시보드" menu />
<Dropdown
actions={dropdownActions}
isVisible={isDropdownVisible}
hideDropdown={hideDropdown}
positionClasses="top-5 right-5"
/>
<button type="button" onClick={showDropdown}>
열기
</button>
<button type="button" onClick={hideDropdown}>
닫기
</button>
</MobileLayout>
);
}
61 changes: 61 additions & 0 deletions src/components/mobile/Dropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useEffect, useRef } from 'react';
import { cn } from '@/lib/utils';

interface DropdownProps {
actions: { title: string; func: () => void }[];
isVisible: boolean;
hideDropdown: () => void;
positionClasses?: string;
}

export default function Dropdown({
actions,
isVisible,
hideDropdown,
positionClasses = 'top-0 right-0',
}: DropdownProps) {
const dropdownRef = useRef<HTMLUListElement | null>(null);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
hideDropdown();
}
};

document.addEventListener('mousedown', handleClickOutside);

return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [hideDropdown]);

return (
<ul
ref={dropdownRef}
className={cn(
'absolute z-10 flex min-w-28 flex-col gap-3 rounded-[20px] border-none bg-white-primary px-3.5 py-4 shadow-md',
positionClasses,
!isVisible && 'hidden',
)}
>
{actions.map((action) => (
<li key={action.title}>
<button
type="button"
onClick={() => {
action.func();
hideDropdown();
}}
className="flex text-sm font-medium leading-none"
>
{action.title}
</button>
</li>
))}
</ul>
);
}
14 changes: 14 additions & 0 deletions src/hooks/useDropdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';

import { useState } from 'react';

const useDropdown = () => {
const [isDropdownVisible, setIsDropdownVisible] = useState(false);

const showDropdown = () => setIsDropdownVisible(true);
const hideDropdown = () => setIsDropdownVisible(false);

return { showDropdown, hideDropdown, isDropdownVisible };
};

export default useDropdown;