Merge branch 'workstream-l'

This commit is contained in:
RevIQ
2026-01-09 18:18:07 +08:00
12 changed files with 1713 additions and 6 deletions

View File

@@ -2345,15 +2345,23 @@ _Implementation notes:_
- Race conditions prevented via transaction-scoped existence checks
- Self-demotion guard in `adminUsersUpdate` prevents superusers from removing their own status
#### Workstream L: Org Pages (Frontend)
#### Workstream L: Org Pages (Frontend)
_Depends on: J1-J6, C3_
- [ ] **L1**: Create `/dashboard` page (org list)
- [ ] **L2**: Create `/dashboard/[org]` page (org overview)
- [ ] **L3**: Create `/dashboard/[org]/members` page
- [ ] **L4**: Create `/dashboard/[org]/settings` page
- [ ] **L5**: Create org invite accept flow
- [x] **L1**: Create `/dashboard` page (org list)
- [x] **L2**: Create `/dashboard/[slug]` page (org overview)
- [x] **L3**: Create `/dashboard/[slug]/members` page
- [x] **L4**: Create `/dashboard/[slug]/settings` page
- [x] **L5**: Create `/invite/accept` page (org invite accept flow)
**Implementation notes:**
- Route param uses `[slug]` to match API contract
- Shared org context via `+layout.svelte` provides role detection (owner/admin/member)
- Role-based UI: owners can manage roles, admins can invite/remove, members view-only
- Confirmation dialogs for destructive actions (remove member, cancel invite, leave/delete org)
- Reusable components: `$lib/components/org/role-badge.svelte`, `confirm-dialog.svelte`
- Sidebar updated with "Organizations" nav item
#### Workstream M: Admin Pages (Frontend)

View File

