diff --git a/lib/data/models/plan_acttion_type.dart b/lib/data/models/plan_acttion_type.dart index 5e493f5..f84723d 100644 --- a/lib/data/models/plan_acttion_type.dart +++ b/lib/data/models/plan_acttion_type.dart @@ -2,7 +2,8 @@ enum PlanActionType { delete(1), //删除 complete(2), //完成 edit(3), //编辑 - completeAll(99); //全部完成 + completeAll(99), //全部完成 + cancelAll(88); //全部未完成 final int value; diff --git a/lib/page/plan/detail/other/footer_btn.dart b/lib/page/plan/detail/other/footer_btn.dart new file mode 100644 index 0000000..6e47b83 --- /dev/null +++ b/lib/page/plan/detail/other/footer_btn.dart @@ -0,0 +1,92 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:plan/api/endpoints/plan_api.dart'; +import 'package:plan/data/models/plan_acttion_type.dart'; +import 'package:plan/page/plan/detail/viewmodel/plan_detail_store.dart'; +import 'package:provider/provider.dart'; +import 'package:remixicon/remixicon.dart'; + +class FooterBtn extends StatefulWidget { + const FooterBtn({super.key}); + + @override + State createState() => _FooterBtnState(); +} + +class _FooterBtnState extends State { + ///切换全部完成、或者全部不完成 + void _toggleAllDone() { + final store = context.read(); + final allDone = store.planDetail.stepsList.every((item) => item.stepStatus == 2); + //刷新ui + store.updatePlanDetail((dto) { + dto.stepsList = store.planDetail.stepsList.map((item) { + return item.copyWith(stepStatus: allDone ? 0 : 2); + }).toList(); + }); + //接口 + editPlanStepApi( + store.planId, + act: allDone ? PlanActionType.cancelAll : PlanActionType.completeAll, + ); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, store, _) { + bool oneDone = store.planDetail.stepsList.any((item) => item.stepStatus == 2); + //是否全部完成 + bool allDone = store.planDetail.stepsList.every((item) => item.stepStatus == 2); + return AnimatedSize( + duration: Duration(milliseconds: 300), + child: Container( + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15), + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: Theme.of(context).colorScheme.surfaceContainerLow, + // color: CupertinoColors., + ), + ), + ), + height: oneDone ? null : 0, + child: GestureDetector( + onTap: _toggleAllDone, + child: Container( + height: 45, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.white, + border: Border.all(color: Colors.black), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 10, + children: [ + Visibility( + visible: !allDone, + replacement: Icon( + CupertinoIcons.refresh_circled, + size: 20, + ), + child: Icon( + CupertinoIcons.checkmark_circle_fill, + color: Colors.green, + size: 20, + ), + ), + Text( + allDone ? "Try again" : "All done!", + style: TextStyle(fontWeight: FontWeight.w700), + ), + ], + ), + ), + ), + ), + ); + }, + ); + } +} diff --git a/lib/page/plan/detail/plan_detail_page.dart b/lib/page/plan/detail/plan_detail_page.dart index 0fb825f..6133fb3 100644 --- a/lib/page/plan/detail/plan_detail_page.dart +++ b/lib/page/plan/detail/plan_detail_page.dart @@ -5,6 +5,7 @@ import 'package:plan/theme/decorations/app_shadows.dart'; import 'package:provider/provider.dart'; import 'other/bar_actions.dart'; +import 'other/footer_btn.dart'; import 'widgets/avatar_card.dart'; import 'widgets/coach_message.dart'; import 'widgets/plan_list.dart'; @@ -27,7 +28,6 @@ class PlanDetailPage extends StatefulWidget { class _PlanDetailPageState extends State { final ScrollController scrollController = ScrollController(); - ///store对象 late PlanDetailStore store; @@ -54,18 +54,25 @@ class _PlanDetailPageState extends State { AvatarCard(), Expanded( child: Padding( - padding: EdgeInsets.all(15), - child: ScrollBox( - child: Container( - decoration: shadowDecoration, - child: Column( - children: [ - CoachMessage(), - PlanList(), - SuggestedTitle(), - SuggestedList(), - ], - ), + padding: EdgeInsets.only(left: 15, right: 15, bottom: 1), + child: Container( + decoration: shadowDecoration, + child: Column( + children: [ + Expanded( + child: ScrollBox( + child: Column( + children: [ + CoachMessage(), + PlanList(), + SuggestedTitle(), + SuggestedList(), + ], + ), + ), + ), + FooterBtn() + ], ), ), ), diff --git a/lib/page/plan/detail/widgets/avatar_card.dart b/lib/page/plan/detail/widgets/avatar_card.dart index 70fa6f6..6198534 100644 --- a/lib/page/plan/detail/widgets/avatar_card.dart +++ b/lib/page/plan/detail/widgets/avatar_card.dart @@ -100,7 +100,11 @@ class _AvatarCardState extends State with SingleTickerProviderStateM borderRadius: BorderRadius.circular(3), border: Border.all(color: Colors.black, width: 1), ), - child: Text(_dialog, style: TextStyle(fontSize: 12)), + child: Text( + _dialog, + style: TextStyle(fontSize: 12), + textAlign: TextAlign.center, + ), ), Positioned( bottom: 0, @@ -200,11 +204,11 @@ class BothSizeTransition extends StatelessWidget { animation: animation, builder: (_, child) { return Align( - alignment: Alignment(0.7, 1), + alignment: Alignment(0.3, 1), child: Opacity( opacity: animation.value, child: Transform( - alignment: Alignment(0.5, 1), + alignment: Alignment(0, 1), transform: Matrix4.identity() ..translate( offset.dx * (1 - animation.value), diff --git a/lib/page/plan/detail/widgets/scroll_box.dart b/lib/page/plan/detail/widgets/scroll_box.dart index 5c95ee0..e70f15a 100644 --- a/lib/page/plan/detail/widgets/scroll_box.dart +++ b/lib/page/plan/detail/widgets/scroll_box.dart @@ -24,6 +24,7 @@ class ScrollBox extends StatelessWidget { ), child: Scrollbar( child: SingleChildScrollView( + physics: const BouncingScrollPhysics(), child: child, ), ), diff --git a/lib/theme/decorations/app_shadows.dart b/lib/theme/decorations/app_shadows.dart index 143ab92..4660fa4 100644 --- a/lib/theme/decorations/app_shadows.dart +++ b/lib/theme/decorations/app_shadows.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; ///阴影卡片 final shadowDecoration = BoxDecoration( - border: Border.all(color: Colors.black, width: 2), + border: Border.all(color: Colors.black, width: 1.5), borderRadius: BorderRadius.circular(5), color: Colors.white, boxShadow: const [