feat(profile): add username + preferred_locale; wire to Inertia + middleware

- DB: users.username (unique), users.preferred_locale (default from app.locale)
- Backend: validation, model fillable; share supportedLocales; SetLocaleFromUser
- Frontend: profile page fields + types
- Filament: SuperAdmin profile page with username/language

feat(admin-nav): move Tasks to Bibliothek and add menu labels

fix(tasks-table): show localized title/emotion/event type; add translated headers

feat(l10n): add missing table headers for emotions and event types; normalize en/de files

refactor: tidy translations for tasks/emotions/event types
This commit is contained in:
2025-09-11 21:17:19 +02:00
parent 40aa5fc188
commit fc1e64fea3
33 changed files with 960 additions and 161 deletions

View File

@@ -22,7 +22,7 @@ const breadcrumbs: BreadcrumbItem[] = [
];
export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail: boolean; status?: string }) {
const { auth } = usePage<SharedData>().props;
const { auth, supportedLocales } = usePage<SharedData>().props as SharedData & { supportedLocales: string[] };
return (
<AppLayout breadcrumbs={breadcrumbs}>
@@ -74,6 +74,40 @@ export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail:
<InputError className="mt-2" message={errors.email} />
</div>
<div className="grid gap-2">
<Label htmlFor="username">Username</Label>
<Input
id="username"
className="mt-1 block w-full"
defaultValue={(auth.user as any).username ?? ''}
name="username"
autoComplete="username"
placeholder="Username"
/>
<InputError className="mt-2" message={errors.username} />
</div>
<div className="grid gap-2">
<Label htmlFor="preferred_locale">Language</Label>
<select
id="preferred_locale"
name="preferred_locale"
defaultValue={(auth.user as any).preferred_locale ?? 'en'}
className="mt-1 block w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
>
{(supportedLocales ?? ['de', 'en']).map((l) => (
<option key={l} value={l}>
{l.toUpperCase()}
</option>
))}
</select>
<InputError className="mt-2" message={errors.preferred_locale} />
</div>
{mustVerifyEmail && auth.user.email_verified_at === null && (
<div>
<p className="-mt-4 text-sm text-muted-foreground">

View File

@@ -27,6 +27,7 @@ export interface SharedData {
quote: { message: string; author: string };
auth: Auth;
sidebarOpen: boolean;
supportedLocales?: string[];
[key: string]: unknown;
}
@@ -34,6 +35,8 @@ export interface User {
id: number;
name: string;
email: string;
username?: string;
preferred_locale?: string;
avatar?: string;
email_verified_at: string | null;
created_at: string;