6039387857
- Zustand sidebar store with persist middleware (collapse/expand, mobile open) - Sticky header with logo, breadcrumb, theme toggle, locale switcher, user avatar - Collapsible sidebar with Dashboard/Marketplace nav, accordion categories, footer - Mobile responsive: hamburger menu with overlay sidebar on small screens - Theme toggle cycling light/dark/system with mounted guard - Locale switcher setting NEXT_LOCALE cookie with router.refresh - Empty dashboard state with grid icon, "Keine Widgets aktiv" text, add button - AppShell composing header + sidebar + responsive main content area - All user-visible strings via useTranslations (UI-03 compliance)
34 lines
1004 B
TypeScript
34 lines
1004 B
TypeScript
'use client';
|
|
|
|
import { useRouter } from 'next/navigation';
|
|
import { useLocale, useTranslations } from 'next-intl';
|
|
import { useTransition } from 'react';
|
|
|
|
export function LocaleSwitcher() {
|
|
const router = useRouter();
|
|
const locale = useLocale();
|
|
const t = useTranslations('locale');
|
|
const [isPending, startTransition] = useTransition();
|
|
|
|
function switchLocale() {
|
|
const newLocale = locale === 'de' ? 'en' : 'de';
|
|
document.cookie = `NEXT_LOCALE=${newLocale};path=/;max-age=31536000`;
|
|
startTransition(() => {
|
|
router.refresh();
|
|
});
|
|
}
|
|
|
|
const currentLabel = locale === 'de' ? t('de') : t('en');
|
|
|
|
return (
|
|
<button
|
|
onClick={switchLocale}
|
|
disabled={isPending}
|
|
className="inline-flex items-center justify-center rounded-md px-2.5 py-1.5 text-sm font-medium text-muted-foreground hover:bg-muted hover:text-foreground transition-colors disabled:opacity-50"
|
|
aria-label={currentLabel}
|
|
>
|
|
{locale === 'de' ? 'EN' : 'DE'}
|
|
</button>
|
|
);
|
|
}
|