diff --git a/components/Home/UpcomingEvents.tsx b/components/Home/UpcomingEvents.tsx index a46c04419..a4e902214 100644 --- a/components/Home/UpcomingEvents.tsx +++ b/components/Home/UpcomingEvents.tsx @@ -1,7 +1,9 @@ +import { observer } from 'mobx-react'; import Link from 'next/link'; -import { FC } from 'react'; -import { Button, Card, Col, Container, Row } from 'react-bootstrap'; +import { FC, useContext } from 'react'; +import { Button, Card, Col, Row } from 'react-bootstrap'; +import { I18nContext } from '../../models/Translation'; import { ArticleMeta } from '../../pages/api/core'; import { SectionTitle } from './SectionTitle'; @@ -9,10 +11,12 @@ interface UpcomingEventsProps { events: ArticleMeta[]; } -export const UpcomingEvents: FC = ({ events }) => ( -
- - 近期活动 +export const UpcomingEvents: FC = observer(({ events }) => { + const { t } = useContext(I18nContext); + + return ( + <> + {t('upcoming_events')} {events.map(({ name, meta, path }) => ( @@ -20,24 +24,24 @@ export const UpcomingEvents: FC = ({ events }) => ( {name} - 时间: {meta?.start || 'N/A'} + {t('activity_time')}: {meta?.start || 'N/A'} - 地点: {meta?.address || 'N/A'} + {t('activity_location')}: {meta?.address || 'N/A'} - 查看详情 + {t('view_details')} ))}
-
-
-
-); + + ); +}); diff --git a/eslint.config.ts b/eslint.config.ts index 603f41a6b..2590175c1 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -47,7 +47,7 @@ export default tsEslint.config( warnOnUnsupportedTypeScriptVersion: false, }, }, - // @ts-expect-error Next.js 15.4 compatibility bug + // @ts-expect-error https://github.com/vercel/next.js/issues/81695 rules: { // spellchecker '@cspell/spellchecker': [ diff --git a/pages/activity/[[...page]].tsx b/pages/activity/[[...page]].tsx new file mode 100644 index 000000000..54f164f14 --- /dev/null +++ b/pages/activity/[[...page]].tsx @@ -0,0 +1,84 @@ +import { observer } from 'mobx-react'; +import { Pager, PagerProps } from 'mobx-restful-table'; +import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from 'next'; +import { FC, useContext } from 'react'; +import { Container } from 'react-bootstrap'; + +import { UpcomingEvents } from '../../components/Home/UpcomingEvents'; +import { PageHead } from '../../components/Layout/PageHead'; +import { isServer } from '../../models/configuration'; +import { I18nContext } from '../../models/Translation'; +import { ArticleMeta, getMarkdownListSortedByDate } from '../api/core'; + +const ITEMS_PER_PAGE = 10; + +interface ActivityPageProps extends Pick { + activities: ArticleMeta[]; +} + +export const getStaticPaths: GetStaticPaths = async () => { + const activities = await getMarkdownListSortedByDate('/article/Wiki/_posts/Activity'); + const totalPages = Math.ceil(activities.length / ITEMS_PER_PAGE); + + const paths = [ + { params: { page: [] } }, + ...Array.from({ length: totalPages }, (_, i) => ({ + params: { page: [i + 1 + ''] }, + })), + ]; + + return { paths, fallback: false }; +}; + +export const getStaticProps: GetStaticProps = async ({ params }) => { + const pageIndex = Number(params?.page?.[0]) || 1; + const activities = await getMarkdownListSortedByDate('/article/Wiki/_posts/Activity'); + + const startIndex = (pageIndex - 1) * ITEMS_PER_PAGE; + const endIndex = startIndex + ITEMS_PER_PAGE; + const paginatedActivities = activities.slice(startIndex, endIndex); + const pageCount = Math.ceil(activities.length / ITEMS_PER_PAGE); + + return { + props: { activities: paginatedActivities, pageIndex, pageCount }, + revalidate: 3600, + }; +}; + +const ActivityPage: FC> = observer( + ({ activities, pageIndex, pageCount }) => { + const { t } = useContext(I18nContext); + + return ( + + + +
+

{t('activity_calendar')}

+

{t('activity_calendar_description')}

+
+ +
+

{t('activity_calendar')}

+