删除账号

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> currentMedicationsList;
String activityLevel;
int? qStatus;
UserProfileDto({
this.id = 0,
@@ -20,6 +21,7 @@ class UserProfileDto {
List<String>? dietaryPreferencesList,
List<String>? medicalInformationList,
List<String>? 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<String>() ?? [],
currentMedicationsList: (json["current_medications"] as List?)?.cast<String>() ?? [],
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);
}
///删除账号
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: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<MyPage> with AutomaticKeepAliveClientMixin {
setState(() {
_userProfile = res;
});
_showEditProfile();
}
void _goEdit() async {
@@ -37,6 +39,33 @@ class _MyPageState extends State<MyPage> with AutomaticKeepAliveClientMixin {
_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
Widget build(BuildContext context) {
return SafeArea(

View File

@@ -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<UserCard> {
widget.onEdit();
}
void _handLogout() {
var appStore = context.read<AppStore>();
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? 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
@@ -89,6 +145,16 @@ class _UserCardState extends State<UserCard> {
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),
),
),
),
],
),
);

View File

@@ -207,83 +207,80 @@ class _LoginPageState extends State<LoginPage> {
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;
});
},
),
),
],
),
),
),
),

View File

@@ -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"},
),
),
],
),
),
),
],