← back to Sdcc Awards

cypressaward/frontend/app/awards/page.tsx

229 lines

'use client'

import { useState, useEffect } from 'react'

interface Award {
  id: number
  recipient_organization: string
  amount: number
  amount_text: string
  case_name: string
  court: string
  year: number
  date_awarded: string
  purpose: string
  law_firm: string
  settlement_administrator: string
  source_url: string
  source_title: string
  verified: boolean
  notes?: string
  created_at: string
}

export default function AwardsPage() {
  const [awards, setAwards] = useState<Award[]>([])
  const [filteredAwards, setFilteredAwards] = useState<Award[]>([])
  const [loading, setLoading] = useState(true)
  const [searchTerm, setSearchTerm] = useState('')

  useEffect(() => {
    async function fetchAwards() {
      // Always use the comprehensive data file with all 17 verified awards
      const { allCyPresAwards } = await import('@/lib/all-awards-data')
      const fallbackAwards = allCyPresAwards.map((award, index) => ({
        id: index + 1,
        recipient_organization: award.recipient_organization,
        amount: award.amount,
        amount_text: award.amount_text,
        case_name: award.case_name,
        court: award.court,
        year: award.case_year,
        date_awarded: `${award.case_year}-01-01`,
        purpose: award.category || '',
        law_firm: '',
        settlement_administrator: '',
        source_url: award.source_url || '',
        source_title: award.case_name,
        verified: true,
        created_at: new Date().toISOString()
      }))
      // Sort by year (newest first), then by amount (largest first)
      const sortedAwards = fallbackAwards.sort((a, b) => {
        if (b.year !== a.year) return b.year - a.year;
        return b.amount - a.amount;
      });
      
      setAwards(sortedAwards)
      setFilteredAwards(sortedAwards)
      setLoading(false)
    }

    fetchAwards()
  }, [])

  // Filter awards based on search criteria
  useEffect(() => {
    let filtered = awards

    // Text search across multiple fields
    if (searchTerm) {
      const search = searchTerm.toLowerCase()
      filtered = filtered.filter(award => 
        award.recipient_organization.toLowerCase().includes(search) ||
        award.case_name.toLowerCase().includes(search) ||
        award.court.toLowerCase().includes(search) ||
        award.purpose.toLowerCase().includes(search) ||
        award.law_firm.toLowerCase().includes(search) ||
        award.settlement_administrator.toLowerCase().includes(search) ||
        (award.notes && award.notes.toLowerCase().includes(search))
      )
    }

    setFilteredAwards(filtered)
  }, [awards, searchTerm])

  const formatCurrency = (amount: number) => {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD',
      minimumFractionDigits: 0,
      maximumFractionDigits: 0,
    }).format(amount)
  }

  const formatDate = (dateString: string) => {
    return new Date(dateString).toLocaleDateString('en-US', {
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    })
  }


  const totalAwards = filteredAwards.reduce((sum, award) => sum + award.amount, 0)

  const clearSearch = () => {
    setSearchTerm('')
  }

  if (loading) {
    return (
      <div className="container mx-auto px-4 py-8">
        <div className="text-center">Loading cy pres awards...</div>
      </div>
    )
  }

  return (
    <div className="container mx-auto px-4 py-8">
      <div className="mb-8">
        <h1 className="text-4xl font-bold mb-4 text-gray-900">Cy Pres Awards Database</h1>
        <p className="text-lg text-gray-600 mb-6">
          Verified real cy pres awards from class action settlements. All data sourced from court documents and official records.
        </p>

        <div className="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg p-6 mb-6">
          <div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-center">
            <div>
              <div className="text-3xl font-bold text-blue-600">{filteredAwards.length}</div>
              <div className="text-sm text-gray-600">Filtered Awards</div>
            </div>
            <div>
              <div className="text-3xl font-bold text-green-600">{formatCurrency(totalAwards)}</div>
              <div className="text-sm text-gray-600">Total Distributed</div>
            </div>
            <div>
              <div className="text-3xl font-bold text-purple-600">{new Set(filteredAwards.map(a => a.case_name)).size}</div>
              <div className="text-sm text-gray-600">Unique Cases</div>
            </div>
            <div>
              <div className="text-3xl font-bold text-orange-600">{new Set(filteredAwards.map(a => a.recipient_organization)).size}</div>
              <div className="text-sm text-gray-600">Organizations</div>
            </div>
          </div>
        </div>

        {/* Search Bar */}
        <div className="mb-6">
          <div className="flex items-center space-x-4">
            <div className="flex-1">
              <input
                type="text"
                placeholder="Search awards by organization, case name, court, or category..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
              />
            </div>
            {searchTerm && (
              <button
                onClick={clearSearch}
                className="px-4 py-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 transition-colors"
              >
                Clear
              </button>
            )}
          </div>
        </div>
      </div>

      <div className="space-y-6">
        {filteredAwards.map((award) => (
          <div key={award.id} className="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
            <div className="flex justify-between items-start mb-4">
              <div className="flex-1">
                <h3 className="text-xl font-bold text-gray-900 mb-2">
                  {award.recipient_organization}
                </h3>
                <p className="text-lg text-green-600 font-semibold mb-2">
                  {formatCurrency(award.amount)}
                </p>
                <p className="text-gray-700 font-medium mb-1">
                  {award.case_name}
                </p>
                <div className="flex flex-wrap gap-4 text-sm text-gray-600">
                  <span><strong>Court:</strong> {award.court}</span>
                  <span><strong>Year:</strong> {award.year}</span>
                  <span><strong>Category:</strong> {award.purpose}</span>
                </div>
                {award.source_url && (
                  <div className="mt-2">
                    <a 
                      href={award.source_url} 
                      target="_blank" 
                      rel="noopener noreferrer"
                      className="inline-flex items-center text-blue-600 hover:text-blue-800 text-sm"
                    >
                      View Article/Source
                      <svg className="ml-1 w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
                      </svg>
                    </a>
                  </div>
                )}
              </div>
              <div className="text-right">
                <span className="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">
                  Verified ✓
                </span>
              </div>
            </div>
          </div>
        ))}
      </div>

      {filteredAwards.length === 0 && (
        <div className="text-center py-12">
          <div className="text-gray-500 text-lg">No awards found matching your criteria.</div>
          <button
            onClick={clearSearch}
            className="mt-4 text-blue-600 hover:underline"
          >
            Clear all filters
          </button>
        </div>
      )}
    </div>
  )
}