Skip to content

Commit 6663484

Browse files
committed
Created a calendar section pulling RSS
1 parent 44450b4 commit 6663484

File tree

5 files changed

+95
-2
lines changed

5 files changed

+95
-2
lines changed

package-lock.json

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"react": "^19.2.0",
2727
"react-dom": "^19.2.0",
2828
"react-icons": "^5.5.0",
29-
"tailwindcss": "^4.1.17"
29+
"tailwindcss": "^4.1.17",
30+
"xml-js": "^1.6.11"
3031
},
3132
"devDependencies": {
3233
"@eslint/js": "^9.39.1",

src/components/Calendar.astro

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
import EventList from '../components/EventList.jsx';
3+
const RSS_URL = "https://www.meetup.com/Kyoto-Tech-Meetup/events/rss/";
4+
5+
const rssResponse = await fetch(RSS_URL);
6+
const rssText = await rssResponse.text();
7+
8+
// Minimal XML → JS parser
9+
import { xml2js } from "xml-js";
10+
const parsed = xml2js(rssText, { compact: true });
11+
let eventNames = [];
12+
13+
if (Array.isArray(parsed.rss.channel.item)) {
14+
console.log(parsed.rss.channel.item[0]);
15+
const items = parsed.rss.channel.item.map(evt => ({
16+
title: evt.title._cdata,
17+
link: evt.link._text,
18+
pubDate: evt.pubDate._text,
19+
description: evt.description?._text ?? "",
20+
}));
21+
22+
23+
eventNames = items;
24+
25+
} else {
26+
// handle the case where it's a single item object
27+
console.log(parsed.rss.channel.item.title);
28+
}
29+
30+
console.log(eventNames);
31+
32+
---
33+
34+
<section class="p-6">
35+
36+
<EventList client:load events={eventNames} />
37+
38+
</section>
39+

src/components/EventList.jsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export default function EventList({ events }) {
2+
return (
3+
<ul className="space-y-6">
4+
{events.map(event => (
5+
<li key={event.link} className="p-4 border rounded-xl shadow-sm">
6+
<a
7+
href={event.link}
8+
target="_blank"
9+
rel="noopener noreferrer"
10+
className="text-xl font-semibold text-blue-600 hover:underline"
11+
>
12+
{event.title}
13+
</a>
14+
<p className="text-sm text-gray-500 mt-1">
15+
{new Date(event.pubDate).toLocaleString()}
16+
</p>
17+
<div
18+
className="prose prose-sm mt-2"
19+
dangerouslySetInnerHTML={{ __html: event.description }}
20+
/>
21+
</li>
22+
))}
23+
</ul>
24+
);
25+
}

src/pages/index.astro

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import Layout from "../layouts/Layout.astro";
33
import WhyJoin from "../components/WhyJoin.astro";
44
import WhatWeDo from "../components/WhatWeDo.astro";
5+
import Calendar from "../components/Calendar.astro";
6+
import EventList from "../components/EventList.jsx";
57
import { FaGithub, FaDiscord, FaMeetup } from "react-icons/fa";
68
79
type ActivityContent =
@@ -125,6 +127,19 @@ const activities: Activity[] = [
125127
</div>
126128
</section>
127129

130+
<section id="calendar" class="bg-white px-6 py-16 md:px-12">
131+
<div class="mx-auto max-w-5xl">
132+
<p class="text-sm font-semibold uppercase tracking-[0.3em] text-slate-500">
133+
Upcoming Meetups
134+
</p>
135+
<h2 class="mt-3 text-3xl font-semibold text-slate-900">
136+
Kyoto Tech Meetup Calendar
137+
</h2>
138+
139+
<Calendar />
140+
</div>
141+
</section>
142+
128143
<section id="who-comes" class="bg-white/95 px-6 py-16 md:px-12">
129144
<div class="mx-auto flex max-w-5xl flex-col gap-10 lg:flex-row">
130145
<div class="flex-1">

0 commit comments

Comments
 (0)