删除账号

This commit is contained in:
zhutao
2025-08-29 14:22:44 +08:00
parent 00dd33830c
commit 8d7038b713
6 changed files with 210 additions and 103 deletions

View File

@@ -9,6 +9,7 @@ class UserProfileDto {
List<String> medicalInformationList; List<String> medicalInformationList;
List<String> currentMedicationsList; List<String> currentMedicationsList;
String activityLevel; String activityLevel;
int? qStatus;
UserProfileDto({ UserProfileDto({
this.id = 0, this.id = 0,
@@ -20,6 +21,7 @@ class UserProfileDto {
List<String>? dietaryPreferencesList, List<String>? dietaryPreferencesList,
List<String>? medicalInformationList, List<String>? medicalInformationList,
List<String>? currentMedicationsList, List<String>? currentMedicationsList,
this.qStatus,
this.activityLevel = "", this.activityLevel = "",
}) : foodAllergiesList = foodAllergiesList ?? [], }) : foodAllergiesList = foodAllergiesList ?? [],
dietaryPreferencesList = dietaryPreferencesList ?? [], dietaryPreferencesList = dietaryPreferencesList ?? [],
@@ -38,6 +40,7 @@ class UserProfileDto {
"medical_information": medicalInformationList, "medical_information": medicalInformationList,
"current_medications": currentMedicationsList, "current_medications": currentMedicationsList,
"activity_level": activityLevel, "activity_level": activityLevel,
"q_status": qStatus,
}; };
} }
@@ -53,6 +56,7 @@ class UserProfileDto {
medicalInformationList: (json["medical_information"] as List?)?.cast<String>() ?? [], medicalInformationList: (json["medical_information"] as List?)?.cast<String>() ?? [],
currentMedicationsList: (json["current_medications"] as List?)?.cast<String>() ?? [], currentMedicationsList: (json["current_medications"] as List?)?.cast<String>() ?? [],
activityLevel: json["activity_level"] ?? "", activityLevel: json["activity_level"] ?? "",
qStatus: json["q_status"],
); );
} }
} }

View File

@@ -47,3 +47,8 @@ Future<LoginDto> thirdLoginApi(String token, OtherLoginType type) async {
}); });
return LoginDto.fromJson(res); return LoginDto.fromJson(res);
} }
///删除账号
Future<void> deleteAccountApi() async {
return Request().get("/delete_account");
}

View File

@@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:food_health/api/dto/user_profile_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/api/endpoints/profile_api.dart';
@@ -30,6 +31,7 @@ class _MyPageState extends State<MyPage> with AutomaticKeepAliveClientMixin {
setState(() { setState(() {
_userProfile = res; _userProfile = res;
}); });
_showEditProfile();
} }
void _goEdit() async { void _goEdit() async {
@@ -37,6 +39,33 @@ class _MyPageState extends State<MyPage> with AutomaticKeepAliveClientMixin {
_init(); _init();
} }
void _showEditProfile() {
if (_userProfile.qStatus != 1) {
showCupertinoDialog(
context: context,
builder: (_) => CupertinoAlertDialog(
title: Text("Complete Your Profile"),
content: Text("Lets 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SafeArea( return SafeArea(

View File

@@ -1,5 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.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/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/config/theme/custom_colors.dart';
import 'package:food_health/providers/app_store.dart'; import 'package:food_health/providers/app_store.dart';
import 'package:food_health/router/config/route_paths.dart'; import 'package:food_health/router/config/route_paths.dart';
@@ -27,10 +30,63 @@ class _UserCardState extends State<UserCard> {
widget.onEdit(); widget.onEdit();
} }
void _handLogout() { ///退出登陆
var appStore = context.read<AppStore>(); void _handLogout() async {
appStore.logout(); await showCupertinoDialog(
context.go(RoutePaths.login); context: context,
builder: (_) => CupertinoAlertDialog(
title: Text("Log Out?"),
content: Text("Are you sure you want to log out? Youll 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>();
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 wont 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>();
appStore.logout();
context.go(RoutePaths.login);
},
),
],
),
);
} }
@override @override
@@ -89,6 +145,16 @@ class _UserCardState extends State<UserCard> {
decoration: BoxDecoration(color: Theme.of(context).colorScheme.surfaceContainer), decoration: BoxDecoration(color: Theme.of(context).colorScheme.surfaceContainer),
onTap: _handLogout, onTap: _handLogout,
), ),
Container(
margin: const EdgeInsets.only(top: 10),
child: InkWell(
onTap: _handDelete,
child: Text(
"Delete Account ",
style: TextStyle(color: Colors.red, fontSize: 14),
),
),
),
], ],
), ),
); );

View File

@@ -207,83 +207,80 @@ class _LoginPageState extends State<LoginPage> {
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
body: SafeArea( body: SafeArea(
child: Stack( child: Container(
alignment: Alignment.center, width: double.infinity,
children: [ padding: EdgeInsets.only(
Container( top: 0.07.sh,
width: double.infinity, left: 20,
padding: EdgeInsets.only( right: 20,
top: 0.07.sh, ),
left: 20, child: Column(
right: 20, children: [
LogoBox(),
PageHeader(),
InputBox(
hintText: "Email",
controller: _emailController,
), ),
child: Column( SizedBox(height: 15),
children: [ InputBox(
LogoBox(), obscureText: _hidePassword,
PageHeader(), hintText: "Password",
InputBox( controller: _passwordController,
hintText: "Email", suffix: InkWell(
controller: _emailController, 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();
},
),
],
), ),
), Container(
Positioned( margin: EdgeInsets.only(top: 20),
bottom: 20, height: 45,
child: AgreementBox( child: CustomButton(
checked: _agree, loading: _subLoading,
onChanged: (value) { round: false,
setState(() { onPressed: _handSubmit,
_agree = value; 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;
});
},
),
),
],
),
), ),
), ),
), ),

View File

@@ -17,6 +17,7 @@ class AgreementBox extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( SizedBox(
width: 25, width: 25,
@@ -31,33 +32,38 @@ class AgreementBox extends StatelessWidget {
), ),
), ),
), ),
RichText( GestureDetector(
text: TextSpan( onTap: () {
style: Theme.of(context).textTheme.labelSmall, onChanged(!checked);
children: [ },
TextSpan( child: RichText(
text: "I agree to the ", text: TextSpan(
), style: Theme.of(context).textTheme.labelSmall,
TextSpan( children: [
text: "Terms", TextSpan(
style: TextStyle(color: Theme.of(context).primaryColor), text: "I agree to the ",
recognizer: TapGestureRecognizer() ),
..onTap = () => context.push( TextSpan(
RoutePaths.agreement, text: "Terms",
extra: {"title": "Terms of Service", "url": "https://support.curain.ai/privacy/derma/terms_service.html"}, style: TextStyle(color: Theme.of(context).primaryColor),
), recognizer: TapGestureRecognizer()
), ..onTap = () => context.push(
TextSpan(text: " & "), RoutePaths.agreement,
TextSpan( extra: {"title": "Terms of Service", "url": "https://support.curain.ai/privacy/foodcura/terms_service.html"},
text: "Privacy Policy", ),
style: TextStyle(color: Theme.of(context).primaryColor), ),
recognizer: TapGestureRecognizer() TextSpan(text: " & "),
..onTap = () => context.push( TextSpan(
RoutePaths.agreement, text: "Privacy Policy",
extra: {"title": "Privacy", "url": "https://support.curain.ai/privacy/derma/privacy_policy.html"}, 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"},
),
),
],
),
), ),
), ),
], ],