feat: Revamped design - improved dark mode visibility, mobile UX fixes, updated trust signals

This commit is contained in:
Satyam
2026-02-16 01:49:50 +05:30
parent e88e1e4da5
commit e0da94aa0c
15 changed files with 1887 additions and 377 deletions
@@ -4,7 +4,8 @@ import { useNavigate } from 'react-router-dom';
import { Icons } from '../landing/constants';
import { ChevronLeft, ChevronRight, X } from 'lucide-react';
const IntelligenceSidePanel = ({ data, onClose }) => {
const IntelligenceSidePanel = ({ data, onClose, variant = 'default' }) => {
const isSheet = variant === 'sheet';
const navigate = useNavigate();
const [activeTab, setActiveTab] = useState('details');
// Initialize photos from data or use empty array if not present
@@ -65,31 +66,41 @@ const IntelligenceSidePanel = ({ data, onClose }) => {
return (
<div
ref={panelRef}
className="absolute top-4 right-4 bottom-4 w-80 bg-slate-900/80 backdrop-blur-xl rounded-xl p-6 shadow-2xl border border-white/10 transform transition-transform duration-300 z-40 flex flex-col text-white"
className={isSheet
? 'px-6 pb-6 pt-2 flex flex-col text-zinc-900 dark:text-white'
: 'absolute top-4 right-4 bottom-4 w-80 bg-slate-900/80 backdrop-blur-xl rounded-xl p-6 shadow-2xl border border-white/10 transform transition-transform duration-300 z-40 flex flex-col text-white'
}
role="dialog"
aria-modal="true"
aria-label="Property Intelligence Details"
>
{/* Header */}
<div className="flex justify-between items-center mb-4 pb-4 border-b border-white/10">
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-cyan-400 rounded-full animate-pulse"></div>
<h3 className="font-heading font-bold text-lg tracking-wide">INTEL_FEED</h3>
{/* Header — only on desktop panel, mobile sheet provides its own */}
{!isSheet && (
<div className="flex justify-between items-center mb-4 pb-4 border-b border-white/10">
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-cyan-400 rounded-full animate-pulse"></div>
<h3 className="font-heading font-bold text-lg tracking-wide">INTEL_FEED</h3>
</div>
<button
ref={closeButtonRef}
onClick={onClose}
className="text-gray-400 hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-cyan-400 rounded-full p-1"
aria-label="Close details panel"
>
</button>
</div>
<button
ref={closeButtonRef}
onClick={onClose}
className="text-gray-400 hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-cyan-400 rounded-full p-1"
aria-label="Close details panel"
>
</button>
</div>
)}
{/* Tabs */}
<div className="flex border-b border-white/10 mb-4" role="tablist">
<div className={`flex mb-4 border-b ${isSheet ? 'border-zinc-200 dark:border-white/10' : 'border-white/10'}`} role="tablist">
<button
className={`flex-1 py-2 text-sm font-bold uppercase tracking-wider transition-colors border-b-2 ${activeTab === 'details' ? 'border-cyan-400 text-cyan-400' : 'border-transparent text-gray-400 hover:text-white'}`}
className={`flex-1 py-2 text-sm font-bold uppercase tracking-wider transition-colors border-b-2 ${activeTab === 'details'
? 'border-cyan-400 text-cyan-400'
: isSheet
? 'border-transparent text-zinc-400 dark:text-gray-400 hover:text-zinc-900 dark:hover:text-white'
: 'border-transparent text-gray-400 hover:text-white'
}`}
onClick={() => setActiveTab('details')}
role="tab"
aria-selected={activeTab === 'details'}
@@ -99,7 +110,12 @@ const IntelligenceSidePanel = ({ data, onClose }) => {
Details
</button>
<button
className={`flex-1 py-2 text-sm font-bold uppercase tracking-wider transition-colors border-b-2 ${activeTab === 'photos' ? 'border-cyan-400 text-cyan-400' : 'border-transparent text-gray-400 hover:text-white'}`}
className={`flex-1 py-2 text-sm font-bold uppercase tracking-wider transition-colors border-b-2 ${activeTab === 'photos'
? 'border-cyan-400 text-cyan-400'
: isSheet
? 'border-transparent text-zinc-400 dark:text-gray-400 hover:text-zinc-900 dark:hover:text-white'
: 'border-transparent text-gray-400 hover:text-white'
}`}
onClick={() => setActiveTab('photos')}
role="tab"
aria-selected={activeTab === 'photos'}
@@ -110,31 +126,64 @@ const IntelligenceSidePanel = ({ data, onClose }) => {
</button>
</div>
{/* Content Area */}
<div className="flex-grow overflow-y-auto custom-scrollbar relative">
{/* Status / Weather Quick Bar */}
<div className={`flex items-center gap-2 mb-4 flex-wrap ${isSheet ? '' : ''}`}>
{data.status && (
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider
${data.status === 'Urgent'
? 'bg-red-500/15 text-red-400 border border-red-500/25'
: data.status === 'Action Required'
? 'bg-amber-500/15 text-amber-400 border border-amber-500/25'
: data.status === 'Monitoring'
? 'bg-blue-500/15 text-blue-400 border border-blue-500/25'
: 'bg-emerald-500/15 text-emerald-400 border border-emerald-500/25'
}
`}>
<span className={`w-1.5 h-1.5 rounded-full ${
data.status === 'Urgent' ? 'bg-red-400 animate-pulse' :
data.status === 'Action Required' ? 'bg-amber-400' :
data.status === 'Monitoring' ? 'bg-blue-400' : 'bg-emerald-400'
}`} />
{data.status}
</span>
)}
{data.weather && data.weather !== 'Clear' && (
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider bg-yellow-500/10 text-yellow-400 border border-yellow-500/20">
{'\u26C8'} {data.weather}
</span>
)}
{data.weather === 'Clear' && (
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider ${isSheet ? 'bg-zinc-100 dark:bg-white/5 text-zinc-400 dark:text-gray-500 border border-zinc-200 dark:border-white/10' : 'bg-white/5 text-gray-500 border border-white/10'}`}>
{'\u2600'} Clear
</span>
)}
</div>
{/* Content Area — data-lenis-prevent stops Lenis from hijacking wheel/touch scroll */}
<div data-lenis-prevent className="flex-grow overflow-y-auto overscroll-contain relative">
{/* DETAILS TAB */}
{activeTab === 'details' && (
<div role="tabpanel" id="panel-details" aria-labelledby="tab-details" className="space-y-6 animate-in fade-in slide-in-from-right-4 duration-300">
<div className="p-4 bg-cyan-400/5 rounded-lg border border-cyan-400/20 relative overflow-hidden group/card hover:bg-cyan-400/10 transition-colors">
<div className={`p-4 rounded-lg border relative overflow-hidden group/card transition-colors ${isSheet ? 'bg-cyan-500/5 dark:bg-cyan-400/5 border-cyan-500/20 dark:border-cyan-400/20 hover:bg-cyan-500/10 dark:hover:bg-cyan-400/10' : 'bg-cyan-400/5 border-cyan-400/20 hover:bg-cyan-400/10'}`}>
<div className="absolute top-0 right-0 p-1 opacity-20 group-hover/card:opacity-40 transition-opacity">
<Icons.Chart />
</div>
<label className="text-[10px] text-cyan-400 font-bold uppercase tracking-widest mb-1 block">Projected Value</label>
<div className="text-3xl font-heading font-bold text-white">{data.gain}</div>
<label className={`text-[10px] font-bold uppercase tracking-widest mb-1 block ${isSheet ? 'text-cyan-600 dark:text-cyan-400' : 'text-cyan-400'}`}>Projected Value</label>
<div className={`text-3xl font-heading font-bold ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.gain}</div>
</div>
<div>
<label className="text-[10px] text-gray-500 font-bold uppercase tracking-widest mb-1 block">Location Target</label>
<div className="text-white font-bold text-lg leading-tight mb-1">{data.address}</div>
<div className="text-xs text-gray-400">Dallas-Fort Worth Metroplex {data.type} Zone</div>
<label className={`text-[10px] font-bold uppercase tracking-widest mb-1 block ${isSheet ? 'text-zinc-400 dark:text-gray-500' : 'text-gray-500'}`}>Location Target</label>
<div className={`font-bold text-lg leading-tight mb-1 ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.address}</div>
<div className={`text-xs ${isSheet ? 'text-zinc-500 dark:text-gray-400' : 'text-gray-400'}`}>Dallas-Fort Worth Metroplex {data.type} Zone</div>
</div>
{/* Divider */}
<div className="h-px bg-white/10 w-full"></div>
<div className={`h-px w-full ${isSheet ? 'bg-zinc-200 dark:bg-white/10' : 'bg-white/10'}`}></div>
<div>
<label className="text-[10px] text-gray-500 font-bold uppercase tracking-widest mb-2 block">Detected Issue</label>
<label className={`text-[10px] font-bold uppercase tracking-widest mb-2 block ${isSheet ? 'text-zinc-400 dark:text-gray-500' : 'text-gray-500'}`}>Detected Issue</label>
<div className={`flex items-center gap-2 font-bold ${data.problem.includes('Severe') ? 'text-red-500' : 'text-yellow-400'}`}>
<span className="animate-pulse"></span> {data.problem}
</div>
@@ -145,17 +194,17 @@ const IntelligenceSidePanel = ({ data, onClose }) => {
<div className="space-y-4 animate-in slide-in-from-right-4 duration-300">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-[10px] text-gray-500 font-bold uppercase tracking-widest mb-1 block">Built</label>
<div className="text-sm text-white font-medium">{data.specs.built}</div>
<label className={`text-[10px] font-bold uppercase tracking-widest mb-1 block ${isSheet ? 'text-zinc-400 dark:text-gray-500' : 'text-gray-500'}`}>Built</label>
<div className={`text-sm font-medium ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.specs.built}</div>
</div>
<div>
<label className="text-[10px] text-gray-500 font-bold uppercase tracking-widest mb-1 block">Maintenance</label>
<div className="text-sm text-white font-medium">{data.specs.maintenance}</div>
<label className={`text-[10px] font-bold uppercase tracking-widest mb-1 block ${isSheet ? 'text-zinc-400 dark:text-gray-500' : 'text-gray-500'}`}>Maintenance</label>
<div className={`text-sm font-medium ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.specs.maintenance}</div>
</div>
</div>
<div className="p-3 bg-slate-800/50 rounded-lg border border-white/5">
<div className={`p-3 rounded-lg border ${isSheet ? 'bg-zinc-100 dark:bg-slate-800/50 border-zinc-200 dark:border-white/5' : 'bg-slate-800/50 border-white/5'}`}>
<label className="text-[10px] text-purple-400 font-bold uppercase tracking-widest mb-1 block">Management</label>
<div className="text-sm text-white font-bold">{data.management.name}</div>
<div className={`text-sm font-bold ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.management.name}</div>
<div
onClick={() => navigate('/login')}
className="text-xs text-blue-400 cursor-pointer hover:underline mt-1 focus:outline-none focus:ring-1 focus:ring-blue-400 rounded"
@@ -171,30 +220,30 @@ const IntelligenceSidePanel = ({ data, onClose }) => {
<div className="space-y-4 animate-in slide-in-from-right-4 duration-300">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-[10px] text-gray-500 font-bold uppercase tracking-widest mb-1 block">Roof Specs</label>
<div className="text-sm text-white font-medium">{data.specs.roofSize}</div>
<label className={`text-[10px] font-bold uppercase tracking-widest mb-1 block ${isSheet ? 'text-zinc-400 dark:text-gray-500' : 'text-gray-500'}`}>Roof Specs</label>
<div className={`text-sm font-medium ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.specs.roofSize}</div>
</div>
<div>
<label className="text-[10px] text-gray-500 font-bold uppercase tracking-widest mb-1 block">Risk History</label>
<div className="text-sm text-white font-medium">{data.specs.eventHistory}</div>
<label className={`text-[10px] font-bold uppercase tracking-widest mb-1 block ${isSheet ? 'text-zinc-400 dark:text-gray-500' : 'text-gray-500'}`}>Risk History</label>
<div className={`text-sm font-medium ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.specs.eventHistory}</div>
</div>
</div>
<div className="p-3 bg-slate-800/50 rounded-lg border border-white/5">
<div className={`p-3 rounded-lg border ${isSheet ? 'bg-zinc-100 dark:bg-slate-800/50 border-zinc-200 dark:border-white/5' : 'bg-slate-800/50 border-white/5'}`}>
<label className="text-[10px] text-emerald-400 font-bold uppercase tracking-widest mb-1 block">Owner Intelligence</label>
<div className="flex justify-between items-end">
<div>
<div className="text-xs text-gray-400 mb-0.5">FICO Score</div>
<div className="text-sm text-white font-bold">{data.owner.fico}</div>
<div className={`text-xs mb-0.5 ${isSheet ? 'text-zinc-500 dark:text-gray-400' : 'text-gray-400'}`}>FICO Score</div>
<div className={`text-sm font-bold ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.owner.fico}</div>
</div>
<div className="text-right">
<div className="text-xs text-gray-400 mb-0.5">Profile</div>
<div className="text-xs text-white font-medium">{data.owner.profile}</div>
<div className={`text-xs mb-0.5 ${isSheet ? 'text-zinc-500 dark:text-gray-400' : 'text-gray-400'}`}>Profile</div>
<div className={`text-xs font-medium ${isSheet ? 'text-zinc-900 dark:text-white' : 'text-white'}`}>{data.owner.profile}</div>
</div>
</div>
</div>
</div>
) : (
<div className="text-xs text-gray-400 italic">
<div className={`text-xs italic ${isSheet ? 'text-zinc-500 dark:text-gray-400' : 'text-gray-400'}`}>
&gt; ANALYSIS: {data.type === 'Commercial' ? 'High-value commercial asset at risk. Immediate inspection recommended.' : 'High probability of insurance approval due to recent storm activity.'}
</div>
)}
@@ -214,11 +263,11 @@ const IntelligenceSidePanel = ({ data, onClose }) => {
<div role="tabpanel" id="panel-photos" aria-labelledby="tab-photos" className="space-y-4 animate-in fade-in slide-in-from-right-4 duration-300 h-full flex flex-col">
{/* Photo Grid */}
<div className="grid grid-cols-2 gap-3 pb-20"> {/* pb-20 for bottom fixed button space if needed, though button is inline here */}
<div className="grid grid-cols-2 gap-3 pb-4">
{photos.map((photo, index) => (
<div
key={photo.id}
className="relative aspect-square rounded-lg overflow-hidden group border border-white/10 hover:border-cyan-400/50 transition-colors cursor-pointer"
className={`relative aspect-square rounded-lg overflow-hidden group border transition-colors cursor-pointer ${isSheet ? 'border-zinc-200 dark:border-white/10 hover:border-cyan-500/50 dark:hover:border-cyan-400/50' : 'border-white/10 hover:border-cyan-400/50'}`}
onClick={() => setLightboxIndex(index)}
>
<img
@@ -226,18 +275,19 @@ const IntelligenceSidePanel = ({ data, onClose }) => {
alt={photo.caption || 'Property view'}
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
<span className="text-cyan-400 text-xs font-bold uppercase tracking-widest border border-cyan-400/50 px-2 py-1 rounded-full backdrop-blur-sm shadow-[0_0_10px_rgba(34,211,238,0.3)]">View</span>
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex flex-col items-center justify-end p-2">
<span className="text-cyan-400 text-xs font-bold uppercase tracking-widest border border-cyan-400/50 px-2 py-1 rounded-full backdrop-blur-sm shadow-[0_0_10px_rgba(34,211,238,0.3)] mb-1.5">View</span>
{photo.caption && (
<span className="text-white/80 text-[9px] text-center leading-tight font-mono">{photo.caption}</span>
)}
</div>
</div>
))}
{/* Upload Placeholders if empty */}
{photos.length === 0 && (
<div className="col-span-2 py-8 text-center border-2 border-dashed border-white/10 rounded-lg bg-white/5">
<p className="text-gray-400 text-xs mb-2">No photos available</p>
<div className={`col-span-2 py-8 text-center border-2 border-dashed rounded-lg ${isSheet ? 'border-zinc-200 dark:border-white/10 bg-zinc-50 dark:bg-white/5' : 'border-white/10 bg-white/5'}`}>
<p className={`text-xs mb-2 ${isSheet ? 'text-zinc-400 dark:text-gray-400' : 'text-gray-400'}`}>No photos available</p>
</div>
)}
</div>