248 lines
7.2 KiB
Dart
248 lines
7.2 KiB
Dart
import 'package:easy_refresh/easy_refresh.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_common/widget/common_widget.dart';
|
|
import 'package:food_hub_app/provider/food_provider.dart';
|
|
import 'package:food_hub_app/views/moment_form.dart';
|
|
import 'package:food_hub_app/views/record_form.dart';
|
|
import 'package:food_hub_app/widgets/common/easy_refresh.dart';
|
|
import 'package:food_hub_app/widgets/common/index.dart';
|
|
import 'package:food_hub_app/widgets/recipe/calendar.dart';
|
|
import 'package:food_hub_app/widgets/recipe/list.dart';
|
|
import 'package:food_hub_app/widgets/recipe/timeline.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
enum RecordTab {
|
|
recipe('菜谱'),
|
|
calendar('日历'),
|
|
timeline('时间轴');
|
|
|
|
final String label;
|
|
|
|
const RecordTab(this.label);
|
|
}
|
|
|
|
class RecordPage extends StatefulWidget {
|
|
const RecordPage({super.key});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _RecordPageState();
|
|
}
|
|
|
|
class _RecordPageState extends State<RecordPage> {
|
|
final EasyRefreshController _freshController = EasyRefreshController(
|
|
controlFinishRefresh: true,
|
|
controlFinishLoad: true,
|
|
);
|
|
final ScrollController _scrollController = ScrollController();
|
|
bool _showScrollToTop = false;
|
|
final List<Widget> _tabPages = [
|
|
RecipeList(),
|
|
RecipeCalendar(),
|
|
RecipeTimeline(),
|
|
];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_scrollController.addListener(_onScroll);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_scrollController.removeListener(_onScroll);
|
|
_freshController.dispose();
|
|
_scrollController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
// 下拉刷新
|
|
Future<void> _onRefresh() async {
|
|
_freshController.finishRefresh();
|
|
}
|
|
|
|
// 上拉加载
|
|
Future<void> _onLoad() async {
|
|
final provider = context.read<FoodProvider>();
|
|
if (provider.hasMore) {
|
|
await provider.refreshFoodStats();
|
|
_freshController.finishLoad(IndicatorResult.success);
|
|
} else {
|
|
_freshController.finishLoad(IndicatorResult.noMore);
|
|
}
|
|
}
|
|
|
|
void _onScroll() {
|
|
// 当滚动距离超过时显示返回顶部按钮
|
|
if (_scrollController.offset > 100) {
|
|
if (!_showScrollToTop) {
|
|
setState(() {
|
|
_showScrollToTop = true;
|
|
});
|
|
}
|
|
} else {
|
|
if (_showScrollToTop) {
|
|
setState(() {
|
|
_showScrollToTop = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// 滚动到顶部
|
|
void _scrollToTop() => scrollToTopAnimateTo(_scrollController);
|
|
|
|
Widget _buildTabs({
|
|
required BuildContext context,
|
|
required RecordTab currentTab,
|
|
required ValueChanged<RecordTab> onTabChanged,
|
|
}) {
|
|
return Container(
|
|
padding: EdgeInsets.all(8),
|
|
child: buildToggleSwitch(
|
|
context: context,
|
|
currentTab: currentTab,
|
|
tabValues: RecordTab.values,
|
|
labels: RecordTab.values.map((e) => e.label).toList(),
|
|
onTabChanged: onTabChanged,
|
|
),
|
|
);
|
|
}
|
|
|
|
void _onTabChange(RecordTab tab, FoodProvider provider) {
|
|
provider.currentRecordTab = tab;
|
|
provider.onRecordTabChange();
|
|
}
|
|
|
|
void _handleAddRecord(FoodProvider provider) {
|
|
provider.resetRecordForm();
|
|
provider.isEditing = false;
|
|
Navigator.pop(context);
|
|
|
|
showModalBottomSheet(
|
|
context: context,
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
isScrollControlled: true,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
|
),
|
|
builder: (context) => RecordForm(),
|
|
);
|
|
}
|
|
|
|
void _handleAddMoment(FoodProvider provider) {
|
|
provider.resetMomentForm();
|
|
provider.isEditing = false;
|
|
Navigator.pop(context);
|
|
|
|
showModalBottomSheet(
|
|
context: context,
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
isScrollControlled: true,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
|
),
|
|
builder: (context) => MomentForm(),
|
|
);
|
|
}
|
|
|
|
void _onPressAdd(FoodProvider provider) {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
|
),
|
|
builder:
|
|
(context) => Padding(
|
|
padding: EdgeInsetsGeometry.symmetric(horizontal: 0, vertical: 8),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const SizedBox(height: 8),
|
|
Text('请选择操作', style: Theme.of(context).textTheme.titleLarge),
|
|
const SizedBox(height: 10),
|
|
ListTile(
|
|
leading: Icon(
|
|
Icons.book,
|
|
color: Theme.of(context).colorScheme.primary,
|
|
),
|
|
title: Text(
|
|
'新增菜谱',
|
|
style: Theme.of(context).textTheme.bodyLarge,
|
|
),
|
|
onTap: () => {},
|
|
),
|
|
ListTile(
|
|
leading: Icon(
|
|
Icons.note_add,
|
|
color: Theme.of(context).colorScheme.primary,
|
|
),
|
|
title: Text(
|
|
'新增记录',
|
|
style: Theme.of(context).textTheme.bodyLarge,
|
|
),
|
|
onTap: () => _handleAddRecord(provider),
|
|
),
|
|
ListTile(
|
|
leading: Icon(
|
|
Icons.group,
|
|
color: Theme.of(context).colorScheme.primary,
|
|
),
|
|
title: Text(
|
|
'发布朋友圈',
|
|
style: Theme.of(context).textTheme.bodyLarge,
|
|
),
|
|
onTap: () => _handleAddMoment(provider),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final provider = context.watch<FoodProvider>();
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.transparent,
|
|
appBar: AppBar(
|
|
elevation: 0,
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
title: Text('记录', style: Theme.of(context).textTheme.titleLarge),
|
|
centerTitle: true,
|
|
leading: Builder(
|
|
builder:
|
|
(context) => IconButton(
|
|
icon: Icon(Icons.menu, color: Theme.of(context).primaryColor),
|
|
onPressed: () => {},
|
|
),
|
|
),
|
|
actions: [
|
|
IconButton(
|
|
icon: Icon(Icons.search, color: Theme.of(context).primaryColor),
|
|
onPressed: () {},
|
|
),
|
|
IconButton(
|
|
icon: Icon(Icons.add, color: Theme.of(context).primaryColor),
|
|
onPressed: () => _onPressAdd(provider),
|
|
),
|
|
],
|
|
),
|
|
body: Padding(
|
|
padding: const EdgeInsets.all(10),
|
|
child: Column(
|
|
children: [
|
|
_buildTabs(
|
|
context: context,
|
|
currentTab: provider.currentRecordTab,
|
|
onTabChanged: (tab) => _onTabChange(tab, provider),
|
|
),
|
|
Expanded(child: _tabPages[provider.currentRecordTab.index]),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|