fix: gộp các nút thành viên và bỏ MemberDashboard

This commit is contained in:
2026-06-27 16:53:19 +07:00
parent 400a3d098d
commit 4ee46371fa
14 changed files with 2638 additions and 497 deletions
+57 -40
View File
@@ -1,29 +1,31 @@
import React, { useState } from 'react';
import { LayoutDashboard, Settings, Compass, ShieldAlert, LogOut, LogIn, Globe, Sun, Moon, Image as ImageIcon } from 'lucide-react';
import { Compass, Map, Image as ImageIcon, Settings, ShieldAlert, Users, LogOut, LogIn, Globe, Sun, Moon } from 'lucide-react';
import { useTranslation } from '@/hooks/useTranslation';
import { useTheme } from '@/hooks/useTheme';
interface MapProfileDropdownProps {
user: any;
onLogout?: () => void;
onGoToDashboard?: () => void;
onOpenSettings: () => void;
onOpenCreateTour: () => void;
onOpenReport: () => void;
onOpenLogin: () => void;
onOpenMyPhotos?: () => void;
onOpenMyPhotos: () => void;
onOpenMyTours: () => void;
onOpenFriends: () => void;
onOpenAdmin?: () => void;
}
export const MapProfileDropdown: React.FC<MapProfileDropdownProps> = ({
user,
onLogout,
onGoToDashboard,
onOpenSettings,
onOpenCreateTour,
onOpenReport,
onOpenLogin,
onOpenMyPhotos,
onOpenMyTours,
onOpenFriends,
onOpenAdmin,
}) => {
const [isOpen, setIsOpen] = useState(false);
@@ -44,6 +46,11 @@ export const MapProfileDropdown: React.FC<MapProfileDropdownProps> = ({
);
};
const handleItemClick = (callback: () => void) => {
setIsOpen(false);
callback();
};
return (
<div className="relative inline-block text-left select-none pointer-events-auto">
{/* TRIGGER BUTTON */}
@@ -69,17 +76,18 @@ export const MapProfileDropdown: React.FC<MapProfileDropdownProps> = ({
{isOpen && (
<>
<div
className="fixed inset-0 z-40 bg-black/50 sm:bg-transparent"
className="fixed inset-0 z-[999998] bg-black/50 sm:bg-transparent"
onClick={() => setIsOpen(false)}
/>
<div
className="fixed bottom-0 left-0 right-0 sm:absolute sm:bottom-auto sm:top-14 sm:right-0 sm:left-auto z-50 w-full sm:w-64 bg-slate-900 border-t sm:border border-slate-800 rounded-t-3xl sm:rounded-2xl p-3 sm:p-2 shadow-2xl animate-in slide-in-from-bottom sm:slide-in-from-top-2 duration-300 text-xs text-slate-200"
className="fixed bottom-0 left-0 right-0 sm:absolute sm:bottom-auto sm:top-14 sm:right-0 sm:left-auto z-[999999] w-full sm:w-64 bg-slate-900 border-t sm:border border-slate-800 rounded-t-3xl sm:rounded-2xl p-3 sm:p-2 shadow-2xl animate-in slide-in-from-bottom sm:slide-in-from-top-2 duration-300 text-xs text-slate-200"
>
<div className="w-12 h-1 bg-slate-700 rounded-full mx-auto mb-3 sm:hidden" />
{isAuthenticated ? (
<div className="flex flex-col space-y-1">
{/* User info header */}
<div className="px-4 py-2 border-b border-slate-800/60 mb-1 flex items-center gap-3">
<div className="w-8 h-8 rounded-full overflow-hidden shrink-0 border border-slate-700">
{user?.avatar ? (
@@ -94,57 +102,73 @@ export const MapProfileDropdown: React.FC<MapProfileDropdownProps> = ({
</div>
</div>
{/* Extra System Admin option */}
{user?.isAdmin && (
<button
onClick={() => { setIsOpen(false); onOpenAdmin?.(); }}
className="flex items-center gap-3 w-full px-4 py-3 bg-blue-950/20 hover:bg-slate-805 rounded-xl text-left transition-colors font-bold text-blue-400 cursor-pointer"
onClick={() => handleItemClick(onOpenAdmin || (() => {}))}
className="flex items-center gap-3 w-full px-4 py-2.5 bg-blue-950/20 hover:bg-slate-800 rounded-lg text-left transition-colors font-bold text-blue-400 cursor-pointer"
>
<Settings className="w-4 h-4 shrink-0 text-blue-400" /> Quản trị hệ thống
</button>
)}
{/* 1. Tạo tour */}
<button
onClick={() => { setIsOpen(false); onGoToDashboard?.(); }}
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-xl text-left transition-colors font-bold cursor-pointer"
onClick={() => handleItemClick(onOpenCreateTour)}
className="flex items-center gap-3 w-full px-4 py-2.5 hover:bg-slate-800 rounded-lg text-left transition-colors font-semibold cursor-pointer"
>
<LayoutDashboard className="w-4 h-4 text-blue-400 shrink-0" /> Bảng điều khiển
<Compass className="w-4 h-4 text-amber-400 shrink-0" /> Tạo tour
</button>
{/* 2. Hành trình của tôi */}
<button
onClick={() => { setIsOpen(false); onOpenSettings(); }}
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-xl text-left transition-colors font-bold cursor-pointer"
onClick={() => handleItemClick(onOpenMyTours)}
className="flex items-center gap-3 w-full px-4 py-2.5 hover:bg-slate-800 rounded-lg text-left transition-colors font-semibold cursor-pointer"
>
<Settings className="w-4 h-4 text-emerald-400 shrink-0" /> Cài đt cá nhân
</button>
<button
onClick={() => { setIsOpen(false); onOpenCreateTour(); }}
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-xl text-left transition-colors font-bold cursor-pointer"
>
<Compass className="w-4 h-4 text-amber-400 shrink-0" /> Tạo Tour mới
<Map className="w-4 h-4 text-blue-400 shrink-0" /> Hành trình của tôi
</button>
{/* 3. Thư viện ảnh */}
<button
onClick={() => { setIsOpen(false); onOpenMyPhotos?.(); }}
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-xl text-left transition-colors font-bold cursor-pointer"
onClick={() => handleItemClick(onOpenMyPhotos)}
className="flex items-center gap-3 w-full px-4 py-2.5 hover:bg-slate-800 rounded-lg text-left transition-colors font-semibold cursor-pointer"
>
<ImageIcon className="w-4 h-4 text-sky-400 shrink-0" /> nh của tôi
<ImageIcon className="w-4 h-4 text-emerald-400 shrink-0" /> Thư viện nh
</button>
{/* 4. Cài đặt */}
<button
onClick={() => { setIsOpen(false); onOpenReport(); }}
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-xl text-left transition-colors font-bold cursor-pointer"
onClick={() => handleItemClick(onOpenSettings)}
className="flex items-center gap-3 w-full px-4 py-2.5 hover:bg-slate-800 rounded-lg text-left transition-colors font-semibold cursor-pointer"
>
<ShieldAlert className="w-4 h-4 text-rose-400 shrink-0" /> Báo cáo sai phạm
<Settings className="w-4 h-4 text-slate-400 shrink-0" /> Cài đt
</button>
<div className="h-[1px] bg-slate-855 my-1 mx-2" />
{/* 5. Báo cáo vi phạm */}
<button
onClick={() => { setIsOpen(false); onLogout?.(); }}
className="flex items-center gap-3 w-full px-4 py-3 text-rose-400 hover:bg-slate-800 rounded-xl text-left font-black transition-colors cursor-pointer"
onClick={() => handleItemClick(onOpenReport)}
className="flex items-center gap-3 w-full px-4 py-2.5 hover:bg-slate-800 rounded-lg text-left transition-colors font-semibold cursor-pointer"
>
<LogOut className="w-4 h-4 shrink-0" /> Đăng xuất
<ShieldAlert className="w-4 h-4 text-rose-400 shrink-0" /> Báo cáo vi phạm
</button>
{/* STRICT VISUAL DIVIDER LINE */}
<div className="border-b border-slate-800 my-1 mx-2" />
{/* 6. Danh sách bạn bè */}
<button
onClick={() => handleItemClick(onOpenFriends)}
className="flex items-center gap-3 w-full px-4 py-2.5 hover:bg-slate-800 rounded-lg text-left transition-colors font-semibold cursor-pointer"
>
<Users className="w-4 h-4 text-indigo-400 shrink-0" /> Danh sách bạn
</button>
{/* 7. Đăng xuất */}
<button
onClick={() => handleItemClick(onLogout || (() => {}))}
className="flex items-center gap-3 w-full px-4 py-2.5 text-rose-400 hover:bg-slate-800 rounded-lg text-left font-bold transition-colors cursor-pointer"
>
<LogOut className="w-4 h-4 shrink-0 text-rose-500" /> Đăng xuất
</button>
</div>
) : (
@@ -188,17 +212,10 @@ export const MapProfileDropdown: React.FC<MapProfileDropdownProps> = ({
</div>
</div>
<button
onClick={() => { setIsOpen(false); onOpenMyPhotos?.(); }}
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-xl text-left transition-colors font-bold cursor-pointer"
>
<ImageIcon className="w-4 h-4 text-sky-400 shrink-0" /> nh của tôi
</button>
<div className="h-[1px] bg-slate-850 my-1 mx-2" />
<button
onClick={() => { setIsOpen(false); onOpenLogin(); }}
onClick={() => handleItemClick(onOpenLogin)}
className="flex items-center gap-3 w-full px-4 py-3 text-blue-400 hover:bg-slate-800 rounded-xl text-left font-black transition-colors cursor-pointer"
>
<LogIn className="w-4 h-4 shrink-0" /> Đăng / Đăng nhập