← back to Goodquestion
src/components/market/MarketSizeChart.tsx
221 lines
'use client'
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
PieChart,
Pie,
Cell,
} from 'recharts'
import { TrendingUp } from 'lucide-react'
import type { MarketSize } from '@/types/swot'
interface MarketSizeChartProps {
marketSize: MarketSize
demographics: {
population: number
medianIncome: number
averageHouseholdSize: number
targetDemographicPercentage: number
}
}
export function MarketSizeChart({ marketSize, demographics }: MarketSizeChartProps) {
const marketData = [
{
name: 'Total Addressable Market',
value: marketSize.totalAddressableMarket,
color: '#3b82f6',
},
{
name: 'Serviceable Market',
value: marketSize.serviceableMarket,
color: '#8b5cf6',
},
{
name: 'Target Market',
value: marketSize.targetMarket,
color: '#22c55e',
},
]
const barChartData = [
{
name: 'TAM',
value: marketSize.totalAddressableMarket,
},
{
name: 'SAM',
value: marketSize.serviceableMarket,
},
{
name: 'SOM',
value: marketSize.targetMarket,
},
]
const COLORS = ['#3b82f6', '#8b5cf6', '#22c55e']
const formatCurrency = (value: number) => {
if (value >= 1000000) {
return `$${(value / 1000000).toFixed(1)}M`
}
if (value >= 1000) {
return `$${(value / 1000).toFixed(0)}K`
}
return `$${value.toLocaleString()}`
}
return (
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<TrendingUp className="h-5 w-5" />
Market Size Analysis
</CardTitle>
<CardDescription>
Potential market share: {marketSize.marketSharePotential}%
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid md:grid-cols-2 gap-6">
{/* Bar Chart */}
<div>
<h4 className="text-sm font-semibold mb-4">Market Breakdown</h4>
<ResponsiveContainer width="100%" height={250}>
<BarChart data={barChartData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis tickFormatter={formatCurrency} />
<Tooltip formatter={(value: any) => formatCurrency(value)} />
<Bar dataKey="value" fill="#3b82f6">
{barChartData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index]} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
</div>
{/* Pie Chart */}
<div>
<h4 className="text-sm font-semibold mb-4">Market Distribution</h4>
<ResponsiveContainer width="100%" height={250}>
<PieChart>
<Pie
data={marketData}
cx="50%"
cy="50%"
labelLine={false}
label={({ name, percent }) => `${name.split(' ')[0]}: ${(percent * 100).toFixed(0)}%`}
outerRadius={80}
fill="#8884d8"
dataKey="value"
>
{marketData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
<Tooltip formatter={(value: any) => formatCurrency(value)} />
</PieChart>
</ResponsiveContainer>
</div>
</div>
{/* Market Details */}
<div className="grid md:grid-cols-3 gap-4 mt-6">
<div className="bg-blue-50 p-4 rounded-lg">
<div className="text-xs text-blue-600 font-medium mb-1">
Total Addressable Market
</div>
<div className="text-2xl font-bold text-blue-900">
{formatCurrency(marketSize.totalAddressableMarket)}
</div>
<div className="text-xs text-blue-600 mt-1">
Total market potential
</div>
</div>
<div className="bg-purple-50 p-4 rounded-lg">
<div className="text-xs text-purple-600 font-medium mb-1">
Serviceable Market
</div>
<div className="text-2xl font-bold text-purple-900">
{formatCurrency(marketSize.serviceableMarket)}
</div>
<div className="text-xs text-purple-600 mt-1">
Realistically serviceable
</div>
</div>
<div className="bg-green-50 p-4 rounded-lg">
<div className="text-xs text-green-600 font-medium mb-1">
Target Market
</div>
<div className="text-2xl font-bold text-green-900">
{formatCurrency(marketSize.targetMarket)}
</div>
<div className="text-xs text-green-600 mt-1">
Initial target segment
</div>
</div>
</div>
{/* Assumptions */}
{marketSize.assumptions.length > 0 && (
<div className="mt-6 p-4 bg-muted/50 rounded-lg">
<h4 className="text-sm font-semibold mb-2">Key Assumptions</h4>
<ul className="text-sm space-y-1 list-disc list-inside text-muted-foreground">
{marketSize.assumptions.map((assumption, index) => (
<li key={index}>{assumption}</li>
))}
</ul>
</div>
)}
</CardContent>
</Card>
{/* Demographics */}
<Card>
<CardHeader>
<CardTitle>Local Demographics</CardTitle>
</CardHeader>
<CardContent>
<div className="grid md:grid-cols-4 gap-4">
<div className="text-center p-4 bg-muted/50 rounded-lg">
<div className="text-3xl font-bold text-primary">
{demographics.population.toLocaleString()}
</div>
<div className="text-sm text-muted-foreground mt-1">Population</div>
</div>
<div className="text-center p-4 bg-muted/50 rounded-lg">
<div className="text-3xl font-bold text-primary">
${demographics.medianIncome.toLocaleString()}
</div>
<div className="text-sm text-muted-foreground mt-1">Median Income</div>
</div>
<div className="text-center p-4 bg-muted/50 rounded-lg">
<div className="text-3xl font-bold text-primary">
{demographics.averageHouseholdSize.toFixed(1)}
</div>
<div className="text-sm text-muted-foreground mt-1">Avg Household Size</div>
</div>
<div className="text-center p-4 bg-muted/50 rounded-lg">
<div className="text-3xl font-bold text-primary">
{demographics.targetDemographicPercentage}%
</div>
<div className="text-sm text-muted-foreground mt-1">Target Demographic</div>
</div>
</div>
</CardContent>
</Card>
</div>
)
}