320 lines
8.9 KiB
Markdown
320 lines
8.9 KiB
Markdown
# RFCP - Iteration 10.2: Purple → Orange Gradient
|
||
|
||
**Goal:** Replace current warm palette (maroon→yellow) with purple→orange palette for better map contrast and intuitive UX
|
||
**Priority:** P2 (UX Polish)
|
||
**Estimated Time:** 15-20 minutes
|
||
**Status:** Ready for Implementation
|
||
|
||
---
|
||
|
||
## 📋 Overview
|
||
|
||
After Iteration 10.1 fixed the cyan/green color conflict, user feedback indicated the current warm palette (yellow=good, red=bad) feels counter-intuitive. This iteration implements a purple→orange gradient that:
|
||
- Avoids map feature conflicts (no purple on maps)
|
||
- Provides intuitive "heat" visualization (orange = hot/strong signal)
|
||
- Maintains professional RF tool aesthetic
|
||
|
||
---
|
||
|
||
## 🐛 Current Issue
|
||
|
||
**User Feedback:** "тепер зона червона, а градієнт жовтий :) хз навіть як краще було"
|
||
|
||
**Problem:**
|
||
- Yellow (#ffeb3b) = excellent signal → near antenna center
|
||
- Red/Maroon (#8b0000) = weak signal → coverage edges
|
||
- This feels **counter-intuitive** (users expect red = danger/bad)
|
||
|
||
**Current Palette (Iteration 10.1):**
|
||
```
|
||
Deep Maroon → Red → Orange → Yellow
|
||
(weak) ←──────────────→ (strong)
|
||
#4a0000 → #8b0000 → #ff9800 → #ffeb3b
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ Solution: Purple → Orange Palette
|
||
|
||
**New Palette:**
|
||
```
|
||
Deep Purple → Purple → Lavender → Peach → Orange → Bright Orange
|
||
(weak) ←────────────────────────────────────→ (strong)
|
||
```
|
||
|
||
**Color Values:**
|
||
```typescript
|
||
export function createRsrpGradient(): string[] {
|
||
return [
|
||
'#1a0033', // Deep purple (very poor signal, -130 dBm)
|
||
'#4a148c', // Dark purple
|
||
'#7b1fa2', // Purple
|
||
'#ab47bc', // Light purple / Lavender
|
||
'#ff8a65', // Peach / Light orange
|
||
'#ff6f00', // Dark orange
|
||
'#ffb74d', // Bright orange (excellent signal, -50 dBm)
|
||
];
|
||
}
|
||
```
|
||
|
||
**Why Purple → Orange:**
|
||
- ✅ **No map conflicts:** Purple doesn't appear on OpenTopoMap or OpenStreetMap
|
||
- ✅ **Intuitive heat:** Orange = "hot" = strong signal (like thermal imaging)
|
||
- ✅ **Professional aesthetic:** Used in professional RF planning tools
|
||
- ✅ **Good contrast:** Purple/Orange highly distinguishable
|
||
- ✅ **Colorblind-friendly:** Purple-orange works for most color vision types
|
||
|
||
---
|
||
|
||
## 📁 Files to Modify
|
||
|
||
### 1. `src/utils/colorGradient.ts`
|
||
|
||
**Current Code (lines ~5-15):**
|
||
```typescript
|
||
export function createRsrpGradient(): string[] {
|
||
return [
|
||
'#4a0000', // Deep maroon (very poor signal)
|
||
'#8b0000', // Dark red
|
||
'#cc0000', // Red
|
||
'#ff0000', // Bright red
|
||
'#ff4444', // Orange-red
|
||
'#ff9800', // Orange
|
||
'#ffeb3b', // Yellow (excellent signal)
|
||
];
|
||
}
|
||
```
|
||
|
||
**Replace With:**
|
||
```typescript
|
||
export function createRsrpGradient(): string[] {
|
||
return [
|
||
'#1a0033', // Deep purple (very poor signal, -130 dBm)
|
||
'#4a148c', // Dark purple
|
||
'#7b1fa2', // Purple
|
||
'#ab47bc', // Light purple / Lavender
|
||
'#ff8a65', // Peach / Light orange
|
||
'#ff6f00', // Dark orange
|
||
'#ffb74d', // Bright orange (excellent signal, -50 dBm)
|
||
];
|
||
}
|
||
```
|
||
|
||
### 2. `src/constants/rsrp-thresholds.ts`
|
||
|
||
**Find and Update SIGNAL_COLORS:**
|
||
```typescript
|
||
// Old:
|
||
export const SIGNAL_COLORS = {
|
||
excellent: '#ffeb3b', // Yellow
|
||
good: '#ff9800', // Orange
|
||
fair: '#ff4444', // Orange-red
|
||
poor: '#ff0000', // Red
|
||
veryPoor: '#cc0000', // Dark red
|
||
terrible: '#8b0000', // Very dark red
|
||
};
|
||
|
||
// New:
|
||
export const SIGNAL_COLORS = {
|
||
excellent: '#ffb74d', // Bright orange (-50 to -70 dBm)
|
||
good: '#ff6f00', // Dark orange (-70 to -85 dBm)
|
||
fair: '#ff8a65', // Peach (-85 to -100 dBm)
|
||
poor: '#ab47bc', // Light purple (-100 to -110 dBm)
|
||
veryPoor: '#7b1fa2', // Purple (-110 to -120 dBm)
|
||
terrible: '#4a148c', // Dark purple (-120 to -130 dBm)
|
||
};
|
||
```
|
||
|
||
### 3. Check Legend Component (if exists)
|
||
|
||
**Search for hardcoded colors:**
|
||
```bash
|
||
grep -rn "#ffeb3b\|#ff9800\|#8b0000" src/
|
||
```
|
||
|
||
If found in legend or other components, update to match new palette.
|
||
|
||
---
|
||
|
||
## 🔍 Investigation Commands
|
||
|
||
**Before making changes, verify file locations:**
|
||
```bash
|
||
# Find gradient file
|
||
find /opt/rfcp/frontend/src -name "colorGradient.ts" -o -name "*gradient*"
|
||
|
||
# Find threshold constants
|
||
find /opt/rfcp/frontend/src -name "*threshold*" -o -name "*rsrp*"
|
||
|
||
# Check for hardcoded old colors
|
||
grep -rn "#ffeb3b\|#4a0000\|#8b0000" /opt/rfcp/frontend/src/
|
||
|
||
# Check legend component
|
||
find /opt/rfcp/frontend/src -name "*Legend*" -o -name "*legend*"
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 Testing Checklist
|
||
|
||
### Visual Testing
|
||
|
||
- [ ] **Gradient smoothness:** Colors transition smoothly from purple to orange
|
||
- [ ] **Center coverage:** Bright orange (#ffb74d) visible near antenna
|
||
- [ ] **Edge coverage:** Deep purple (#1a0033) visible at coverage edges
|
||
- [ ] **Map contrast:** No color conflicts with OpenTopoMap features
|
||
- [ ] **Different zoom levels:** Gradient looks correct at zoom 8, 12, 16
|
||
|
||
### Legend Testing
|
||
|
||
- [ ] **Legend colors match:** RSRP legend shows new color scheme
|
||
- [ ] **Labels correct:** dBm values still display correctly
|
||
- [ ] **Readability:** Legend text readable against new colors
|
||
|
||
### Regression Testing
|
||
|
||
- [ ] **50m resolution:** Still works without crash (Iteration 10.1 fix intact)
|
||
- [ ] **Delete confirmation:** Still shows dialog (Iteration 10.1 fix intact)
|
||
- [ ] **Keyboard shortcuts:** All shortcuts still functional
|
||
- [ ] **Multi-sector:** Coverage calculation still correct
|
||
|
||
### Edge Cases
|
||
|
||
- [ ] **Single site:** Gradient displays correctly
|
||
- [ ] **Multiple sites:** Overlapping coverage shows strongest signal
|
||
- [ ] **Terrain enabled:** Gradient still visible with terrain layer
|
||
- [ ] **Dark mode:** Colors work in dark mode (if applicable)
|
||
|
||
---
|
||
|
||
## 🏗️ Build & Deploy
|
||
|
||
```bash
|
||
# Navigate to frontend
|
||
cd /opt/rfcp/frontend
|
||
|
||
# Install dependencies (if needed)
|
||
npm install
|
||
|
||
# Run development server to test
|
||
npm run dev
|
||
|
||
# Build for production
|
||
npm run build
|
||
|
||
# Check for errors
|
||
# Expected: 0 TypeScript errors, 0 ESLint errors
|
||
|
||
# Deploy (reload Caddy)
|
||
sudo systemctl reload caddy
|
||
|
||
# Verify deployment
|
||
curl -s https://rfcp.eliah.one | head -20
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 Commit Message
|
||
|
||
```
|
||
feat(heatmap): replace warm palette with purple→orange gradient
|
||
|
||
- Changed RSRP gradient from maroon→yellow to purple→orange
|
||
- Updated SIGNAL_COLORS constants to match new palette
|
||
- Better map contrast (purple not present on maps)
|
||
- More intuitive heat visualization (orange = strong signal)
|
||
|
||
Colors: #1a0033 (weak) → #ffb74d (strong)
|
||
|
||
Iteration: 10.2
|
||
Fixes: User feedback on gradient aesthetics
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ Success Criteria
|
||
|
||
**Must Pass:**
|
||
1. ✅ Gradient displays purple (weak) → orange (strong)
|
||
2. ✅ No cyan, green, or blue colors anywhere
|
||
3. ✅ Legend matches new color scheme
|
||
4. ✅ No regression in 50m resolution performance
|
||
5. ✅ TypeScript: 0 errors
|
||
6. ✅ ESLint: 0 errors
|
||
7. ✅ Production build succeeds
|
||
|
||
**User Acceptance:**
|
||
- Олег confirms: "виглядає краще" or "норм"
|
||
- If not satisfied → Iteration 10.3 with alternative palette
|
||
|
||
---
|
||
|
||
## 🎨 Alternative Palettes (If Needed)
|
||
|
||
**Option C: Grayscale → Orange (Fallback)**
|
||
```typescript
|
||
return [
|
||
'#1a1a1a', // Near black (very poor)
|
||
'#4a4a4a', // Dark gray
|
||
'#808080', // Medium gray
|
||
'#b3b3b3', // Light gray
|
||
'#ff6f00', // Dark orange
|
||
'#ff9800', // Orange
|
||
'#ffb74d', // Light orange (excellent)
|
||
];
|
||
```
|
||
|
||
**Option D: Blue → Red (Classic Heat)**
|
||
```typescript
|
||
return [
|
||
'#0d47a1', // Dark blue (very poor)
|
||
'#1976d2', // Blue
|
||
'#42a5f5', // Light blue
|
||
'#fff176', // Yellow
|
||
'#ff9800', // Orange
|
||
'#f44336', // Red
|
||
'#b71c1c', // Dark red (excellent)
|
||
];
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 Color Reference Table
|
||
|
||
| RSRP Range | Signal Quality | Old Color | New Color | Hex |
|
||
|------------|----------------|-----------|-----------|-----|
|
||
| > -70 dBm | Excellent | Yellow | Bright Orange | #ffb74d |
|
||
| -70 to -85 | Good | Orange | Dark Orange | #ff6f00 |
|
||
| -85 to -100 | Fair | Orange-Red | Peach | #ff8a65 |
|
||
| -100 to -110 | Poor | Red | Light Purple | #ab47bc |
|
||
| -110 to -120 | Very Poor | Dark Red | Purple | #7b1fa2 |
|
||
| < -120 dBm | Terrible | Maroon | Dark Purple | #4a148c |
|
||
| < -130 dBm | No Service | Deep Maroon | Deep Purple | #1a0033 |
|
||
|
||
---
|
||
|
||
## 🤖 Instructions for Claude Code
|
||
|
||
**Context:**
|
||
- Project: RFCP (RF Coverage Planning) - `/opt/rfcp/frontend/`
|
||
- Framework: React 18 + TypeScript + Vite + Leaflet
|
||
- This is a simple color palette change in 2-3 files
|
||
|
||
**Implementation Steps:**
|
||
1. Search for `colorGradient.ts` and update gradient array
|
||
2. Search for `rsrp-thresholds.ts` and update SIGNAL_COLORS
|
||
3. Search for any hardcoded old colors and update them
|
||
4. Run `npm run build` to verify no errors
|
||
5. Test at https://rfcp.eliah.one after deploy
|
||
|
||
**Priority:** Quick UX fix, should take ~15 minutes
|
||
|
||
**Success:** User sees purple (weak) → orange (strong) gradient on map
|
||
|
||
---
|
||
|
||
**Document Created:** 2025-01-30
|
||
**Author:** Claude (Sonnet 4.5) + Олег
|
||
**Status:** Ready for Implementation
|
||
**Next:** Віддати Claude Code → Test → Screenshot → Confirm
|