# Admin UI Redesign - Implementation Plan
## Overview
This plan outlines the migration from the current scattered admin structure to a clean, hierarchy-driven navigation centered on **Tryouts**.
### Guiding Principles
1. **One main page per domain** - Features live under their parent, not as separate menu items
2. **URL reflects depth** - Path structure shows relationship (`/admin/tryout/{id}/questions`)
3. **Tree as map** - Hierarchy tree shows structure; drill-down shows details
4. **Consistent naming** - Use "Tryout" instead of "Exam" throughout
---
## 1. URL Structure
### New URL Scheme
| Old Route | New Route | Description |
|-----------|-----------|-------------|
| `/admin/exams` | `/admin/tryouts` | Hierarchy tree (main entry) |
| `/admin/student-attempts` | `/admin/tryout/{tryout_id}/attempts` | Attempts filtered by tryout |
| - | `/admin/tryout/{tryout_id}/questions` | Questions filtered by tryout |
| - | `/admin/tryout/{tryout_id}/questions/{question_id}/workspace` | Question workspace |
| - | `/admin/tryout/{tryout_id}/questions/{question_id}/workspace/{tab}` | Workspace tabs |
| - | `/admin/tryout/{tryout_id}/normalization` | Normalization settings for this tryout |
| `/admin/questions` | `/admin/questions` | Global question list (kept) |
| (none) | `/admin/import-tryout` | Import tryout modal/page |
> **Note:** Import is tryout-level, not question-level. Import button lives on `/admin/tryouts` page header.
### Hierarchy Depth Convention
```
/admin/tryouts → Level 0: Root
/admin/tryout/{tryout_id} → Level 1: Entity
/admin/tryout/{tryout_id}/attempts → Level 2: Related data
/admin/tryout/{tryout_id}/questions → Level 2: Related data
/admin/tryout/{tryout_id}/questions/{id} → Level 3: Specific item
/admin/tryout/{tryout_id}/questions/{id}/workspace → Level 4: Detail view
```
---
## 2. Navigation Structure
### Proposed Navigation
```
Questions
├── /admin/questions # Global question list
└── /admin/tryout/*/questions/*/workspace # Direct link from tree
Tryouts
├── /admin/tryouts # Tree: Website → Tryout → Stat → Actions + Import button
├── /admin/tryout/*/attempts # Filtered attempts
├── /admin/tryout/*/questions # Questions in this tryout
├── /admin/tryout/*/normalization # Normalization settings
└── /admin/import-tryout # Import modal/page
Reports
├── /admin/reports # Dashboard
├── /admin/item-statistics
└── /admin/calibration-status
Settings
├── /admin/settings
├── /admin/websites
└── /admin/password
```
### Navigation Item Definition
```python
ADMIN_NAV_ITEMS = (
("Dashboard", "/admin/dashboard", ("/admin/dashboard",)),
("Questions", "/admin/questions", (
"/admin/questions",
"/admin/tryout/*/questions/*/workspace", # Pattern for direct links
)),
("Tryouts", "/admin/tryouts", (
"/admin/tryouts",
"/admin/tryout/*/attempts",
"/admin/tryout/*/questions",
"/admin/tryout/*/normalization",
"/admin/import-tryout",
)),
("Reports", "/admin/reports", (
"/admin/reports",
"/admin/item-statistics",
"/admin/calibration-status",
)),
("Settings", "/admin/settings", (
"/admin/settings",
"/admin/websites",
"/admin/password",
)),
("Logout", "/admin/logout", ("/admin/logout",)),
)
```
---
## 3. Tryouts Tree Structure
### Visual Design
```
┌─ Tryouts ───────────────────────────────────────────────────────────────────┐
│ │
│ [+ Import Tryout] │
│ │
│ 🌐 Website A │
│ │ │
│ ├─ 📋 132380 - UTBK 2024 [●] │
│ │ └─ [Expanded on click] │
│ │ │
│ ├─ 📋 132381 - SIMAK UI [✓] │
│ │ │
│ └─ 📋 132382 - PAS Semester 1 [○] │
│ │
│ 🌐 Website B │
│ └─ ... │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
Expanded Tryout View:
┌─ 📋 132380 - UTBK 2024 ─────────────────────────────────────────────────────┐
│ │
│ ┌─ Stat Card ─────────────────────────────────────────────────────────┐ │
│ │ 👥 150 participants │ NM: 672 avg │ NN: 505 avg │ │
│ │ ✓ 98% completion │ 📐 Calibration: ████████░░ 85% (17/20) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ [📝 Questions (20)] [👥 Attempts (150)] [📐 Normalization] [⚙ Settings]│
│ │
└──────────────────────────────────────────────────────────────────────────────┘
Legend:
[●] Partial (50-89% calibrated)
[✓] Ready (≥90% calibrated)
[○] Needs Data (<50% calibrated)
```
### Import Button Location
- **Location:** Header of `/admin/tryouts` page
- **Label:** "[+ Import Tryout]" or "[Import Tryout JSON]"
- **Behavior:** Opens import modal/page
- **Why:** Import is tryout-level operation (imports questions WITH tryout context)
### Stat Card Components
| Field | Source | Display |
|-------|--------|---------|
| Participants | `TryoutStats.participant_count` | 👥 {count} |
| Avg NM | `AVG(Session.NM)` where completed | 📊 {value} avg |
| Avg NN | `AVG(Session.NN)` where completed | 📈 {value} avg |
| Completion Rate | `completed / participants * 100` | ✓ {percentage}% |
| Calibration | `calibrated_items / total_items` | 📐 Progress bar + {count}/{total} |
### Action Buttons
| Action | Target URL | Icon |
|--------|------------|------|
| Questions | `/admin/tryout/{id}/questions` | 📝 |
| Attempts | `/admin/tryout/{id}/attempts` | 👥 |
| Normalization | `/admin/tryout/{id}/normalization` | 📐 |
| Settings | `/admin/tryout/{id}/settings` (or modal) | ⚙ |
---
## 4. Page Specifications
### 4.1 `/admin/tryouts` (Main Tree)
**Purpose:** Primary navigation entry, shows structure at a glance
**Default State:**
- Websites expanded
- Tryouts collapsed
- Shows calibration indicator dot next to each tryout
**Interactions:**
- Click tryout → expand/collapse
- Expanded tryout shows stat card + action buttons
- Actions navigate to filtered views
### 4.2 `/admin/tryout/{tryout_id}/questions`
**Purpose:** View all questions in a specific tryout
**Behavior:**
- Shows only original/imported questions (basis items)
- Pre-filtered by `tryout_id`
- Links to workspace for AI variant generation
**Table Columns:**
| Column | Description |
|--------|-------------|
| ID | Question internal ID |
| Stem Preview | First 100 chars of question text |
| Difficulty | Current difficulty level |
| Calibration | P-value or IRT-b indicator |
| Variants | Count of generated variants |
| Actions | [View] [Workspace] |
### 4.3 `/admin/tryout/{tryout_id}/questions/{question_id}/workspace`
**Purpose:** Generate and manage question variants
**Tabs:**
| Tab | Purpose |
|-----|---------|
| Generate | AI variant generation interface |
| Review | Review generated variants |
| Batch | Batch generation options |
**Access Pattern:**
- Opens from question list or tree direct link
- Context: knows parent tryout, parent question
### 4.4 `/admin/tryout/{tryout_id}/attempts`
**Purpose:** View student attempts for specific tryout
**Current Implementation:** Already exists at `/admin/student-attempts` → migrate URL
**Enhancements:**
- Pre-filtered by `tryout_id` (no dropdown needed on this page)
- Stat card from parent tryout shown at top
### 4.5 `/admin/tryout/{tryout_id}/normalization`
**Purpose:** Configure normalization settings for a specific tryout
**Settings (per-tryout):**
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| Mode | Select | Auto | Auto (calculate from data) or Manual (fixed values) |
| Rataan | Number | 500 | Target mean for normalization |
| SB | Number | 100 | Target standard deviation |
| Recalculate | Button | - | Re-run normalization on existing sessions |
**Formula:** `NN = 500 + 100 × ((NM - Rataan) / SB)`
**UI:**
- Simple form with current values
- "Recalculate" button triggers normalization job
- Shows last normalization timestamp
### 4.6 `/admin/import-tryout`
**Purpose:** Import tryout data (questions + metadata) from JSON
**Access:** Via "[+ Import Tryout]" button on `/admin/tryouts` page
**Behavior:**
- Opens modal or dedicated page
- Upload JSON file or paste JSON content
- Preview import before confirming
- Creates new tryout with questions
**URL Convention:** Not under specific tryout (it's creating a new one)
---
## 5. Deprecations
### Routes to Remove
| Route | Reason |
|-------|--------|
| `/admin/exams` | Renamed to `/admin/tryouts` |
| `/admin/student-attempts` | URL changed to `/admin/tryout/{id}/attempts` |
| `/admin/templates` | AI uses basis items directly |
| `/admin/basis-items` | Merge into question workspace |
| `/admin/hierarchy` | Tree IS the hierarchy |
| `/admin/question-quality` | Merged into tryout stat card |
### Legacy Redirects
```python
LEGACY_URL_MAP = {
"/admin/exams": "/admin/tryouts",
"/admin/student-attempts": "/admin/tryouts", # Or redirect to tryouts with guidance
"/admin/hierarchy": "/admin/tryouts",
"/admin/question-quality": "/admin/tryouts",
# Templates and basis-items: 404 (removed)
}
```
---
## 6. Implementation Phases
### Phase 1: Foundation
- [ ] Rename `/admin/exams` → `/admin/tryouts` (keep old route for now)
- [ ] Implement tree structure in `/admin/tryouts`
- [ ] Move `TryoutStats` info into tree stat cards
- [ ] Add calibration indicator dots
### Phase 2: URL Migration
- [ ] Create `/admin/tryout/{id}/attempts` (redirect from old route)
- [ ] Create `/admin/tryout/{id}/questions`
- [ ] Update navigation items
### Phase 3: Workspace Integration
- [ ] Create question workspace route
- [ ] Implement workspace tabs
- [ ] Connect workspace to tree and question list
### Phase 4: Cleanup
- [ ] Add legacy redirects
- [ ] Remove deprecated routes
- [ ] Update all hardcoded links in views
### Phase 5: Polish
- [ ] Review all pages for consistency
- [ ] Update documentation
- [ ] Test all navigation paths
---
## 7. Open Questions
1. ~~Normalization settings~~ - **RESOLVED**: Move under tryout context as `/admin/tryout/{id}/normalization`
2. ~~Import questions page~~ - **RESOLVED**: Import is tryout-level. Button on `/admin/tryouts` header, not a separate page.
3. **Tryout settings** - What settings are actually needed? (Scoring mode, time limits, selection criteria?)
4. **Global questions page** - Is `/admin/questions` (unfiltered) still useful, or should every question access go through tryout context?
5. **Templates deprecation** - Confirm that `/admin/templates` is truly unused and can be safely removed?
6. **Legacy routes for deleted pages** - Should `/admin/templates` and `/admin/basis-items` redirect somewhere or return 404?
---
## 8. Files to Modify
### Primary Changes
- `app/admin_web.py` - Major route restructuring
- Navigation definition in `admin_web.py`
- Legacy URL map
### Likely Additions
- Static assets for tree expansion/collapse (if not using existing)
### Documentation Updates
- `ADMIN_UI_REDESIGN_PLAN.md` - Update to reflect final structure
- `PROJECT_UNDERSTANDING.md` - Update route documentation
---
## 9. Changelog
| Version | Date | Changes |
|---------|------|---------|
| 1.0 | 2026-06-17 | Initial draft based on discussion |
| 1.1 | 2026-06-17 | - Move normalization to `/admin/tryout/{id}/normalization`
- Move import button to `/admin/tryouts` header
- Add normalization page spec (4.5)
- Rename import page spec (4.6)
- Update navigation and action buttons |