docs: archive DASHBOARD_PLAN.md and update task tracking
- Move completed DASHBOARD_PLAN.md to docs/archive/ - Update COMPLETED.md with dashboard implementation details - Update TODO.md to reflect dashboard completion - Mark remaining dashboard features as optional Phase 4
This commit is contained in:
616
docs/archive/DASHBOARD_PLAN.md
Normal file
616
docs/archive/DASHBOARD_PLAN.md
Normal file
@@ -0,0 +1,616 @@
|
||||
# Dashboard Plan - spotlight.cam
|
||||
|
||||
> **✅ COMPLETED:** 2025-11-21
|
||||
> **Archived:** This plan has been fully implemented. See `docs/archive/COMPLETED.md` for implementation details.
|
||||
|
||||
**Created:** 2025-11-21
|
||||
**Status:** ✅ IMPLEMENTED
|
||||
**Priority:** HIGH - Core UX improvement
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
Create a centralized dashboard for logged-in users to:
|
||||
- View checked-in events with quick access to chats
|
||||
- Manage active matches and conversations
|
||||
- Track video exchange status
|
||||
- Monitor rating completion
|
||||
- See pending match requests
|
||||
|
||||
**Route:** `/dashboard` (default landing page after login)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Dashboard Sections
|
||||
|
||||
### 1. Active Events Section
|
||||
**Purpose:** Show events user is currently participating in
|
||||
|
||||
**Data Source:** `EventParticipant` joined with `Event`
|
||||
|
||||
**Card Content:**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 🎉 Warsaw Dance Festival │
|
||||
│ 📍 Warsaw, Poland │
|
||||
│ 📅 Nov 23-25, 2025 │
|
||||
│ │
|
||||
│ Your heats: J&J NOV 1 L, STR INT 2 F │
|
||||
│ 👥 45 participants • 12 online │
|
||||
│ │
|
||||
│ [Enter Event Chat] ──────────────────► │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Event name, location, dates
|
||||
- User's declared heats (from `EventUserHeat`)
|
||||
- Participant count, online count (from Socket.IO active users)
|
||||
- **Primary action:** "Enter Event Chat" → `/events/:slug/chat`
|
||||
- Sort: Upcoming events first, then by start date
|
||||
|
||||
**Empty State:**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 📅 No Active Events │
|
||||
│ │
|
||||
│ Check in at an event to start │
|
||||
│ connecting with other dancers! │
|
||||
│ │
|
||||
│ [Browse Events] ────────────────────► │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Active Matches Section
|
||||
**Purpose:** Show ongoing match conversations and their status
|
||||
|
||||
**Data Source:** `Match` joined with `User`, `Event`, `Rating`, `Message`
|
||||
|
||||
**Card Content:**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 👤 Sarah Martinez │
|
||||
│ @sarah_swings │
|
||||
│ 📍 Warsaw Dance Festival │
|
||||
│ │
|
||||
│ Video Exchange: │
|
||||
│ ✅ You sent • ✅ Received │
|
||||
│ │
|
||||
│ Ratings: │
|
||||
│ ✅ You rated • ⏳ Waiting for partner │
|
||||
│ │
|
||||
│ 💬 3 new messages │
|
||||
│ │
|
||||
│ [Open Chat] [Rate Partner] ──────────► │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Status Indicators:**
|
||||
|
||||
**Video Exchange:**
|
||||
- ✅ You sent video (check for message: "📹 Video sent:")
|
||||
- ✅ You received video (check for message from partner)
|
||||
- ⏳ No videos yet
|
||||
- 🔗 Link shared (message type: 'link')
|
||||
|
||||
**Ratings:**
|
||||
- ✅ You rated (Rating exists with raterId = currentUser)
|
||||
- ✅ Partner rated you (Rating exists with ratedId = currentUser)
|
||||
- ⏳ Not rated yet
|
||||
- ⚠️ Complete collaboration to rate
|
||||
|
||||
**Actions:**
|
||||
- **Primary:** "Open Chat" → `/matches/:slug`
|
||||
- **Secondary:** "Rate Partner" → `/matches/:slug/rate` (only if video exchanged)
|
||||
|
||||
**Match States:**
|
||||
- **Pending** (status='pending'): Show "Waiting for acceptance"
|
||||
- **Accepted** (status='accepted'): Active conversation
|
||||
- **Completed** (status='completed'): Both rated, show summary
|
||||
|
||||
**Sort Order:**
|
||||
1. Unread messages (new messages first)
|
||||
2. Pending ratings (video sent but not rated)
|
||||
3. Recently active (latest message timestamp)
|
||||
|
||||
**Empty State:**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 🤝 No Active Matches │
|
||||
│ │
|
||||
│ Join an event chat and send a match │
|
||||
│ request to start collaborating! │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Match Requests Section
|
||||
**Purpose:** Show pending incoming/outgoing match requests
|
||||
|
||||
**Data Source:** `Match` where `status='pending'`
|
||||
|
||||
**Incoming Request Card:**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 📨 Match Request from John Dancer │
|
||||
│ @john_dancer │
|
||||
│ 📍 Warsaw Dance Festival │
|
||||
│ Heats: J&J NOV 1 L, STR INT 2 F │
|
||||
│ │
|
||||
│ [Accept] [Decline] ──────────────────► │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Outgoing Request Card:**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 📤 Request sent to Sarah Martinez │
|
||||
│ @sarah_swings │
|
||||
│ 📍 Warsaw Dance Festival │
|
||||
│ │
|
||||
│ ⏳ Waiting for response... │
|
||||
│ │
|
||||
│ [Cancel Request] ────────────────────► │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Logic:**
|
||||
- **Incoming:** `Match.user2Id = currentUser.id` AND `status='pending'`
|
||||
- **Outgoing:** `Match.user1Id = currentUser.id` AND `status='pending'`
|
||||
|
||||
**Empty State:**
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 📭 No Pending Requests │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Recent Activity Feed (Optional - Phase 2)
|
||||
**Purpose:** Show recent notifications and updates
|
||||
|
||||
**Content:**
|
||||
- 🎉 New match accepted
|
||||
- 💬 New message in match chat
|
||||
- ⭐ Partner rated you
|
||||
- 📹 Video received
|
||||
- 📨 New match request
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Technical Implementation
|
||||
|
||||
### Backend - New API Endpoint
|
||||
|
||||
**Endpoint:** `GET /api/dashboard`
|
||||
|
||||
**Response Structure:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"activeEvents": [
|
||||
{
|
||||
"id": 420,
|
||||
"slug": "another-dance-event",
|
||||
"name": "Another Dance Event",
|
||||
"location": "Warsaw, Poland",
|
||||
"startDate": "2025-11-23",
|
||||
"endDate": "2025-11-25",
|
||||
"participantsCount": 45,
|
||||
"onlineCount": 12,
|
||||
"myHeats": [
|
||||
{
|
||||
"id": 1,
|
||||
"competitionType": { "name": "Jack & Jill", "abbreviation": "J&J" },
|
||||
"division": { "name": "Novice", "abbreviation": "NOV" },
|
||||
"heatNumber": 1,
|
||||
"role": "Leader"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"activeMatches": [
|
||||
{
|
||||
"id": 123,
|
||||
"slug": "match-abc123",
|
||||
"partner": {
|
||||
"id": 456,
|
||||
"username": "sarah_swings",
|
||||
"firstName": "Sarah",
|
||||
"lastName": "Martinez",
|
||||
"avatar": "https://..."
|
||||
},
|
||||
"event": {
|
||||
"id": 420,
|
||||
"name": "Warsaw Dance Festival"
|
||||
},
|
||||
"videoExchange": {
|
||||
"sentByMe": true,
|
||||
"receivedFromPartner": true,
|
||||
"lastVideoTimestamp": "2025-11-21T15:30:00Z"
|
||||
},
|
||||
"ratings": {
|
||||
"ratedByMe": true,
|
||||
"ratedByPartner": false
|
||||
},
|
||||
"unreadCount": 3,
|
||||
"lastMessageAt": "2025-11-21T16:00:00Z",
|
||||
"status": "accepted"
|
||||
}
|
||||
],
|
||||
"matchRequests": {
|
||||
"incoming": [
|
||||
{
|
||||
"id": 124,
|
||||
"slug": "match-def456",
|
||||
"requester": {
|
||||
"id": 789,
|
||||
"username": "john_dancer",
|
||||
"firstName": "John",
|
||||
"lastName": "Dancer",
|
||||
"avatar": "https://..."
|
||||
},
|
||||
"event": {
|
||||
"id": 420,
|
||||
"name": "Warsaw Dance Festival"
|
||||
},
|
||||
"requesterHeats": [ /* heats array */ ],
|
||||
"createdAt": "2025-11-21T14:00:00Z"
|
||||
}
|
||||
],
|
||||
"outgoing": [
|
||||
{
|
||||
"id": 125,
|
||||
"slug": "match-ghi789",
|
||||
"recipient": {
|
||||
"id": 101,
|
||||
"username": "anna_swing",
|
||||
"firstName": "Anna",
|
||||
"lastName": "Swing",
|
||||
"avatar": "https://..."
|
||||
},
|
||||
"event": {
|
||||
"id": 420,
|
||||
"name": "Warsaw Dance Festival"
|
||||
},
|
||||
"createdAt": "2025-11-21T13:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation Notes:**
|
||||
|
||||
1. **Video Exchange Detection:**
|
||||
- Query `Message` table for match's chat room
|
||||
- Check for messages containing "📹 Video sent:" or type='link'
|
||||
- Track sender to determine who sent/received
|
||||
|
||||
2. **Unread Message Count:**
|
||||
- Option A: Add `lastReadAt` field to Match model (requires migration)
|
||||
- Option B: Client-side tracking with localStorage
|
||||
- Option C: Skip for MVP, add later
|
||||
|
||||
3. **Online Count:**
|
||||
- Socket.IO activeUsers map (real-time, not persistent)
|
||||
- Return from backend when available
|
||||
|
||||
---
|
||||
|
||||
### Frontend Components
|
||||
|
||||
**New Components to Create:**
|
||||
|
||||
1. **`DashboardPage.jsx`** - Main dashboard page
|
||||
2. **`components/dashboard/`**
|
||||
- `EventCard.jsx` - Active event card (reuse/extend existing EventCard)
|
||||
- `MatchCard.jsx` - Active match card with status indicators
|
||||
- `MatchRequestCard.jsx` - Incoming/outgoing request card
|
||||
- `VideoExchangeStatus.jsx` - Visual indicator for video status
|
||||
- `RatingStatus.jsx` - Visual indicator for rating status
|
||||
- `EmptyState.jsx` - Generic empty state component
|
||||
|
||||
**Component Hierarchy:**
|
||||
```
|
||||
DashboardPage
|
||||
├── Layout
|
||||
│ ├── Header
|
||||
│ └── Content
|
||||
│ ├── Section: Active Events
|
||||
│ │ ├── EventCard (multiple)
|
||||
│ │ └── EmptyState (if no events)
|
||||
│ ├── Section: Active Matches
|
||||
│ │ ├── MatchCard (multiple)
|
||||
│ │ │ ├── VideoExchangeStatus
|
||||
│ │ │ └── RatingStatus
|
||||
│ │ └── EmptyState (if no matches)
|
||||
│ └── Section: Match Requests
|
||||
│ ├── Subsection: Incoming
|
||||
│ │ └── MatchRequestCard (multiple)
|
||||
│ └── Subsection: Outgoing
|
||||
│ └── MatchRequestCard (multiple)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Implementation Roadmap
|
||||
|
||||
### Phase 1: Backend Foundation (4-5 hours)
|
||||
|
||||
**Step 1: Create Dashboard API Endpoint (2h)**
|
||||
- [ ] Create `GET /api/dashboard` route
|
||||
- [ ] Implement data aggregation logic:
|
||||
- Query user's active events with heats
|
||||
- Query accepted matches with partner info
|
||||
- Detect video exchange from messages
|
||||
- Check rating completion
|
||||
- Query pending match requests
|
||||
- [ ] Add unit tests
|
||||
- [ ] Test with real data
|
||||
|
||||
**Step 2: Enhance Match Model (Optional, 1h)**
|
||||
- [ ] Consider adding fields to Match:
|
||||
- `videosSent` (JSON: { user1Sent: bool, user2Sent: bool })
|
||||
- `lastReadBy` (JSON: { user1: timestamp, user2: timestamp })
|
||||
- [ ] Create migration if needed
|
||||
- [ ] Update API to use new fields
|
||||
|
||||
**Step 3: Socket.IO Enhancement (1h)**
|
||||
- [ ] Add event: `dashboard_update` for real-time updates
|
||||
- [ ] Emit when:
|
||||
- New match request received
|
||||
- Match accepted
|
||||
- New message in match chat
|
||||
- Partner rated
|
||||
|
||||
### Phase 2: Frontend Implementation (6-8 hours)
|
||||
|
||||
**Step 1: Create Dashboard Components (3h)**
|
||||
- [ ] Create `pages/DashboardPage.jsx`
|
||||
- [ ] Create `components/dashboard/EventCard.jsx`
|
||||
- [ ] Create `components/dashboard/MatchCard.jsx`
|
||||
- [ ] Create `components/dashboard/MatchRequestCard.jsx`
|
||||
- [ ] Create `components/dashboard/VideoExchangeStatus.jsx`
|
||||
- [ ] Create `components/dashboard/RatingStatus.jsx`
|
||||
- [ ] Create `components/dashboard/EmptyState.jsx`
|
||||
|
||||
**Step 2: API Integration (2h)**
|
||||
- [ ] Add `dashboardAPI.getData()` to services/api.js
|
||||
- [ ] Fetch dashboard data on mount
|
||||
- [ ] Handle loading and error states
|
||||
|
||||
**Step 3: Routing & Navigation (1h)**
|
||||
- [ ] Add `/dashboard` route
|
||||
- [ ] Redirect to `/dashboard` after login (instead of `/events`)
|
||||
- [ ] Update navbar to highlight dashboard when active
|
||||
- [ ] Add "Dashboard" link to main navigation
|
||||
|
||||
**Step 4: Real-time Updates (1h)**
|
||||
- [ ] Listen to Socket.IO `dashboard_update` event
|
||||
- [ ] Update dashboard data when events occur
|
||||
- [ ] Show toast notifications for important events
|
||||
|
||||
**Step 5: Polish & Responsive Design (1h)**
|
||||
- [ ] Mobile-responsive layout (stack cards vertically)
|
||||
- [ ] Loading skeletons
|
||||
- [ ] Smooth animations
|
||||
- [ ] Empty states with helpful CTAs
|
||||
|
||||
### Phase 3: Testing & Refinement (2h)
|
||||
- [ ] Manual testing of all dashboard features
|
||||
- [ ] Test edge cases (no events, no matches, all completed)
|
||||
- [ ] Test real-time updates
|
||||
- [ ] Fix bugs and polish UX
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Design Mockup
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ [Logo] Dashboard Events Matches Profile [👤] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
🏠 Dashboard
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 📅 Your Events [View All]│
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
||||
│ │ 🎉 Warsaw Festival │ │ 🎉 Swing Camp BCN │ │
|
||||
│ │ Nov 23-25 │ │ Dec 10-12 │ │
|
||||
│ │ 45 participants │ │ 120 participants │ │
|
||||
│ │ [Enter Chat] ───────►│ │ [Enter Chat] ───────►│ │
|
||||
│ └──────────────────────┘ └──────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 💬 Active Matches [View All]│
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ 👤 Sarah Martinez @sarah_swings │ │
|
||||
│ │ 📍 Warsaw Dance Festival │ │
|
||||
│ │ │ │
|
||||
│ │ Videos: ✅ Sent • ✅ Received │ │
|
||||
│ │ Ratings: ✅ You rated • ⏳ Waiting │ │
|
||||
│ │ │ │
|
||||
│ │ 💬 3 new messages │ │
|
||||
│ │ │ │
|
||||
│ │ [Open Chat] ──────────────────────────────────────► │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ 👤 John Dancer @john_dancer │ │
|
||||
│ │ 📍 Swing Camp Barcelona │ │
|
||||
│ │ │ │
|
||||
│ │ Videos: ✅ Sent • ⏳ Waiting │ │
|
||||
│ │ Ratings: ⏳ Not ready to rate │ │
|
||||
│ │ │ │
|
||||
│ │ [Open Chat] [Send Video] ─────────────────────────► │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 📨 Match Requests │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Incoming (2) │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ 👤 Anna Swing @anna_swing │ │
|
||||
│ │ 📍 Warsaw Dance Festival │ │
|
||||
│ │ Heats: J&J NOV 1 L │ │
|
||||
│ │ │ │
|
||||
│ │ [Accept] [Decline] ───────────────────────────────► │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Outgoing (1) │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ 👤 Mike Lead @mike_lead │ │
|
||||
│ │ 📍 Swing Camp Barcelona │ │
|
||||
│ │ │ │
|
||||
│ │ ⏳ Waiting for response... [Cancel] │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Success Metrics
|
||||
|
||||
**User Engagement:**
|
||||
- % of users who visit dashboard after login (target: 80%+)
|
||||
- Average time spent on dashboard (target: 2-3 min)
|
||||
- Click-through rate to event chats (target: 60%+)
|
||||
- Click-through rate to match chats (target: 80%+)
|
||||
|
||||
**Feature Adoption:**
|
||||
- % of users who complete video exchange (track via dashboard)
|
||||
- % of users who complete ratings (track via dashboard)
|
||||
- Match acceptance rate from dashboard (target: 70%+)
|
||||
|
||||
**Technical Performance:**
|
||||
- Dashboard load time (target: < 500ms)
|
||||
- API response time (target: < 200ms)
|
||||
- Real-time update latency (target: < 100ms)
|
||||
|
||||
---
|
||||
|
||||
## 🚧 Future Enhancements (Phase 4+)
|
||||
|
||||
1. **Activity Feed**
|
||||
- Timeline of all user activities
|
||||
- Filterable by type (matches, messages, ratings)
|
||||
|
||||
2. **Statistics Dashboard**
|
||||
- Total matches
|
||||
- Average rating received
|
||||
- Events attended
|
||||
- Videos exchanged
|
||||
|
||||
3. **Calendar Integration**
|
||||
- Show upcoming events on calendar
|
||||
- Add to Google Calendar / iCal
|
||||
|
||||
4. **Quick Actions**
|
||||
- "Find matches in my next event"
|
||||
- "Review past collaborations"
|
||||
- "Update my competition heats"
|
||||
|
||||
5. **Notifications Center**
|
||||
- Centralized notification inbox
|
||||
- Mark as read/unread
|
||||
- Notification preferences
|
||||
|
||||
6. **Mobile-First Enhancements**
|
||||
- Swipe gestures for actions
|
||||
- Bottom navigation bar
|
||||
- Native app feel
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Technical Considerations
|
||||
|
||||
### Video Exchange Tracking
|
||||
|
||||
**Current State:**
|
||||
- Videos sent via WebRTC P2P (don't touch server)
|
||||
- Only confirmation message saved: "📹 Video sent: {filename} ({size} MB)"
|
||||
- No explicit tracking in database
|
||||
|
||||
**Options:**
|
||||
|
||||
**Option A: Parse messages (MVP approach)**
|
||||
- ✅ No database changes
|
||||
- ✅ Works with existing implementation
|
||||
- ❌ Fragile (depends on message format)
|
||||
- ❌ Can't distinguish between re-sends
|
||||
|
||||
**Option B: Add tracking fields to Match model**
|
||||
- ✅ Explicit, reliable tracking
|
||||
- ✅ Can track timestamps, file info
|
||||
- ❌ Requires migration
|
||||
- ❌ Needs frontend changes to send tracking events
|
||||
|
||||
**Recommendation:** Start with Option A (parse messages) for MVP, migrate to Option B in Phase 2.
|
||||
|
||||
### Unread Message Count
|
||||
|
||||
**Options:**
|
||||
|
||||
**Option A: Client-side with localStorage**
|
||||
- ✅ No backend changes
|
||||
- ✅ Simple implementation
|
||||
- ❌ Not synced across devices
|
||||
- ❌ Lost on cache clear
|
||||
|
||||
**Option B: Add lastReadAt to Match model**
|
||||
- ✅ Synced across devices
|
||||
- ✅ Persistent
|
||||
- ❌ Requires migration
|
||||
- ❌ More complex logic
|
||||
|
||||
**Option C: Separate ReadReceipt table**
|
||||
- ✅ Most flexible
|
||||
- ✅ Can support group chats later
|
||||
- ❌ Most complex
|
||||
- ❌ Additional queries
|
||||
|
||||
**Recommendation:** Start with Option A for MVP, migrate to Option B in Phase 2.
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- Dashboard should be the default landing page after login
|
||||
- Current flow: Login → `/events` (should become → `/dashboard`)
|
||||
- Keep existing navigation working (direct links to /events, /matches still accessible)
|
||||
- Dashboard is read-only (no actions except navigation)
|
||||
- Actions (accept match, send message) happen on dedicated pages
|
||||
- Focus on information density without overwhelming the user
|
||||
- Use consistent design language with existing pages
|
||||
|
||||
---
|
||||
|
||||
**Total Estimated Effort:** 12-15 hours
|
||||
**Priority:** HIGH (Core UX improvement)
|
||||
**Dependencies:** None (works with existing backend)
|
||||
**Risk:** LOW (additive feature, doesn't break existing functionality)
|
||||
|
||||
---
|
||||
|
||||
**Created by:** Claude Code
|
||||
**Date:** 2025-11-21
|
||||
**Version:** 1.0
|
||||
Reference in New Issue
Block a user