feat(hail-recon): Hail Recon integration — storm intel panel, hail history, auto storm mode, address monitoring
This commit is contained in:
@@ -3,6 +3,7 @@ import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { useMockStore } from '../data/mockStore';
|
||||
import { useHailHistory, hailSeverityColor, daysAgo } from '../hooks/useHailRecon';
|
||||
import { SpotlightCard } from '../components/SpotlightCard';
|
||||
import { AnimatedCounter } from '../components/AnimatedCounter';
|
||||
import { toast } from 'sonner';
|
||||
@@ -15,7 +16,7 @@ import {
|
||||
MessageSquare, CheckCircle, ChevronDown, Activity, AlertTriangle,
|
||||
TrendingUp, Calendar, DollarSign, GitPullRequest, AlertCircle,
|
||||
Milestone, FolderOpen, Upload, Trash2, Eye, Pencil, X as XIcon,
|
||||
File, StickyNote, Download, Image as ImageIcon
|
||||
File, StickyNote, Download, Image as ImageIcon, CloudLightning
|
||||
} from 'lucide-react';
|
||||
|
||||
// ── Neomorphic constants (mirrors OwnerProjectDetail) ─────────────────────────
|
||||
@@ -209,6 +210,89 @@ const TABS_SIMPLE = [
|
||||
];
|
||||
|
||||
// ── Main component ────────────────────────────────────────────────────────────
|
||||
// ── Hail History Section ──────────────────────────────────────────────────────
|
||||
function HailHistorySection({ leadId, lat, lng }) {
|
||||
const { history, loading, hitCount, lastHit, maxSize } = useHailHistory(leadId, lat, lng, 12);
|
||||
|
||||
const summaryColor = maxSize >= 2.0 ? 'text-red-600 dark:text-red-400' :
|
||||
maxSize >= 1.5 ? 'text-orange-600 dark:text-orange-400' :
|
||||
maxSize >= 1.0 ? 'text-yellow-600 dark:text-yellow-400' :
|
||||
'text-zinc-400';
|
||||
|
||||
return (
|
||||
<div className="rounded-2xl border border-zinc-200 dark:border-white/[0.06] bg-white dark:bg-zinc-900/40 overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-3 px-5 py-4 border-b border-zinc-100 dark:border-white/[0.04]">
|
||||
<div className="p-2 rounded-xl bg-amber-500/10 border border-amber-500/20">
|
||||
<CloudLightning size={16} className="text-amber-500" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-sm font-black uppercase tracking-widest text-zinc-900 dark:text-white">Hail Impact History</h3>
|
||||
<p className="text-[10px] text-zinc-500 mt-0.5">Last 12 months · Powered by Hail Recon</p>
|
||||
</div>
|
||||
{!loading && hitCount > 0 && (
|
||||
<div className="text-right">
|
||||
<p className={`text-lg font-black font-mono ${summaryColor}`}>{hitCount}x</p>
|
||||
<p className="text-[10px] text-zinc-400">
|
||||
{lastHit ? `Last: ${daysAgo(lastHit.date)}d ago` : ''}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
<div className="px-5 py-4">
|
||||
{loading ? (
|
||||
<div className="flex items-center gap-2 py-4">
|
||||
<div className="w-4 h-4 rounded-full border-2 border-amber-500 border-t-transparent animate-spin" />
|
||||
<p className="text-xs text-zinc-400">Checking hail history...</p>
|
||||
</div>
|
||||
) : hitCount === 0 ? (
|
||||
<div className="flex items-center gap-2 py-2">
|
||||
<Shield size={14} className="text-emerald-500 shrink-0" />
|
||||
<p className="text-sm text-zinc-500">No hail impacts recorded in the last 12 months.</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
{history.map((event, i) => {
|
||||
const textCls = hailSeverityColor(event.hailSize, 'text');
|
||||
const bgCls = hailSeverityColor(event.hailSize, 'bg');
|
||||
const brdCls = hailSeverityColor(event.hailSize, 'border');
|
||||
const days = daysAgo(event.date);
|
||||
const dateObj = new Date(event.date);
|
||||
const dateLabel = dateObj.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
|
||||
return (
|
||||
<div key={i} className="flex items-center gap-3 py-2.5 border-b border-zinc-100 dark:border-white/[0.04] last:border-0">
|
||||
{/* Date */}
|
||||
<div className="w-28 shrink-0">
|
||||
<p className="text-xs font-semibold text-zinc-700 dark:text-zinc-200">{dateLabel}</p>
|
||||
<p className="text-[10px] text-zinc-400">{days === 0 ? 'Today' : `${days}d ago`}</p>
|
||||
</div>
|
||||
{/* Size badge */}
|
||||
<span className={`inline-flex items-center px-2 py-0.5 rounded-lg text-xs font-black border ${bgCls} ${brdCls} ${textCls}`}>
|
||||
{event.hailSize?.toFixed(2)}"
|
||||
</span>
|
||||
{/* Severity label */}
|
||||
<span className={`text-[11px] font-semibold ${textCls}`}>
|
||||
{event.hailSize >= 2.0 ? 'Severe' :
|
||||
event.hailSize >= 1.5 ? 'Significant' :
|
||||
event.hailSize >= 1.0 ? 'Moderate' : 'Trace'}
|
||||
</span>
|
||||
{i === 0 && (
|
||||
<span className="ml-auto text-[10px] font-bold px-2 py-0.5 rounded-full bg-amber-100 dark:bg-amber-500/15 text-amber-600 dark:text-amber-400 border border-amber-200 dark:border-amber-500/20">
|
||||
Most Recent
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function LeadProjectPage() {
|
||||
const { leadId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
@@ -468,11 +552,17 @@ export default function LeadProjectPage() {
|
||||
)}
|
||||
</NeoCard>
|
||||
</div>
|
||||
<HailHistorySection
|
||||
leadId={leadId}
|
||||
lat={lead.lat ?? 33.055}
|
||||
lng={lead.lng ?? -96.752}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Overview for simple (no project data) */}
|
||||
{activeTab === 'overview' && !proj && (
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<NeoCard spotlightColor="rgba(59,130,246,0.08)">
|
||||
<div className="flex items-center gap-3 mb-5">
|
||||
@@ -528,6 +618,12 @@ export default function LeadProjectPage() {
|
||||
</div>
|
||||
</NeoCard>
|
||||
</div>
|
||||
<HailHistorySection
|
||||
leadId={leadId}
|
||||
lat={lead.lat ?? 33.055}
|
||||
lng={lead.lng ?? -96.752}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── CONTACT (simple only) ── */}
|
||||
|
||||
Reference in New Issue
Block a user