@@ -0,0 +1,258 @@
# Test Plan: Organization Dashboard (Workstream L)
## Overview
Manual UI test plan for organization management pages:
- `/dashboard` - Org list
- `/dashboard/[slug]` - Org overview
- `/dashboard/[slug]/members` - Member management
- `/dashboard/[slug]/settings` - Org settings
- `/invite/accept` - Invite acceptance
## Prerequisites
- Dev server running: `bun run --cwd apps/publisher-dashboard dev`
- Test user accounts with different roles in an org (owner, admin, member)
- At least one org with multiple members
---
## 1. Organization List (`/dashboard`)
### 1.1 Authentication
- [ ] Unauthenticated user visiting `/dashboard` redirects to `/auth/login`
- [ ] After login, user returns to `/dashboard`
### 1.2 Empty State
- [ ] New user with no orgs sees "You're not a member of any organizations yet"
- [ ] "Create Organization" button is visible and functional
### 1.3 Org List Display
- [ ] All user's orgs display in a grid
- [ ] Each card shows: org name, slug, logo (or placeholder), created date
- [ ] Cards are clickable and navigate to `/dashboard/[slug]`
### 1.4 Loading States
- [ ] Loading spinner shows while fetching orgs
- [ ] Error state displays if API fails
---
## 2. Organization Overview (`/dashboard/[slug]`)
### 2.1 Access Control
- [ ] Non-member visiting org page sees error "Failed to load organization"
- [ ] Member can view org overview
### 2.2 Header Section
- [ ] Org name displays correctly
- [ ] Org slug displays below name
- [ ] Logo displays if set, placeholder icon if not
- [ ] Current user's role badge shows (Owner/Admin/Member)
- [ ] Settings button visible only for admin/owner
### 2.3 Stats Cards
- [ ] Members card shows correct count
- [ ] Members card is clickable, navigates to members page
- [ ] Sites card shows correct count
### 2.4 Team Members Preview
- [ ] Shows up to 5 members with avatar, name/email, role badge
- [ ] "View all" link navigates to members page
### 2.5 Connected Sites Preview
- [ ] Shows up to 5 sites with domain
- [ ] Empty state if no sites
---
## 3. Members Management (`/dashboard/[slug]/members`)
### 3.1 View Permissions (All Roles)
- [ ] Members table displays all org members
- [ ] Each row shows: avatar, name, email, role badge, joined date
- [ ] Current user marked with "(You)"
### 3.2 Invite Form (Admin/Owner Only)
- [ ] Invite form visible for admin and owner
- [ ] Invite form hidden for member role
- [ ] Email input validates email format
- [ ] Role dropdown shows appropriate options:
- Owner: can invite member, admin, owner
- Admin: can invite member, admin only
- [ ] "Send Invite" disabled when email empty
- [ ] Success toast on invite sent
- [ ] Error toast on failure (e.g., user already member)
### 3.3 Pending Invitations (Admin/Owner Only)
- [ ] Pending invites section visible for admin/owner
- [ ] Hidden for member role
- [ ] Shows: email, role, invited by, expiration
- [ ] Cancel button removes invite with confirmation dialog
- [ ] Cancelled invite disappears from list
### 3.4 Role Management (Owner Only)
- [ ] Owner sees role dropdown for each member (except self)
- [ ] Admin sees static role badges (no dropdown)
- [ ] Member sees static role badges
- [ ] Changing role updates immediately
- [ ] Success toast on role change
### 3.5 Remove Member
- [ ] Owner can remove any member (except self)
- [ ] Admin can remove members only (not other admins/owners)
- [ ] Member cannot remove anyone
- [ ] Remove button shows confirmation dialog
- [ ] Removed member disappears from list
- [ ] Cannot remove self (no remove button for current user)
---
## 4. Organization Settings (`/dashboard/[slug]/settings`)
### 4.1 Access Control
- [ ] Settings page accessible to admin and owner
- [ ] Member role can access but sees limited options
### 4.2 General Settings (Admin/Owner)
- [ ] Display name input pre-filled with current value
- [ ] Logo URL input pre-filled if set
- [ ] Save button disabled when no changes
- [ ] Save button enabled when form is dirty
- [ ] Success toast on save
- [ ] Changes reflected in org header after save
### 4.3 Leave Organization (Member/Admin Only)
- [ ] "Leave Organization" section visible for member and admin
- [ ] Hidden for owner (owners cannot leave)
- [ ] Warning alert explains consequences
- [ ] Leave button shows confirmation dialog
- [ ] After leaving, redirects to `/dashboard`
- [ ] User no longer sees org in their list
### 4.4 Danger Zone (Owner Only)
- [ ] Delete section visible only for owner
- [ ] Hidden for admin and member
- [ ] Warning alert explains permanent deletion
- [ ] Delete button shows confirmation dialog
- [ ] Confirmation describes what will be deleted
- [ ] After delete, redirects to `/dashboard`
- [ ] Org no longer appears for any user
---
## 5. Invite Accept Flow (`/invite/accept`)
### 5.1 Unauthenticated User
- [ ] Visiting with token redirects to login
- [ ] After login, returns to accept page with token
- [ ] Invite automatically accepted
### 5.2 Authenticated User - Valid Token
- [ ] Page shows "Accepting invitation..." initially
- [ ] Success message: "You've joined the organization!"
- [ ] Auto-redirects to `/dashboard` after success
### 5.3 Authenticated User - Invalid/Expired Token
- [ ] Error message: "This invitation has expired or is invalid"
- [ ] "Try again" button visible
- [ ] "Go to Dashboard" button navigates to `/dashboard`
- [ ] "Sign in with a different account" link visible
### 5.4 Already a Member
- [ ] Error message: "You're already a member of this organization"
### 5.5 Email Mismatch
- [ ] Error message: "This invitation was sent to a different email address"
- [ ] Suggests logging in with correct account
### 5.6 No Token
- [ ] Error message: "No invitation token provided"
---
## 6. Navigation & Sidebar
### 6.1 Sidebar
- [ ] "Organizations" nav item visible in sidebar
- [ ] Building icon displays correctly
- [ ] Clicking navigates to `/dashboard`
- [ ] Active state shows when on `/dashboard` routes
### 6.2 Breadcrumb Navigation
- [ ] Back links work correctly on settings page
- [ ] "Back to organizations" link on error pages
---
## 7. Cross-Cutting Concerns
### 7.1 Loading States
- [ ] All pages show loading spinner during data fetch
- [ ] Skeleton states or spinners for async operations
### 7.2 Error Handling
- [ ] API errors display user-friendly messages
- [ ] Toast notifications for action results
- [ ] Error states don't crash the app
### 7.3 Responsive Design
- [ ] Pages render correctly on mobile viewport
- [ ] Tables scroll horizontally on small screens
- [ ] Forms stack vertically on mobile
### 7.4 Query Invalidation
- [ ] After invite: invites list refreshes
- [ ] After role change: members list refreshes
- [ ] After remove member: members list refreshes
- [ ] After org update: org details refresh
- [ ] After leave/delete: orgs list refreshes
---
## 8. Edge Cases
### 8.1 Last Owner Protection
- [ ] Last owner cannot leave organization
- [ ] Must transfer ownership before leaving
### 8.2 Self-Actions
- [ ] Cannot remove yourself from org
- [ ] Cannot change your own role (as owner)
### 8.3 Concurrent Updates
- [ ] UI handles stale data gracefully
- [ ] Refresh shows latest state
### 8.4 Long Content
- [ ] Long org names truncate or wrap properly
- [ ] Long email addresses don't break layout
---
## Test Matrix: Role-Based Features
| Feature | Owner | Admin | Member |
|---------|-------|-------|--------|
| View org overview | Yes | Yes | Yes |
| View members list | Yes | Yes | Yes |
| Access settings page | Yes | Yes | Yes |
| Edit org settings | Yes | Yes | No |
| Send invites | Yes | Yes | No |
| Cancel invites | Yes | Yes | No |
| Change member roles | Yes | No | No |
| Remove members | Yes | Members only | No |
| Remove admins | Yes | No | No |
| Leave organization | No | Yes | Yes |
| Delete organization | Yes | No | No |
---
## Regression Checklist
After any changes to org pages, verify:
- [ ] Existing orgs still load correctly
- [ ] Role detection still works
- [ ] All CRUD operations function
- [ ] Error states still display
- [ ] Navigation works end-to-end