← back to Sdcc Awards
cypressaward/frontend/app/administrators/page.tsx
229 lines
'use client'
import { useEffect, useState } from 'react'
import { supabase } from '@/lib/supabase'
interface Administrator {
id: number
name: string
type: string
location: string
phone: string
email: string
website: string
description: string
specialties: string
cy_pres_capable: boolean
press_page: string
notes: string
source: string
}
export default function AdministratorsPage() {
const [administrators, setAdministrators] = useState<Administrator[]>([])
const [loading, setLoading] = useState(true)
const [selectedAdmin, setSelectedAdmin] = useState<Administrator | null>(null)
const [showModal, setShowModal] = useState(false)
useEffect(() => {
fetchAdministrators()
}, [])
async function fetchAdministrators() {
try {
const { data, error } = await supabase
.from('scraped_administrators')
.select('*')
.order('name', { ascending: true })
if (error) throw error
setAdministrators(data || [])
} catch (error) {
console.error('Error fetching administrators:', error)
} finally {
setLoading(false)
}
}
function openModal(admin: Administrator) {
setSelectedAdmin(admin)
setShowModal(true)
}
function closeModal() {
setShowModal(false)
setSelectedAdmin(null)
}
return (
<div className="min-h-screen bg-gray-50 py-8">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="bg-white shadow-xl rounded-lg">
<div className="px-6 py-4 border-b border-gray-200">
<h1 className="text-3xl font-bold text-gray-900">Settlement Administrators</h1>
<p className="text-gray-600 mt-2">Class action settlement administrators and claims processors with cy pres distribution capabilities</p>
</div>
{loading ? (
<div className="flex justify-center py-12">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
) : (
<div className="grid gap-4 p-6 md:grid-cols-2 lg:grid-cols-3">
{administrators.map((admin) => (
<div
key={admin.id}
className="bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-lg transition-shadow p-6"
>
<div className="flex justify-between items-start mb-3">
<h3 className="text-lg font-semibold text-gray-900">{admin.name}</h3>
{admin.cy_pres_capable && (
<span className="px-2 py-1 text-xs font-medium bg-green-100 text-green-800 rounded-full">
Cy Pres
</span>
)}
</div>
<p className="text-sm text-gray-600 mb-2">
<span className="font-medium">Location:</span> {admin.location}
</p>
{admin.phone && (
<p className="text-sm text-gray-600 mb-2">
<span className="font-medium">Phone:</span> {admin.phone}
</p>
)}
<p className="text-sm text-gray-700 mb-4 line-clamp-2">
{admin.description}
</p>
<div className="flex gap-2">
<button
onClick={() => openModal(admin)}
className="flex-1 px-3 py-2 bg-blue-600 text-white text-sm rounded-md hover:bg-blue-700 transition"
>
View Details
</button>
{admin.website && (
<a
href={admin.website}
target="_blank"
rel="noopener noreferrer"
className="flex-1 px-3 py-2 bg-gray-100 text-gray-700 text-sm rounded-md hover:bg-gray-200 transition text-center"
>
Website
</a>
)}
</div>
</div>
))}
</div>
)}
</div>
</div>
{/* Modal */}
{showModal && selectedAdmin && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
<div className="bg-white rounded-lg max-w-3xl w-full max-h-[90vh] overflow-y-auto">
<div className="p-6">
<div className="flex justify-between items-start mb-4">
<div>
<h2 className="text-2xl font-bold text-gray-900">{selectedAdmin.name}</h2>
{selectedAdmin.cy_pres_capable && (
<span className="inline-block mt-2 px-3 py-1 text-sm font-medium bg-green-100 text-green-800 rounded-full">
Cy Pres Capable
</span>
)}
</div>
<button
onClick={closeModal}
className="text-gray-400 hover:text-gray-600"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div className="space-y-4">
<div>
<h3 className="font-semibold text-gray-700">Description</h3>
<p className="text-gray-900">{selectedAdmin.description}</p>
</div>
<div>
<h3 className="font-semibold text-gray-700">Specialties</h3>
<p className="text-gray-900">{selectedAdmin.specialties}</p>
</div>
<div className="grid md:grid-cols-2 gap-4">
<div>
<h3 className="font-semibold text-gray-700">Location</h3>
<p className="text-gray-900">{selectedAdmin.location}</p>
</div>
{selectedAdmin.phone && (
<div>
<h3 className="font-semibold text-gray-700">Phone</h3>
<p className="text-gray-900">{selectedAdmin.phone}</p>
</div>
)}
</div>
{selectedAdmin.email && (
<div>
<h3 className="font-semibold text-gray-700">Email</h3>
<p className="text-gray-900">{selectedAdmin.email}</p>
</div>
)}
{selectedAdmin.notes && (
<div>
<h3 className="font-semibold text-gray-700">Notes</h3>
<p className="text-gray-900">{selectedAdmin.notes}</p>
</div>
)}
<div>
<h3 className="font-semibold text-gray-700">Type</h3>
<p className="text-gray-900 capitalize">{selectedAdmin.type.replace('_', ' ')}</p>
</div>
</div>
<div className="mt-6 flex gap-3">
{selectedAdmin.website && (
<a
href={selectedAdmin.website}
target="_blank"
rel="noopener noreferrer"
className="flex-1 px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition text-center font-medium"
>
Visit Website
</a>
)}
{selectedAdmin.press_page && (
<a
href={selectedAdmin.press_page}
target="_blank"
rel="noopener noreferrer"
className="flex-1 px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition text-center font-medium"
>
Press & News
</a>
)}
<button
onClick={closeModal}
className="flex-1 px-4 py-2 bg-gray-200 text-gray-800 rounded-md hover:bg-gray-300 transition font-medium"
>
Close
</button>
</div>
</div>
</div>
</div>
)}
</div>
)
}