import 'package:flutter/material.dart'; import '../models/activity.dart'; import '../services/activity_service.dart'; import '../utils/constants.dart'; import 'activity_detail_screen.dart'; import 'create_activity_screen.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { String _selectedCategory = '全部'; String _timeFilter = '全部'; List _activities = []; bool _loading = true; @override void initState() { super.initState(); _loadActivities(); } void _loadActivities() { setState(() { _activities = ActivityService.getMockActivities(); _loading = false; }); } List get _filteredActivities { return _activities.where((a) { if (_selectedCategory != '全部' && a.category != _selectedCategory) return false; return true; }).toList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.location_on, size: 18, color: Color(0xFF1976D2)), const SizedBox(width: 4), const Text('成都', style: TextStyle(fontSize: 16, color: Color(0xFF666666))), const SizedBox(width: 16), Expanded( child: Container( height: 36, decoration: BoxDecoration( color: const Color(0xFFF5F5F5), borderRadius: BorderRadius.circular(18), ), child: const Row( children: [ SizedBox(width: 12), Icon(Icons.search, size: 20, color: Color(0xFF999999)), SizedBox(width: 8), Text('搜索活动', style: TextStyle(fontSize: 14, color: Color(0xFF999999))), ], ), ), ), ], ), ), body: _loading ? const Center(child: CircularProgressIndicator()) : RefreshIndicator( onRefresh: () async => _loadActivities(), child: CustomScrollView( slivers: [ // Category chips SliverToBoxAdapter( child: SizedBox( height: 48, child: ListView( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), children: AppConstants.activityCategories.map((cat) { final selected = _selectedCategory == cat; return Padding( padding: const EdgeInsets.only(right: 8), child: ChoiceChip( label: Text(cat, style: TextStyle(fontSize: 14, color: selected ? Colors.white : const Color(0xFF666666))), selected: selected, selectedColor: const Color(0xFF1976D2), backgroundColor: const Color(0xFFF5F5F5), onSelected: (_) => setState(() => _selectedCategory = cat), ), ); }).toList(), ), ), ), // Time filter SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( children: ['全部', '今天', '明天', '本周'].map((t) { final selected = _timeFilter == t; return Padding( padding: const EdgeInsets.only(right: 12), child: GestureDetector( onTap: () => setState(() => _timeFilter = t), child: Text(t, style: TextStyle( fontSize: 16, color: selected ? const Color(0xFF1976D2) : const Color(0xFF999999), fontWeight: selected ? FontWeight.w600 : FontWeight.normal, )), ), ); }).toList(), ), ), ), // Activity list SliverList( delegate: SliverChildBuilderDelegate( (ctx, i) => _ActivityCard( activity: _filteredActivities[i], onTap: () => Navigator.push(context, MaterialPageRoute( builder: (_) => ActivityDetailScreen(activity: _filteredActivities[i]), )), ), childCount: _filteredActivities.length, ), ), const SliverToBoxAdapter(child: SizedBox(height: 80)), ], ), ), floatingActionButton: FloatingActionButton.extended( onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const CreateActivityScreen())), icon: const Icon(Icons.add), label: const Text('发起活动', style: TextStyle(fontSize: 16)), backgroundColor: const Color(0xFF1976D2), foregroundColor: Colors.white, ), ); } } class _ActivityCard extends StatelessWidget { final Activity activity; final VoidCallback onTap; const _ActivityCard({required this.activity, required this.onTap}); String _categoryEmoji(String cat) { const map = {'太极':'🧘','茶话会':'🍵','书法':'✍️','摄影':'📷','舞蹈':'💃','户外徒步':'🥾','手工':'🎨','唱歌':'🎵','棋牌':'♟️','读书':'📚','晨练':'🏃'}; return map[cat] ?? '🎯'; } @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(16), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text(_categoryEmoji(activity.category), style: const TextStyle(fontSize: 24)), const SizedBox(width: 8), Expanded(child: Text(activity.title, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600), maxLines: 1, overflow: TextOverflow.ellipsis)), ], ), const SizedBox(height: 12), Row( children: [ const Icon(Icons.access_time, size: 16, color: Color(0xFF999999)), const SizedBox(width: 4), Text(activity.timeDisplay, style: const TextStyle(fontSize: 16, color: Color(0xFF666666))), const SizedBox(width: 16), const Icon(Icons.location_on_outlined, size: 16, color: Color(0xFF999999)), const SizedBox(width: 4), Text(activity.distance != null ? '距你${activity.distance}km' : '', style: const TextStyle(fontSize: 16, color: Color(0xFF666666))), ], ), const SizedBox(height: 12), Row( children: [ Expanded( child: Text( '已报名 ${activity.currentParticipants}/${activity.maxParticipants}人', style: TextStyle( fontSize: 16, color: activity.isFull ? const Color(0xFFF44336) : const Color(0xFF4CAF50), fontWeight: FontWeight.w500, ), ), ), SizedBox( height: 40, child: ElevatedButton( onPressed: activity.isFull ? null : () {}, style: ElevatedButton.styleFrom( minimumSize: const Size(80, 40), padding: const EdgeInsets.symmetric(horizontal: 20), ), child: Text(activity.isFull ? '已满员' : '报名', style: const TextStyle(fontSize: 16)), ), ), ], ), ], ), ), ), ); } }