Files
cnb-center/src/pages/auth/modules/BaseHeader.tsx
abearxiong 7ec6428643 feat: add repository management dialogs and store functionality
- Implement CreateRepoDialog for creating new repositories with form validation.
- Implement EditRepoDialog for editing existing repository details.
- Implement SyncRepoDialog for syncing repositories with Gitea, including repository creation if necessary.
- Implement WorkspaceDetailDialog for managing workspace links and actions.
- Enhance the repo store with new state management for repository actions, including creating, editing, and syncing repositories.
- Add build configuration utilities for repository synchronization.
- Create a new page for repository management, integrating all dialogs and functionalities.
- Add login route for authentication.
2026-02-25 01:02:55 +08:00

80 lines
2.6 KiB
TypeScript

import { Home, User, LogIn, LogOut } from 'lucide-react';
import { Link, useNavigate } from '@tanstack/react-router'
import { useLayoutStore } from '../store';
import { useShallow } from 'zustand/shallow';
import { useMemo } from 'react';
export const BaseHeader = (props: { main?: React.ComponentType | null }) => {
const store = useLayoutStore(useShallow(state => ({
me: state.me,
clearMe: state.clearMe,
links: state.links,
})));
const navigate = useNavigate();
const meInfo = useMemo(() => {
if (!store.me) {
return (
<button
onClick={() => navigate({ to: '/login' })}
className="flex items-center gap-2 px-3 py-1.5 text-sm text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
>
<LogIn className="w-4 h-4" />
<span></span>
</button>
)
}
return (
<div className="flex items-center gap-3">
{store.me.avatar && (
<img
src={store.me.avatar}
alt="Avatar"
className="w-8 h-8 rounded-full object-cover"
/>
)}
{!store.me.avatar && (
<div className="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center">
<User className="w-4 h-4 text-gray-500" />
</div>
)}
<span className="font-medium text-gray-700">{store.me?.username}</span>
<button
onClick={() => store.clearMe?.()}
className="flex items-center gap-1 px-2 py-1 text-sm text-gray-500 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors cursor-pointer"
title="退出登录"
>
<LogOut className="w-4 h-4" />
</button>
</div>
)
}, [store.me, store.clearMe])
return (
<>
<div className="flex gap-2 text-lg w-full h-12 items-center justify-between bg-gray-200">
<div className='px-2'>
{
store.links.map(link => (
<Link
key={link.key || link.title}
to={link.href}
className="px-3 py-1.5 text-sm text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors"
>
{link.key === 'home' && <Home className="w-4 h-4 mr-1" />}
{link.icon && <span className="mr-1">{link.icon}</span>}
{link.title}
</Link>
))
}
</div>
<div className='mr-4'>
{meInfo}
</div>
</div>
<hr />
</>
)
}
export const LayoutMain = () => {
return <BaseHeader />
}