s''
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useMemo } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Link, useTranslation } from "@/i18n/navigation";
|
||||
import { apiFetch } from "@/app/lib/api-client";
|
||||
|
||||
interface Attendee {
|
||||
name: string;
|
||||
@@ -42,7 +43,10 @@ const allMeetups: Meetup[] = [
|
||||
const weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
|
||||
|
||||
function formatMeetupDate(dateStr: string, time: string): string {
|
||||
const d = new Date(dateStr + "T" + time);
|
||||
const normalizedDate = dateStr.includes("T") || dateStr.includes(" ")
|
||||
? dateStr.slice(0, 10)
|
||||
: dateStr;
|
||||
const d = new Date(normalizedDate + "T" + time);
|
||||
const weekday = weekdays[d.getDay()];
|
||||
const year = d.getFullYear();
|
||||
const month = d.getMonth() + 1;
|
||||
@@ -51,6 +55,24 @@ function formatMeetupDate(dateStr: string, time: string): string {
|
||||
return `${weekday}, ${year}年${month}月${day}日, ${timeFormatted}`;
|
||||
}
|
||||
|
||||
function mapMeetup(item: Partial<Meetup> & { id: string; status?: string }): Meetup {
|
||||
return {
|
||||
id: item.id,
|
||||
city: item.city || "线上",
|
||||
emoji: item.emoji || "📍",
|
||||
date: item.date || new Date().toISOString().slice(0, 10),
|
||||
time: item.time || "19:00",
|
||||
venue: item.venue || "待定地点",
|
||||
address: item.address || "活动地址确认中",
|
||||
description: item.description || "数字游民同城交流活动。",
|
||||
rsvpCount: Number(item.rsvpCount || 0),
|
||||
gradientFrom: item.gradientFrom || "#ff4d4f",
|
||||
gradientTo: item.gradientTo || "#ff7a45",
|
||||
attendees: Array.isArray(item.attendees) ? item.attendees : [],
|
||||
isUpcoming: Boolean(item.isUpcoming ?? true),
|
||||
};
|
||||
}
|
||||
|
||||
function MeetupCard({ meetup }: { meetup: Meetup }) {
|
||||
const formattedDate = formatMeetupDate(meetup.date, meetup.time);
|
||||
return (
|
||||
@@ -83,8 +105,20 @@ function MeetupCard({ meetup }: { meetup: Meetup }) {
|
||||
export default function MeetupsPage() {
|
||||
const { t } = useTranslation("meetups");
|
||||
const [activeTab, setActiveTab] = useState<"upcoming" | "previous">("upcoming");
|
||||
const upcomingMeetups = useMemo(() => allMeetups.filter((m) => m.isUpcoming), []);
|
||||
const previousMeetups = useMemo(() => allMeetups.filter((m) => !m.isUpcoming), []);
|
||||
const [meetups, setMeetups] = useState<Meetup[]>(allMeetups);
|
||||
|
||||
useEffect(() => {
|
||||
apiFetch<{ items: Array<Partial<Meetup> & { id: string; status?: string }> }>("/api/meetups")
|
||||
.then((data) => {
|
||||
if (data.items?.length) {
|
||||
setMeetups(data.items.map(mapMeetup));
|
||||
}
|
||||
})
|
||||
.catch(() => setMeetups(allMeetups));
|
||||
}, []);
|
||||
|
||||
const upcomingMeetups = useMemo(() => meetups.filter((m) => m.isUpcoming), [meetups]);
|
||||
const previousMeetups = useMemo(() => meetups.filter((m) => !m.isUpcoming), [meetups]);
|
||||
const displayedMeetups = activeTab === "upcoming" ? upcomingMeetups : previousMeetups;
|
||||
const totalCount = activeTab === "upcoming" ? upcomingMeetups.length : previousMeetups.length;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user