Files
eatvio_app/lib/features/create_recipe/presentation/widgets/ingredients_widget.dart
2025-04-04 20:21:31 +07:00

224 lines
11 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
import 'package:eatvio_app/features/create_recipe/models/ingredient.dart';
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class IngredientsWidget extends StatefulWidget {
const IngredientsWidget({super.key});
@override
State<IngredientsWidget> createState() => _IngredientsWidgetState();
}
class _IngredientsWidgetState extends State<IngredientsWidget> {
late final CreateRecipeCubit createRecipeCubit;
final nameController = TextEditingController();
final gramsController = TextEditingController();
final pcsController = TextEditingController();
@override
void initState() {
super.initState();
createRecipeCubit = context.read<CreateRecipeCubit>();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<CreateRecipeCubit, CreateRecipeState>(
builder: (BuildContext context, CreateRecipeState state) {
return Material(
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Text(
'Ингредиенты ',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Color(0xFF323F4B),
),
),
),
ReorderableListView(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
onReorder: (int oldIndex, int newIndex) {
setState(() {
if (oldIndex < newIndex) {
newIndex -= 1;
}
});
createRecipeCubit.replaceIngredientPosition(oldIndex, newIndex);
},
children: <Widget>[
for (int index = 0; index < state.entity.ingredients.length; index += 1)
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
key: Key('$index'),
leading: Icon(
Icons.drag_handle_rounded,
color: Colors.grey.shade600,
),
title: Text(state.entity.ingredients[index].name),
subtitle: Text('${state.entity.ingredients[index].portion} ${state.entity.ingredients[index].unit == 'gr' ? 'гр' : 'шт'}'),
trailing: IconButton(
onPressed: () {
createRecipeCubit.removeIngredient(index);
},
icon: Icon(
Icons.delete_outline_rounded,
color: Colors.grey.shade600,
),
),
),
],
),
ListTile(
onTap: () {
nameController.clear();
gramsController.clear();
pcsController.clear();
showModalBottomSheet(
useRootNavigator: true,
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
),
isScrollControlled: true,
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, void Function(void Function()) setStateInner) {
return Padding(
padding: const EdgeInsets.all(16) +
EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
const Text(
'Добавление ингредиента',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Color(0xFF323F4B),
),
),
const SizedBox(height: 16),
SizedBox(
width: MediaQuery.of(context).size.width - 32,
child: CustomTextFormField(
autofocus: true,
controller: nameController,
hintText: 'Введите название продукта',
onChanged: (query) {},
),
),
const SizedBox(height: 8),
Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width / 2 - 20,
child: CustomTextFormField(
enabled: pcsController.text.isEmpty ? true : false,
keyboardType: TextInputType.number,
controller: gramsController,
hintText: pcsController.text.isEmpty ? '100' : null,
suffixText: 'гр',
onChanged: (value) {
setStateInner(() {});
},
),
),
const SizedBox(width: 8),
SizedBox(
width: MediaQuery.of(context).size.width / 2 - 20,
child: CustomTextFormField(
enabled: gramsController.text.isEmpty ? true : false,
keyboardType: TextInputType.number,
controller: pcsController,
onChanged: (value) {
setStateInner(() {});
},
hintText: gramsController.text.isEmpty ? '1' : null,
suffixText: 'шт',
),
),
],
),
const SizedBox(height: 12),
InkWell(
onTap: () {
if (nameController.text.isNotEmpty && (pcsController.text.isNotEmpty || gramsController.text.isNotEmpty)) {
createRecipeCubit.addIngredient(
Ingredient(
name: nameController.text,
unit: gramsController.text.isEmpty ? 'pcs' : 'gr',
portion: gramsController.text.isEmpty ? pcsController.text : gramsController.text,
),
);
Navigator.of(context).pop();
setState(() {});
}
},
borderRadius: BorderRadius.circular(20),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
height: 52,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: appTheme.blueA400,
),
child: const Center(
child: Text(
'Добавить',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
),
],
),
);
},
);
},
);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
title: Text(
'Добавить ингредиент',
style: TextStyle(
color: appTheme.blueA400,
),
),
leading: Icon(
Icons.add_rounded,
color: appTheme.blueA400,
),
),
],
),
),
);
},
);
}
}