Skip to main content

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:

  1. Reads the file as a data URL with FileReader
  2. Draws it onto a 256×256 canvas (center-cropped)
  3. Exports as JPEG at 85% quality
  4. 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 valueResolved source
null / undefined/assets/images/user/user.png (default)
starts with / or httpused 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

ActionEndpointMethod
Save name/api/auth/profilePATCH
Save avatar/api/auth/profile/avatarPATCH

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

FileRole
pages/account/index.tsxAccount page component
coreComponents/AvatarPicker.tsxAvatar picker modal
utils/index.tsAVATAR_PRESETS, getUserAvatar()
services/authService.tsupdateProfile(), updateAvatar()
reduxToolkit/reducers/layout/authSlice.tsupdateUser reducer
routers/routes.tsAccount: '/account'
routers/AppRoutes.tsxProtected route for /account