Skip to content

Commit b76bb38

Browse files
CopilotTechQuery
andcommitted
Complete Google Calendar integration to Activity page
Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
1 parent e44210e commit b76bb38

File tree

3 files changed

+171
-62
lines changed

3 files changed

+171
-62
lines changed

components/Home/UpcomingEvents.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,8 @@ export const UpcomingEvents: FC<UpcomingEventsProps> = ({ events }) => (
1919
<Col key={name}>
2020
<Card body>
2121
<Card.Title className="text-dark">{name}</Card.Title>
22-
<Card.Text className="text-dark">
23-
时间: {meta?.start || 'N/A'}
24-
</Card.Text>
25-
<Card.Text className="text-dark">
26-
地点: {meta?.address || 'N/A'}
27-
</Card.Text>
22+
<Card.Text className="text-dark">时间: {meta?.start || 'N/A'}</Card.Text>
23+
<Card.Text className="text-dark">地点: {meta?.address || 'N/A'}</Card.Text>
2824

2925
<Link href={path || '#'} className="btn btn-primary">
3026
查看详情
@@ -34,7 +30,7 @@ export const UpcomingEvents: FC<UpcomingEventsProps> = ({ events }) => (
3430
))}
3531
</Row>
3632
<div className="text-center mt-4">
37-
<Button variant="outline-primary" size="lg" href="/article/Activity">
33+
<Button variant="outline-primary" size="lg" href="/activity">
3834
查看全部活动 →
3935
</Button>
4036
</div>

pages/activity.tsx

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import 'core-js/full/array/from-async';
2+
3+
import { observer } from 'mobx-react';
4+
import { InferGetStaticPropsType } from 'next';
5+
import { FC } from 'react';
6+
import { Container } from 'react-bootstrap';
7+
8+
import { PageHead } from '../components/Layout/PageHead';
9+
import { ArticleMeta, pageListOf, traverseTree } from './api/core';
10+
11+
export const getStaticProps = async () => {
12+
try {
13+
// Try to load activities, but handle case where directory doesn't exist
14+
let activities: ArticleMeta[] = [];
15+
16+
try {
17+
const activitiesData = await Array.fromAsync(pageListOf('/article/Wiki/_posts/Activity'));
18+
19+
activities = activitiesData
20+
.map(root => [...traverseTree(root, 'subs')])
21+
.flat()
22+
.filter((event): event is ArticleMeta => 'meta' in event)
23+
.sort((a, b) => {
24+
const dateA = a.meta?.date ? new Date(a.meta.date).getTime() : 0;
25+
const dateB = b.meta?.date ? new Date(b.meta.date).getTime() : 0;
26+
27+
return dateB - dateA;
28+
});
29+
} catch (dirError) {
30+
console.warn('Activity directory not found, using empty activities list:', dirError);
31+
}
32+
33+
return {
34+
props: { upcomingEvents: activities },
35+
revalidate: 3600,
36+
};
37+
} catch (error) {
38+
console.error('Error loading activities:', error);
39+
40+
return {
41+
props: { upcomingEvents: [] },
42+
revalidate: 3600,
43+
};
44+
}
45+
};
46+
47+
const ActivityPage: FC<InferGetStaticPropsType<typeof getStaticProps>> = observer(
48+
({ upcomingEvents }) => (
49+
<div className="min-vh-100">
50+
<PageHead title="活动日历" />
51+
52+
<Container className="py-5 mt-5">
53+
<div className="row">
54+
<div className="col-12">
55+
<h1 className="mb-4">活动日历</h1>
56+
<p className="lead mb-4">查看 freeCodeCamp 成都社区的最新活动安排和历史活动记录</p>
57+
</div>
58+
</div>
59+
60+
{/* Calendar Iframe */}
61+
<div className="row mb-5">
62+
<div className="col-12">
63+
<h2 className="mb-3">活动日历</h2>
64+
<div className="calendar-container" style={{ minHeight: '600px' }}>
65+
<iframe
66+
src="https://open-source-bazaar.feishu.cn/share/base/view/shrcn6jNjSKvE9MKPqk56SeSd7p"
67+
width="100%"
68+
height="600"
69+
style={{ border: 'none', borderRadius: '8px' }}
70+
title="freeCodeCamp 成都社区活动日历"
71+
allowFullScreen
72+
/>
73+
</div>
74+
</div>
75+
</div>
76+
77+
{/* Activity List Section */}
78+
{upcomingEvents.length > 0 && (
79+
<div className="row">
80+
<div className="col-12">
81+
<h2 className="mb-3">活动列表</h2>
82+
<div className="row g-4">
83+
{upcomingEvents.map(({ name, meta, path }) => (
84+
<div key={name} className="col-md-6 col-lg-4">
85+
<div className="card h-100">
86+
<div className="card-body">
87+
<h5 className="card-title">{name}</h5>
88+
{meta?.start && (
89+
<p className="card-text">
90+
<i className="bi bi-calendar-event me-2" />
91+
时间: {meta.start}
92+
</p>
93+
)}
94+
{meta?.address && (
95+
<p className="card-text">
96+
<i className="bi bi-geo-alt me-2" />
97+
地点: {meta.address}
98+
</p>
99+
)}
100+
{meta?.description && (
101+
<p className="card-text text-muted">{meta.description}</p>
102+
)}
103+
{path && (
104+
<a href={path} className="btn btn-primary">
105+
查看详情
106+
</a>
107+
)}
108+
</div>
109+
</div>
110+
</div>
111+
))}
112+
</div>
113+
</div>
114+
</div>
115+
)}
116+
</Container>
117+
</div>
118+
),
119+
);
120+
121+
export default ActivityPage;

