← back to Goodquestion
src/components/swot/SWOTChart.tsx
210 lines
'use client'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { TrendingUp, TrendingDown, Target, AlertCircle } from 'lucide-react'
import type { Strength, Weakness, Opportunity, Threat } from '@/types/swot'
interface SWOTChartProps {
strengths: Strength[]
weaknesses: Weakness[]
opportunities: Opportunity[]
threats: Threat[]
}
export function SWOTChart({ strengths, weaknesses, opportunities, threats }: SWOTChartProps) {
const getImpactColor = (impact: 'low' | 'medium' | 'high') => {
switch (impact) {
case 'high':
return 'success'
case 'medium':
return 'warning'
case 'low':
return 'secondary'
}
}
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Strengths */}
<Card className="border-green-200 bg-green-50/50">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-green-700">
<TrendingUp className="h-5 w-5" />
Strengths
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{strengths.map((strength) => (
<div
key={strength.id}
className="bg-white p-4 rounded-lg border border-green-200"
>
<div className="flex items-start justify-between mb-2">
<h4 className="font-semibold text-sm">{strength.title}</h4>
<Badge variant={getImpactColor(strength.impact)}>
{strength.impact}
</Badge>
</div>
<p className="text-sm text-muted-foreground mb-2">
{strength.description}
</p>
<div className="flex items-center justify-between text-xs">
<span className="text-muted-foreground">
Category: {strength.category}
</span>
<span className="font-medium">
Confidence: {strength.confidence}%
</span>
</div>
</div>
))}
</div>
</CardContent>
</Card>
{/* Weaknesses */}
<Card className="border-red-200 bg-red-50/50">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-red-700">
<TrendingDown className="h-5 w-5" />
Weaknesses
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{weaknesses.map((weakness) => (
<div
key={weakness.id}
className="bg-white p-4 rounded-lg border border-red-200"
>
<div className="flex items-start justify-between mb-2">
<h4 className="font-semibold text-sm">{weakness.title}</h4>
<Badge variant={getImpactColor(weakness.impact)}>
{weakness.impact}
</Badge>
</div>
<p className="text-sm text-muted-foreground mb-2">
{weakness.description}
</p>
{weakness.mitigationStrategy && (
<div className="bg-yellow-50 p-2 rounded text-xs mb-2">
<strong>Mitigation:</strong> {weakness.mitigationStrategy}
</div>
)}
<div className="flex items-center justify-between text-xs">
<span className="text-muted-foreground">
Category: {weakness.category}
</span>
<span className="font-medium">
Confidence: {weakness.confidence}%
</span>
</div>
</div>
))}
</div>
</CardContent>
</Card>
{/* Opportunities */}
<Card className="border-blue-200 bg-blue-50/50">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-blue-700">
<Target className="h-5 w-5" />
Opportunities
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{opportunities.map((opportunity) => (
<div
key={opportunity.id}
className="bg-white p-4 rounded-lg border border-blue-200"
>
<div className="flex items-start justify-between mb-2">
<h4 className="font-semibold text-sm">{opportunity.title}</h4>
<Badge variant={getImpactColor(opportunity.impact)}>
{opportunity.impact}
</Badge>
</div>
<p className="text-sm text-muted-foreground mb-2">
{opportunity.description}
</p>
<div className="grid grid-cols-2 gap-2 text-xs">
<div>
<span className="text-muted-foreground">Timeframe:</span>
<span className="ml-1 font-medium">{opportunity.timeframe}</span>
</div>
<div>
<span className="text-muted-foreground">Feasibility:</span>
<span className="ml-1 font-medium">{opportunity.feasibility}%</span>
</div>
<div>
<span className="text-muted-foreground">Category:</span>
<span className="ml-1">{opportunity.category}</span>
</div>
<div>
<span className="text-muted-foreground">Confidence:</span>
<span className="ml-1 font-medium">{opportunity.confidence}%</span>
</div>
</div>
</div>
))}
</div>
</CardContent>
</Card>
{/* Threats */}
<Card className="border-orange-200 bg-orange-50/50">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-orange-700">
<AlertCircle className="h-5 w-5" />
Threats
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{threats.map((threat) => (
<div
key={threat.id}
className="bg-white p-4 rounded-lg border border-orange-200"
>
<div className="flex items-start justify-between mb-2">
<h4 className="font-semibold text-sm">{threat.title}</h4>
<Badge
variant={
threat.severity === 'critical'
? 'destructive'
: getImpactColor(threat.impact)
}
>
{threat.severity}
</Badge>
</div>
<p className="text-sm text-muted-foreground mb-2">
{threat.description}
</p>
<div className="grid grid-cols-2 gap-2 text-xs">
<div>
<span className="text-muted-foreground">Category:</span>
<span className="ml-1">{threat.category}</span>
</div>
<div>
<span className="text-muted-foreground">Likelihood:</span>
<span className="ml-1 font-medium">{threat.likelihood}%</span>
</div>
<div className="col-span-2">
<span className="text-muted-foreground">Confidence:</span>
<span className="ml-1 font-medium">{threat.confidence}%</span>
</div>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
)
}