diff --git a/lib/layout/layout_page.dart b/lib/layout/layout_page.dart index 3d37a2a..cb21e75 100644 --- a/lib/layout/layout_page.dart +++ b/lib/layout/layout_page.dart @@ -1,9 +1,14 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import 'package:remixicon/remixicon.dart'; import '../page/home/home_page.dart'; import '../page/profile/my/my_page.dart'; import '../page/record/list/record_list_page.dart'; +import '../providers/user_store.dart'; +import '../router/config/route_paths.dart'; import 'tabbar.dart'; class LayoutPage extends StatefulWidget { @@ -41,6 +46,44 @@ class _LayoutPageState extends State { ), ]; + @override + void initState() { + super.initState(); + _init(); + } + + void _init() async { + UserStore userStore = context.read(); + await userStore.init(); + print(userStore.profile.toString()); + if (userStore.profile.qStatus != 1) { + showCupertinoDialog( + context: context, + builder: (_) => CupertinoAlertDialog( + title: Text("Complete Your Profile"), + content: Text("Let’s get to know you better! Please take a quick survey to personalize your experience."), + actions: [ + CupertinoDialogAction( + child: Text("Take Survey"), + onPressed: () { + context.pop(); + _goEditProfile(); + }, + ), + ], + ), + ); + } + } + + void _goEditProfile() async { + var isUpload = await context.push(RoutePaths.myEdit); + if (isUpload == true) { + UserStore userStore = context.read(); + userStore.init(); + } + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/main.dart b/lib/main.dart index 824360a..7ea405a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:food_health/providers/user_store.dart'; import 'package:food_health/router/routes.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; @@ -12,6 +13,7 @@ void main() { MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => AppStore()), + ChangeNotifierProvider(create: (context) => UserStore()), ], child: MyApp(), ), diff --git a/lib/page/profile/edit/my_edit_page.dart b/lib/page/profile/edit/my_edit_page.dart index 3c1243f..5ffd0ad 100644 --- a/lib/page/profile/edit/my_edit_page.dart +++ b/lib/page/profile/edit/my_edit_page.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:food_health/api/dto/profile_options_dto.dart'; -import 'package:food_health/api/dto/user_profile_dto.dart'; import 'package:food_health/api/endpoints/profile_api.dart'; import 'package:food_health/config/theme/custom_colors.dart'; import 'package:food_health/page/profile/edit/widget/food_allergies.dart'; +import 'package:food_health/providers/user_store.dart'; import 'package:food_health/widgets/common/app_backend.dart'; import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import 'package:remixicon/remixicon.dart'; import 'data/state.dart'; @@ -14,9 +15,7 @@ import 'widget/dietary_preferences.dart'; import 'widget/health_profile.dart'; class MyEditPage extends StatefulWidget { - final UserProfileDto userProfile; - - const MyEditPage({super.key, required this.userProfile}); + const MyEditPage({super.key}); @override State createState() => _MyEditPageState(); @@ -57,7 +56,8 @@ class _MyEditPageState extends State { } void _init() async { - selectionState = SelectionState(widget.userProfile); + UserStore userStore = context.read(); + selectionState = SelectionState(userStore.profile); var res = await getProfileOptionsApi(); setState(() { _options = res; @@ -91,74 +91,89 @@ class _MyEditPageState extends State { if (_loading) { return Center(child: CircularProgressIndicator()); } - return Scaffold( - body: AppBackend( - child: ListView( - padding: EdgeInsets.only(top: 30), - children: [ - buildHeader(), - buildStep(), - buildStepInfo(), - SelectionProvider( - notifier: selectionState, - child: Builder( - builder: (context) { - if (_step == 0) { - return FoodAllergies( - options: _options, - ); - } else if (_step == 1) { - return DietaryPreferences( - options: _options, - ); - } else if (_step == 2) { - return HealthProfile( - options: _options, - ); - } - return SizedBox(); - }, + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, __) async { + if (didPop) return; + if (selectionState.userProfile.qStatus == 1) { + context.pop(); + } + }, + child: Scaffold( + body: AppBackend( + child: Column( + children: [ + Expanded( + child: ListView( + padding: EdgeInsets.only(top: 20), + children: [ + buildHeader(), + buildStep(), + buildStepInfo(), + SelectionProvider( + notifier: selectionState, + child: Builder( + builder: (context) { + if (_step == 0) { + return FoodAllergies( + options: _options, + ); + } else if (_step == 1) { + return DietaryPreferences( + options: _options, + ); + } else if (_step == 2) { + return HealthProfile( + options: _options, + ); + } + return SizedBox(); + }, + ), + ), + ], + ), ), - ), - Container( - margin: EdgeInsets.only(top: 30), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Opacity( - opacity: _step == 0 ? 0.4 : 1, - child: buildItemButton( - title: "Previous", - color: Colors.black, + Container( + margin: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Opacity( + opacity: _step == 0 ? 0.4 : 1, + child: buildItemButton( + title: "Previous", + color: Colors.black, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainer, + ), + onTap: () { + _handStep(false); + }, + ), + ), + buildItemButton( + title: _step == 2 ? "Complete Setup" : "Continue", decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainer, + color: _step == 2 ? Theme.of(context).colorScheme.success : null, + gradient: _step == 2 + ? null + : LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primaryEnd, + ], + ), ), onTap: () { - _handStep(false); + _handStep(true); }, ), - ), - buildItemButton( - title: _step == 2 ? "Complete Setup" : "Continue", - decoration: BoxDecoration( - color: _step == 2 ? Theme.of(context).colorScheme.success : null, - gradient: _step == 2 - ? null - : LinearGradient( - colors: [ - Theme.of(context).colorScheme.primary, - Theme.of(context).colorScheme.primaryEnd, - ], - ), - ), - onTap: () { - _handStep(true); - }, - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/page/profile/my/my_page.dart b/lib/page/profile/my/my_page.dart index 0100660..98d061a 100644 --- a/lib/page/profile/my/my_page.dart +++ b/lib/page/profile/my/my_page.dart @@ -1,12 +1,9 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:food_health/api/dto/user_profile_dto.dart'; -import 'package:food_health/api/endpoints/profile_api.dart'; import 'package:food_health/config/theme/custom_colors.dart'; -import 'package:go_router/go_router.dart'; +import 'package:food_health/providers/user_store.dart'; +import 'package:provider/provider.dart'; import 'package:remixicon/remixicon.dart'; -import '../../../router/config/route_paths.dart'; import 'widget/title_card.dart'; import 'widget/user_card.dart'; @@ -18,56 +15,6 @@ class MyPage extends StatefulWidget { } class _MyPageState extends State with AutomaticKeepAliveClientMixin { - UserProfileDto _userProfile = UserProfileDto(); - - @override - void initState() { - super.initState(); - _init(); - } - - void _init() async { - var res = await getUserProfileApi(); - setState(() { - _userProfile = res; - }); - _showEditProfile(); - } - - void _goEdit() async { - var isUpload = await context.push(RoutePaths.myEdit, extra: _userProfile); - if (isUpload == true) { - _init(); - } - } - - void _showEditProfile() { - if (_userProfile.qStatus != 1) { - showCupertinoDialog( - context: context, - builder: (_) => CupertinoAlertDialog( - title: Text("Complete Your Profile"), - content: Text("Let’s get to know you better! Please take a quick survey to personalize your experience."), - actions: [ - CupertinoDialogAction( - child: Text("Not Now"), - onPressed: () { - context.pop(); - }, - ), - CupertinoDialogAction( - child: Text("Take Survey"), - onPressed: () { - context.pop(); - _goEdit(); - }, - ), - ], - ), - ); - } - } - @override Widget build(BuildContext context) { super.build(context); @@ -75,70 +22,92 @@ class _MyPageState extends State with AutomaticKeepAliveClientMixin { child: ListView( padding: EdgeInsets.all(15), children: [ - UserCard( - detail: _userProfile, - onEdit: _goEdit, - ), - Column( - children: [ - TitleCard( - title: "Food Allergies", - icon: Icon( - RemixIcons.shield_line, - color: Theme.of(context).colorScheme.danger, - ), - child: buildTagList( - emptyText: "No allergies reported", - tags: _userProfile.foodAllergiesList, - color: Theme.of(context).colorScheme.danger, - ), - ), - TitleCard( - title: "No preferences", - icon: Icon( - RemixIcons.heart_line, - color: Theme.of(context).colorScheme.success, - ), - child: buildTagList( - emptyText: "No dietary preferences reported", - tags: _userProfile.dietaryPreferencesList, - color: Theme.of(context).colorScheme.success, - ), - ), - TitleCard( - title: "Medical Information", - icon: Icon( - RemixIcons.user_line, - color: Theme.of(context).colorScheme.primary, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + UserCard(), + Consumer( + builder: (context, store, _) { + return Column( children: [ - Container( - margin: EdgeInsets.only(bottom: 10), - child: Text("Medical Conditions"), - ), - Container( - margin: EdgeInsets.only(bottom: 10), + TitleCard( + title: "Food Allergies", + icon: Icon( + RemixIcons.shield_line, + color: Theme + .of(context) + .colorScheme + .danger, + ), child: buildTagList( - emptyText: "No medical conditions reported", - tags: _userProfile.medicalInformationList, - color: Theme.of(context).colorScheme.primary, + emptyText: "No allergies reported", + tags: store.profile.foodAllergiesList, + color: Theme + .of(context) + .colorScheme + .danger, ), ), - Container( - margin: EdgeInsets.only(bottom: 10), - child: Text("Current Medications"), + TitleCard( + title: "No preferences", + icon: Icon( + RemixIcons.heart_line, + color: Theme + .of(context) + .colorScheme + .success, + ), + child: buildTagList( + emptyText: "No dietary preferences reported", + tags: store.profile.dietaryPreferencesList, + color: Theme + .of(context) + .colorScheme + .success, + ), ), - buildTagList( - emptyText: "No medications reported", - tags: _userProfile.currentMedicationsList, - color: Theme.of(context).colorScheme.primary, + TitleCard( + title: "Medical Information", + icon: Icon( + RemixIcons.user_line, + color: Theme + .of(context) + .colorScheme + .primary, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(bottom: 10), + child: Text("Medical Conditions"), + ), + Container( + margin: EdgeInsets.only(bottom: 10), + child: buildTagList( + emptyText: "No medical conditions reported", + tags: store.profile.medicalInformationList, + color: Theme + .of(context) + .colorScheme + .primary, + ), + ), + Container( + margin: EdgeInsets.only(bottom: 10), + child: Text("Current Medications"), + ), + buildTagList( + emptyText: "No medications reported", + tags: store.profile.currentMedicationsList, + color: Theme + .of(context) + .colorScheme + .primary, + ), + ], + ), ), ], - ), - ), - ], + ); + } ), ], ), diff --git a/lib/page/profile/my/widget/user_card.dart b/lib/page/profile/my/widget/user_card.dart index 63ee381..2a1348a 100644 --- a/lib/page/profile/my/widget/user_card.dart +++ b/lib/page/profile/my/widget/user_card.dart @@ -5,6 +5,7 @@ import 'package:food_health/api/dto/user_profile_dto.dart'; import 'package:food_health/api/endpoints/user_api.dart'; import 'package:food_health/config/theme/custom_colors.dart'; import 'package:food_health/providers/app_store.dart'; +import 'package:food_health/providers/user_store.dart'; import 'package:food_health/router/config/route_paths.dart'; import 'package:food_health/utils/common.dart'; import 'package:go_router/go_router.dart'; @@ -12,22 +13,19 @@ import 'package:provider/provider.dart'; import 'package:remixicon/remixicon.dart'; class UserCard extends StatefulWidget { - final UserProfileDto detail; - final Function() onEdit; - - const UserCard({ - super.key, - required this.detail, - required this.onEdit, - }); + const UserCard({super.key}); @override State createState() => _UserCardState(); } class _UserCardState extends State { - void _goEdit() { - widget.onEdit(); + void _goEditProfile() async { + var isUpload = await context.push(RoutePaths.myEdit); + if (isUpload == true && mounted) { + UserStore userStore = context.read(); + userStore.init(); + } } ///退出登陆 @@ -105,57 +103,61 @@ class _UserCardState extends State { ), ], ), - child: Column( - children: [ - avatarWidget(), - Container( - margin: const EdgeInsets.only(top: 12), - child: Text(getNotEmpty(widget.detail.name) ?? "user", style: Theme.of(context).textTheme.titleMedium), - ), - Container( - margin: const EdgeInsets.only(top: 5), - child: Text(widget.detail.email ?? "", style: Theme.of(context).textTheme.labelMedium), - ), - buildTitledTags( - title: "Age Range", - tag: getNotEmpty(widget.detail.ageRange), - ), - buildTitledTags( - title: "Activity Level", - tag: getNotEmpty(widget.detail.activityLevel), - ), - SizedBox(height: 20), - btnItem( - title: "Edit Profile", - icon: RemixIcons.edit_box_line, - color: Colors.white, - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Theme.of(context).colorScheme.primary, - Theme.of(context).colorScheme.primaryEnd, - ], + child: Consumer( + builder: (context, store, _) { + return Column( + children: [ + avatarWidget(), + Container( + margin: const EdgeInsets.only(top: 12), + child: Text(getNotEmpty(store.profile.name) ?? "user", style: Theme.of(context).textTheme.titleMedium), ), - ), - onTap: _goEdit, - ), - btnItem( - title: "Logout", - icon: RemixIcons.logout_circle_line, - decoration: BoxDecoration(color: Theme.of(context).colorScheme.surfaceContainer), - onTap: _handLogout, - ), - Container( - margin: const EdgeInsets.only(top: 10), - child: InkWell( - onTap: _handDelete, - child: Text( - "Delete Account ", - style: TextStyle(color: Colors.red, fontSize: 14), + Container( + margin: const EdgeInsets.only(top: 5), + child: Text(store.profile.email ?? "", style: Theme.of(context).textTheme.labelMedium), ), - ), - ), - ], + buildTitledTags( + title: "Age Range", + tag: getNotEmpty(store.profile.ageRange), + ), + buildTitledTags( + title: "Activity Level", + tag: getNotEmpty(store.profile.activityLevel), + ), + SizedBox(height: 20), + btnItem( + title: "Edit Profile", + icon: RemixIcons.edit_box_line, + color: Colors.white, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary, + Theme.of(context).colorScheme.primaryEnd, + ], + ), + ), + onTap: _goEditProfile, + ), + btnItem( + title: "Logout", + icon: RemixIcons.logout_circle_line, + decoration: BoxDecoration(color: Theme.of(context).colorScheme.surfaceContainer), + onTap: _handLogout, + ), + Container( + margin: const EdgeInsets.only(top: 10), + child: InkWell( + onTap: _handDelete, + child: Text( + "Delete Account ", + style: TextStyle(color: Colors.red, fontSize: 14), + ), + ), + ), + ], + ); + }, ), ); } diff --git a/lib/page/system/splash/splash_page.dart b/lib/page/system/splash/splash_page.dart index c90f740..d3677a9 100644 --- a/lib/page/system/splash/splash_page.dart +++ b/lib/page/system/splash/splash_page.dart @@ -1,6 +1,7 @@ import 'package:food_health/providers/app_store.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:food_health/providers/user_store.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; diff --git a/lib/providers/user_store.dart b/lib/providers/user_store.dart new file mode 100644 index 0000000..41524f6 --- /dev/null +++ b/lib/providers/user_store.dart @@ -0,0 +1,14 @@ +import 'package:flutter/cupertino.dart'; +import 'package:food_health/api/dto/user_profile_dto.dart'; +import 'package:food_health/api/endpoints/profile_api.dart'; + +class UserStore with ChangeNotifier { + UserProfileDto profile = UserProfileDto(); + + //初始化数据 + Future init() async { + var res = await getUserProfileApi(); + profile = res; + notifyListeners(); + } +} diff --git a/lib/router/modules/serve.dart b/lib/router/modules/serve.dart index dfadf66..f3a572f 100644 --- a/lib/router/modules/serve.dart +++ b/lib/router/modules/serve.dart @@ -8,10 +8,7 @@ List serverRoutes = [ RouteType( path: RoutePaths.myEdit, child: (state) { - var extra = state.extra as dynamic; - return MyEditPage( - userProfile: extra, - ); + return MyEditPage(); }, ),