MIRROR/src/app/page.tsx
LIRUI 012715ee81
Some checks failed
部署 Next.js 站点到 Gitea / deploy (push) Has been cancelled
0228.6
2025-02-28 23:49:57 +08:00

130 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
/**
* 魔镜主页面src\app\page.tsx
* 集成所有子组件并管理主要状态
*/
import { useState, useEffect, useMemo } from "react";
import AnalogClock from "../components/AnalogClock";
import CalendarGrid from "../components/CalendarGrid";
import WeatherSection from "../components/WeatherSection";
import NewsSection from "../components/NewsSection";
import { generateCalendarDays } from "@/utils/calendar";
import { WeatherData, NewsItem, SunData } from "@/types/magic-mirror";
import VoiceAssistant from "@/components/VoiceAssistant";
import useSWR from "swr";
// 定义通用数据获取器
const fetcher = (url: string) => fetch(url).then((res) => res.json());
const MagicMirror = () => {
const [time, setTime] = useState(new Date());
const calendarDays = useMemo(() => generateCalendarDays(), []);
// 天气示例数据
const { data: weatherData, error: weatherError } = useSWR<WeatherData>(
"/api/weather",
(url: string) => fetch(url).then((res) => res.json())
);
// 新闻数据
const { data: newsItems = [], error: newsError } = useSWR<NewsItem[]>(
"/api/news",
(url: string) => fetch(url).then((res) => res.json())
);
// 在组件顶部新增SWR请求
// 日出日落数据
const { data: sunData = [] } = useSWR<SunData[]>("/api/sun", fetcher);
// 合并天气数据和日出日落数据
const mergedWeatherData = useMemo(() => {
if (weatherData && sunData.length > 0) {
return {
...weatherData,
sunrise: sunData[0]?.sunrise || "06:00",
sunset: sunData[0]?.sunset || "18:00",
};
}
return weatherData;
}, [weatherData, sunData]);
// 时间更新
useEffect(() => {
const timer = setInterval(() => setTime(new Date()), 1000);
return () => clearInterval(timer);
}, []);
// 生成问候语
const greeting = useMemo(() => {
const hours = time.getHours();
if (hours < 5) return "夜深了";
if (hours < 12) return "早上好";
if (hours < 18) return "下午好";
return "晚上好";
}, [time]);
return (
<div className="min-h-screen bg-black text-gray-100 font-sans antialiased overflow-hidden">
{/* 左上角时间模块 */}
<div className="absolute top-8 left-8 flex items-start gap-8">
{/* 时间日期模块 */}
<div className="space-y-1">
<div className="text-2xl font-light">
{time.toLocaleDateString("zh-CN", { weekday: "long" })}
</div>
<div className="text-gray-400 text-sm">
{time.toLocaleDateString("zh-CN", {
year: "numeric",
month: "long",
day: "numeric",
})}
</div>
<div className="flex items-end gap-2">
<div className="text-5xl font-light">
{time.toLocaleTimeString("zh-CN", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
})}
</div>
<div className="text-gray-400 mb-5">
{time.getSeconds().toString().padStart(2, "0")}
</div>
</div>
</div>
<AnalogClock time={time} />
</div>
{/* 日历模块 */}
<div className="absolute top-48 left-8 w-64">
<div className="mb-4 text-gray-300 text-sm">
{time.toLocaleDateString("zh-CN", { month: "long", year: "numeric" })}
</div>
<CalendarGrid days={calendarDays} />
</div>
{/* 分隔线 */}
<div className="absolute left-8 w-64 top-[420px] border-t border-white/10" />
{/* 待办事项 */}
<div className="absolute left-8 w-64 top-[460px] space-y-2 font-light">
<div className="text-gray-400 text-sm"></div>
<div className="text-gray-300 space-y-1">
<div> 10:00</div>
<div> </div>
<div> </div>
</div>
</div>
{/*<WeatherSection data={weatherData} />*/}
<WeatherSection data={mergedWeatherData} />
<NewsSection items={newsItems} />
<VoiceAssistant greeting={greeting} />
</div>
);
};
export default MagicMirror;