Merge branch 'dev/hot-fix/randy' into 'development'

[HOTFIX/FE] Fixing Dropdown Button Logout

See merge request mbugroup/lti-web-client!80
This commit is contained in:
Adnan Zahir
2025-12-10 13:44:20 +07:00
4 changed files with 131 additions and 13 deletions
@@ -52,6 +52,7 @@ export default function ProjectFlockLayout({
closeOnBackdropClick={isDetail ? true : false}
onBackdropClick={handleBackdropClick}
variant='right'
zIndex='99999'
sidebarContent={isOpen && <div className=''>{children}</div>}
/>
</>
+1 -1
View File
@@ -54,7 +54,7 @@ const FloatingActionsButton = ({
<div
className={cn(
`absolute ${positionStyles} inset-x-1/2 -translate-x-1/2 z-50`,
'mx-auto w-full max-w-lg sm:mx-0 bg-base-300 p-4 rounded-xl shadow-md transition-all duration-300 transform',
'mx-auto w-full max-w-sm sm:mx-0 bg-base-300 p-4 rounded-xl shadow-md transition-all duration-300 transform',
'bg-slate-950 backdrop-blur-md'
)}
>
+13 -12
View File
@@ -7,6 +7,7 @@ import { Icon } from '@iconify/react';
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
import Button from '@/components/Button';
import Dropdown from '@/components/dropdown/Dropdown';
import { useAuth } from '@/services/hooks/useAuth';
import { AuthApi } from '@/services/api/auth';
@@ -52,21 +53,21 @@ const Navbar = ({ title, toggleSidebar }: NavbarProps) => {
</div>
<div className='flex gap-2'>
<div className='dropdown dropdown-end'>
<div
tabIndex={0}
role='button'
className='btn btn-ghost btn-circle avatar'
>
<div className='w-10 rounded-full border grid place-items-center'>
<Icon icon='uil:user' width={40} height={40} />
<Dropdown
position='bottom-end'
trigger={
<div className='btn btn-ghost btn-circle avatar'>
<div className='w-10 rounded-full border flex justify-center items-center'>
<Icon icon='uil:user' width={40} height={40} />
</div>
</div>
</div>
<Menu className='dropdown-content w-52 mt-3 p-2 bg-base-100 shadow rounded-box menu-sm'>
}
contentClassName='w-52 mt-3'
>
<Menu className='p-2 bg-base-100 shadow rounded-box menu-sm'>
<MenuItem title='Logout' onClick={logoutClickHandler} />
</Menu>
</div>
</Dropdown>
</div>
</div>
);
+116
View File
@@ -0,0 +1,116 @@
'use client';
import { ReactNode, useRef, useEffect, useState } from 'react';
import { cn } from '@/lib/helper';
interface DropdownProps {
trigger: ReactNode;
children: ReactNode;
position?:
| 'top'
| 'bottom'
| 'left'
| 'right'
| 'top-start'
| 'top-end'
| 'bottom-start'
| 'bottom-end'
| 'left-start'
| 'left-end'
| 'right-start'
| 'right-end';
align?: 'start' | 'center' | 'end';
hover?: boolean;
className?: string;
contentClassName?: string;
}
const Dropdown = ({
trigger,
children,
position = 'bottom',
align = 'start',
hover = false,
className,
contentClassName,
}: DropdownProps) => {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
// Handle click outside to close dropdown
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setIsOpen(false);
}
};
if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen]);
// Build position classes
const getPositionClasses = () => {
const classes: string[] = [];
// Handle combined positions like 'top-start'
if (position.includes('-')) {
const [pos, al] = position.split('-');
classes.push(`dropdown-${pos}`);
classes.push(`dropdown-${al}`);
} else {
classes.push(`dropdown-${position}`);
if (align !== 'start') {
classes.push(`dropdown-${align}`);
}
}
return classes.join(' ');
};
const handleToggle = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
// alert('clicked');
setIsOpen(!isOpen);
};
return (
<div
ref={dropdownRef}
className={cn(
'dropdown',
getPositionClasses(),
hover && 'dropdown-hover',
isOpen && 'dropdown-open',
className
)}
>
{/* Trigger Button */}
<div onClick={handleToggle} className='cursor-pointer'>
{trigger}
</div>
{/* Dropdown Content - Only render when open */}
{isOpen && (
<div
tabIndex={-1}
className={cn('dropdown-content z-[10]', contentClassName)}
onClick={() => setIsOpen(false)} // Close on item click
>
{children}
</div>
)}
</div>
);
};
export default Dropdown;