Files
food_health_flutter/lib/page/profile/edit/my_edit_page.dart
zhutao c175a979a5 1
2025-09-01 10:18:39 +08:00

293 lines
8.0 KiB
Dart

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/widgets/common/app_backend.dart';
import 'package:go_router/go_router.dart';
import 'package:remixicon/remixicon.dart';
import 'data/state.dart';
import 'widget/dietary_preferences.dart';
import 'widget/health_profile.dart';
class MyEditPage extends StatefulWidget {
final UserProfileDto userProfile;
const MyEditPage({super.key, required this.userProfile});
@override
State<MyEditPage> createState() => _MyEditPageState();
}
class _MyEditPageState extends State<MyEditPage> {
late SelectionState selectionState;
List<ProfileOptionDto> _options = [];
var _loading = true;
///步骤
var _step = 0;
var stepList = [
StepItem(
title: "Food Allergies",
icon: RemixIcons.shield_line,
subTitle: "Tell us about your allergies so we can help keep you safe",
),
StepItem(
title: "Dietary Preferences",
icon: RemixIcons.heart_line,
subTitle: "What dietary restrictions or preferences do you follow?",
),
StepItem(
title: "Health Profile",
icon: RemixIcons.user_line,
subTitle: "Share relevant health information for personalized recommendations",
),
];
@override
void initState() {
super.initState();
_init();
}
void _init() async {
selectionState = SelectionState(widget.userProfile);
var res = await getProfileOptionsApi();
setState(() {
_options = res;
_loading = false;
});
}
///设置步骤
void _handStep(bool isNext) {
if (_step == 2 && isNext) {
_submit();
return;
}
setState(() {
_step = (_step + (isNext ? 1 : -1)).clamp(0, 2);
});
}
void _submit() async {
EasyLoading.show(
status: 'Saving…',
maskType: EasyLoadingMaskType.clear,
);
await updateProfileApi(selectionState.userProfile);
EasyLoading.dismiss();
context.pop(true);
}
@override
Widget build(BuildContext context) {
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();
},
),
),
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,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
),
onTap: () {
_handStep(false);
},
),
),
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);
},
),
],
),
),
],
),
),
);
}
///构建顶部
Widget buildHeader() {
return Column(
children: [
Text(
"Welcome to FoodSafe",
style: Theme.of(context).textTheme.titleLarge,
),
Container(
margin: EdgeInsets.only(top: 5),
child: Text(
"Let's customize your food safety experience",
style: Theme.of(context).textTheme.labelMedium,
),
),
],
);
}
///步骤条
Widget buildStep() {
return Container(
margin: EdgeInsets.only(top: 20),
child: Row(
spacing: 10,
children: stepList.asMap().entries.map((entre) {
//数据
var item = entre.value;
var index = entre.key;
var isLast = index == stepList.length - 1;
//颜色
var selectColor = Theme.of(context).colorScheme.primary;
var unselectedColor = Theme.of(context).colorScheme.surfaceContainerHigh;
return Expanded(
flex: isLast ? 0 : 1,
child: Row(
spacing: 10,
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: _step >= index ? selectColor : unselectedColor,
shape: BoxShape.circle,
),
child: Icon(
item.icon,
color: _step >= index ? Colors.white : Color(0xff9ca3af),
),
),
Visibility(
visible: !isLast,
child: Expanded(
child: Container(
height: 3,
color: _step > index ? selectColor : unselectedColor,
),
),
),
],
),
);
}).toList(),
),
);
}
///步骤条信息
Widget buildStepInfo() {
var stepInfo = stepList[_step];
return Container(
margin: EdgeInsets.only(top: 20, bottom: 30),
child: Column(
children: [
Text(
stepInfo.title,
style: Theme.of(context).textTheme.titleMedium,
),
Container(
margin: EdgeInsets.only(top: 5),
child: Text(
stepInfo.subTitle,
style: Theme.of(context).textTheme.labelMedium,
textAlign: TextAlign.center,
),
),
],
),
);
}
///item按钮
Widget buildItemButton({
required String title,
Color color = Colors.white,
required BoxDecoration decoration,
required Function() onTap,
}) {
return InkWell(
onTap: onTap,
child: Container(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
decoration: decoration.copyWith(
borderRadius: BorderRadius.circular(8),
),
child: Text(
title,
style: TextStyle(color: color),
),
),
);
}
}
class StepItem {
final IconData icon;
final String title;
final String subTitle;
StepItem({
required this.icon,
required this.title,
required this.subTitle,
});
}