My Account Page
The /account route gives each authenticated user a dedicated page to manage their profile — display name and avatar. It is accessible via the "Account" link in the header profile dropdown.
Layout
┌─────────────────────────────────────────────────────┐
│ [Avatar card — left] [Personal info form — right]│
│ │
│ ┌──────────────┐ ┌───────────────────────┐ │
│ │ [Avatar] │ │ First Name [input] │ │
│ │ Full Name │ │ Last Name [input] │ │
│ │ email@... │ │ Email [read] │ │
│ │ │ │ │ │
│ │[Change avatar│ │ [Save changes] │ │
│ │ button] │ └───────────────────────┘ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────┘
Avatar picker modal
Clicking "Change avatar" opens the AvatarPicker modal (coreComponents/AvatarPicker.tsx).
Preset avatars
Six preset thumbnails sourced from the Zono theme's avtar/ folder. Defined as a static array in utils/index.ts:
export const AVATAR_PRESETS = [
{ id: "avtar-2", src: "/assets/images/avtar/2.jpg" },
{ id: "avtar-3", src: "/assets/images/avtar/3.jpg" },
{ id: "avtar-4", src: "/assets/images/avtar/4.jpg" },
{ id: "avtar-7", src: "/assets/images/avtar/7.jpg" },
{ id: "avtar-8", src: "/assets/images/avtar/8.jpg" },
{ id: "avtar-10", src: "/assets/images/avtar/10.jpg" },
];
To change the preset images: replace the image files in public/assets/images/avtar/ and update the AVATAR_PRESETS array to match.
Photo upload
The user can upload any image file. The frontend:
- Reads the file as a data URL with
FileReader - Draws it onto a 256×256 canvas (center-cropped)
- Exports as JPEG at 85% quality
- Rejects files whose base64 representation exceeds 512 KB
The resulting base64 data URL is stored in cloud.users.usr_avatar_url.
Avatar resolution helper
getUserAvatar(avatarUrl?) in utils/index.ts resolves the correct image source:
avatarUrl value | Resolved source |
|---|---|
null / undefined | /assets/images/user/user.png (default) |
starts with / or http | used as-is (preset path) |
starts with data: | used as-is (base64 upload) |
Used by the Account page, the AvatarPicker preview, the header Profile widget, and the lock screen.
API calls
| Action | Endpoint | Method |
|---|---|---|
| Save name | /api/auth/profile | PATCH |
| Save avatar | /api/auth/profile/avatar | PATCH |
Both endpoints return the updated UserInfo object. The frontend dispatches updateUser(result) to update the Redux store immediately.
Redux
updateUser(payload: Partial<UserInfo>) reducer in reduxToolkit/reducers/layout/authSlice.ts — merges the returned UserInfo into the current user state.
Files
| File | Role |
|---|---|
pages/account/index.tsx | Account page component |
coreComponents/AvatarPicker.tsx | Avatar picker modal |
utils/index.ts | AVATAR_PRESETS, getUserAvatar() |
services/authService.ts | updateProfile(), updateAvatar() |
reduxToolkit/reducers/layout/authSlice.ts | updateUser reducer |
routers/routes.ts | Account: '/account' |
routers/AppRoutes.tsx | Protected route for /account |