# Mentor UI Redesign (Complete Workspace Experience)

## 1. Overview

Mentors are a **first-class role** in the MOPC platform. They guide finalist teams through the mentoring round (Round 6) — a collaboration layer between Jury 2 finalist selection and the Live Finals. The redesigned mentor experience provides a dedicated dashboard and full workspace for file collaboration, threaded comments, and file promotion to official submissions.

### What Changes

| Area | Current State | Redesigned State |
|------|---------------|------------------|
| **Dashboard** | Basic list of assigned projects | Rich dashboard with activity feed, status cards, metrics |
| **Messaging** | Simple chat via `MentorMessage` model | Enhanced messaging integrated into workspace |
| **File Sharing** | None — teams upload to official submission only | Full private workspace with file upload/download |
| **Comments** | None | Threaded file comments with @mentions |
| **File Promotion** | None | Promote workspace files to official submission slots |
| **Milestones** | Basic `MentorMilestone` tracking | Interactive milestone progress UI |
| **Navigation** | `/mentor` and `/mentor/projects` | Full IA with team-specific workspaces |

### Design Principles

1. **Privacy-first** — Workspace is private (mentor + team + admin only; jury can't see it)
2. **No duplication** — Promoted files reuse MinIO objects (no storage duplication)
3. **Provenance tracking** — Full audit trail from workspace upload → promotion → submission
4. **Mobile-friendly** — File review on tablets is a primary use case
5. **Integrated** — Workspace is tightly integrated with existing submission system

---

## 2. Current Mentor Experience (Baseline)

### Existing Components

| File | Purpose |
|------|---------|
| `src/components/layouts/mentor-nav.tsx` | Top navigation (Dashboard, My Projects, Resources) |
| `src/components/shared/mentor-chat.tsx` | Chat component for mentor-team messaging |
| `src/server/routers/mentor.ts` | tRPC procedures (assign, getSuggestions, etc.) |
| `src/server/services/mentor-matching.ts` | AI-based mentor-project matching |

### Current Data Models

```
MentorAssignment {
  id, projectId, mentorId, method, assignedAt, assignedBy
  aiConfidenceScore, expertiseMatchScore, aiReasoning
  completionStatus, lastViewedAt
}

MentorMessage {
  id, mentorAssignmentId, senderId, message, createdAt, isRead
}

MentorNote {
  id, mentorAssignmentId, note, isVisibleToAdmin, createdAt
}

MentorMilestone {
  id, competitionId, name, description, sortOrder
}

MentorMilestoneCompletion {
  id, mentorAssignmentId, milestoneId, completedAt, notes
}
```

### Current Mentor Procedures (src/server/routers/mentor.ts)

| Procedure | Purpose |
|-----------|---------|
| `getSuggestions` | Get AI-suggested mentors for a project |
| `assign` | Manually assign mentor to project |
| `unassign` | Remove mentor assignment |
| `getMyAssignments` | List mentor's assigned projects |
| `getAssignmentDetail` | Get detailed view of a single assignment |
| `sendMessage` | Send message to team |
| `getMessages` | Retrieve chat history |
| `addNote` | Add private mentor note |
| `getNotes` | Retrieve mentor's notes |
| `completeMilestone` | Mark a milestone as complete |
| `getMilestones` | Get milestone list + completion status |

### What's Missing

- No file workspace
- No threaded comments
- No file promotion mechanism
- No visual file preview
- No mentor dashboard metrics
- No admin monitoring of mentor activity
- No file versioning in workspace
- No mobile-optimized file review

---

## 3. Mentor Dashboard (Landing Page)

The mentor dashboard is the entry point for all mentoring activities. It provides an at-a-glance view of assigned teams, workspace activity, and upcoming deadlines.

### Route

```
/mentor (dashboard)
```

### ASCII Mockup

```
┌──────────────────────────────────────────────────────────────────────────┐
│ MOPC 2026 — Mentor Dashboard                           [🔔 3] [Profile ▾]│
├──────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│ Mentoring Period: June 1 – June 30, 2026                                │
│ ⏱ 18 days remaining                                                     │
│                                                                          │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐               │
│ │ 3              │ │ 12             │ │ 5              │               │
│ │ Assigned Teams │ │ Unread Messages│ │ Files Reviewed │               │
│ └────────────────┘ └────────────────┘ └────────────────┘               │
│                                                                          │
│ ┌─ My Assigned Teams ───────────────────────────────────────────────┐   │
│ │                                                                    │   │
│ │ ┌────────────────────────────────────────────────────────────┐    │   │
│ │ │ 🚀 OceanClean AI — Startup                                │    │   │
│ │ │ Team Lead: Sarah Johnson · sjohnson@oceanclean.ai          │    │   │
│ │ │                                                            │    │   │
│ │ │ 💬 2 unread messages · 📁 3 files uploaded                │    │   │
│ │ │ 🔄 Last activity: 2 hours ago                              │    │   │
│ │ │                                                            │    │   │
│ │ │ Status: ✅ Active    Milestones: 2/4 completed            │    │   │
│ │ │                                                            │    │   │
│ │ │ [Open Workspace]                           [View Details]  │    │   │
│ │ └────────────────────────────────────────────────────────────┘    │   │
│ │                                                                    │   │
│ │ ┌────────────────────────────────────────────────────────────┐    │   │
│ │ │ 💡 Blue Carbon Hub — Business Concept                     │    │   │
│ │ │ Team Lead: Dr. Maria Santos · msantos@bluecarbonhub.org    │    │   │
│ │ │                                                            │    │   │
│ │ │ 💬 0 unread · 📁 1 file uploaded                          │    │   │
│ │ │ 🔄 Last activity: 2 days ago                               │    │   │
│ │ │                                                            │    │   │
│ │ │ Status: ⚠ Needs Attention    Milestones: 1/4 completed   │    │   │
│ │ │                                                            │    │   │
│ │ │ [Open Workspace]                           [View Details]  │    │   │
│ │ └────────────────────────────────────────────────────────────┘    │   │
│ │                                                                    │   │
│ │ ┌────────────────────────────────────────────────────────────┐    │   │
│ │ │ 🌊 SeaWatch Monitor — Startup                             │    │   │
│ │ │ Team Lead: John Chen · jchen@seawatch.io                   │    │   │
│ │ │                                                            │    │   │
│ │ │ 💬 0 unread · 📁 0 files                                  │    │   │
│ │ │ 🔄 Last activity: Never                                    │    │   │
│ │ │                                                            │    │   │
│ │ │ Status: ⚠ No Activity Yet    Milestones: 0/4 completed   │    │   │
│ │ │                                                            │    │   │
│ │ │ [Open Workspace]                           [View Details]  │    │   │
│ │ └────────────────────────────────────────────────────────────┘    │   │
│ │                                                                    │   │
│ └────────────────────────────────────────────────────────────────────┘   │
│                                                                          │
│ ┌─ Milestone Progress ───────────────────────────────────────────┐      │
│ │                                                                 │      │
│ │ ☑ Initial Review (3/3 teams completed)                         │      │
│ │ ├─ OceanClean AI: ✅ Jun 2                                     │      │
│ │ ├─ Blue Carbon Hub: ✅ Jun 3                                   │      │
│ │ └─ SeaWatch Monitor: ✅ Jun 4                                  │      │
│ │                                                                 │      │
│ │ ☐ Business Plan Feedback (1/3 teams completed)                 │      │
│ │ ├─ OceanClean AI: ✅ Jun 5                                     │      │
│ │ ├─ Blue Carbon Hub: ⏳ In progress                             │      │
│ │ └─ SeaWatch Monitor: ⏳ Not started                            │      │
│ │                                                                 │      │
│ │ ☐ Pitch Deck Review (0/3 teams)                                │      │
│ │ ☐ Final Submission Review (0/3 teams)                          │      │
│ │                                                                 │      │
│ └─────────────────────────────────────────────────────────────────┘      │
│                                                                          │
│ ┌─ Recent Activity ────────────────────────────────────────────┐         │
│ │                                                              │         │
│ │ 2 hours ago                                                  │         │
│ │ 📁 Sarah Johnson uploaded "Business Plan v3.pdf"             │         │
│ │    in OceanClean AI workspace                                │         │
│ │                                                              │         │
│ │ 5 hours ago                                                  │         │
│ │ 💬 You sent a message to Blue Carbon Hub                     │         │
│ │                                                              │         │
│ │ Yesterday                                                    │         │
│ │ ✅ You completed "Initial Review" for SeaWatch Monitor       │         │
│ │                                                              │         │
│ │ 2 days ago                                                   │         │
│ │ 📁 You uploaded "Financial Model Template.xlsx"              │         │
│ │    in OceanClean AI workspace                                │         │
│ │                                                              │         │
│ └──────────────────────────────────────────────────────────────┘         │
│                                                                          │
└──────────────────────────────────────────────────────────────────────────┘
```

### Data Requirements

**Team Cards:**
```typescript
// Query: mentor.getMyDashboard
{
  teams: [
    {
      projectId: string,
      projectTitle: string,
      projectCategory: "STARTUP" | "BUSINESS_CONCEPT",
      teamLead: { name, email },
      mentorAssignmentId: string,
      status: "active" | "needs_attention" | "no_activity" | "completed",
      unreadMessageCount: number,
      fileCount: number,
      lastActivity: Date | null,
      milestonesCompleted: number,
      milestonesTotal: number,
    }
  ],
  stats: {
    totalTeams: number,
    unreadMessages: number,
    filesReviewed: number,
    filesPromoted: number,
  },
  mentoring: {
    windowOpenAt: Date,
    windowCloseAt: Date,
    daysRemaining: number,
  }
}
```

**Status Logic:**
- `no_activity` — lastActivity is null (team hasn't engaged)
- `needs_attention` — lastActivity > 3 days ago OR unreadMessageCount > 0
- `active` — Regular engagement
- `completed` — All milestones done

**Activity Feed:**
```typescript
// Query: mentor.getRecentActivity (limit: 10)
{
  activities: [
    {
      id: string,
      type: "FILE_UPLOADED" | "MESSAGE_SENT" | "MILESTONE_COMPLETED" | "FILE_PROMOTED",
      actor: { id, name },
      projectTitle: string,
      timestamp: Date,
      metadata: { fileName?, milestoneId? }
    }
  ]
}
```

### Component Breakdown

```
MentorDashboard (page)
├─ MentorHeader (period info, countdown, stats cards)
├─ TeamCardList
│  └─ TeamCard (reusable, shows status + quick actions)
├─ MilestoneProgressSection
│  └─ MilestoneExpandableList (shows per-team breakdown)
└─ RecentActivityFeed
   └─ ActivityItem (icon + text + timestamp)
```

---

## 4. Workspace (Per-Team Private Collaboration Space)

The workspace is the heart of the mentor experience. It's a split-pane interface with files on the left and detail view on the right.

### Route

```
/mentor/team/[projectId]
/mentor/team/[projectId]/files
/mentor/team/[projectId]/file/[fileId]
/mentor/team/[projectId]/chat
/mentor/team/[projectId]/milestones
```

### ASCII Mockup — File List View

```
┌──────────────────────────────────────────────────────────────────────────┐
│ ← Back to Dashboard                                     [🔔 3] [Profile ▾]│
├──────────────────────────────────────────────────────────────────────────┤
│ OceanClean AI — Workspace                                                │
│ Team Lead: Sarah Johnson · sjohnson@oceanclean.ai                        │
│ Mentoring Period: June 1 – June 30 · ⏱ 18 days remaining                │
├──────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│ [📁 Files] [💬 Chat (2)] [📋 Milestones (2/4)]                          │
│                                                                          │
│ ┌─────────────────────┬────────────────────────────────────────────────┐│
│ │ Files (5)           │ File Detail                                    ││
│ │ [📤 Upload File]    │                                                ││
│ │                     │ ┌────────────────────────────────────────────┐ ││
│ │ ───────────────────│ │ 📄 Business Plan v3.pdf                   │ ││
│ │                     │ │ Uploaded by Sarah Johnson (Team)          │ ││
│ │ 📄 Business Plan..  │ │ Jun 8, 2026 · 2.4 MB                       │ ││
│ │ Sarah · Jun 8       │ │                                            │ ││
│ │ 💬 4 comments       │ │ [📥 Download]  [💬 Comments (4)]           │ ││
│ │ [Open →]            │ │ [🚀 Promote to Submission]                 │ ││
│ │                     │ │                                            │ ││
│ │ 📊 Financial Mod..  │ │ ───────────────────────────────────────── │ ││
│ │ You · Jun 6         │ │                                            │ ││
│ │ 💬 2 comments       │ │ 💬 Comments (4)                            │ ││
│ │ [Open →]            │ │                                            │ ││
│ │                     │ │ Dr. Martin Duval (Mentor) · Jun 8, 14:30  │ ││
│ │ 📄 Market Analys..  │ │ Section 3.2 needs stronger market         │ ││
│ │ Sarah · Jun 5       │ │ analysis. Consider adding competitor      │ ││
│ │ 💬 1 comment        │ │ comparisons and market size estimates.    │ ││
│ │ [Open →]            │ │                                            │ ││
│ │                     │ │   └─ Sarah Johnson (Team) · Jun 8, 16:00  │ ││
│ │ 📄 Pitch Deck Dr..  │ │      Good point! We'll add a competitive  │ ││
│ │ Sarah · Jun 4       │ │      landscape section in the next ver.   │ ││
│ │ ✅ PROMOTED         │ │                                            │ ││
│ │ [View]              │ │ Dr. Martin Duval (Mentor) · Jun 9, 10:00  │ ││
│ │                     │ │ Financial projections look much better.   │ ││
│ │ 🎥 Video Pitch      │ │ Revenue model is solid. Ready to promote? │ ││
│ │ Sarah · Jun 3       │ │                                            │ ││
│ │ 💬 0 comments       │ │   └─ Sarah Johnson (Team) · Jun 9, 11:30  │ ││
│ │ [Open →]            │ │      Yes! Please promote to the Business  │ ││
│ │                     │ │      Plan requirement slot.                │ ││
│ │                     │ │                                            │ ││
│ │                     │ │ [Add comment...                         ] │ ││
│ │                     │ │ [Post Comment]                             │ ││
│ │                     │ └────────────────────────────────────────────┘ ││
│ │                     │                                                ││
│ └─────────────────────┴────────────────────────────────────────────────┘│
│                                                                          │
└──────────────────────────────────────────────────────────────────────────┘
```

### Split-Pane Behavior

| State | Left Pane | Right Pane |
|-------|-----------|------------|
| **Default** | File list | File upload instructions + quick stats |
| **File selected** | File list (selected file highlighted) | File detail (preview, comments, actions) |
| **Mobile** | Stack vertically — file list on top, detail below when file selected |

### File List Item Structure

```typescript
interface WorkspaceFile {
  id: string
  fileName: string
  uploadedBy: { id, name, role: "MENTOR" | "TEAM" }
  uploadedAt: Date
  size: number
  mimeType: string
  commentCount: number
  isPromoted: boolean
  promotedToSlot?: { requirementName: string, submissionWindowName: string }
}
```

### File Actions

| Action | Visibility | Behavior |
|--------|------------|----------|
| **Download** | Always | Get MinIO pre-signed URL, trigger browser download |
| **Comment** | Always | Open comment thread in right pane |
| **Promote** | Only if not already promoted | Show promotion dialog (see section 5) |
| **Delete** | Uploader or admin only | Soft delete (mark as deleted, don't remove from MinIO) |

---

## 5. File Review & Comments (Threaded Discussion)

### Comment Thread UI

```
┌──────────────────────────────────────────────────────────────┐
│ 💬 Comments on: Business Plan v3.pdf                          │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ Dr. Martin Duval (Mentor)                     Jun 8, 14:30  │
│ Section 3.2 needs stronger market analysis. Consider        │
│ adding competitor comparisons and market size estimates.     │
│                                                              │
│   └─ Sarah Johnson (Team)                    Jun 8, 16:00   │
│      Good point! We'll add a competitive landscape           │
│      section in the next version. @Dr. Martin would you      │
│      prefer a SWOT matrix or Porter's 5 Forces analysis?     │
│                                                              │
│        └─ Dr. Martin Duval (Mentor)          Jun 8, 17:00   │
│           Porter's 5 Forces would be stronger for this       │
│           type of technology play. Focus on threat of        │
│           substitutes and competitive rivalry.                │
│                                                              │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ Dr. Martin Duval (Mentor)                     Jun 9, 10:00  │
│ Financial projections look much better. Revenue model is     │
│ solid. Ready to promote this to official submission?         │
│                                                              │
│   └─ Sarah Johnson (Team)                    Jun 9, 11:30   │
│      Yes! Please promote to the Business Plan slot.          │
│                                                              │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ [Add comment...                                            ] │
│                                                              │
│ [@mention team member]                       [Post Comment] │
└──────────────────────────────────────────────────────────────┘
```

### Comment Features

**Threading:**
- Top-level comments (parentCommentId = null)
- Nested replies (parentCommentId = parent's ID)
- Maximum nesting depth: 3 levels (prevents deep threading hell)

**@Mentions:**
- Typing `@` triggers autocomplete of team members + mentor
- Mentioned users get in-app notification
- Mention is rendered as a link to user profile

**Formatting:**
- Plain text only (no rich text editor — keep it simple)
- Auto-linkify URLs
- Preserve line breaks

**Deletion:**
- Author can delete own comments within 1 hour of posting
- Admin can delete any comment
- Deleted comments show "[Comment deleted]" placeholder (preserve thread structure)

### Comment API

| Procedure | Purpose |
|-----------|---------|
| `mentorWorkspace.addComment(fileId, content, parentCommentId?)` | Add comment |
| `mentorWorkspace.listComments(fileId)` | Get threaded comments |
| `mentorWorkspace.deleteComment(commentId)` | Delete comment |

### Comment Data Structure

```typescript
interface MentorFileComment {
  id: string
  mentorFileId: string
  authorId: string
  author: { id, name, role }
  content: string
  parentCommentId: string | null
  replies: MentorFileComment[]  // Nested replies
  createdAt: Date
  updatedAt: Date
}
```

---

## 6. File Promotion (Workspace → Official Submission)

File promotion is the **key value add** of the mentor workspace. It allows refined documents to become official submissions without manual re-upload.

### Promotion Flow

```
┌────────────────────────────────────────────────────────────────┐
│ Step 1: Mentor/Team clicks "Promote →" on a workspace file    │
└────────────────────────────────────────────────────────────────┘
                            ↓
┌────────────────────────────────────────────────────────────────┐
│ Step 2: Promotion Dialog Appears                               │
│                                                                │
│ ┌────────────────────────────────────────────────────────┐    │
│ │ Promote File to Official Submission                    │    │
│ │                                                        │    │
│ │ File: Business Plan v3.pdf                             │    │
│ │ Size: 2.4 MB                                           │    │
│ │                                                        │    │
│ │ Target Submission Window:                              │    │
│ │ ┌────────────────────────────────────────────────┐     │    │
│ │ │ Round 2 Docs (Semi-finalist Submissions) ▾    │     │    │
│ │ └────────────────────────────────────────────────┘     │    │
│ │                                                        │    │
│ │ Replaces Requirement Slot:                             │    │
│ │ ┌────────────────────────────────────────────────┐     │    │
│ │ │ Business Plan ▾                                │     │    │
│ │ └────────────────────────────────────────────────┘     │    │
│ │                                                        │    │
│ │ Current file in this slot:                             │    │
│ │ "Business Plan v2.pdf" uploaded Jun 3, 2026            │    │
│ │                                                        │    │
│ │ ⚠ This will replace the existing file. The old file   │    │
│ │ will remain in version history but won't be shown      │    │
│ │ to jurors.                                             │    │
│ │                                                        │    │
│ │ [Cancel]                    [Promote & Replace File]   │    │
│ └────────────────────────────────────────────────────────┘    │
└────────────────────────────────────────────────────────────────┘
                            ↓
┌────────────────────────────────────────────────────────────────┐
│ Step 3: Server Executes Promotion                              │
│                                                                │
│ 1. Validate:                                                   │
│    ✓ Workspace is active                                       │
│    ✓ File not already promoted                                │
│    ✓ Submission window exists and is accessible               │
│    ✓ User has permission (team lead or admin)                 │
│                                                                │
│ 2. Find existing ProjectFile for that requirement slot:        │
│    ProjectFile.where(projectId, requirementId)                 │
│                                                                │
│ 3. Create new ProjectFile:                                     │
│    {                                                           │
│      projectId: project.id,                                    │
│      submissionWindowId: selected window,                      │
│      requirementId: selected requirement,                      │
│      fileName: "Business Plan v3.pdf",                         │
│      mimeType: "application/pdf",                              │
│      size: 2.4MB,                                              │
│      bucket: same as MentorFile,                               │
│      objectKey: same as MentorFile,  // NO DUPLICATION        │
│      version: 3,  // increment from previous                  │
│    }                                                           │
│                                                                │
│ 4. Update old file (if exists):                                │
│    oldFile.replacedById = newFile.id                           │
│                                                                │
│ 5. Update MentorFile:                                          │
│    {                                                           │
│      isPromoted: true,                                         │
│      promotedToFileId: newFile.id,                             │
│      promotedAt: now,                                          │
│      promotedByUserId: actor.id,                               │
│    }                                                           │
│                                                                │
│ 6. Audit log entry:                                            │
│    {                                                           │
│      action: "MENTOR_FILE_PROMOTED",                           │
│      actorId: actor.id,                                        │
│      targetType: "PROJECT_FILE",                               │
│      targetId: newFile.id,                                     │
│      metadata: {                                               │
│        mentorFileId: mentorFile.id,                            │
│        submissionWindowId: window.id,                          │
│        requirementId: requirement.id,                          │
│        replacedFileId: oldFile?.id,                            │
│      }                                                         │
│    }                                                           │
└────────────────────────────────────────────────────────────────┘
                            ↓
┌────────────────────────────────────────────────────────────────┐
│ Step 4: UI Updates                                             │
│                                                                │
│ - MentorFile shows "✅ PROMOTED" badge                         │
│ - Promote button disabled                                      │
│ - Toast: "File promoted to Business Plan slot"                │
│ - ProjectFile now visible to jury in evaluation round          │
└────────────────────────────────────────────────────────────────┘
```

### Promotion Dialog Component

```tsx
// components/mentor/file-promotion-dialog.tsx

interface FilePromotionDialogProps {
  mentorFile: WorkspaceFile
  availableWindows: SubmissionWindow[]
  currentWindowId: string  // Default selection
  onPromote: (windowId: string, requirementId: string | null) => Promise<void>
}

// Logic:
// 1. User selects target submission window
// 2. Load requirements for that window (via tRPC query)
// 3. Show dropdown of available requirement slots
// 4. Show warning if slot already has a file
// 5. Confirm and execute promotion
```

### Promotion Rules

| Rule | Enforcement |
|------|-------------|
| **Only unpromoted files** | isPromoted = false |
| **Workspace must be active** | workspaceOpenAt <= now <= workspaceCloseAt |
| **User must have permission** | Team lead OR admin OR (mentor if config allows) |
| **Target window must exist** | SubmissionWindow.id valid |
| **No file duplication** | ProjectFile.objectKey = MentorFile.objectKey (same MinIO object) |
| **Versioning** | New file increments version number |
| **Audit trail** | Full provenance logged |

### Unpromote (Revert)

Admin can revert a promotion:

```
1. Find ProjectFile created by promotion (via MentorFile.promotedToFileId)
2. If it replaced a previous file, restore that file (set replacedById = null)
3. Delete the promoted ProjectFile
4. Reset MentorFile flags:
   - isPromoted = false
   - promotedToFileId = null
   - promotedAt = null
   - promotedByUserId = null
5. Audit log: "MENTOR_FILE_UNPROMOTED"
```

**API:**
- `mentorWorkspace.unpromoteFile(mentorFileId)` — admin only

---

## 7. Messaging (Team Communication)

The workspace includes integrated chat for real-time communication between mentor and team.

### Chat Tab UI

```
┌──────────────────────────────────────────────────────────────┐
│ [📁 Files] [💬 Chat (2)] [📋 Milestones]                     │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ ┌────────────────────────────────────────────────────────┐  │
│ │ Dr. Martin Duval (Mentor)             Jun 8, 10:30 AM  │  │
│ │ Welcome to the mentoring workspace! I've reviewed      │  │
│ │ your initial application. Let's focus on strengthening │  │
│ │ the financial projections first. I'll upload a         │  │
│ │ template to the Files tab.                             │  │
│ └────────────────────────────────────────────────────────┘  │
│                                                              │
│ ┌────────────────────────────────────────────────────────┐  │
│ │                             Jun 8, 2:15 PM             │  │
│ │                       Sarah Johnson (Team)             │  │
│ │                    Thank you! We've uploaded the       │  │
│ │                    revised business plan to the        │  │
│ │                    Files section. Looking forward      │  │
│ │                    to your feedback.                   │  │
│ └────────────────────────────────────────────────────────┘  │
│                                                              │
│ ┌────────────────────────────────────────────────────────┐  │
│ │ Dr. Martin Duval (Mentor)             Jun 9, 9:00 AM   │  │
│ │ Excellent work on the revisions! I've left detailed    │  │
│ │ comments on the file. The market analysis is much      │  │
│ │ stronger now. One more iteration should get us to      │  │
│ │ a promotion-ready version.                             │  │
│ └────────────────────────────────────────────────────────┘  │
│                                                              │
│ ─────────────────────────────────────────────────────────── │
│                                                              │
│ [Type a message...                                        ] │
│                                                              │
│ [📎 Attach File]                              [Send]        │
└──────────────────────────────────────────────────────────────┘
```

### Message Features

**Real-time Updates:**
- Polling every 10 seconds for new messages
- WebSocket support if available
- Unread count badge on tab

**Message Types:**
| Type | Description |
|------|-------------|
| `text` | Plain text message |
| `file_reference` | Link to a workspace file ("I've uploaded X — see Files tab") |
| `milestone` | Milestone completion notification |

**Notifications:**
- In-app notification on new message
- Email notification if recipient hasn't viewed workspace in 24 hours
- Push notification if enabled

**Read Receipts:**
- Messages marked as read when chat tab is viewed
- No "typing..." indicator (keep it simple)

---

## 8. Milestones (Progress Tracking)

Milestones are optional admin-defined checkpoints for mentoring progress. They're displayed in the workspace and on the mentor dashboard.

### Milestones Tab UI

```
┌──────────────────────────────────────────────────────────────┐
│ [📁 Files] [💬 Chat] [📋 Milestones (2/4)]                   │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ Mentoring Progress                                           │
│                                                              │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ✅ Initial Review                                       │ │
│ │ Completed: Jun 2, 2026 by Dr. Martin Duval              │ │
│ │ Notes: Reviewed application materials. Strong concept   │ │
│ │ but needs financial model refinement.                   │ │
│ └─────────────────────────────────────────────────────────┘ │
│                                                              │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ✅ Business Plan Feedback                               │ │
│ │ Completed: Jun 5, 2026 by Dr. Martin Duval              │ │
│ │ Notes: Provided detailed comments on v2. Team responded │ │
│ │ with v3 incorporating all feedback.                     │ │
│ └─────────────────────────────────────────────────────────┘ │
│                                                              │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ⏳ Pitch Deck Review                                    │ │
│ │                                                         │ │
│ │ [Mark as Complete]                                      │ │
│ │                                                         │ │
│ │ Optional Notes:                                         │ │
│ │ [Reviewed draft deck. Suggested stronger opening...  ] │ │
│ │                                                         │ │
│ └─────────────────────────────────────────────────────────┘ │
│                                                              │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ⏳ Final Submission Review                              │ │
│ │                                                         │ │
│ │ [Mark as Complete]                                      │ │
│ └─────────────────────────────────────────────────────────┘ │
│                                                              │
└──────────────────────────────────────────────────────────────┘
```

### Milestone Data Model

```prisma
model MentorMilestone {
  id              String @id @default(cuid())
  competitionId   String
  name            String       // "Initial Review", "Business Plan Feedback"
  description     String?      @db.Text
  sortOrder       Int @default(0)
  isRequired      Boolean @default(false)  // If true, must be completed before workspace closes

  competition     Competition @relation(...)
  completions     MentorMilestoneCompletion[]
}

model MentorMilestoneCompletion {
  id                  String @id @default(cuid())
  mentorAssignmentId  String
  milestoneId         String
  completedAt         DateTime @default(now())
  notes               String? @db.Text

  mentorAssignment MentorAssignment @relation(...)
  milestone        MentorMilestone @relation(...)

  @@unique([mentorAssignmentId, milestoneId])
}
```

### Milestone API

| Procedure | Purpose |
|-----------|---------|
| `mentor.getMilestones(mentorAssignmentId)` | Get milestones + completion status for a team |
| `mentor.completeMilestone(assignmentId, milestoneId, notes)` | Mark milestone complete |
| `mentor.uncompleteMilestone(completionId)` | Revert completion (admin only) |

---

## 9. Navigation & Information Architecture

### Route Structure

```
/mentor/                                    → Dashboard (landing page)
/mentor/team/[projectId]                    → Workspace (redirects to /files)
/mentor/team/[projectId]/files              → File list + detail split-pane
/mentor/team/[projectId]/file/[fileId]      → Full-screen file detail (mobile)
/mentor/team/[projectId]/chat               → Chat tab
/mentor/team/[projectId]/milestones         → Milestones tab
/mentor/notifications                       → Notification center
/mentor/settings                            → Mentor profile/preferences
```

### Navigation Component

```tsx
// components/layouts/mentor-workspace-nav.tsx

interface MentorWorkspaceNavProps {
  projectId: string
  currentTab: "files" | "chat" | "milestones"
  unreadMessageCount: number
  milestonesCompleted: number
  milestonesTotal: number
}

// Renders:
// [📁 Files] [💬 Chat (2)] [📋 Milestones (2/4)]
```

### Breadcrumb

```
Dashboard > My Projects > OceanClean AI > Files
```

---

## 10. Admin View of Mentoring (Monitoring & Override)

Admin can monitor all mentoring activity and intervene when needed.

### Admin Dashboard — Mentoring Overview

```
┌──────────────────────────────────────────────────────────────────────────┐
│ Admin Dashboard > Mentoring Overview                                     │
├──────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│ Mentoring Period: June 1 – June 30, 2026 · ⏱ 18 days remaining          │
│                                                                          │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐               │
│ │ 12             │ │ 8              │ │ 4              │               │
│ │ Active Pairs   │ │ Files Promoted │ │ Inactive Teams │               │
│ └────────────────┘ └────────────────┘ └────────────────┘               │
│                                                                          │
│ ┌─ Mentor-Team Pairings ────────────────────────────────────────────┐   │
│ │                                                                    │   │
│ │ Search: [Filter by mentor, project, or status...]                 │   │
│ │                                                                    │   │
│ │ Mentor              | Project          | Files | Msgs | Last Act  │   │
│ │ ────────────────────┼──────────────────┼───────┼──────┼────────── │   │
│ │ Dr. Martin Duval    | OceanClean AI    | 5     | 8    | 2 hrs ago │   │
│ │                     | Blue Carbon Hub  | 1     | 3    | 2 days    │   │
│ │                     | SeaWatch Monitor | 0     | 0    | Never     │   │
│ │                     |                  |       |      | [Reassign]│   │
│ │                                                                    │   │
│ │ Dr. Lisa Chen       | WaveGen Pro      | 3     | 12   | 5 hrs ago │   │
│ │                     | Reef Restore AI  | 2     | 6    | 1 day     │   │
│ │                                                                    │   │
│ │ Prof. Ahmed Hassan  | PlasticTrack     | 4     | 10   | 3 hrs ago │   │
│ │                     | CoralSense       | 1     | 2    | 4 days    │   │
│ │                     |                  |       |      | ⚠ Flag    │   │
│ │                                                                    │   │
│ └────────────────────────────────────────────────────────────────────┘   │
│                                                                          │
│ ┌─ Alerts ──────────────────────────────────────────────────────────┐   │
│ │                                                                    │   │
│ │ ⚠ 4 teams have no activity in the last 5 days                     │   │
│ │ ⚠ 2 mentors are at max capacity (3 teams each)                    │   │
│ │ ⚠ 1 team has unread messages for 48+ hours                        │   │
│ │                                                                    │   │
│ └────────────────────────────────────────────────────────────────────┘   │
│                                                                          │
│ [Export Mentoring Report]  [Bulk Reassign]  [Extend Deadline]           │
└──────────────────────────────────────────────────────────────────────────┘
```

### Admin Actions

| Action | Purpose |
|--------|---------|
| **View any workspace** | Full read/write access to all workspaces |
| **Reassign mentor** | Change mentor for a project mid-stream |
| **Promote files on behalf of team** | Force promotion if team is unresponsive |
| **Extend deadline for specific team** | Grant extra time |
| **Flag inactive pairs** | Mark for follow-up |
| **Export workspace data** | Download all files, messages, comments for audit |

### Admin Workspace Access

Admin sees an additional "Admin Actions" section in any workspace:

```
┌─ Admin Actions ─────────────────────────────────────────┐
│                                                         │
│ [Reassign Mentor]  [Extend Deadline]  [Export Data]    │
│ [Promote File (Override)]  [Close Workspace]           │
│                                                         │
└─────────────────────────────────────────────────────────┘
```

---

## 11. Mobile Experience (Tablet-Optimized)

The workspace is designed to work well on tablets (iPad, Android tablets) for file review on the go.

### Mobile Layout

**Portrait Mode:**
```
┌─────────────────────────────┐
│ ← Back    OceanClean AI     │
├─────────────────────────────┤
│ [Files] [Chat] [Milestones] │
├─────────────────────────────┤
│                             │
│ Files (5)                   │
│                             │
│ 📄 Business Plan v3.pdf     │
│ Sarah · Jun 8 · 💬 4        │
│ [Open]                      │
│                             │
│ 📊 Financial Model.xlsx     │
│ You · Jun 6 · 💬 2          │
│ [Open]                      │
│                             │
│ 📄 Market Analysis.pdf      │
│ Sarah · Jun 5 · 💬 1        │
│ [Open]                      │
│                             │
│ ...                         │
│                             │
└─────────────────────────────┘

Tap a file →

┌─────────────────────────────┐
│ ← Back to Files             │
├─────────────────────────────┤
│ 📄 Business Plan v3.pdf     │
│ Sarah Johnson (Team)        │
│ Jun 8, 2026 · 2.4 MB        │
├─────────────────────────────┤
│                             │
│ [📥 Download]               │
│ [🚀 Promote]                │
│                             │
│ ───────────────────────     │
│                             │
│ 💬 Comments (4)             │
│                             │
│ Dr. Martin · Jun 8, 14:30   │
│ Section 3.2 needs stronger  │
│ market analysis...          │
│                             │
│   └─ Sarah · Jun 8, 16:00   │
│      Good point! We'll add  │
│      a competitive section. │
│                             │
│ [Add comment...]            │
│                             │
└─────────────────────────────┘
```

**Landscape Mode:**
```
┌───────────────────────────────────────────────────────────┐
│ ← Back to Dashboard      OceanClean AI    [🔔 3] [Menu ▾]│
├──────────────┬────────────────────────────────────────────┤
│ Files (5)    │ 📄 Business Plan v3.pdf                   │
│              │ Sarah Johnson · Jun 8 · 2.4 MB            │
│ 📄 Business..│ [📥 Download] [🚀 Promote]                │
│ 💬 4         │                                            │
│              │ ──────────────────────────────────────     │
│ 📊 Financia..│ 💬 Comments (4)                           │
│ 💬 2         │                                            │
│              │ Dr. Martin · Jun 8, 14:30                 │
│ 📄 Market A..│ Section 3.2 needs stronger...             │
│ 💬 1         │   └─ Sarah · Jun 8, 16:00                 │
│              │      Good point! We'll add...              │
│              │                                            │
└──────────────┴────────────────────────────────────────────┘
```

### Mobile-Specific Features

- **Swipe gestures** — Swipe left on file to reveal delete/promote actions
- **Pull to refresh** — Refresh file list and comments
- **Touch-friendly targets** — Minimum 44px tap targets
- **Offline mode** — Download files for offline review, sync comments when back online
- **File preview** — In-app PDF preview (no external app required)

---

## 12. Accessibility

### WCAG 2.1 AA Compliance

| Feature | Implementation |
|---------|----------------|
| **Keyboard navigation** | Full keyboard access to all workspace features |
| **Screen reader support** | ARIA labels on all interactive elements |
| **Color contrast** | 4.5:1 minimum for all text |
| **Focus indicators** | Visible focus ring on all focusable elements |
| **Alt text** | File type icons have descriptive labels |
| **Error messaging** | Clear, descriptive error messages on validation failures |

### File Preview Accessibility

For PDF file previews:
- Use `<iframe>` with PDF.js (accessible)
- Provide "Download" button as alternative to in-browser preview
- Alt text: "PDF preview of [filename]"

For image files:
- Show full-size image with alt text from file description
- Zoom controls for low vision users

For other file types (Excel, PowerPoint):
- No in-browser preview — download only
- Clear file type indicator and size

---

## 13. Component Library

### New Components

| Component | Path | Purpose |
|-----------|------|---------|
| `MentorDashboard` | `src/app/(mentor)/mentor/page.tsx` | Landing page |
| `TeamCard` | `src/components/mentor/team-card.tsx` | Reusable team summary card |
| `WorkspaceLayout` | `src/app/(mentor)/mentor/team/[projectId]/layout.tsx` | Workspace shell with tabs |
| `FileList` | `src/components/mentor/file-list.tsx` | Left pane file list |
| `FileDetail` | `src/components/mentor/file-detail.tsx` | Right pane file detail |
| `FilePromotionDialog` | `src/components/mentor/file-promotion-dialog.tsx` | Promotion confirmation dialog |
| `FileUploadZone` | `src/components/mentor/file-upload-zone.tsx` | Drag-and-drop upload area |
| `CommentThread` | `src/components/mentor/comment-thread.tsx` | Threaded comment display |
| `CommentInput` | `src/components/mentor/comment-input.tsx` | Comment textarea with @mentions |
| `MilestoneList` | `src/components/mentor/milestone-list.tsx` | Milestone progress view |
| `MentorActivityFeed` | `src/components/mentor/activity-feed.tsx` | Recent activity stream |
| `WorkspaceStatusBadge` | `src/components/mentor/workspace-status-badge.tsx` | Status indicator (active, needs attention, etc.) |

### Modified Existing Components

| Component | Changes |
|-----------|---------|
| `MentorChat` | Integrate into workspace tabs, add file reference support |
| `MentorNav` | Add "Workspaces" navigation item |

---

## 14. API Reference (New tRPC Procedures)

### Router: `mentorWorkspace`

All procedures require mentor, team lead, or admin authentication.

```typescript
// src/server/routers/mentor-workspace.ts

export const mentorWorkspaceRouter = router({
  // File Upload
  getUploadUrl: mentorOrTeamProcedure
    .input(z.object({
      mentorAssignmentId: z.string(),
      fileName: z.string(),
      mimeType: z.string(),
    }))
    .mutation(async ({ ctx, input }) => {
      // Generate MinIO pre-signed PUT URL
      return { uploadUrl, objectKey }
    }),

  saveFile: mentorOrTeamProcedure
    .input(z.object({
      mentorAssignmentId: z.string(),
      fileName: z.string(),
      mimeType: z.string(),
      size: z.number(),
      bucket: z.string(),
      objectKey: z.string(),
      description: z.string().optional(),
    }))
    .mutation(async ({ ctx, input }) => {
      // Create MentorFile record
      return mentorFile
    }),

  // File Management
  listFiles: mentorOrTeamProcedure
    .input(z.object({
      mentorAssignmentId: z.string(),
    }))
    .query(async ({ ctx, input }) => {
      // Return MentorFile[] with comment counts
      return { files }
    }),

  getFileDownloadUrl: mentorOrTeamProcedure
    .input(z.object({
      mentorFileId: z.string(),
    }))
    .query(async ({ ctx, input }) => {
      // Generate MinIO pre-signed GET URL
      return { downloadUrl, expiresAt }
    }),

  deleteFile: mentorOrTeamProcedure
    .input(z.object({
      mentorFileId: z.string(),
    }))
    .mutation(async ({ ctx, input }) => {
      // Soft delete (mark as deleted)
      // Only uploader or admin can delete
      return { success: true }
    }),

  // Comments
  addComment: mentorOrTeamProcedure
    .input(z.object({
      mentorFileId: z.string(),
      content: z.string().min(1),
      parentCommentId: z.string().optional(),
    }))
    .mutation(async ({ ctx, input }) => {
      // Create MentorFileComment
      // Parse @mentions and create notifications
      return comment
    }),

  listComments: mentorOrTeamProcedure
    .input(z.object({
      mentorFileId: z.string(),
    }))
    .query(async ({ ctx, input }) => {
      // Return threaded comments (with nested replies)
      return { comments }
    }),

  deleteComment: mentorOrTeamProcedure
    .input(z.object({
      commentId: z.string(),
    }))
    .mutation(async ({ ctx, input }) => {
      // Only author or admin can delete
      // Replace with "[Comment deleted]" placeholder
      return { success: true }
    }),

  // File Promotion
  promoteFile: protectedProcedure
    .input(z.object({
      mentorFileId: z.string(),
      submissionWindowId: z.string(),
      requirementId: z.string().optional(),
    }))
    .mutation(async ({ ctx, input }) => {
      // Validate permissions (team lead or admin)
      // Execute promotion (create ProjectFile, update MentorFile)
      // Audit log
      return { mentorFile, projectFile }
    }),

  unpromoteFile: adminProcedure
    .input(z.object({
      mentorFileId: z.string(),
    }))
    .mutation(async ({ ctx, input }) => {
      // Revert promotion (admin only)
      return { success: true }
    }),

  // Workspace Status
  getWorkspaceStatus: mentorOrTeamProcedure
    .input(z.object({
      mentorAssignmentId: z.string(),
    }))
    .query(async ({ ctx, input }) => {
      // Summary stats for workspace
      return {
        fileCount,
        unreadMessageCount,
        milestonesCompleted,
        milestonesTotal,
        lastActivity,
      }
    }),
})
```

### Authorization Helper

```typescript
// Check if user can access workspace
async function canAccessWorkspace(
  userId: string,
  mentorAssignmentId: string,
  prisma: PrismaClient
): Promise<boolean> {
  const assignment = await prisma.mentorAssignment.findUnique({
    where: { id: mentorAssignmentId },
    include: {
      mentor: true,
      project: {
        include: {
          teamMembers: true,
        },
      },
    },
  })

  if (!assignment) return false

  // Mentor
  if (assignment.mentorId === userId) return true

  // Team lead
  const teamLead = assignment.project.teamMembers.find(
    (tm) => tm.role === 'LEAD'
  )
  if (teamLead?.userId === userId) return true

  // Any team member (for read access)
  const isTeamMember = assignment.project.teamMembers.some(
    (tm) => tm.userId === userId
  )
  if (isTeamMember) return true

  // Admin (checked in middleware)
  return false
}
```

---

## 15. Service Layer

### New Service: `mentor-workspace.ts`

```typescript
// src/server/services/mentor-workspace.ts

import { PrismaClient, MentorFile, ProjectFile } from '@prisma/client'
import { generatePresignedUrl } from './minio-client'
import { logAudit } from '../utils/audit'

/**
 * Generate MinIO pre-signed PUT URL for workspace file upload
 */
export async function getWorkspaceUploadUrl(
  mentorAssignmentId: string,
  fileName: string,
  mimeType: string,
  actorId: string,
  prisma: PrismaClient
): Promise<{ uploadUrl: string; objectKey: string }> {
  // Validate workspace is active
  const assignment = await prisma.mentorAssignment.findUniqueOrThrow({
    where: { id: mentorAssignmentId },
  })

  if (!assignment.workspaceEnabled) {
    throw new Error('Workspace is not enabled for this assignment')
  }

  const now = new Date()
  if (
    assignment.workspaceOpenAt &&
    assignment.workspaceCloseAt &&
    (now < assignment.workspaceOpenAt || now > assignment.workspaceCloseAt)
  ) {
    throw new Error('Workspace is not currently open')
  }

  // Generate object key
  const objectKey = `mentor-workspace/${mentorAssignmentId}/${Date.now()}-${fileName}`

  // Generate pre-signed PUT URL (15-minute expiry)
  const uploadUrl = await generatePresignedUrl(
    process.env.MINIO_BUCKET!,
    objectKey,
    'PUT',
    15 * 60,
    mimeType
  )

  return { uploadUrl, objectKey }
}

/**
 * Save file metadata after upload
 */
export async function saveWorkspaceFile(
  mentorAssignmentId: string,
  uploadedByUserId: string,
  file: {
    fileName: string
    mimeType: string
    size: number
    bucket: string
    objectKey: string
  },
  description: string | null,
  prisma: PrismaClient
): Promise<MentorFile> {
  const mentorFile = await prisma.mentorFile.create({
    data: {
      mentorAssignmentId,
      uploadedByUserId,
      fileName: file.fileName,
      mimeType: file.mimeType,
      size: file.size,
      bucket: file.bucket,
      objectKey: file.objectKey,
      description,
    },
  })

  // Audit log
  await logAudit(prisma, {
    action: 'MENTOR_FILE_UPLOADED',
    actorId: uploadedByUserId,
    targetType: 'MENTOR_FILE',
    targetId: mentorFile.id,
    metadata: {
      fileName: file.fileName,
      size: file.size,
      mentorAssignmentId,
    },
  })

  return mentorFile
}

/**
 * Promote workspace file to official submission
 */
export async function promoteFileToSubmission(
  mentorFileId: string,
  submissionWindowId: string,
  requirementId: string | null,
  actorId: string,
  prisma: PrismaClient
): Promise<{ mentorFile: MentorFile; projectFile: ProjectFile }> {
  // 1. Validate mentor file
  const mentorFile = await prisma.mentorFile.findUniqueOrThrow({
    where: { id: mentorFileId },
    include: {
      mentorAssignment: {
        include: {
          project: true,
        },
      },
    },
  })

  if (mentorFile.isPromoted) {
    throw new Error('This file has already been promoted')
  }

  // 2. Validate workspace is active
  const { mentorAssignment } = mentorFile
  const now = new Date()
  if (
    !mentorAssignment.workspaceEnabled ||
    (mentorAssignment.workspaceCloseAt && now > mentorAssignment.workspaceCloseAt)
  ) {
    throw new Error('Workspace is closed — cannot promote files')
  }

  // 3. Find existing file in target slot (if requirementId provided)
  let replacedFile: ProjectFile | null = null
  if (requirementId) {
    replacedFile = await prisma.projectFile.findFirst({
      where: {
        projectId: mentorAssignment.projectId,
        requirementId,
        replacedById: null,
      },
    })
  }

  // 4. Determine version number
  const existingVersions = await prisma.projectFile.findMany({
    where: {
      projectId: mentorAssignment.projectId,
      submissionWindowId,
      requirementId,
    },
    orderBy: { version: 'desc' },
    take: 1,
  })
  const nextVersion = existingVersions.length > 0 ? existingVersions[0].version + 1 : 1

  // 5. Create new ProjectFile (reusing same MinIO object)
  const projectFile = await prisma.projectFile.create({
    data: {
      projectId: mentorAssignment.projectId,
      submissionWindowId,
      requirementId,
      fileType: 'SUBMISSION',
      fileName: mentorFile.fileName,
      mimeType: mentorFile.mimeType,
      size: mentorFile.size,
      bucket: mentorFile.bucket,
      objectKey: mentorFile.objectKey,  // NO DUPLICATION
      version: nextVersion,
      isLate: false,
    },
  })

  // 6. Update old file if it exists
  if (replacedFile) {
    await prisma.projectFile.update({
      where: { id: replacedFile.id },
      data: { replacedById: projectFile.id },
    })
  }

  // 7. Update MentorFile
  const updatedMentorFile = await prisma.mentorFile.update({
    where: { id: mentorFileId },
    data: {
      isPromoted: true,
      promotedToFileId: projectFile.id,
      promotedAt: now,
      promotedByUserId: actorId,
    },
  })

  // 8. Audit log
  await logAudit(prisma, {
    action: 'MENTOR_FILE_PROMOTED',
    actorId,
    targetType: 'PROJECT_FILE',
    targetId: projectFile.id,
    metadata: {
      mentorFileId,
      submissionWindowId,
      requirementId,
      replacedFileId: replacedFile?.id,
      version: nextVersion,
    },
  })

  return { mentorFile: updatedMentorFile, projectFile }
}

/**
 * Revert promotion (admin only)
 */
export async function unpromoteFile(
  mentorFileId: string,
  actorId: string,
  prisma: PrismaClient
): Promise<void> {
  const mentorFile = await prisma.mentorFile.findUniqueOrThrow({
    where: { id: mentorFileId },
    include: { promotedFile: true },
  })

  if (!mentorFile.isPromoted || !mentorFile.promotedFile) {
    throw new Error('File is not promoted')
  }

  const promotedFile = mentorFile.promotedFile

  // 1. If promoted file replaced a previous file, restore that file
  if (promotedFile.replacedById) {
    const previousFile = await prisma.projectFile.findUnique({
      where: { replacedById: promotedFile.id },
    })
    if (previousFile) {
      await prisma.projectFile.update({
        where: { id: previousFile.id },
        data: { replacedById: null },
      })
    }
  }

  // 2. Delete the promoted ProjectFile
  await prisma.projectFile.delete({
    where: { id: promotedFile.id },
  })

  // 3. Reset MentorFile flags
  await prisma.mentorFile.update({
    where: { id: mentorFileId },
    data: {
      isPromoted: false,
      promotedToFileId: null,
      promotedAt: null,
      promotedByUserId: null,
    },
  })

  // 4. Audit log
  await logAudit(prisma, {
    action: 'MENTOR_FILE_UNPROMOTED',
    actorId,
    targetType: 'MENTOR_FILE',
    targetId: mentorFileId,
    metadata: {
      deletedProjectFileId: promotedFile.id,
    },
  })
}
```

---

## 16. Edge Cases & Error Handling

| Scenario | Handling |
|----------|----------|
| **Team doesn't want mentoring but admin assigns anyway** | Assignment created; team sees mentor in dashboard with explanation |
| **Mentor goes inactive during period** | Admin can reassign; previous workspace preserved (read-only for old mentor) |
| **File promoted then mentor period closes** | Promoted file remains as official submission; MentorFile remains in workspace |
| **Team tries to promote file for requirement that doesn't exist** | Error — must select valid requirement or leave requirementId null |
| **Two files promoted to same requirement slot** | Second promotion replaces first (versioning applies) |
| **Mentoring file is larger than requirement maxSizeMB** | Warning shown but promotion allowed (admin override implicit) |
| **Workspace closed but team needs one more upload** | Admin can extend via round window adjustment or grant grace period |
| **Promoted file deleted from workspace** | ProjectFile remains (separate record); MentorFile keeps audit trail |
| **Mentor uploads file then leaves program** | Files remain accessible in workspace; admin can reassign mentor |
| **File upload fails mid-way** | MinIO object exists but no MentorFile record → cleanup job deletes orphaned objects weekly |
| **Comment with @mention for user not in workspace** | @mention rendered as plain text, no notification sent |
| **Workspace accessed after mentoring round ends** | Read-only mode — can view files and messages, can't upload or comment |

---

## 17. Performance Considerations

### File Upload Optimization

- **Direct MinIO upload** — Files never touch the Next.js server
- **Pre-signed URLs** — 15-minute expiry, client uploads directly
- **Chunked upload** — For files > 5 MB, use multipart upload
- **Progress feedback** — Real-time upload progress bar

### File List Performance

- **Pagination** — Load 20 files at a time (infinite scroll)
- **Comment count caching** — Denormalized comment count on MentorFile
- **Thumbnail generation** — For images, generate thumbnails on upload

### Real-time Updates

- **Polling strategy** — Poll every 10s for new messages, 30s for file list
- **WebSocket upgrade** — If available, use WebSocket for real-time updates
- **Optimistic UI** — Show uploaded file immediately, sync in background

---

## 18. Security

### Access Control

```typescript
// Every workspace procedure checks:
1. User is authenticated
2. User is mentor OR team member OR admin
3. Workspace is active (or admin override)
```

### File Storage Security

- **Private bucket** — All workspace files in private MinIO bucket
- **Pre-signed URLs** — Expire after 15 minutes
- **No directory listing** — Can't enumerate workspace files without database access
- **Audit trail** — Every file upload, download, promotion logged

### XSS Prevention

- **Sanitize filenames** — Strip HTML, escape special chars
- **Sanitize comments** — Plain text only, no HTML tags
- **Validate MIME types** — Only allow whitelisted file types

---

## 19. Testing Strategy

### Unit Tests

```typescript
// Test file promotion logic
describe('promoteFileToSubmission', () => {
  it('should create ProjectFile with same objectKey', async () => {
    const { mentorFile, projectFile } = await promoteFileToSubmission(...)
    expect(projectFile.objectKey).toBe(mentorFile.objectKey)
    expect(mentorFile.isPromoted).toBe(true)
  })

  it('should increment version number', async () => {
    // Upload file v1
    // Promote to create ProjectFile v1
    // Upload file v2
    // Promote to create ProjectFile v2
    expect(projectFile.version).toBe(2)
  })

  it('should replace previous file in slot', async () => {
    // Promote file1 to slot A
    // Promote file2 to slot A
    expect(file1.replacedById).toBe(file2.id)
  })
})
```

### Integration Tests

```typescript
// Test full workspace flow
describe('Workspace Integration', () => {
  it('should allow mentor to upload, team to comment, and promote', async () => {
    // 1. Mentor uploads file
    const uploadUrl = await trpc.mentorWorkspace.getUploadUrl(...)
    // Upload to MinIO
    const file = await trpc.mentorWorkspace.saveFile(...)

    // 2. Team adds comment
    const comment = await trpc.mentorWorkspace.addComment(...)
    expect(comment.authorId).toBe(teamMemberId)

    // 3. Promote file
    const { projectFile } = await trpc.mentorWorkspace.promoteFile(...)
    expect(projectFile.projectId).toBe(project.id)
  })
})
```

### E2E Tests (Playwright)

```typescript
// Test workspace UI
test('Mentor can upload file and view comments', async ({ page }) => {
  await page.goto('/mentor/team/project-123/files')

  // Upload file
  await page.click('text=Upload File')
  await page.setInputFiles('input[type=file]', 'test-file.pdf')
  await page.click('text=Upload')

  // Wait for file to appear
  await page.waitForSelector('text=test-file.pdf')

  // Open file detail
  await page.click('text=test-file.pdf')

  // Add comment
  await page.fill('textarea[placeholder="Add comment..."]', 'Looks good!')
  await page.click('text=Post Comment')

  // Verify comment appears
  await page.waitForSelector('text=Looks good!')
})
```

---

## 20. Rollout Plan

### Phase 1: Foundation (Week 1-2)

- [ ] Create data models (MentorFile, MentorFileComment)
- [ ] Migration script
- [ ] Basic tRPC procedures (upload, list, download)
- [ ] Service layer (`mentor-workspace.ts`)

### Phase 2: Core UI (Week 3-4)

- [ ] Mentor dashboard
- [ ] Workspace layout (split-pane)
- [ ] File list component
- [ ] File detail component
- [ ] File upload zone

### Phase 3: Comments & Chat (Week 5)

- [ ] Comment thread component
- [ ] @mention support
- [ ] Enhanced chat integration

### Phase 4: File Promotion (Week 6)

- [ ] Promotion dialog
- [ ] Promotion service logic
- [ ] Unpromote (admin override)
- [ ] Audit trail

### Phase 5: Admin Tools (Week 7)

- [ ] Admin monitoring dashboard
- [ ] Reassignment flow
- [ ] Workspace export
- [ ] Activity alerts

### Phase 6: Polish & Mobile (Week 8)

- [ ] Mobile responsive design
- [ ] Accessibility audit
- [ ] Performance optimization
- [ ] E2E tests

---

## 21. Success Metrics

| Metric | Target |
|--------|--------|
| **Mentor engagement** | 80%+ of mentors upload at least 1 file |
| **Team engagement** | 90%+ of finalist teams engage in workspace |
| **File promotion rate** | 50%+ of workspace files promoted to submission |
| **Comment activity** | Average 3+ comments per promoted file |
| **Milestone completion** | 70%+ of mentors complete all milestones |
| **Mobile usage** | 30%+ of workspace access from mobile/tablet |
| **Time to first file upload** | < 24 hours after mentoring round opens |
| **Admin intervention rate** | < 10% of assignments require admin reassignment |

---

## 22. Future Enhancements (Post-MVP)

### Video Integration

- Loom/Zoom integration for mentor video feedback
- Record screen share reviews of files

### Real-time Collaboration

- Live document editing (Google Docs-style)
- Shared whiteboard for brainstorming

### AI-Powered Features

- AI-generated file summaries
- Suggested comments based on file content
- Auto-tagging files by topic

### Analytics Dashboard

- Mentor performance metrics
- Team engagement heatmaps
- File promotion success rates

### Templates Library

- Mentor-created templates (financial models, pitch decks)
- Template marketplace

---

## Document Complete

This document provides a comprehensive blueprint for the Mentor UI redesign. It covers:

- Current baseline (existing mentor features)
- Dashboard design (landing page with team cards, metrics, activity feed)
- Workspace architecture (split-pane file management)
- File review & comments (threaded discussion)
- File promotion (workspace → official submission)
- Messaging integration
- Milestones tracking
- Navigation & IA
- Admin monitoring
- Mobile experience
- Accessibility
- Component library
- API reference
- Service layer
- Edge cases & security
- Testing strategy
- Rollout plan
- Success metrics

The redesigned mentor experience transforms mentoring from basic messaging into a full collaboration workspace with file management, threaded comments, and seamless integration with the submission system.
