Skip to content

Commit

Permalink
feat: 重构用户菜单组件,引入新的对话框组件以替代链接跳转方式,优化用户交互体验。
Browse files Browse the repository at this point in the history
  • Loading branch information
zyh320888 committed Oct 22, 2024
1 parent df93f0d commit 26fa196
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 68 deletions.
38 changes: 38 additions & 0 deletions app/components/auth/ProfileDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Dialog, DialogTitle, DialogDescription, DialogRoot } from '~/components/ui/Dialog';
import { useAuth } from '~/hooks/useAuth';

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

export function ProfileDialog({ isOpen, onClose }: ProfileDialogProps) {
const { user } = useAuth();

if (!user) return null;

return (
<DialogRoot open={isOpen}>
<Dialog onBackdrop={onClose} onClose={onClose}>
<DialogTitle>个人信息</DialogTitle>
<DialogDescription>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-bolt-elements-textPrimary">
昵称
</label>
<p className="mt-1 text-bolt-elements-textSecondary">{user.nickname}</p>
</div>
<div>
<label className="block text-sm font-medium text-bolt-elements-textPrimary">
手机号
</label>
<p className="mt-1 text-bolt-elements-textSecondary">{user.phone}</p>
</div>
{/* 可以根据需要添加更多用户信息 */}
</div>
</DialogDescription>
</Dialog>
</DialogRoot>
);
}
24 changes: 24 additions & 0 deletions app/components/auth/SubscriptionDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Dialog, DialogTitle, DialogDescription, DialogRoot } from '~/components/ui/Dialog';

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

export function SubscriptionDialog({ isOpen, onClose }: SubscriptionDialogProps) {
return (
<DialogRoot open={isOpen}>
<Dialog onBackdrop={onClose} onClose={onClose}>
<DialogTitle>订阅信息</DialogTitle>
<DialogDescription>
<div className="space-y-4">
<p className="text-bolt-elements-textSecondary">
这里显示用户的订阅信息。您可以根据实际需求添加更多详细内容。
</p>
{/* 可以添加更多订阅相关的信息 */}
</div>
</DialogDescription>
</Dialog>
</DialogRoot>
);
}
130 changes: 69 additions & 61 deletions app/components/header/UserMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,82 @@
import { Menu, Transition } from '@headlessui/react';
import { Fragment } from 'react';
import { Fragment, useState } from 'react';
import { useAuth } from '~/hooks/useAuth';
import { Avatar } from '~/components/ui/Avatar';
import { Link } from '@remix-run/react';
import { ProfileDialog } from '~/components/auth/ProfileDialog';
import { SubscriptionDialog } from '~/components/auth/SubscriptionDialog';

export function UserMenu() {
const { user, logout } = useAuth();
const [isProfileOpen, setIsProfileOpen] = useState(false);
const [isSubscriptionOpen, setIsSubscriptionOpen] = useState(false);

if (!user) return null;

return (
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button className="inline-flex items-center gap-x-1.5 rounded-md bg-bolt-elements-background-depth-2 px-3 py-2 text-sm font-medium text-bolt-elements-textPrimary hover:bg-bolt-elements-background-depth-3 transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-bolt-elements-button-primary-background">
<Avatar src={user.avatarUrl} alt={user.nickname} />
<span className="ml-2">{user.nickname}</span>
<div className="i-ph:caret-down-fill text-bolt-elements-textSecondary" aria-hidden="true" />
</Menu.Button>
</div>
<>
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button className="inline-flex items-center gap-x-1.5 rounded-md bg-bolt-elements-background-depth-1 px-3 py-2 text-sm font-medium text-bolt-elements-textPrimary hover:bg-bolt-elements-background-depth-2 transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-bolt-elements-button-primary-background">
<Avatar src={user.avatarUrl} alt={user.nickname} />
<span className="ml-2">{user.nickname}</span>
<div className="i-ph:caret-down-fill text-bolt-elements-textSecondary" aria-hidden="true" />
</Menu.Button>
</div>

<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-bolt-elements-background-depth-2 shadow-lg ring-1 ring-bolt-elements-borderColor focus:outline-none">
<div className="py-1">
<Menu.Item>
{({ active }) => (
<Link
to="/profile"
className={`${
active ? 'bg-bolt-elements-button-primary-background text-bolt-elements-button-primary-text' : 'text-bolt-elements-textSecondary'
} block px-4 py-2 text-sm transition-colors duration-150 ease-in-out`}
>
个人信息
</Link>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<Link
to="/subscription"
className={`${
active ? 'bg-bolt-elements-button-primary-background text-bolt-elements-button-primary-text' : 'text-bolt-elements-textSecondary'
} block px-4 py-2 text-sm transition-colors duration-150 ease-in-out`}
>
订阅信息
</Link>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<button
onClick={logout}
className={`${
active ? 'bg-bolt-elements-button-primary-background text-bolt-elements-button-primary-text' : 'text-bolt-elements-textSecondary'
} block w-full text-left px-4 py-2 text-sm transition-colors duration-150 ease-in-out`}
>
退出登录
</button>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-bolt-elements-background-depth-1 shadow-lg ring-1 ring-bolt-elements-borderColor focus:outline-none">
<div className="py-1">
<Menu.Item>
{({ active }) => (
<button
onClick={() => setIsProfileOpen(true)}
className={`${
active ? 'bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary' : 'text-bolt-elements-textSecondary'
} block w-full text-left px-4 py-2 text-sm transition-colors duration-150 ease-in-out`}
>
个人信息
</button>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<button
onClick={() => setIsSubscriptionOpen(true)}
className={`${
active ? 'bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary' : 'text-bolt-elements-textSecondary'
} block w-full text-left px-4 py-2 text-sm transition-colors duration-150 ease-in-out`}
>
订阅信息
</button>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<button
onClick={logout}
className={`${
active ? 'bg-bolt-elements-background-depth-2 text-bolt-elements-textPrimary' : 'text-bolt-elements-textSecondary'
} block w-full text-left px-4 py-2 text-sm transition-colors duration-150 ease-in-out`}
>
退出登录
</button>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>

<ProfileDialog isOpen={isProfileOpen} onClose={() => setIsProfileOpen(false)} />
<SubscriptionDialog isOpen={isSubscriptionOpen} onClose={() => setIsSubscriptionOpen(false)} />
</>
);
}
27 changes: 20 additions & 7 deletions app/hooks/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,25 @@ export function useAuth() {
const navigate = useNavigate();

useEffect(() => {
const token = localStorage.getItem('token');
const storedUser = localStorage.getItem('user');
if (token && storedUser) {
setIsAuthenticated(true);
setUser(JSON.parse(storedUser));
}
setIsLoading(false);
const checkAuth = () => {
const token = localStorage.getItem('token');
const storedUser = localStorage.getItem('user');
if (token && storedUser) {
setIsAuthenticated(true);
setUser(JSON.parse(storedUser));
} else {
setIsAuthenticated(false);
setUser(null);
}
setIsLoading(false);
};

checkAuth();
window.addEventListener('storage', checkAuth);

return () => {
window.removeEventListener('storage', checkAuth);
};
}, []);

const login = (token: string, userData: User) => {
Expand All @@ -36,6 +48,7 @@ export function useAuth() {
localStorage.removeItem('user');
setIsAuthenticated(false);
setUser(null);
navigate('/');
};

return { isAuthenticated, isLoading, user, login, logout };
Expand Down

0 comments on commit 26fa196

Please sign in to comment.