@mytec: started iter10.2
This commit is contained in:
319
RFCP-Iteration10.2-Purple-Orange-Gradient.md
Normal file
319
RFCP-Iteration10.2-Purple-Orange-Gradient.md
Normal file
@@ -0,0 +1,319 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user