Avatar Gradient System Migration¶
Overview¶
The avatar gradient system has been refactored from storing explicit color values (colorFrom/colorTo) to using predefined gradient indices (0-29). This provides better consistency, maintainability, and simpler API.
Frontend Changes¶
New Exports in gradients.ts¶
// Total number of available gradients
export const GRADIENT_COUNT = 30;
// Access gradients by index
export const AVATAR_GRADIENTS: AvatarGradient[] = [
/* 30 gradients */
];
ProfilePic Component API¶
Old API (deprecated):
<ProfilePic colorFrom="#F44336" colorTo="#E57373" />
New API:
<ProfilePic gradientIndex={0} />
Fallback behavior:
- Indices 0-29: Use predefined gradient
- Indices ≥30: White background with thin black border
Backend Changes¶
New Function: generate_avatar_gradient_index()¶
Located in backend/app/utils/colors.py:
from app.utils.colors import generate_avatar_gradient_index
# Generate random gradient index (0-29)
gradient_index = generate_avatar_gradient_index()
Updated FHIR Extension¶
Extension Format:
{
"url": "urn:quillmedical:avatar-gradient",
"valueInteger": 12 # Gradient index
}
Updated FHIR Client Function¶
New API (backend/app/fhir_client.py):
from app.fhir_client import add_avatar_gradient_extension
patient = Patient()
add_avatar_gradient_extension(patient, gradient_index=5) # Or None for random
Migration Strategy¶
For New Patients¶
All new patients should use the gradient index system:
# When creating new patient
patient = Patient()
add_avatar_gradient_extension(patient) # Random index 0-29
For Existing Patients¶
Existing patients with colorFrom/colorTo extensions will need migrating to gradient indices using a backfill script.
Backfill Script (to be created):
# Pseudo-code for migration script
for patient in get_all_patients():
# Add new gradient index extension
gradient_index = generate_avatar_gradient_index()
add_avatar_gradient_extension(patient, gradient_index)
# Update patient in FHIR
update_fhir_patient(patient)
Frontend Reading FHIR Extensions¶
The frontend should read the gradient index from FHIR:
// Extract gradient index from FHIR Patient extension
function getGradientIndex(patient: FHIRPatient): number {
const extension = patient.extension?.find(
ext => ext.url === "urn:quillmedical:avatar-gradient"
);
return extension?.valueInteger ?? 0; // Fallback to gradient 0
}
// Use in component
<ProfilePic gradientIndex={getGradientIndex(patient)} />
Benefits of New System¶
- Consistency: Same index always produces same colors across entire app
- Maintainability: Update all avatar colors by editing one file (
gradients.ts) - Simplicity: Single integer instead of two hex color strings
- Type Safety: Frontend validates indices via TypeScript
- Performance: Smaller FHIR extension data (integer vs two strings)
- Scalability: Easy to add more gradients (just append to array)
Configuration¶
Updating GRADIENT_COUNT¶
If you add more gradients to the frontend:
- Add new gradients to
frontend/src/components/profile-pic/gradients.ts - Update
GRADIENT_COUNTconstant inbackend/app/utils/colors.py - Ensure
GRADIENT_COUNTmatchesAVATAR_GRADIENTS.length
Current Gradient Count¶
- Frontend: 30 gradients (indices 0-29)
- Backend:
GRADIENT_COUNT = 30
Testing¶
Frontend Tests¶
cd frontend
yarn test ProfilePic
Backend Tests¶
cd backend
poetry run pytest tests/test_colors.py -v
Rollback Plan¶
If migration causes issues:
- Revert frontend to accept
colorFrom/colorToprops again - Revert backend to store colour pairs instead of indices
- Patients without the new extension will get a random gradient on next update
Next Steps¶
- ✅ Frontend gradient index system implemented
- ✅ Backend random gradient index generator created
- ✅ FHIR extension updated to use
valueInteger - 🔲 Create backfill script to migrate existing patients
- 🔲 Update patient creation scripts to use new API
- 🔲 Update frontend Home.tsx to read gradient index from FHIR
- 🔲 Add tests for new gradient index system
- 🔲 Update API documentation