Add user profile customization with name, role, email, and phone

- Add UserProfileSchema to ClientSettings with name, role, email, phone fields
- Update database layer to persist profile data in client_settings table
- Rewrite ProfileOverlay component as editable form with save/cancel actions
- Update Topbar to display user's initials from profile name
- Profile data loaded on app mount and saved via settings.update RPC

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 00:26:57 -04:00
parent 0624026af3
commit c8a39e6416
4 changed files with 126 additions and 6 deletions

View File

@@ -187,6 +187,8 @@ export type ClientSettings = z.infer<typeof import("./rpcSchemas.js").ClientSett
export type ServerSettings = z.infer<typeof import("./rpcSchemas.js").ServerSettingsSchema>;
export type UserProfile = z.infer<typeof import("./rpcSchemas.js").UserProfileSchema>;
export type RpcRequestMap = {
"portfolio.get": undefined;
"portfolio.addHolding": { ticker: string };

View File

@@ -28,12 +28,20 @@ const tickerString = z.string().trim().min(1).max(16);
const nonNegativeIndex = z.number().int().min(0);
const unknownRecord = z.record(z.unknown());
export const UserProfileSchema = z.object({
name: z.string().min(1).default(""),
role: z.string().min(1).default(""),
email: z.string().email().optional(),
phone: z.string().optional(),
});
export const ClientSettingsSchema = z.object({
theme: z.enum(["light", "dark", "system"]),
density: z.enum(["comfortable", "compact", "dense"]),
sidebarWidth: z.number().int().min(160).max(520),
navCollapsed: z.record(z.boolean()),
keybindings: z.record(z.string()),
profile: UserProfileSchema.partial().default({}),
});
export const ServerSettingsSchema = z.object({