← back to Sdcc Awards
cypressaward/frontend/components/home/recent-awards.tsx
163 lines
'use client'
import { useQuery } from '@tanstack/react-query'
import { Card } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { ExternalLink, TrendingUp, Award } from 'lucide-react'
interface AwardData {
id: string
caseTitle: string
recipientName: string
amount: number
dateAwarded: string
court: string
category: string[]
sourceUrl?: string
}
async function fetchRecentAwards(): Promise<AwardData[]> {
// This would fetch from your API
return [
{
id: '1',
caseTitle: 'In re: Google Location History Litigation',
recipientName: 'Electronic Frontier Foundation',
amount: 2500000,
dateAwarded: '2024-01-15',
court: 'N.D. Cal.',
category: ['privacy', 'technology'],
sourceUrl: 'https://example.com/case1'
},
{
id: '2',
caseTitle: 'Student Loan Forgiveness Settlement',
recipientName: 'Student Borrower Protection Center',
amount: 1800000,
dateAwarded: '2024-01-10',
court: 'D. Mass.',
category: ['education', 'consumer'],
sourceUrl: 'https://example.com/case2'
},
{
id: '3',
caseTitle: 'Healthcare Data Breach Class Action',
recipientName: 'Patient Privacy Rights',
amount: 950000,
dateAwarded: '2023-12-20',
court: 'S.D.N.Y.',
category: ['healthcare', 'privacy'],
sourceUrl: 'https://example.com/case3'
},
{
id: '4',
caseTitle: 'Wage & Hour Violations Settlement',
recipientName: 'National Employment Law Project',
amount: 750000,
dateAwarded: '2023-12-15',
court: 'C.D. Cal.',
category: ['labor', 'employment'],
sourceUrl: 'https://example.com/case4'
},
{
id: '5',
caseTitle: 'Environmental Contamination Settlement',
recipientName: 'Clean Water Action',
amount: 3200000,
dateAwarded: '2023-11-30',
court: 'E.D. Mich.',
category: ['environment', 'health'],
sourceUrl: 'https://example.com/case5'
}
]
}
export function RecentAwards() {
const { data: awards, isLoading } = useQuery({
queryKey: ['recent-awards'],
queryFn: fetchRecentAwards,
refetchInterval: 300000 // Refresh every 5 minutes
})
if (isLoading) {
return (
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
{[1, 2, 3].map(i => (
<div key={i} className="h-32 bg-gray-200 rounded-lg animate-pulse"></div>
))}
</div>
)
}
const formatAmount = (amount: number) => {
if (amount >= 1000000) {
return `$${(amount / 1000000).toFixed(1)}M`
}
return `$${(amount / 1000).toFixed(0)}K`
}
return (
<div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
{awards?.map((award) => (
<Card key={award.id} className="p-4 hover:shadow-md transition-shadow">
<div className="flex justify-between items-start mb-2">
<Award className="h-5 w-5 text-green-600 flex-shrink-0" />
<span className="text-2xl font-bold text-green-600">
{formatAmount(award.amount)}
</span>
</div>
<h4 className="font-semibold text-sm mb-1 line-clamp-2">
{award.recipientName}
</h4>
<p className="text-xs text-gray-600 mb-2 line-clamp-2">
{award.caseTitle}
</p>
<div className="flex flex-wrap gap-1 mb-2">
{award.category.map(cat => (
<Badge key={cat} variant="secondary" className="text-xs">
{cat}
</Badge>
))}
</div>
<div className="flex justify-between items-center text-xs text-gray-500">
<span>{award.court}</span>
<span>{new Date(award.dateAwarded).toLocaleDateString()}</span>
</div>
{award.sourceUrl && (
<a
href={award.sourceUrl}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center text-xs text-blue-600 hover:underline mt-2"
>
View Source
<ExternalLink className="h-3 w-3 ml-1" />
</a>
)}
</Card>
))}
</div>
<div className="mt-6 p-4 bg-green-50 border border-green-200 rounded-lg">
<div className="flex items-start space-x-2">
<TrendingUp className="h-5 w-5 text-green-600 mt-0.5" />
<div>
<p className="text-sm font-semibold text-green-900">
${awards ? (awards.reduce((sum, a) => sum + a.amount, 0) / 1000000).toFixed(1) : '0'}M
in cy pres awards tracked this month
</p>
<p className="text-xs text-green-700 mt-1">
Awards over $50,000 are automatically tracked and verified from public court records
</p>
</div>
</div>
</div>
</div>
)
}