feat(routing): enable elevation profile and steep slope/incline warnings in routing API and frontend
This commit is contained in:
+80
-9
@@ -392,18 +392,89 @@ function App() {
|
||||
|
||||
{/* Route Summary Card */}
|
||||
{routeData && (
|
||||
<div className="route-summary glass-morphism" style={{ marginTop: '15px', padding: '12px', borderRadius: '8px', background: 'rgba(15, 23, 42, 0.6)' }}>
|
||||
<h4 style={{ margin: '0 0 8px 0', fontSize: '0.9rem', color: '#38bdf8' }}>Route Overview / تفاصيل المسار</h4>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '0.85rem', marginBottom: '4px' }}>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<Gauge size={13} color="#38bdf8" />
|
||||
{(Number(routeData.distance || 0) / 1000).toFixed(1)} km
|
||||
<div className="route-summary glass-morphism" style={{ marginTop: '15px', padding: '14px', borderRadius: '10px', background: 'rgba(15, 23, 42, 0.75)', border: '1px solid rgba(56, 189, 248, 0.3)' }}>
|
||||
<h4 style={{ margin: '0 0 10px 0', fontSize: '0.92rem', color: '#38bdf8', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<span>{routeData.routeName || 'تفاصيل المسار'}</span>
|
||||
<span style={{ fontSize: '0.75rem', background: 'rgba(56, 189, 248, 0.15)', color: '#38bdf8', padding: '2px 8px', borderRadius: 999 }}>
|
||||
{routeData.tags ? routeData.tags[0] : 'FASTEST'}
|
||||
</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<Clock size={13} color="#22c55e" />
|
||||
{Math.round(Number(routeData.time || routeData.duration || 0) / 60000)} min
|
||||
</h4>
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '0.85rem', marginBottom: '8px' }}>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: '4px', color: '#e2e8f0' }}>
|
||||
<Gauge size={14} color="#38bdf8" />
|
||||
{(Number(routeData.distance || 0) / 1000).toFixed(1)} كم
|
||||
</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: '4px', color: '#4ade80' }}>
|
||||
<Clock size={14} color="#22c55e" />
|
||||
{Math.round(Number(routeData.duration || 0) / 60)} دقيقة
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Elevation & Slope Summary */}
|
||||
{routeData.elevationSummary && (
|
||||
<div style={{ marginTop: 10, paddingTop: 8, borderTop: '1px solid rgba(255,255,255,0.08)', fontSize: '0.78rem' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', color: '#94a3b8', marginBottom: 4 }}>
|
||||
<span>📈 إجمالي الصعود: <strong style={{ color: '#4ade80' }}>+{routeData.elevationSummary.totalAscentMeters}م</strong></span>
|
||||
<span>📉 إجمالي الهبوط: <strong style={{ color: '#38bdf8' }}>-{routeData.elevationSummary.totalDescentMeters}م</strong></span>
|
||||
</div>
|
||||
{(routeData.elevationSummary.maxInclinePercent > 0 || routeData.elevationSummary.maxDeclinePercent < 0) && (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', color: '#94a3b8' }}>
|
||||
<span>أقصى صعود: <strong style={{ color: '#fbbf24' }}>+{routeData.elevationSummary.maxInclinePercent}%</strong></span>
|
||||
<span>أقصى انحدار: <strong style={{ color: '#f87171' }}>{routeData.elevationSummary.maxDeclinePercent}%</strong></span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Steep Slope Warnings Alert */}
|
||||
{routeData.elevationSummary?.steepWarnings && routeData.elevationSummary.steepWarnings.length > 0 && (
|
||||
<div style={{
|
||||
marginTop: 10,
|
||||
padding: '8px 10px',
|
||||
background: 'rgba(239, 68, 68, 0.15)',
|
||||
border: '1px solid rgba(239, 68, 68, 0.35)',
|
||||
borderRadius: 8,
|
||||
fontSize: '0.75rem',
|
||||
color: '#fca5a5'
|
||||
}}>
|
||||
<div style={{ fontWeight: 700, display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
|
||||
<AlertTriangle size={13} color="#ef4444" />
|
||||
<span>تحذير تضاريسي للمركبات الثقيلة:</span>
|
||||
</div>
|
||||
{routeData.elevationSummary.steepWarnings.slice(0, 2).map((w: any, idx: number) => (
|
||||
<div key={idx} style={{ marginTop: 2 }}>
|
||||
• {w.street ? `شارع ${w.street}: ` : ''}{w.slopePercent > 0 ? `صعود حاد (+${w.slopePercent}%)` : `منحدر جبلي شديد (${w.slopePercent}%)`}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Turn by turn expandable instructions */}
|
||||
{routeData.instructions && routeData.instructions.length > 0 && (
|
||||
<details style={{ marginTop: 10, fontSize: '0.75rem', color: '#cbd5e1' }}>
|
||||
<summary style={{ cursor: 'pointer', color: '#38bdf8', fontWeight: 600, padding: '4px 0' }}>
|
||||
عرض خطوات المسار بالتفصيل ({routeData.instructions.length} خطوة)
|
||||
</summary>
|
||||
<div style={{ maxHeight: 180, overflowY: 'auto', marginTop: 6, paddingRight: 4, display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||
{routeData.instructions.map((inst: any, idx: number) => (
|
||||
<div key={idx} style={{
|
||||
padding: '4px 6px',
|
||||
borderRadius: 4,
|
||||
background: inst.slopeWarning ? 'rgba(245, 158, 11, 0.12)' : 'rgba(255,255,255,0.03)',
|
||||
borderRight: inst.slopeWarning ? '3px solid #f59e0b' : '1px solid transparent'
|
||||
}}>
|
||||
<div style={{ fontWeight: inst.slopeWarning ? 700 : 400, color: inst.slopeWarning ? '#fbbf24' : '#e2e8f0' }}>
|
||||
{idx + 1}. {inst.text}
|
||||
</div>
|
||||
<div style={{ fontSize: '0.7rem', color: '#94a3b8' }}>
|
||||
{inst.distance ? `${Math.round(inst.distance)}م` : ''} {inst.slopePercent ? `| انحدار: ${inst.slopePercent}%` : ''}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user