plan creation screen added

This commit is contained in:
Username1548
2024-12-02 15:55:57 +07:00
parent a1d9e13514
commit 1688ac1dc8
55 changed files with 3506 additions and 350 deletions

View File

@@ -0,0 +1,145 @@
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
import 'package:eatvio_app/features/create_plan/presentation/widgets/options_count_button.dart';
import 'package:eatvio_app/features/create_plan/presentation/widgets/plan_duration_drop_down_widget.dart';
import 'package:eatvio_app/features/create_plan/presentation/widgets/plan_image_picker_widget.dart';
import 'package:eatvio_app/features/create_plan/presentation/widgets/plan_type_choice_widget.dart';
import 'package:eatvio_app/features/create_plan/presentation/widgets/select_exact_option_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CreatePlanScreen extends StatelessWidget {
static const name = 'createPlanScreen';
static const path = '/create-Plan-screen';
const CreatePlanScreen({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => sl<CreatePlanCubit>(),
child: const CreatePlanScreenContent(),
);
}
}
class CreatePlanScreenContent extends StatelessWidget {
const CreatePlanScreenContent({super.key});
@override
Widget build(BuildContext context) {
final s = S.of(context);
return Scaffold(
backgroundColor: appTheme.gray100,
appBar: AppBar(
centerTitle: true,
title: Text(
s.adding_plan,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
),
body: Stack(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8),
MainBackgroundBouble(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 16),
Text(
s.label,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
hintText: s.plan_label_desc,
onChanged: (value) {
context.read<CreatePlanCubit>().setName(value);
},
maxLength: 150,
),
SizedBox(height: 12),
Text(
s.plan_duration,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
PlanDurationDropDownWidget(),
SizedBox(height: 20),
PlanImagePickerWidget(),
SizedBox(height: 16),
PlanTypeChoiceWidget(),
SizedBox(height: 16),
Text(
s.plan_desc,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
SizedBox(
height: 132,
child: CustomTextFormField(
textAlignVertical: TextAlignVertical.top,
maxLength: 1000,
maxLines: null,
minLines: null,
expands: true,
hintText: s.plan_desc_example,
onChanged: (value) {
context.read<CreatePlanCubit>().setDetails(value);
},
),
),
SizedBox(height: 16),
],
),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.only(left: 16),
child: Text(
s.plan_desc,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.blueGray400),
),
),
SizedBox(height: 8),
OptionsCountButton(),
SizedBox(height: 200),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 24.0),
child: Align(
alignment: Alignment.bottomCenter,
child: SelectExactOptionWidget(),
),
),
],
),
);
}
}

View File

@@ -0,0 +1,43 @@
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
class CreatePlanCubit extends Cubit<CreatePlanState> {
CreatePlanCubit() : super(CreatePlanState.initial());
void setDetails(String text) {
emit(state.copyWith(planData: state.planData.copyWith(details: text)));
}
void setName(String name) {
emit(state.copyWith(planData: state.planData.copyWith(name: name)));
}
void setDuration(int index) {
emit(
state.copyWith(
durationIndex: index,
planData: state.planData.copyWith(
duration: durationValues[index],
),
),
);
}
void setImage(XFile? image) {
emit(state.copyWith(planData: state.planData.copyWith(image: image)));
}
void setPlanState(String planState) {
emit(state.copyWith(planData: state.planData.copyWith(state: planState)));
}
void setPlanType(List<bool> type) {
emit(state.copyWith(planData: state.planData.copyWith(type: type)));
}
void setSelectedOptionIndex(int? index) {
emit(state.copyWith(selectedOptionIndex: index));
}
}

View File

@@ -0,0 +1,25 @@
import 'package:eatvio_app/features/create_plan/models/create_plan_model.dart';
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'create_plan_state.freezed.dart';
@freezed
class CreatePlanState with _$CreatePlanState {
const factory CreatePlanState({
required bool isLoading,
required String? errorMessage,
required CreatePlanModel planData,
int? durationIndex,
int? selectedOptionIndex,
}) = _CreatePlanState;
factory CreatePlanState.initial() => CreatePlanState(
isLoading: false,
errorMessage: null,
planData: CreatePlanModel(
type: [false, false, false, false],
options: [PacketOptions.empty(), PacketOptions.empty(), PacketOptions.empty()],
),
);
}

View File

