import 'package:flutter/material.dart'; import "package:flutter_staggered_grid_view/flutter_staggered_grid_view.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; if (_timeFilter == '今天') { return DateUtils.isSameDay(a.time, DateTime.now()); } if (_timeFilter == '明天') { final tomorrow = DateTime.now().add(const Duration(days: 1)); return DateUtils.isSameDay(a.time, tomorrow); } return true; }).toList(); } @override Widget build(BuildContext context) { final filteredActivities = _filteredActivities; 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: [ SliverList( delegate: SliverChildListDelegate([ 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(), ), ), 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(), ), ), ]), ), SliverPadding( padding: const EdgeInsets.all(12), sliver: SliverMasonryGrid.count( crossAxisCount: 2, mainAxisSpacing: 10, crossAxisSpacing: 10, childCount: filteredActivities.length, itemBuilder: (ctx, i) => _ActivityCard( key: ValueKey(filteredActivities[i].id), activity: filteredActivities[i], onTap: () => Navigator.push( context, MaterialPageRoute( builder: (_) => ActivityDetailScreen( activity: filteredActivities[i], ), ), ), ), ), ), 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 StatefulWidget { final Activity activity; final VoidCallback onTap; const _ActivityCard({ super.key, required this.activity, required this.onTap, }); @override State<_ActivityCard> createState() => _ActivityCardState(); } class _ActivityCardState extends State<_ActivityCard> { bool _isJoined = false; void _joinActivity() { setState(() => _isJoined = true); ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar(const SnackBar(content: Text("报名成功!"))); } @override Widget build(BuildContext context) { final activity = widget.activity; final canJoin = !activity.isFull && !_isJoined; final imageHeight = activity.id.hashCode.isOdd ? 160.0 : 210.0; return Material( color: Colors.transparent, child: Ink( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.06), blurRadius: 6, offset: const Offset(0, 2), ), ], ), child: InkWell( onTap: widget.onTap, borderRadius: BorderRadius.circular(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), child: Image.network( "https://picsum.photos/seed/${activity.title.hashCode.abs()}/400/300", height: imageHeight, width: double.infinity, fit: BoxFit.cover, errorBuilder: (_, __, ___) => Container( height: imageHeight, color: const Color(0xFFE0E0E0), ), ), ), Padding( padding: const EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( activity.title, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w700, color: Color(0xFF333333), ), ), const SizedBox(height: 4), Row( children: [ CircleAvatar( radius: 10, backgroundImage: NetworkImage( "https://i.pravatar.cc/40?img=${activity.category.hashCode.abs() % 40 + 1}", ), ), const SizedBox(width: 4), Text( activity.category, style: const TextStyle( fontSize: 12, color: Color(0xFF999999), ), ), const Spacer(), Text( "${activity.currentParticipants}人", style: const TextStyle( fontSize: 12, color: Color(0xFFFF6B35), ), ), ], ), const SizedBox(height: 8), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: canJoin ? _joinActivity : null, style: ElevatedButton.styleFrom( minimumSize: const Size.fromHeight(36), backgroundColor: const Color(0xFF1976D2), foregroundColor: Colors.white, disabledBackgroundColor: const Color(0xFFE0E0E0), disabledForegroundColor: const Color(0xFF999999), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), textStyle: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, ), padding: EdgeInsets.zero, ), child: Text( _isJoined ? "已报名" : activity.isFull ? "已满员" : "报名", ), ), ), ], ), ), ], ), ), ), ); } }