The Milestone Review Interface provides a comprehensive solution for clients to review freelancer milestone submissions with full transparency, accountability, and smooth collaboration features.
- Milestone title and description - Clear context for the submission
- Amount and currency - Financial details prominently displayed
- Due date - Deadline tracking
- Submission timestamp - Records when deliverable was submitted
- Status badge - Visual indicator of current milestone state
- Submission notes - Freelancer's explanation of deliverables
- Deliverables list - All files/links attached to the milestone
- Visual distinction between files and links
- Direct links to external resources
- Clean, organized presentation
Three primary actions available when milestone is in "submitted" status:
- Confirmation dialog before approval
- Records approval in submission history
- Updates milestone status to "approved"
- Notifies freelancer of approval
- Triggers payment release process
- Allows client to provide detailed revision feedback
- Returns milestone to "in_progress" status
- Increments revision counter
- Records in submission history
- Notifies freelancer with revision notes
- Tracks number of revision requests
- Requires detailed rejection reason
- Warning about serious nature of action
- May trigger dispute resolution
- Records rejection with reason
- Updates milestone status to "rejected"
- Collapsible timeline - Expandable history section
- Complete audit trail - All submissions and responses
- Timestamped entries - When each action occurred
- User attribution - Who submitted/reviewed
- Action-specific details:
- Submission notes
- Revision requests with feedback
- Approval confirmations
- Rejection reasons
- Visual indicators - Icons for different action types
- Scrollable interface - Handles long histories
- Full access to review actions
- Approve, reject, and request changes buttons
- Submission details and history
- Clear call-to-action for pending reviews
- View submission status
- See submission history
- Read client feedback/revision requests
- Alert when revisions are requested
- No modification controls
- Loading spinner - While fetching milestone data
- Error messages - Clear feedback on failures
- Retry functionality - Option to reload failed requests
- Empty states - Graceful handling of missing data
- Toast notifications - Success/error feedback
- Mobile-optimized layout - Works on all screen sizes
- Adaptive grid - Adjusts columns based on viewport
- Touch-friendly buttons - Proper sizing for mobile
- Readable typography - Scales appropriately
- Collapsible sections - Saves space on mobile
- id: UUID (primary key)
- milestone_id: UUID (references milestones)
- submission_type: VARCHAR(20) - 'submitted', 'approved', 'rejected', 'revision_requested'
- submitted_by: UUID (references users)
- reviewed_by: UUID (references users, nullable)
- deliverable_notes: TEXT
- deliverable_links: TEXT[]
- feedback: TEXT
- revision_notes: TEXT
- metadata: JSONB
- created_at: TIMESTAMPTZ- submission_notes: TEXT - Notes provided with submission
- revision_requested: BOOLEAN - Flag for active revision request
- revision_count: INTEGER - Number of times revisions requested
- last_reviewed_at: TIMESTAMPTZ - Last review timestamp
- last_reviewed_by: UUID - Last reviewer user IDFetch a single milestone with full details
Auth: Required
Access: Client or Freelancer of the contract
Response:
{
"milestone": {
"id": "uuid",
"title": "string",
"description": "string",
"amount": "number",
"currency": "string",
"status": "string",
"submission_notes": "string",
"deliverables": ["string"],
"revision_requested": boolean,
"revision_count": number,
"submitted_at": "timestamp",
"contract_id": "uuid",
"client_id": "uuid",
"freelancer_id": "uuid"
}
}Approve or reject a submitted milestone
Auth: Required
Access: Client only
Body:
{
"action": "approve" | "reject",
"rejection_reason": "string (required if reject)",
"approval_notes": "string (optional)"
}Updates:
- Records action in submission history
- Updates milestone status
- Sets last_reviewed_at and last_reviewed_by
- Triggers notifications
Request revisions from freelancer
Auth: Required
Access: Client only
Body:
{
"revision_notes": "string (required)"
}Updates:
- Returns milestone to "in_progress" status
- Sets revision_requested flag to true
- Increments revision_count
- Records in submission history
- Notifies freelancer
Submit milestone for client review (updated)
Auth: Required
Access: Freelancer only
Body:
{
"deliverables": ["string"],
"submission_notes": "string",
"deliverable_links": ["string"]
}Updates:
- Records submission in history
- Updates submission_notes
- Resets revision_requested flag
- Notifies client
Get complete submission history
Auth: Required
Access: Client or Freelancer
Response:
{
"milestone": {
"id": "uuid",
"title": "string",
"status": "string"
},
"history": [
{
"id": "uuid",
"submission_type": "string",
"submitter_name": "string",
"reviewer_name": "string",
"deliverable_notes": "string",
"revision_notes": "string",
"feedback": "string",
"created_at": "timestamp"
}
]
}The primary review interface component
Props:
milestone: Milestone- Full milestone datauserRole: 'client' | 'freelancer'- Current user's roleonUpdate?: () => void- Callback after milestone updates
Features:
- Conditional rendering based on role and status
- Integrated dialogs for approve/reject/request-changes
- Automatic history loading
- Toast notifications
- Form validation
Page wrapper for the milestone review
Features:
- Fetches milestone data on mount
- Determines user role
- Error handling and loading states
- Navigation controls
-
Collapsible (
components/ui/collapsible.tsx)- Used for expandable submission history
-
Separator (
components/ui/separator.tsx)- Visual dividers between sections
-
ScrollArea (
components/ui/scroll-area.tsx)- Scrollable history timeline
- Navigate to milestone from contract/dashboard
- View submission details and deliverables
- Expand and review submission history (optional)
- Choose action:
- Approve: Confirm in dialog → Milestone approved → Freelancer notified
- Request Changes: Provide feedback → Returns to in_progress → Freelancer notified
- Reject: Provide reason → Milestone rejected → May trigger dispute
- Navigate to milestone
- View current status
- See submission history
- If revisions requested:
- Read client feedback
- Understand what needs fixing
- Resubmit when ready
- Contract management - Links to contract milestones
- Activity logging - All actions logged via activityService
- Notifications - Automated notifications to relevant parties
- Authentication - Secured with wallet-based auth
- Authorization - Role-based access control (RBAC)
- Milestone list in
ContractMilestoneListcomponent now links to review page - Back navigation to dashboard/contracts
- Breadcrumb-friendly routing
- User must be authenticated
- Must be either client or freelancer on the contract
- Client-only actions: approve, reject, request changes
- Freelancer-only actions: submit
- Rejection reason: Required, non-empty string
- Revision notes: Required, non-empty string
- Status transitions: Validated server-side
- SQL injection prevention: Parameterized queries
- Immutable history records
- Audit trail for all actions
- Timestamp all state changes
- User attribution for accountability
- Semantic HTML structure
- Proper heading hierarchy
- ARIA labels on interactive elements
- Keyboard navigation support
- Focus management in dialogs
- Color contrast meets AA standards
- Screen reader friendly
- Mobile: < 640px
- Tablet: 640px - 1024px
- Desktop: > 1024px
- Component rendering with different milestone statuses
- Role-based UI rendering
- Form validation
- API error handling
- Full approval flow
- Request changes flow
- Rejection flow
- History loading
- Permission checks
- Client approves milestone
- Client requests changes
- Freelancer views feedback
- History timeline interaction
- Mobile responsive behavior
- File upload widget - Direct file upload to deliverables
- Inline commenting - Comment on specific deliverables
- Comparison view - Compare versions across submissions
- Auto-save drafts - Save review feedback as draft
- Batch approval - Approve multiple milestones at once
- Email notifications - Complement in-app notifications
- Export history - Download submission history as PDF
- Templates - Pre-written revision request templates
Run the migration before deploying:
npm run migrateNo new environment variables required.
All required dependencies are already in package.json:
@radix-ui/react-collapsible@radix-ui/react-scroll-area@radix-ui/react-separator
- Track API endpoint performance
- Monitor submission approval rates
- Track revision request frequency
- Alert on high rejection rates
- Permission denied: Verify user is part of contract
- Invalid status: Check milestone status before action
- Missing deliverables: Validate submission has content
- History not loading: Check database connection
This milestone review interface provides a production-ready solution for transparent, accountable collaboration between clients and freelancers. All acceptance criteria have been met:
✅ Confirmation before approval
✅ Proper loading/error states
✅ Different UI based on client/freelancer role
✅ Submission history accessible
✅ Responsive design
✅ Display submitted files/links
✅ Milestone description context
✅ Submission timestamps
✅ Approve and request changes functionality
The implementation follows best practices for security, accessibility, and user experience.