@@ -0,0 +1,249 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'create_plan_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$CreatePlanState {
bool get isLoading => throw _privateConstructorUsedError;
String? get errorMessage => throw _privateConstructorUsedError;
CreatePlanModel get planData => throw _privateConstructorUsedError;
int? get durationIndex => throw _privateConstructorUsedError;
int? get selectedOptionIndex => throw _privateConstructorUsedError;
/// Create a copy of CreatePlanState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CreatePlanStateCopyWith<CreatePlanState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CreatePlanStateCopyWith<$Res> {
factory $CreatePlanStateCopyWith(
CreatePlanState value, $Res Function(CreatePlanState) then) =
_$CreatePlanStateCopyWithImpl<$Res, CreatePlanState>;
@useResult
$Res call(
{bool isLoading,
String? errorMessage,
CreatePlanModel planData,
int? durationIndex,
int? selectedOptionIndex});
$CreatePlanModelCopyWith<$Res> get planData;
}
/// @nodoc
class _$CreatePlanStateCopyWithImpl<$Res, $Val extends CreatePlanState>
implements $CreatePlanStateCopyWith<$Res> {
_$CreatePlanStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CreatePlanState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isLoading = null,
Object? errorMessage = freezed,
Object? planData = null,
Object? durationIndex = freezed,
Object? selectedOptionIndex = freezed,
}) {
return _then(_value.copyWith(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
errorMessage: freezed == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String?,
planData: null == planData
? _value.planData
: planData // ignore: cast_nullable_to_non_nullable
as CreatePlanModel,
durationIndex: freezed == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
as int?,
selectedOptionIndex: freezed == selectedOptionIndex
? _value.selectedOptionIndex
: selectedOptionIndex // ignore: cast_nullable_to_non_nullable
as int?,
) as $Val);
}
/// Create a copy of CreatePlanState
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$CreatePlanModelCopyWith<$Res> get planData {
return $CreatePlanModelCopyWith<$Res>(_value.planData, (value) {
return _then(_value.copyWith(planData: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$CreatePlanStateImplCopyWith<$Res>
implements $CreatePlanStateCopyWith<$Res> {
factory _$$CreatePlanStateImplCopyWith(_$CreatePlanStateImpl value,
$Res Function(_$CreatePlanStateImpl) then) =
__$$CreatePlanStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{bool isLoading,
String? errorMessage,
CreatePlanModel planData,
int? durationIndex,
int? selectedOptionIndex});
@override
$CreatePlanModelCopyWith<$Res> get planData;
}
/// @nodoc
class __$$CreatePlanStateImplCopyWithImpl<$Res>
extends _$CreatePlanStateCopyWithImpl<$Res, _$CreatePlanStateImpl>
implements _$$CreatePlanStateImplCopyWith<$Res> {
__$$CreatePlanStateImplCopyWithImpl(
_$CreatePlanStateImpl _value, $Res Function(_$CreatePlanStateImpl) _then)
: super(_value, _then);
/// Create a copy of CreatePlanState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isLoading = null,
Object? errorMessage = freezed,
Object? planData = null,
Object? durationIndex = freezed,
Object? selectedOptionIndex = freezed,
}) {
return _then(_$CreatePlanStateImpl(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
errorMessage: freezed == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String?,
planData: null == planData
? _value.planData
: planData // ignore: cast_nullable_to_non_nullable
as CreatePlanModel,
durationIndex: freezed == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
as int?,
selectedOptionIndex: freezed == selectedOptionIndex
? _value.selectedOptionIndex
: selectedOptionIndex // ignore: cast_nullable_to_non_nullable
as int?,
));
}
}
/// @nodoc
class _$CreatePlanStateImpl implements _CreatePlanState {
const _$CreatePlanStateImpl(
{required this.isLoading,
required this.errorMessage,
required this.planData,
this.durationIndex,
this.selectedOptionIndex});
@override
final bool isLoading;
@override
final String? errorMessage;
@override
final CreatePlanModel planData;
@override
final int? durationIndex;
@override
final int? selectedOptionIndex;
@override
String toString() {
return 'CreatePlanState(isLoading: $isLoading, errorMessage: $errorMessage, planData: $planData, durationIndex: $durationIndex, selectedOptionIndex: $selectedOptionIndex)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CreatePlanStateImpl &&
(identical(other.isLoading, isLoading) ||
other.isLoading == isLoading) &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage) &&
(identical(other.planData, planData) ||
other.planData == planData) &&
(identical(other.durationIndex, durationIndex) ||
other.durationIndex == durationIndex) &&
(identical(other.selectedOptionIndex, selectedOptionIndex) ||
other.selectedOptionIndex == selectedOptionIndex));
}
@override
int get hashCode => Object.hash(runtimeType, isLoading, errorMessage,
planData, durationIndex, selectedOptionIndex);
/// Create a copy of CreatePlanState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CreatePlanStateImplCopyWith<_$CreatePlanStateImpl> get copyWith =>
__$$CreatePlanStateImplCopyWithImpl<_$CreatePlanStateImpl>(
this, _$identity);
}
abstract class _CreatePlanState implements CreatePlanState {
const factory _CreatePlanState(
{required final bool isLoading,
required final String? errorMessage,
required final CreatePlanModel planData,
final int? durationIndex,
final int? selectedOptionIndex}) = _$CreatePlanStateImpl;
@override
bool get isLoading;
@override
String? get errorMessage;
@override
CreatePlanModel get planData;
@override
int? get durationIndex;
@override
int? get selectedOptionIndex;
/// Create a copy of CreatePlanState
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CreatePlanStateImplCopyWith<_$CreatePlanStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
class OptionWidget extends StatelessWidget {
const OptionWidget({super.key});
@override
Widget build(BuildContext context) {
return Placeholder();
}
}

View File

@@ -0,0 +1,82 @@
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class OptionsCountButton extends StatelessWidget {
const OptionsCountButton({super.key});
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<CreatePlanCubit, CreatePlanState>(
builder: (context, state) {
final selectedOption = state.selectedOptionIndex;
return Container(
margin: EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: appTheme.whiteA700,
borderRadius: BorderRadius.circular(100),
),
padding: const EdgeInsets.all(4),
child: Row(
children: [
Expanded(
child: _AnimatedOptionButton(
isSelected: selectedOption == null,
text: s.one_option,
onTap: () {
context.read<CreatePlanCubit>().setSelectedOptionIndex(null);
},
),
),
Expanded(
child: _AnimatedOptionButton(
isSelected: selectedOption != null,
text: s.three_options,
onTap: () {
context.read<CreatePlanCubit>().setSelectedOptionIndex(0);
},
),
),
],
),
);
},
);
}
}
class _AnimatedOptionButton extends StatelessWidget {
const _AnimatedOptionButton({required this.text, required this.isSelected, required this.onTap});
final String text;
final bool isSelected;
final void Function() onTap;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: isSelected ? appTheme.blueA400 : appTheme.whiteA700,
),
child: Center(
child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 200),
style: TextStyles.textMSemibold.copyWith(
color: isSelected ? appTheme.whiteA700 : appTheme.black,
),
child: Text(text),
),
),
),
);
}
}

