|
import React, { useState } from "react"; |
|
import { PolicyData } from "../types"; |
|
|
|
interface AIPoliciesTableProps { |
|
policies: PolicyData[]; |
|
} |
|
|
|
const AIPoliciesTable: React.FC<AIPoliciesTableProps> = ({ policies }) => { |
|
const initialOpenYears = policies.reduce((acc, policy) => { |
|
const year = new Date(policy.releaseDate).getFullYear(); |
|
acc[year] = true; |
|
return acc; |
|
}, {} as { [key: number]: boolean }); |
|
|
|
const [openYears, setOpenYears] = useState<{ [key: number]: boolean }>(initialOpenYears); |
|
|
|
const toggleYear = (year: number) => { |
|
setOpenYears((prev) => ({ ...prev, [year]: !prev[year] })); |
|
}; |
|
|
|
const groupedPolicies = policies.reduce((acc, policy) => { |
|
const year = new Date(policy.releaseDate).getFullYear(); |
|
if (!acc[year]) { |
|
acc[year] = []; |
|
} |
|
acc[year].push(policy); |
|
return acc; |
|
}, {} as { [key: number]: PolicyData[] }); |
|
|
|
const sortedYears = Object.keys(groupedPolicies) |
|
.map(Number) |
|
.sort((a, b) => b - a); |
|
|
|
const formatDate = (dateString: string) => { |
|
const date = new Date(dateString); |
|
const options: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', year: 'numeric' }; |
|
return date.toLocaleDateString('en-US', options); |
|
}; |
|
|
|
return ( |
|
<div className="container mx-auto p-6"> |
|
{sortedYears.map((year) => ( |
|
<div key={year} className="mb-12"> |
|
<button |
|
onClick={() => toggleYear(year)} |
|
className="text-2xl font-semibold mb-6 focus:outline-none text-gray-800 dark:text-white" |
|
> |
|
{year} {openYears[year] ? "▲" : "▼"} |
|
</button> |
|
{openYears[year] && ( |
|
<table className="w-full border-collapse table-auto shadow-lg rounded-lg"> |
|
<tbody> |
|
{groupedPolicies[year].map((policy, index) => ( |
|
<tr |
|
key={`${year}-${index}`} |
|
className={`${ |
|
index % 2 === 0 ? "bg-gray-300" : "bg-gray-500" |
|
} dark:${ |
|
index % 2 === 0 ? "bg-gray-700" : "bg-gray-900" |
|
} border-b border-gray-200 dark:border-gray-700`} |
|
> |
|
<td className="py-6 px-6 text-gray-900 dark:text-white"> |
|
<div className="text-lg font-medium">{policy.zh}</div> |
|
<div className="text-sm text-gray-500 dark:text-gray-400 mt-2"> |
|
{policy.en} |
|
</div> |
|
<div className="text-xs text-gray-400 dark:text-gray-500 mt-2"> |
|
{formatDate(policy.releaseDate)} |
|
</div> |
|
</td> |
|
<td className="py-6 px-6 text-right"> |
|
{policy.link.zh && ( |
|
<a |
|
href={policy.link.zh} |
|
target="_blank" |
|
rel="noopener noreferrer" |
|
className="text-blue-500 hover:underline dark:text-blue-400 mr-4" |
|
> |
|
中文 |
|
</a> |
|
)} |
|
{policy.link.en && ( |
|
<a |
|
href={policy.link.en} |
|
target="_blank" |
|
rel="noopener noreferrer" |
|
className="text-blue-500 hover:underline dark:text-blue-400" |
|
> |
|
English |
|
</a> |
|
)} |
|
</td> |
|
</tr> |
|
))} |
|
</tbody> |
|
</table> |
|
)} |
|
</div> |
|
))} |
|
</div> |
|
); |
|
}; |
|
|
|
export default AIPoliciesTable; |
|
|