Files
food_hub_app/lib/widgets/recipe/timeline.dart
2026-06-27 17:12:38 +08:00

116 lines
3.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_common/widget/common_widget.dart';
import 'package:flutter_common/widget/year_selector.dart';
import 'package:food_hub_app/models/recipe.dart';
import 'package:food_hub_app/provider/food_provider.dart';
import 'package:food_hub_app/widgets/common/image.dart';
import 'package:timelines_plus/timelines_plus.dart';
import 'package:provider/provider.dart';
class RecipeTimeline extends StatefulWidget {
const RecipeTimeline({super.key});
@override
State<StatefulWidget> createState() => _RecipeTimeline();
}
class _RecipeTimeline extends State<RecipeTimeline> {
Widget buildTimelineCard(BuildContext context, FoodRecord record) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.date_range,
color: Theme.of(context).colorScheme.primary,
),
SizedBox(width: 5),
Text(
record.date,
style: Theme.of(context).textTheme.titleMedium,
),
],
),
SizedBox(height: 8),
CommonCard(
child: Column(
children: [
Text(
record.name,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 5),
CommonImage(imageUrls: [record.imageUrl], index: 0),
],
),
),
SizedBox(height: 20)
],
);
}
Widget buildTimeline(BuildContext context, List<FoodRecord> recordList) {
if (recordList.isEmpty) {
return buildEmptyData();
} else {
final colors = Theme.of(context).colorScheme;
return Timeline.tileBuilder(
padding: const EdgeInsets.only(bottom: 80),
theme: TimelineThemeData(nodePosition: 0, indicatorPosition: 0),
builder: TimelineTileBuilder.connected(
itemCount: recordList.length,
connectorBuilder:
(context, index, type) =>
Connector.solidLine(thickness: 2, color: colors.primary),
indicatorBuilder: (context, index) {
return Indicator.dot(size: 12.0, color: colors.primary);
},
contentsBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 8),
child: buildTimelineCard(context, recordList[index]),
);
},
),
);
}
}
Widget _buildContent(FoodProvider provider) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
YearSelector(
currentYear: provider.selectYear,
onYearChanged: (year) {
provider.selectYear = year;
provider.refreshRecordList();
},
),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 10),
child: buildTimeline(context, provider.recordList),
),
),
],
);
}
@override
Widget build(BuildContext context) {
final provider = context.watch<FoodProvider>();
return Stack(
children: [
if (provider.isLoading)
buildLoadingIndicator()
else
_buildContent(provider),
],
);
}
}