diff --git a/lib/api/dto/user_profile_dto.dart b/lib/api/dto/user_profile_dto.dart index bd2608e..0b9a244 100644 --- a/lib/api/dto/user_profile_dto.dart +++ b/lib/api/dto/user_profile_dto.dart @@ -9,6 +9,7 @@ class UserProfileDto { List medicalInformationList; List currentMedicationsList; String activityLevel; + int? qStatus; UserProfileDto({ this.id = 0, @@ -20,6 +21,7 @@ class UserProfileDto { List? dietaryPreferencesList, List? medicalInformationList, List? currentMedicationsList, + this.qStatus, this.activityLevel = "", }) : foodAllergiesList = foodAllergiesList ?? [], dietaryPreferencesList = dietaryPreferencesList ?? [], @@ -38,6 +40,7 @@ class UserProfileDto { "medical_information": medicalInformationList, "current_medications": currentMedicationsList, "activity_level": activityLevel, + "q_status": qStatus, }; } @@ -53,6 +56,7 @@ class UserProfileDto { medicalInformationList: (json["medical_information"] as List?)?.cast() ?? [], currentMedicationsList: (json["current_medications"] as List?)?.cast() ?? [], activityLevel: json["activity_level"] ?? "", + qStatus: json["q_status"], ); } } diff --git a/lib/api/endpoints/user_api.dart b/lib/api/endpoints/user_api.dart index a013d73..a378cc5 100644 --- a/lib/api/endpoints/user_api.dart +++ b/lib/api/endpoints/user_api.dart @@ -47,3 +47,8 @@ Future thirdLoginApi(String token, OtherLoginType type) async { }); return LoginDto.fromJson(res); } + +///删除账号 +Future deleteAccountApi() async { + return Request().get("/delete_account"); +} diff --git a/lib/page/profile/my/my_page.dart b/lib/page/profile/my/my_page.dart index 54f9745..4333206 100644 --- a/lib/page/profile/my/my_page.dart +++ b/lib/page/profile/my/my_page.dart @@ -1,3 +1,4 @@ +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'; @@ -30,6 +31,7 @@ class _MyPageState extends State with AutomaticKeepAliveClientMixin { setState(() { _userProfile = res; }); + _showEditProfile(); } void _goEdit() async { @@ -37,6 +39,33 @@ class _MyPageState extends State with AutomaticKeepAliveClientMixin { _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) { return SafeArea( diff --git a/lib/page/profile/my/widget/user_card.dart b/lib/page/profile/my/widget/user_card.dart index 36b65cc..63ee381 100644 --- a/lib/page/profile/my/widget/user_card.dart +++ b/lib/page/profile/my/widget/user_card.dart @@ -1,5 +1,8 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; 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/router/config/route_paths.dart'; @@ -27,10 +30,63 @@ class _UserCardState extends State { widget.onEdit(); } - void _handLogout() { - var appStore = context.read(); - appStore.logout(); - context.go(RoutePaths.login); + ///退出登陆 + void _handLogout() async { + await showCupertinoDialog( + context: context, + builder: (_) => CupertinoAlertDialog( + title: Text("Log Out?"), + content: Text("Are you sure you want to log out? You’ll need to sign in again to access your account."), + actions: [ + CupertinoDialogAction( + child: Text("Cancel"), + onPressed: () { + context.pop(); + }, + ), + CupertinoDialogAction( + child: Text("Log Out"), + onPressed: () { + context.pop(); + var appStore = context.read(); + appStore.logout(); + context.go(RoutePaths.login); + }, + ), + ], + ), + ); + } + + ///注销账号 + void _handDelete() async { + await showCupertinoDialog( + context: context, + builder: (_) => CupertinoAlertDialog( + title: Text("Delete Account?"), + content: Text("Are you sure you want to delete your account? You won’t be able to recover your account."), + actions: [ + CupertinoDialogAction( + onPressed: () { + context.pop(); + }, + child: Text("Cancel"), + ), + CupertinoDialogAction( + child: Text("Delete"), + onPressed: () async { + context.pop(); + EasyLoading.show(); + await deleteAccountApi(); + EasyLoading.dismiss(); + var appStore = context.read(); + appStore.logout(); + context.go(RoutePaths.login); + }, + ), + ], + ), + ); } @override @@ -89,6 +145,16 @@ class _UserCardState extends State { 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/login/login_page.dart b/lib/page/system/login/login_page.dart index 77ea54c..ff9f9ba 100644 --- a/lib/page/system/login/login_page.dart +++ b/lib/page/system/login/login_page.dart @@ -207,83 +207,80 @@ class _LoginPageState extends State { child: Scaffold( resizeToAvoidBottomInset: false, body: SafeArea( - child: Stack( - alignment: Alignment.center, - children: [ - Container( - width: double.infinity, - padding: EdgeInsets.only( - top: 0.07.sh, - left: 20, - right: 20, + child: Container( + width: double.infinity, + padding: EdgeInsets.only( + top: 0.07.sh, + left: 20, + right: 20, + ), + child: Column( + children: [ + LogoBox(), + PageHeader(), + InputBox( + hintText: "Email", + controller: _emailController, ), - child: Column( - children: [ - LogoBox(), - PageHeader(), - InputBox( - hintText: "Email", - controller: _emailController, + SizedBox(height: 15), + InputBox( + obscureText: _hidePassword, + hintText: "Password", + controller: _passwordController, + suffix: InkWell( + onTap: () { + setState(() { + _hidePassword = !_hidePassword; + }); + }, + child: Icon( + _hidePassword ? RemixIcons.eye_off_fill : RemixIcons.eye_fill, + size: 20, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - SizedBox(height: 15), - InputBox( - obscureText: _hidePassword, - hintText: "Password", - controller: _passwordController, - suffix: InkWell( - onTap: () { - setState(() { - _hidePassword = !_hidePassword; - }); - }, - child: Icon( - _hidePassword ? RemixIcons.eye_off_fill : RemixIcons.eye_fill, - size: 20, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - Container( - margin: EdgeInsets.only(top: 20), - height: 45, - child: CustomButton( - loading: _subLoading, - round: false, - onPressed: _handSubmit, - child: Text("Continue"), - ), - ), - LoginDivider(), - OtherButton( - title: "Continue with Google", - icon: "assets/image/google.png", - onTap: () { - _handleGoogleSignIn(); - }, - ), - SizedBox(height: 15), - OtherButton( - title: "Continue with Apple", - icon: "assets/image/apple.png", - onTap: () { - _handAppleSignIn(); - }, - ), - ], + ), ), - ), - Positioned( - bottom: 20, - child: AgreementBox( - checked: _agree, - onChanged: (value) { - setState(() { - _agree = value; - }); + Container( + margin: EdgeInsets.only(top: 20), + height: 45, + child: CustomButton( + loading: _subLoading, + round: false, + onPressed: _handSubmit, + child: Text("Continue"), + ), + ), + LoginDivider(), + OtherButton( + title: "Continue with Google", + icon: "assets/image/google.png", + onTap: () { + _handleGoogleSignIn(); }, ), - ), - ], + SizedBox(height: 15), + OtherButton( + title: "Continue with Apple", + icon: "assets/image/apple.png", + onTap: () { + _handAppleSignIn(); + }, + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 40), + alignment: Alignment.center, + child: AgreementBox( + checked: _agree, + onChanged: (value) { + setState(() { + _agree = value; + }); + }, + ), + ), + ], + ), ), ), ), diff --git a/lib/page/system/login/widget/agreement_box.dart b/lib/page/system/login/widget/agreement_box.dart index ea5f566..f14b54f 100644 --- a/lib/page/system/login/widget/agreement_box.dart +++ b/lib/page/system/login/widget/agreement_box.dart @@ -17,6 +17,7 @@ class AgreementBox extends StatelessWidget { @override Widget build(BuildContext context) { return Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 25, @@ -31,33 +32,38 @@ class AgreementBox extends StatelessWidget { ), ), ), - RichText( - text: TextSpan( - style: Theme.of(context).textTheme.labelSmall, - children: [ - TextSpan( - text: "I agree to the ", - ), - TextSpan( - text: "Terms", - style: TextStyle(color: Theme.of(context).primaryColor), - recognizer: TapGestureRecognizer() - ..onTap = () => context.push( - RoutePaths.agreement, - extra: {"title": "Terms of Service", "url": "https://support.curain.ai/privacy/derma/terms_service.html"}, - ), - ), - TextSpan(text: " & "), - TextSpan( - text: "Privacy Policy", - style: TextStyle(color: Theme.of(context).primaryColor), - recognizer: TapGestureRecognizer() - ..onTap = () => context.push( - RoutePaths.agreement, - extra: {"title": "Privacy", "url": "https://support.curain.ai/privacy/derma/privacy_policy.html"}, - ), - ), - ], + GestureDetector( + onTap: () { + onChanged(!checked); + }, + child: RichText( + text: TextSpan( + style: Theme.of(context).textTheme.labelSmall, + children: [ + TextSpan( + text: "I agree to the ", + ), + TextSpan( + text: "Terms", + style: TextStyle(color: Theme.of(context).primaryColor), + recognizer: TapGestureRecognizer() + ..onTap = () => context.push( + RoutePaths.agreement, + extra: {"title": "Terms of Service", "url": "https://support.curain.ai/privacy/foodcura/terms_service.html"}, + ), + ), + TextSpan(text: " & "), + TextSpan( + text: "Privacy Policy", + style: TextStyle(color: Theme.of(context).primaryColor), + recognizer: TapGestureRecognizer() + ..onTap = () => context.push( + RoutePaths.agreement, + extra: {"title": "Privacy", "url": "https://support.curain.ai/privacy/foodcura/privacy_policy.html"}, + ), + ), + ], + ), ), ), ],