feat(02-02): login page UI, header/sidebar auth wiring, i18n keys
- Create split-screen login page with branding left (#ffed00) and form right (D-01) - Login form has username, password, and remember-me checkbox (D-02) - Wire header user avatar with auth store: shows user initial, dropdown with role badge and logout - Wire sidebar footer with auth store: shows user name, role, and initial - Add auth, header role, and admin i18n keys to both de.json and en.json - All new UI strings use t() function (no hardcoded text) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,11 +2,21 @@
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useSidebarStore } from '@/lib/stores/sidebar-store';
|
||||
import { useAuthStore } from '@/lib/stores/auth-store';
|
||||
import { LocaleSwitcher } from '@/components/locale-switcher';
|
||||
|
||||
export function SidebarFooter() {
|
||||
const t = useTranslations('sidebar');
|
||||
const tHeader = useTranslations('header');
|
||||
const isCollapsed = useSidebarStore((s) => s.isCollapsed);
|
||||
const user = useAuthStore((s) => s.user);
|
||||
|
||||
const userInitial = user
|
||||
? (user.displayName ?? user.username).charAt(0).toUpperCase()
|
||||
: '?';
|
||||
|
||||
const userName = user?.displayName ?? user?.username ?? t('userPlaceholder');
|
||||
const roleLabel = user ? tHeader(`role.${user.role}`) : '';
|
||||
|
||||
return (
|
||||
<div className="border-t border-sidebar-border p-3 flex flex-col gap-2">
|
||||
@@ -39,29 +49,22 @@ export function SidebarFooter() {
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* User info placeholder */}
|
||||
{/* User info - wired to auth store */}
|
||||
<div className="flex items-center gap-3 px-2 py-1.5">
|
||||
<div className="h-7 w-7 shrink-0 rounded-full bg-muted flex items-center justify-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
||||
<circle cx="12" cy="7" r="4" />
|
||||
</svg>
|
||||
<div className="h-7 w-7 shrink-0 rounded-full bg-primary flex items-center justify-center text-xs font-medium text-primary-foreground">
|
||||
{userInitial}
|
||||
</div>
|
||||
{!isCollapsed && (
|
||||
<span className="text-sm text-sidebar-foreground truncate">
|
||||
{t('userPlaceholder')}
|
||||
</span>
|
||||
<div className="flex flex-col overflow-hidden">
|
||||
<span className="text-sm text-sidebar-foreground truncate">
|
||||
{userName}
|
||||
</span>
|
||||
{user && (
|
||||
<span className="text-xs text-muted-foreground truncate">
|
||||
{roleLabel}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user