footprint/frontend/src/pages/HomePage.js

127 lines
4.3 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { checkinService } from '../services/api';
import CheckinForm from '../components/CheckinForm';
import CheckinList from '../components/CheckinList';
import MapView from '../components/MapView';
const HomePage = ({ user }) => {
const [checkins, setCheckins] = useState([]);
const [stats, setStats] = useState(null);
const [loading, setLoading] = useState(true);
const [view, setView] = useState('list'); // 'list' or 'map'
useEffect(() => {
loadCheckins();
loadStats();
}, []);
const loadCheckins = async () => {
try {
const response = await checkinService.getAll({ limit: 100 });
setCheckins(response.data.checkins);
} catch (error) {
console.error('加载打卡记录失败:', error);
} finally {
setLoading(false);
}
};
const loadStats = async () => {
try {
const response = await checkinService.getStats();
setStats(response.data.stats);
} catch (error) {
console.error('加载统计信息失败:', error);
}
};
const handleCheckinSuccess = (newCheckin) => {
setCheckins([newCheckin, ...checkins]);
loadStats();
};
return (
<div className="min-h-screen bg-gray-50">
{/* 头部 */}
<header className="bg-white shadow-sm">
<div className="max-w-7xl mx-auto px-4 py-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center">
<div>
<h1 className="text-2xl font-bold text-gray-900">📍 Footprint</h1>
<p className="text-sm text-gray-600">你好, {user.username}</p>
</div>
<div className="flex items-center gap-4">
{stats && (
<div className="text-right text-sm">
<p className="text-gray-600">
总打卡: <span className="font-semibold">{stats.total_checkins}</span>
</p>
<p className="text-gray-600">
打卡天数: <span className="font-semibold">{stats.total_days}</span>
</p>
</div>
)}
</div>
</div>
</div>
</header>
{/* 主内容 */}
<main className="max-w-7xl mx-auto px-4 py-8 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* 左侧:打卡表单 */}
<div className="lg:col-span-1">
<CheckinForm onSuccess={handleCheckinSuccess} />
</div>
{/* 右侧:打卡记录或地图 */}
<div className="lg:col-span-2">
<div className="bg-white rounded-lg shadow-sm p-6">
{/* 视图切换 */}
<div className="flex justify-between items-center mb-6">
<h2 className="text-xl font-semibold text-gray-900">我的足迹</h2>
<div className="flex gap-2">
<button
onClick={() => setView('list')}
className={`px-4 py-2 rounded-lg transition-colors ${
view === 'list'
? 'bg-blue-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
列表
</button>
<button
onClick={() => setView('map')}
className={`px-4 py-2 rounded-lg transition-colors ${
view === 'map'
? 'bg-blue-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
地图
</button>
</div>
</div>
{/* 内容区域 */}
{loading ? (
<div className="text-center py-12">
<div className="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
<p className="mt-2 text-gray-600">加载中...</p>
</div>
) : view === 'list' ? (
<CheckinList checkins={checkins} onUpdate={loadCheckins} />
) : (
<MapView checkins={checkins} />
)}
</div>
</div>
</div>
</main>
</div>
);
};
export default HomePage;