基本完成
This commit is contained in:
292
lib/page/profile/edit/my_edit_page.dart
Normal file
292
lib/page/profile/edit/my_edit_page.dart
Normal file
@@ -0,0 +1,292 @@
|
||||
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: "Help us keep you safe by telling us about your allergies",
|
||||
),
|
||||
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();
|
||||
}
|
||||
|
||||
@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 personalize 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,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user