View File

@@ -0,0 +1,65 @@
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/utils/localization_utils.dart';
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class PlanDurationDropDownWidget extends StatefulWidget {
const PlanDurationDropDownWidget({super.key});
@override
State<PlanDurationDropDownWidget> createState() => _PlanDurationDropDownWidgetState();
}
class _PlanDurationDropDownWidgetState extends State<PlanDurationDropDownWidget> {
final List<String> durationDropDownTitles = [];
@override
void didChangeDependencies() {
super.didChangeDependencies();
final s = S.of(context);
if (durationDropDownTitles.isEmpty) {
durationValues.forEach((element) {
durationDropDownTitles.add('$element ${getDayForm(element, s)}');
});
}
}
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<CreatePlanCubit, CreatePlanState>(
builder: (context, state) {
return CustomDropDownButton(
hint: Text(
s.choose_plan_duration,
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
onChanged: (value) {
if (value != null) {
context.read<CreatePlanCubit>().setDuration(durationDropDownTitles.indexOf(value));
}
},
items: durationDropDownTitles
.mapIndexed(
(index, value) => DropdownMenuItem(
child: Text(
durationDropDownTitles[index],
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
value: durationDropDownTitles[index],
),
)
.toList(),
value: state.durationIndex == null ? null : durationDropDownTitles[state.durationIndex ?? 0],
);
},
);
}
}

View File

@@ -0,0 +1,145 @@
import 'dart:io';
import 'package:dotted_border/dotted_border.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:image_picker/image_picker.dart';
class PlanImagePickerWidget extends StatefulWidget {
const PlanImagePickerWidget({super.key});
@override
State<PlanImagePickerWidget> createState() => _PlanImagePickerWidgetState();
}
class _PlanImagePickerWidgetState extends State<PlanImagePickerWidget> {
void _showImagePickerOptions(S s, CreatePlanCubit cubit) {
showCupertinoModalPopup<void>(
context: context,
builder: (context) => CupertinoActionSheet(
actions: [
CupertinoActionSheetAction(
onPressed: () async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.camera);
cubit.setImage(image);
Navigator.of(context).pop();
},
child: Row(
children: [
Icon(Icons.photo_camera),
SizedBox(width: 8),
Text(s.photo),
],
),
),
CupertinoActionSheetAction(
onPressed: () async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
cubit.setImage(image);
Navigator.of(context).pop();
},
child: Row(
children: [
Icon(Icons.photo),
SizedBox(width: 8),
Text(s.gallery),
],
),
),
],
cancelButton: CupertinoActionSheetAction(
onPressed: () => Navigator.of(context).pop(),
isDestructiveAction: true,
child: const Text('Отмена'),
),
),
);
}
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<CreatePlanCubit, CreatePlanState>(
builder: (context, state) {
return GestureDetector(
onTap: () {
_showImagePickerOptions(s, context.read<CreatePlanCubit>());
},
child: Container(
height: 240,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
image: state.planData.image != null ? DecorationImage(fit: BoxFit.cover, image: FileImage(File(state.planData.image?.path ?? ''))) : null,
color: appTheme.gray50,
),
width: MediaQuery.sizeOf(context).width,
padding: state.planData.image != null ? null : EdgeInsets.all(8),
child: state.planData.image != null
? Padding(
padding: const EdgeInsets.only(top: 6, right: 6),
child: GestureDetector(
onTap: () {
context.read<CreatePlanCubit>().setImage(null);
},
child: Align(
alignment: Alignment.topRight,
child: Container(
width: 34,
height: 34,
decoration: BoxDecoration(
color: appTheme.dividerColor,
shape: BoxShape.circle,
),
child: Icon(
Icons.close_rounded,
color: Colors.grey,
size: 16,
),
),
),
),
)
: Stack(
children: [
DottedBorder(
stackFit: StackFit.expand,
dashPattern: [14, 14],
color: appTheme.dottedBorder,
borderType: BorderType.RRect,
radius: Radius.circular(12),
child: SizedBox.expand(),
),
Center(
child: Column(
children: [
SizedBox(
height: 48,
),
SvgPicture.asset('assets/icons/eatvio_logo.svg'),
SizedBox(
height: 24,
),
Text(
s.add_cover,
style: TextStyles.textMMedium.copyWith(color: appTheme.gray),
),
],
),
),
],
),
),
);
},
);
}
}

