184 lines
9.4 KiB
Markdown
184 lines
9.4 KiB
Markdown
# Profile
|
|
|
|
- **Route:** `/profile`
|
|
- **API:** GET /v1/auth/me · PATCH /v1/user/me (pending) · POST /v1/auth/password-reset
|
|
- **Visual reference:** `source/RenewCMS Screens Back-office.dc.html`, group "Profile" (open it in a browser; each state is drawn at desktop and mobile, with a light/dark toggle).
|
|
|
|
Opened from the account menu at the bottom of the sidebar. Username, email and password are read-only. The display name is optional, trimmed, and up to 60 characters.
|
|
|
|
Once saved it replaces the username everywhere a person is named:
|
|
|
|
- the sidebar chip and the account menu (name, and the avatar initials)
|
|
- the Home greeting ("Good morning, Marta Alves")
|
|
- the Display name column of the Users list
|
|
- the emails RenewCMS sends, such as "Marta Alves invited you to RenewCMS"
|
|
|
|
Saving it empty goes back to the username. Logging in still uses the username.
|
|
|
|
The reset link uses the same flow as "Forgot password" and ends on the auth board's "Choose a new password" screen ([reset-password.md](reset-password.md)).
|
|
|
|
## The page
|
|
|
|
Three cards under the title "Profile" and the subtitle "Your account on this RenewCMS workspace.", 720 px wide at most.
|
|
|
|
| Card | Content |
|
|
|---|---|
|
|
| Display name | Title "Display name". Text "Shown instead of your username across the back-office and in the emails RenewCMS sends. Leave it empty to use your username." One input, label "Display name (optional)", placeholder "e.g. Marta Alves", with a live counter "n / 60" in mono on the right of the help row. A footer strip holds a status line on the left and the Save button on the right. |
|
|
| Account | Title "Account". Text "Set when your account was created. You log in with your username, even after adding a display name." Two disabled inputs with a lock icon: Username and Email (two columns on desktop, one on mobile). |
|
|
| Password | Title "Password". Text "To change it, we'll email a reset link to marta@renew.example. The link works once, within 1 hour." A disabled input showing "••••••••••••" beside the button "Send reset link" (mail icon). A note appears under them once a request has been made. |
|
|
|
|
**Footer status line** (12 px): "Unsaved changes" in the warning color while dirty and not saving. Otherwise "You appear as “Marta Alves”." when a display name is saved, or "You appear as “marta”, your username." when it isn't.
|
|
|
|
**Save button:** full opacity when the value changed and is valid, or while saving. 40 % opacity and inert otherwise. Enter in the field saves.
|
|
|
|
**Counting:** characters are counted as Unicode characters, not bytes or UTF-16 units. The counter turns red over 60.
|
|
|
|
**Leaving the page** with unsaved changes asks for confirmation.
|
|
|
|
**Mobile:** cards use 16 px padding, inputs are 44 px, the two account inputs stack, and the password input and its button stack.
|
|
|
|
## The account menu
|
|
|
|
Opened from the account chip at the bottom of the sidebar (chevrons-up-down icon; `aria-haspopup="menu"`, `aria-expanded`). The chip takes the sand fill with ink text while the menu is open, and while `/profile` is the current page.
|
|
|
|
Desktop: a 224 px popover above the chip, aligned to its left. Mobile: the account row in the navigation drawer opens it as a bottom sheet with a grab handle. Escape or a click outside closes both.
|
|
|
|
| Part | Content |
|
|
|---|---|
|
|
| Header | The name in semibold (display name, or the username), and the email in muted 12 px (14 px on mobile, with a 36 px initials avatar beside them) |
|
|
| Item | Profile (circle-user icon), highlighted while on `/profile` |
|
|
| Separator | |
|
|
| Label | "Theme": 11 px, weight 500, uppercase, letter-spacing .04em, muted |
|
|
| Items | System, Light, Dark: a radio-style group, the current choice carries a check icon at the right edge; choosing one applies the theme at once and keeps the menu open |
|
|
| Separator | |
|
|
| Label | "Language", styled like "Theme" |
|
|
| Items | English, Français (each in its own language, with `lang`): a radio-style group with a check on the current one; choosing one applies the language at once and keeps the menu open |
|
|
| Separator | |
|
|
| Item | Log out (log-out icon) |
|
|
|
|
Avatar initials come from the first letters of the first two words of the display name, uppercased ("Marta Alves" gives MA). Without a display name they come from the username.
|
|
|
|
The board's menu now carries System, Light and Dark, matching the shipped UserMenu. The theme choice stays in the account menu; the Profile page does not repeat it. Items are 32 px on desktop and 48 px in the mobile sheet.
|
|
|
|
## States
|
|
|
|
### Account menu
|
|
|
|
**Trigger:** The account chip at the bottom of the sidebar. On mobile, the account row in the navigation drawer opens it as a sheet. Escape or a click outside closes it.
|
|
|
|
- Breadcrumbs: Home (mobile title "Home")
|
|
- Page behind the menu: Home, default
|
|
- Menu open, as described above, with the Theme group (System, Light, Dark) and the Language group (English, Français) between Profile and Log out. The board shows Light and English checked
|
|
|
|
### Loading
|
|
|
|
**Trigger:** Opened directly by URL before /auth/me has returned. From the menu, the cached user renders straight away.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Three skeleton cards (one input, two inputs, one input)
|
|
|
|
### Default, no display name
|
|
|
|
**Trigger:** The usual first visit. The username is used everywhere.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Display name: empty, placeholder "e.g. Marta Alves", counter "0 / 60"
|
|
- Footer: "You appear as “marta”, your username."
|
|
- Save: 40 % opacity
|
|
|
|
### Editing
|
|
|
|
**Trigger:** Typing in the field. Save turns on, and leaving the page asks for confirmation.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Display name: "Marta Alves"; focused; counter "11 / 60"
|
|
- Footer: "Unsaved changes" (warning)
|
|
- Save: enabled
|
|
|
|
### Too long
|
|
|
|
**Trigger:** Over 60 characters. Checked as you type, and Save stays off.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Display name: "Marta Alves, Head of Renovations, Brussels and Wallonia office"; focused; counter red
|
|
- **Error "Use 60 characters or fewer."**
|
|
- Footer: "Unsaved changes" (warning)
|
|
- Save: 40 % opacity
|
|
|
|
### Saving
|
|
|
|
**Trigger:** Save, or Enter in the field. The field is disabled.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Display name: "Marta Alves", disabled, dimmed
|
|
- Save: "Saving…" with a loader
|
|
|
|
### Saved
|
|
|
|
**Trigger:** 200: the sidebar and account menu switch to the display name at once, and a toast confirms.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Sidebar chip: "Marta Alves", initials MA
|
|
- Display name: "Marta Alves"; counter "11 / 60"
|
|
- Footer: "You appear as “Marta Alves”."
|
|
- Toast (success, circle-check): **Display name saved** "You now appear as Marta Alves across RenewCMS and in emails."
|
|
|
|
### Save failed
|
|
|
|
**Trigger:** 500 or network failure. The typed value is kept.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Alert (error) in the Display name card: "Couldn't save your display name. Your text is still here. Try again in a moment."
|
|
- Display name: "Marta Alves"
|
|
- Footer: "Unsaved changes" (warning)
|
|
- Save: enabled
|
|
|
|
### Reset: sending
|
|
|
|
**Trigger:** "Send reset link". No confirmation, since it only sends an email.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Button: "Sending…" with a loader
|
|
- Sidebar chip shows the display name "Marta Alves"
|
|
|
|
### Reset: sent
|
|
|
|
**Trigger:** 200. The message stays until the page is left. "Send again" sends a new link and the old one stops working.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Button: "Send again" (mail)
|
|
- Note (success, mail-check): **Reset link sent** "Check marta@renew.example. The link works once, within 1 hour."
|
|
|
|
### Reset: too many requests (429)
|
|
|
|
**Trigger:** Rate limited. The button is disabled for 5 minutes.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Button: "Send reset link", 40 % opacity, disabled
|
|
- Note (warning, clock-alert): **Too many requests** "You've asked for several links recently. Wait a few minutes, then try again."
|
|
|
|
### Reset: failed
|
|
|
|
**Trigger:** 500 or network failure. The button can be pressed again.
|
|
|
|
- Breadcrumbs: Profile (mobile title "Profile")
|
|
- Button: "Send reset link"
|
|
- Note (error, circle-x): **Couldn't send the link** "Check your connection and try again."
|
|
|
|
### Display names in the Users list
|
|
|
|
**Trigger:** The Display name column of the Users list shows the name when one is set and a dash when not. Your own row follows your saved name. This state needs the Users page ([users.md](users.md)).
|
|
|
|
- Breadcrumbs: Users (mobile title "Users")
|
|
- Signed-in user's display name: "Marta Alves" (sidebar chip shows it too)
|
|
- Row `marta@renew.example` (you): display name "Marta Alves", role owner, Accepted
|
|
- Row `ines.duarte@renew.example`: display name "Inès Duarte", role admin, Accepted
|
|
- Row `jonas@renew.example`: display name "—" (muted), role admin, Accepted
|
|
|
|
## Notes for implementation
|
|
|
|
- `PATCH /v1/user/me` is marked pending by the design: it does not exist yet. `GET /v1/auth/me` has to start returning the display name.
|
|
- The Password card sends the reset email to the account's own address through the existing `POST /v1/auth/password-reset`. The link ends on the reset confirm screen, and a successful reset invalidates the current session like any other reset.
|
|
- "Disabled for 5 minutes" is the design's number. The real window comes from the `Retry-After` header, as on the login and reset screens.
|
|
- Resolved: the theme choice (System, Light, Dark) stays in the account menu, as the board now draws it. The board still draws Profile highlighted on Home; the app highlights it only on `/profile`.
|