Complete Phase 2: Frontend implementation with React + TypeScript

Frontend Features:
- React 18 + Vite + TypeScript + Tailwind CSS + Zustand
- JWT authentication with automatic token refresh
- Tree library with search and category filtering
- Full tree navigation (decision/action/solution nodes)
- Session management with notes and completion
- Session history with export (Markdown/Text/HTML)
- ErrorBoundary for graceful error handling

Backend Fixes:
- CORS: Added port 5174 to allowed origins
- Sessions: Fixed JSONB datetime serialization (mode='json')

Documentation:
- Updated PROGRESS.md with Phase 2 completion
- Updated 03-DEVELOPMENT-ROADMAP.md with checked items
- Added PHASE-2.5-PERSONAL-BRANCHING.md spec

Seed Data:
- Added backend/scripts/seed_data.py with Password Reset tree

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-01-27 22:42:22 -05:00
parent 7d96807fb1
commit cd10ecd42c
51 changed files with 9014 additions and 111 deletions

View File

@@ -0,0 +1,12 @@
export interface Token {
access_token: string
refresh_token: string
token_type: string
}
export interface AuthState {
user: import('./user').User | null
token: Token | null
isAuthenticated: boolean
isLoading: boolean
}

View File

@@ -0,0 +1,17 @@
export * from './user'
export * from './auth'
export * from './tree'
export * from './session'
// API response wrapper types
export interface PaginatedResponse<T> {
items: T[]
total: number
page: number
size: number
pages: number
}
export interface ApiError {
detail: string
}

View File

@@ -0,0 +1,55 @@
import type { TreeStructure } from './tree'
export interface DecisionRecord {
node_id: string
question: string | null
answer: string | null
action_performed: string | null
notes: string | null
automation_used: boolean
timestamp: string
attachments: string[]
}
export interface Session {
id: string
tree_id: string
user_id: string
tree_snapshot: TreeStructure
path_taken: string[]
decisions: DecisionRecord[]
started_at: string
completed_at: string | null
ticket_number: string | null
client_name: string | null
exported: boolean
}
export interface SessionCreate {
tree_id: string
ticket_number?: string
client_name?: string
}
export interface SessionUpdate {
path_taken?: string[]
decisions?: DecisionRecord[]
ticket_number?: string
client_name?: string
}
export interface SessionExport {
format: 'text' | 'markdown' | 'html'
include_timestamps?: boolean
include_tree_info?: boolean
}
// Navigation state for active session
export interface SessionNavigationState {
activeSession: Session | null
currentNodeId: string
pathTaken: string[]
decisions: DecisionRecord[]
isLoading: boolean
error: string | null
}

View File

@@ -0,0 +1,98 @@
// Tree node types
export type NodeType = 'decision' | 'action' | 'solution'
export interface TreeOption {
id: string
label: string
next_node_id: string
}
export interface TreeNodeBase {
id: string
type: NodeType
}
export interface DecisionNode extends TreeNodeBase {
type: 'decision'
question: string
help_text?: string
options: TreeOption[]
children: TreeNode[]
}
export interface ActionNode extends TreeNodeBase {
type: 'action'
title: string
description: string
commands?: string[]
expected_outcome?: string
next_node_id?: string
children?: TreeNode[]
}
export interface SolutionNode extends TreeNodeBase {
type: 'solution'
title: string
description: string
resolution_steps?: string[]
}
export type TreeNode = DecisionNode | ActionNode | SolutionNode
export interface TreeStructure {
id: string
type: NodeType
question?: string
title?: string
description?: string
help_text?: string
options?: TreeOption[]
commands?: string[]
expected_outcome?: string
next_node_id?: string
resolution_steps?: string[]
children?: TreeStructure[]
}
// API response types
export interface Tree {
id: string
name: string
description: string | null
category: string | null
tree_structure: TreeStructure
author_id: string | null
team_id: string | null
is_active: boolean
version: number
created_at: string
updated_at: string
usage_count: number
}
export interface TreeListItem {
id: string
name: string
description: string | null
category: string | null
is_active: boolean
version: number
usage_count: number
created_at: string
updated_at: string
}
export interface TreeCreate {
name: string
description?: string
category?: string
tree_structure: TreeStructure
}
export interface TreeUpdate {
name?: string
description?: string
category?: string
tree_structure?: TreeStructure
is_active?: boolean
}

View File

@@ -0,0 +1,28 @@
export type UserRole = 'admin' | 'engineer' | 'viewer'
export interface User {
id: string
email: string
name: string
role: UserRole
team_id: string | null
created_at: string
last_login: string | null
}
export interface UserCreate {
email: string
password: string
name: string
role?: UserRole
}
export interface UserLogin {
email: string
password: string
}
export interface UserUpdate {
name?: string
email?: string
}