View File

@@ -0,0 +1,101 @@
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class PlanTypeChoiceWidget extends StatefulWidget {
PlanTypeChoiceWidget({super.key});
@override
State<PlanTypeChoiceWidget> createState() => _PlanTypeChoiceWidgetState();
}
class _PlanTypeChoiceWidgetState extends State<PlanTypeChoiceWidget> {
final List<(String, String)> choiceContent = [];
@override
void didChangeDependencies() {
super.didChangeDependencies();
final s = S.of(context);
if (choiceContent.isEmpty) {
choiceContent.add(
(
'assets/icons/slim.png',
s.slim,
),
);
choiceContent.add(
(
'assets/icons/fitness.png',
s.fitness,
),
);
choiceContent.add(
(
'assets/icons/yoga-pose.png',
s.wellness,
),
);
choiceContent.add(
(
'assets/icons/diet.png',
s.eating_behavior,
),
);
}
}
@override
Widget build(BuildContext context) {
return BlocBuilder<CreatePlanCubit, CreatePlanState>(
builder: (context, state) {
return Row(
children: [
...List.generate(4, (index) {
return Expanded(
child: GestureDetector(
onTap: () {
final planTypes = [...state.planData.type];
planTypes[index] = !planTypes[index];
context.read<CreatePlanCubit>().setPlanType(planTypes);
},
child: Container(
margin: EdgeInsets.only(right: index == 3 ? 0 : 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: state.planData.type[index] ? appTheme.cardBackground : appTheme.whiteA700,
border: Border.all(
width: 1,
color: state.planData.type[index] ? appTheme.blueA400 : appTheme.lightGray00,
),
),
height: 104,
child: Column(
children: [
SizedBox(height: 16),
Image.asset(
choiceContent[index].$1,
height: 30,
),
SizedBox(height: 8),
Text(
choiceContent[index].$2,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
style: TextStyles.textFS10FW500.copyWith(color: appTheme.black),
),
],
),
),
),
);
}),
],
);
},
);
}
}

View File

@@ -0,0 +1,42 @@
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
class SelectExactOptionWidget extends StatelessWidget {
const SelectExactOptionWidget({super.key});
@override
Widget build(BuildContext context) {
return Container(
width: 140,
height: 48,
decoration: BoxDecoration(
color: appTheme.black,
borderRadius: BorderRadius.circular(100),
),
child: Row(
children: [
_OptionButton(isSelected: true, text: '1'),
_OptionButton(isSelected: true, text: '2'),
_OptionButton(isSelected: true, text: '3'),
],
),
);
}
}
class _OptionButton extends StatelessWidget {
const _OptionButton({required this.isSelected, required this.text});
final bool isSelected;
final String text;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: appTheme.whiteA700,
shape: BoxShape.circle,
),
child: Text(text),
);
}
}