pages/index.tsx

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -63,65 +63,57 @@ export const getStaticProps = async () => {
6363
};
6464
};
6565

66-
const HomePage: FC<HomePageProps> = observer(
67-
({ latestArticles, upcomingEvents, sponsors }) => (
68-
<main className="min-vh-100">
69-
<PageHead title="Home" />
66+
const HomePage: FC<HomePageProps> = observer(({ latestArticles, upcomingEvents, sponsors }) => (
67+
<main className="min-vh-100">
68+
<PageHead title="Home" />
7069

71-
<div className={styles.hero}>
72-
<Container>
73-
<Row className="d-flex align-items-center">
74-
<Col xs={12} md={7}>
75-
<h1 className="fw-bold display-4 hero-dark-text">
76-
freeCodeCamp 成都社区
77-
</h1>
78-
<p className="fs-5 mt-3 hero-dark-text">
79-
一个友好的技术社区,致力于交流、学习和互助,帮助成都的开发者和技术爱好者提升个人技术能力。
80-
</p>
81-
<div className="mt-4">
82-
<Button
83-
variant="primary"
84-
size="lg"
85-
className="me-3"
86-
href="https://open-source-bazaar.feishu.cn/share/base/form/shrcnUC1stOces9sfPbHbEseep8"
87-
>
88-
加入社区
89-
</Button>
90-
<Button variant="outline-primary" size="lg" href="#">
91-
查看活动
92-
</Button>
93-
</div>
94-
</Col>
95-
<Col
96-
xs={12}
97-
md={5}
98-
className="d-flex justify-content-center mt-5 mt-md-0"
99-
>
100-
<div
101-
className="bg-white rounded-4 d-flex justify-content-center align-items-center"
102-
style={{ width: '25rem', height: '18.75rem' }}
70+
<div className={styles.hero}>
71+
<Container>
72+
<Row className="d-flex align-items-center">
73+
<Col xs={12} md={7}>
74+
<h1 className="fw-bold display-4 hero-dark-text">freeCodeCamp 成都社区</h1>
75+
<p className="fs-5 mt-3 hero-dark-text">
76+
一个友好的技术社区,致力于交流、学习和互助,帮助成都的开发者和技术爱好者提升个人技术能力。
77+
</p>
78+
<div className="mt-4">
79+
<Button
80+
variant="primary"
81+
size="lg"
82+
className="me-3"
83+
href="https://open-source-bazaar.feishu.cn/share/base/form/shrcnUC1stOces9sfPbHbEseep8"
10384
>
104-
<Image
105-
src="https://github.com/FreeCodeCamp-Chengdu.png"
106-
alt="freeCodeCamp Chengdu"
107-
fluid
108-
className="rounded-3"
109-
style={{ maxWidth: '80%', maxHeight: '80%' }}
110-
/>
111-
</div>
112-
</Col>
113-
</Row>
114-
</Container>
115-
</div>
116-
<UpcomingEvents events={upcomingEvents} />
85+
加入社区
86+
</Button>
87+
<Button variant="outline-primary" size="lg" href="/activity">
88+
查看活动
89+
</Button>
90+
</div>
91+
</Col>
92+
<Col xs={12} md={5} className="d-flex justify-content-center mt-5 mt-md-0">
93+
<div
94+
className="bg-white rounded-4 d-flex justify-content-center align-items-center"
95+
style={{ width: '25rem', height: '18.75rem' }}
96+
>
97+
<Image
98+
src="https://github.com/FreeCodeCamp-Chengdu.png"
99+
alt="freeCodeCamp Chengdu"
100+
fluid
101+
className="rounded-3"
102+
style={{ maxWidth: '80%', maxHeight: '80%' }}
103+
/>
104+
</div>
105+
</Col>
106+
</Row>
107+
</Container>
108+
</div>
109+
<UpcomingEvents events={upcomingEvents} />
117110

118-
<LatestBlogs articles={latestArticles} />
111+
<LatestBlogs articles={latestArticles} />
119112

120-
<CommunityStats />
113+
<CommunityStats />
121114

122-
<Sponsors sponsors={sponsors} />
123-
</main>
124-
),
125-
);
115+
<Sponsors sponsors={sponsors} />
116+
</main>
117+
));
126118

127119
export default HomePage;

0 commit comments

Comments
 (0)