← back to Goodquestion
src/components/market/CompetitorMap.tsx
112 lines
'use client'
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { Store, MapPin, Star, DollarSign } from 'lucide-react'
import type { CompetitorData } from '@/types/swot'
interface CompetitorMapProps {
competitors: CompetitorData[]
businessType: string
}
export function CompetitorMap({ competitors, businessType }: CompetitorMapProps) {
const sortedByDistance = [...competitors].sort((a, b) => a.distance - b.distance)
const getDistanceColor = (distance: number) => {
if (distance < 1) return 'text-red-600'
if (distance < 3) return 'text-orange-600'
if (distance < 5) return 'text-yellow-600'
return 'text-green-600'
}
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Store className="h-5 w-5" />
Competitor Analysis
</CardTitle>
<CardDescription>
{competitors.length} {businessType} businesses found in the area
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
{sortedByDistance.map((competitor, index) => (
<div
key={index}
className="border rounded-lg p-4 hover:shadow-md transition-shadow"
>
<div className="flex items-start justify-between mb-2">
<div className="flex-1">
<h4 className="font-semibold text-lg">{competitor.name}</h4>
<p className="text-sm text-muted-foreground">{competitor.type}</p>
</div>
<div className="flex gap-2">
<Badge variant="outline" className={getDistanceColor(competitor.distance)}>
<MapPin className="h-3 w-3 mr-1" />
{competitor.distance.toFixed(1)} mi
</Badge>
</div>
</div>
<div className="grid grid-cols-3 gap-4 mt-3">
{competitor.yearEstablished && (
<div className="text-sm">
<span className="text-muted-foreground">Established:</span>
<p className="font-medium">{competitor.yearEstablished}</p>
</div>
)}
{competitor.estimatedRevenue && (
<div className="text-sm">
<span className="text-muted-foreground flex items-center gap-1">
<DollarSign className="h-3 w-3" />
Est. Revenue:
</span>
<p className="font-medium">
${(competitor.estimatedRevenue / 1000).toFixed(0)}K
</p>
</div>
)}
{competitor.rating && (
<div className="text-sm">
<span className="text-muted-foreground flex items-center gap-1">
<Star className="h-3 w-3" />
Rating:
</span>
<p className="font-medium">{competitor.rating.toFixed(1)}/5.0</p>
</div>
)}
</div>
</div>
))}
</div>
{/* Summary Stats */}
<div className="grid grid-cols-3 gap-4 mt-6 p-4 bg-muted/50 rounded-lg">
<div className="text-center">
<div className="text-2xl font-bold text-primary">{competitors.length}</div>
<div className="text-xs text-muted-foreground">Total Competitors</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-primary">
{competitors.filter(c => c.distance < 5).length}
</div>
<div className="text-xs text-muted-foreground">Within 5 Miles</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-primary">
{(
competitors.reduce((sum, c) => sum + (c.rating || 0), 0) /
competitors.filter(c => c.rating).length
).toFixed(1)}
</div>
<div className="text-xs text-muted-foreground">Avg Rating</div>
</div>
</div>
</CardContent>
</Card>
)
}