import 'package:flutter/material.dart'; import 'package:flutter_common/widget/common_widget.dart'; import 'package:food_hub_app/models/recipe.dart'; import 'package:food_hub_app/provider/food_provider.dart'; import 'package:food_hub_app/utils/index.dart'; import 'package:food_hub_app/views/record_form.dart'; import 'package:food_hub_app/widgets/common/index.dart'; import 'package:table_calendar/table_calendar.dart'; import 'package:provider/provider.dart'; class RecipeCalendar extends StatefulWidget { const RecipeCalendar({super.key}); @override State createState() => _RecipeCalendarState(); } class _RecipeCalendarState extends State { TableCalendar _recipeCalendar(FoodProvider provider) { return TableCalendar( locale: 'zh_CN', headerStyle: const HeaderStyle( headerPadding: EdgeInsets.symmetric(vertical: 0), formatButtonVisible: false, titleCentered: true, ), firstDay: DateTime.utc(2010, 1, 1), lastDay: DateTime.utc(2100, 12, 31), focusedDay: provider.focusedDay, selectedDayPredicate: (day) => isSameDay(provider.selectedDay, day), onDaySelected: (selectedDay, focusedDay) { if (!isSameDay(provider.selectedDay, selectedDay)) { setState(() { provider.selectedDay = selectedDay; provider.focusedDay = focusedDay; provider.refreshSelectRecord(); }); } }, onPageChanged: (focusedDay) { provider.focusedDay = focusedDay; provider.refreshRecordList(); }, // 自定义日期单元格构建器 calendarBuilders: CalendarBuilders( defaultBuilder: (context, day, focusedDay) => _buildDateItem(day, false, false, provider), selectedBuilder: (context, day, focusedDay) => _buildDateItem(day, true, false, provider), todayBuilder: (context, day, focusedDay) => _buildDateItem(day, false, true, provider), ), ); } Widget _dailyItem(BuildContext context, FoodProvider provider) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(formatDateTime(provider.selectedDay, 'MM月dd日 EEEE')), SizedBox(height: 4), if (provider.selectRecordList.isEmpty) SizedBox(height: 100, child: buildEmptyData()) else Column( children: provider.selectRecordList.map((record) { return Padding( padding: const EdgeInsets.only(bottom: 8), child: _buildRecordItem(context, record), ); }).toList(), ), ], ); } Widget _buildRecordItemAvatar(String name, Color color) { return CircleAvatar( radius: 20, backgroundColor: color, child: Text( name, style: TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), ); } Widget _buildRecordItemBody(String name, String category) { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(name, style: TextStyle(fontWeight: FontWeight.bold)), SizedBox(height: 5), Text(category, style: TextStyle(color: Colors.grey)), ], ); } void _handleEditRecord(BuildContext context, FoodRecord record) { final provider = context.read(); provider.initRecordForm(record); provider.isEditing = true; showModalBottomSheet( context: context, isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), builder: (context) => RecordForm(), ); } Widget _buildRecordItem(BuildContext context, FoodRecord record) { final colors = Theme.of(context).colorScheme; return Card( elevation: 0, color: colors.primary.withAlpha(50), margin: EdgeInsets.zero, child: Padding( padding: EdgeInsets.all(10), child: Row( children: [ _buildRecordItemAvatar(record.category[0], colors.primary), SizedBox(width: 10), Expanded(child: _buildRecordItemBody(record.name, record.category)), circleIconButton( context: context, icon: Icons.chevron_right, onPressed: () => _handleEditRecord(context, record), ), ], ), ), ); } Widget _buildDateItem( DateTime day, bool isSelected, bool isToday, FoodProvider provider, ) { final colors = Theme.of(context).colorScheme; // 检查当前日期是否在需要显示红点的列表中 bool shouldShowRedDot = provider.recordList.any( (item) => item.date == formatDateTime(day), ); late Color boxColor; if (isSelected) { boxColor = colors.secondary; } else { boxColor = isToday ? colors.primary : Colors.transparent; } late Color textColor; if (isSelected) { textColor = colors.surface; } else { textColor = isToday ? colors.surface : colors.onSurface; } return Container( width: 40, height: 40, decoration: BoxDecoration(color: boxColor, shape: BoxShape.circle), child: Stack( alignment: Alignment.center, children: [ // 日期数字始终居中 Text(day.day.toString(), style: TextStyle(color: textColor)), // 红点 if (shouldShowRedDot) Align( alignment: Alignment(0, 0.8), child: Container( width: 6, height: 6, decoration: BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), ), ), ], ), ); } Widget _buildContent(FoodProvider provider) { return SingleChildScrollView( padding: const EdgeInsets.only(bottom: 80), child: Column( children: [ CommonCard(child: _recipeCalendar(provider)), const SizedBox(height: 8), CommonCard(child: _dailyItem(context, provider)), ], ), ); } @override Widget build(BuildContext context) { final provider = context.watch(); if (provider.isLoading) { return buildLoadingIndicator(); } return _buildContent(provider); } }