99 lines
4.1 KiB
TypeScript
99 lines
4.1 KiB
TypeScript
import React, { useEffect } from 'react'
|
|
import { useAppDispatch, useAppSelector } from '../stores/hooks'
|
|
import { fetch } from '../stores/trials/trialsSlice'
|
|
import BaseButton from './BaseButton'
|
|
import BaseButtons from './BaseButtons'
|
|
import { mdiEye, mdiPlus } from '@mdi/js'
|
|
import Link from 'next/link'
|
|
|
|
const RecentTrialsTable = () => {
|
|
const dispatch = useAppDispatch()
|
|
const { trials, loading } = useAppSelector((state) => state.trials)
|
|
|
|
useEffect(() => {
|
|
dispatch(fetch({ query: '?limit=5' }))
|
|
}, [dispatch])
|
|
|
|
const getStatusColor = (status: string) => {
|
|
switch (status) {
|
|
case 'active':
|
|
return 'bg-emerald-100 text-emerald-800 border-emerald-200'
|
|
case 'planned':
|
|
return 'bg-blue-100 text-blue-800 border-blue-200'
|
|
case 'completed':
|
|
return 'bg-purple-100 text-purple-800 border-purple-200'
|
|
case 'draft':
|
|
return 'bg-gray-100 text-gray-800 border-gray-200'
|
|
default:
|
|
return 'bg-gray-50 text-gray-600 border-gray-200'
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white border border-gray-200 rounded-xl overflow-hidden shadow-sm">
|
|
<div className="px-6 py-4 border-b border-gray-100 flex justify-between items-center bg-gray-50/50">
|
|
<h3 className="font-bold text-gray-800">Recent Trials</h3>
|
|
<Link href="/trials/trials-list">
|
|
<BaseButton label="View All" color="white" small />
|
|
</Link>
|
|
</div>
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-sm text-left">
|
|
<thead className="text-xs text-gray-500 uppercase bg-gray-50/30 border-b border-gray-100">
|
|
<tr>
|
|
<th className="px-6 py-3 font-semibold">Trial Name</th>
|
|
<th className="px-6 py-3 font-semibold text-center">Code</th>
|
|
<th className="px-6 py-3 font-semibold text-center">Status</th>
|
|
<th className="px-6 py-3 font-semibold text-center">Created</th>
|
|
<th className="px-6 py-3"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-gray-50">
|
|
{loading && trials.length === 0 ? (
|
|
<tr>
|
|
<td colSpan={5} className="px-6 py-10 text-center text-gray-400">
|
|
<div className="flex items-center justify-center gap-2">
|
|
<div className="w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
|
|
Loading trials...
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
) : trials.length > 0 ? (
|
|
trials.slice(0, 5).map((trial: any) => (
|
|
<tr key={trial.id} className="hover:bg-gray-50/80 transition-colors">
|
|
<td className="px-6 py-4 font-bold text-gray-900">{trial.name}</td>
|
|
<td className="px-6 py-4 text-center font-mono text-gray-500">{trial.code || '-'}</td>
|
|
<td className="px-6 py-4 text-center">
|
|
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-bold border ${getStatusColor(trial.status)}`}>
|
|
{trial.status}
|
|
</span>
|
|
</td>
|
|
<td className="px-6 py-4 text-center text-gray-500">
|
|
{new Date(trial.createdAt).toLocaleDateString()}
|
|
</td>
|
|
<td className="px-6 py-4 text-right">
|
|
<Link href={`/trials/trials-list`}>
|
|
<BaseButton color="info" icon={mdiEye} small rounded-full />
|
|
</Link>
|
|
</td>
|
|
</tr>
|
|
))
|
|
) : (
|
|
<tr>
|
|
<td colSpan={5} className="px-6 py-12 text-center">
|
|
<p className="text-gray-400 mb-4 italic">No trials found in the system.</p>
|
|
<Link href="/trials/trials-list">
|
|
<BaseButton label="Create First Trial" icon={mdiPlus} color="info" small />
|
|
</Link>
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default RecentTrialsTable
|