feat: webview

This commit is contained in:
BLoC
2025-01-29 13:14:20 +03:00
parent ae7c72cd53
commit e8e561fdc6
24 changed files with 1741 additions and 1523 deletions

View File

@@ -17,6 +17,7 @@ import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
import 'package:validators/validators.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'bloc/auth_bloc.dart';
import 'models/auth_model.dart';
@@ -43,11 +44,71 @@ class _AuthScreenState extends State<AuthScreen> {
bool checkboxState = false;
bool hidePassword = true;
final baseUrlController = TextEditingController();
late final WebViewController _controller;
@override
void initState() {
super.initState();
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel(
'FlutterChannel',
onMessageReceived: (JavaScriptMessage message) {
// Handle messages from JavaScript
final data = jsonDecode(message.message);
final email = data['email'];
final password = data['password'];
print('Email: $email, Password: $password');
},
)
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (String url) async {
await _controller.runJavaScript('''
function initializeListeners() {
const emailInput = document.getElementById("inputEmail_main");
const passwordInput = document.getElementById("inputPassword_main");
if (emailInput && passwordInput) {
function sendToFlutter() {
const email = emailInput.value;
const password = passwordInput.value;
const data = JSON.stringify({ email: email, password: password });
if (window.FlutterChannel) {
window.FlutterChannel.postMessage(data);
}
}
emailInput.addEventListener("input", sendToFlutter);
passwordInput.addEventListener("input", sendToFlutter);
} else {
console.error("Email or Password input not found.");
}
}
// Ensure DOM is loaded before attaching listeners
document.addEventListener("DOMContentLoaded", initializeListeners);
initializeListeners();
''');
},
),
)
..loadRequest(Uri.parse(baseUrl));
}
@override
Widget build(BuildContext context) {
FlutterNativeSplash.remove();
final s = S.of(context);
return Scaffold(
appBar: AppBar(
toolbarHeight: 0,
),
body: WebViewWidget(controller: _controller),
);
return Scaffold(
appBar: AppBar(
centerTitle: true,

View File

@@ -110,7 +110,7 @@ class ChatBubbleWidget extends StatelessWidget {
if (text.isNotEmpty)
Text(
text,
style: TextStyles.textFS13FW400.copyWith(color: appTheme.black),
style: TextStyles.textFS13FW400.copyWith(color: appTheme.black, fontSize: 16),
),
SizedBox(height: 8),
Padding(

View File

@@ -28,6 +28,7 @@ class _DevToolsScreenContentState extends State<DevToolsScreenContent> {
final List<TestCases> testCases = [Test850task()];
final controller = TextEditingController();
late final List<TestState> testsStates;
@override
void initState() {
super.initState();

View File

@@ -14,7 +14,11 @@ class DiaryRepository {
});
Future<DiaryDayModel> getDiaryByDate(String date) async {
return (await getDiaryIndexByDate(date)).last;
try {
return (await getDiaryIndexByDate(date)).last;
} catch (e) {
rethrow;
}
}
Future<List<DiaryDayModel>> getDiaryIndexByDate(String date) async {

View File

@@ -120,11 +120,12 @@ class MenuScreen extends StatelessWidget {
_onTapLogout(BuildContext context) {
return () async {
final response = await sl<Dio>().post(
baseUrl + '/api/profile/logout',
);
if (response.statusCode == 204) {
try {
await sl<Dio>().post(
baseUrl + '/api/profile/logout',
);
} catch (e) {
} finally {
await TokenStorage.removeTokenInStorage();
GoRouter.of(context).go('/auth-screen');
}

View File

@@ -59,6 +59,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
late bool canSub;
bool isFirstFetch = true;
int _currentBullet = 0;
@override
void initState() {
super.initState();
@@ -337,7 +338,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: InkWell(
onTap: () {
GoRouter.of(context).pushNamed('blogPostCreateScreen');
GoRouter.of(context).pushNamed('blogPostCreateScreen');
},
borderRadius: BorderRadius.circular(8),
child: Ink(
@@ -658,6 +659,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
)
: CachedNetworkImage(
imageUrl: baseUrl + '/storage/' + state.profile.badges[i].image,
width: 40,
height: 40,
),
i < state.profile.badges.length - 1 ? const SizedBox(width: 8) : const SizedBox.shrink(),
],

View File

@@ -131,7 +131,7 @@ class _CircumferenceChartWidgetState extends State<CircumferenceChartWidget> {
),
),
Stack(
alignment: Alignment.bottomRight,
alignment: Alignment.center,
children: [
SfCartesianChart(
margin: EdgeInsets.symmetric(horizontal: 8),
@@ -172,115 +172,127 @@ class _CircumferenceChartWidgetState extends State<CircumferenceChartWidget> {
tooltipBehavior: TooltipBehavior(enable: true),
),
if (widget.profileCubit != null)
FloatingActionButton.small(
heroTag: 'addCircumference',
onPressed: () {
if (widget.circumferencePoints.isNotEmpty) {
chest = widget.circumferencePoints.last.chestCircumference;
waist = widget.circumferencePoints.last.waistCircumference;
hip = widget.circumferencePoints.last.hipCircumference;
chestController = FixedExtentScrollController(initialItem: chest - 20);
waistController = FixedExtentScrollController(initialItem: waist - 20);
hipController = FixedExtentScrollController(initialItem: hip - 20);
} else {
chestController = FixedExtentScrollController();
waistController = FixedExtentScrollController();
hipController = FixedExtentScrollController();
}
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: chestController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
chest = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
Positioned(
right: 16,
bottom: 16,
child: FloatingActionButton.small(
heroTag: 'addCircumference',
onPressed: () {
if (widget.circumferencePoints.isNotEmpty) {
chest = widget.circumferencePoints.last.chestCircumference;
waist = widget.circumferencePoints.last.waistCircumference;
hip = widget.circumferencePoints.last.hipCircumference;
chestController = FixedExtentScrollController(initialItem: chest - 20);
waistController = FixedExtentScrollController(initialItem: waist - 20);
hipController = FixedExtentScrollController(initialItem: hip - 20);
} else {
chestController = FixedExtentScrollController();
waistController = FixedExtentScrollController();
hipController = FixedExtentScrollController();
}
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: chestController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
chest = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
),
),
),
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: waistController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
waist = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: waistController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
waist = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
),
),
),
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: hipController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
hip = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: hipController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
hip = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
),
),
),
],
),
),
InkWell(
onTap: () {
widget.profileCubit?.addCircumference(
chestCircumference: chest + 20,
waistCircumference: waist + 20,
hipCircumference: hip + 20,
);
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
],
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
InkWell(
onTap: () {
widget.profileCubit?.addCircumference(
chestCircumference: chest + 20,
waistCircumference: waist + 20,
hipCircumference: hip + 20,
);
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
),
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
),
),
),
if (widget.circumferencePoints.isEmpty)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 48),
child: Text(
'Добавьте Ваши замеры',
textAlign: TextAlign.center,
),
),
],

View File

@@ -45,38 +45,44 @@ class ImtChartWidget extends StatelessWidget {
],
),
),
SfCartesianChart(
margin: EdgeInsets.symmetric(horizontal: 8),
enableAxisAnimation: true,
plotAreaBorderWidth: 0,
trackballBehavior: TrackballBehavior(
enable: true,
activationMode: ActivationMode.singleTap,
tooltipDisplayMode: TrackballDisplayMode.groupAllPoints,
tooltipSettings: InteractiveTooltip(),
lineType: TrackballLineType.vertical,
),
primaryXAxis: DateTimeCategoryAxis(
tickPosition: TickPosition.inside,
majorTickLines: MajorTickLines(
size: 0,
Stack(
alignment: Alignment.center,
children: [
SfCartesianChart(
margin: EdgeInsets.symmetric(horizontal: 8),
enableAxisAnimation: true,
plotAreaBorderWidth: 0,
trackballBehavior: TrackballBehavior(
enable: true,
activationMode: ActivationMode.singleTap,
tooltipDisplayMode: TrackballDisplayMode.groupAllPoints,
tooltipSettings: InteractiveTooltip(),
lineType: TrackballLineType.vertical,
),
primaryXAxis: DateTimeCategoryAxis(
tickPosition: TickPosition.inside,
majorTickLines: MajorTickLines(
size: 0,
),
edgeLabelPlacement: EdgeLabelPlacement.shift,
dateFormat: DateFormat.MMMd('ru'),
labelStyle: TextStyle(
color: Colors.grey,
),
majorGridLines: MajorGridLines(dashArray: [1], color: Colors.grey.withValues(alpha: 0.3)),
axisLine: AxisLine(
color: Colors.grey.withValues(alpha: 0.3),
width: 0.4,
),
),
primaryYAxis: NumericAxis(
isVisible: false,
),
series: _getSplineSeries(),
tooltipBehavior: TooltipBehavior(enable: true),
),
edgeLabelPlacement: EdgeLabelPlacement.shift,
dateFormat: DateFormat.MMMd('ru'),
labelStyle: TextStyle(
color: Colors.grey,
),
majorGridLines: MajorGridLines(dashArray: [1], color: Colors.grey.withValues(alpha: 0.3)),
axisLine: AxisLine(
color: Colors.grey.withValues(alpha: 0.3),
width: 0.4,
),
),
primaryYAxis: NumericAxis(
isVisible: false,
),
series: _getSplineSeries(),
tooltipBehavior: TooltipBehavior(enable: true),
if (weightPoints.isEmpty) Text('Индекс Массы Тела рассчитывается при указанных весе и росте'),
],
),
],
);

View File

@@ -13,7 +13,7 @@ class WeightChartWidget extends StatefulWidget {
const WeightChartWidget({
super.key,
required this.weightPoints,
this.profileCubit,
this.profileCubit,
});
@override
@@ -70,7 +70,7 @@ class _WeightChartWidgetState extends State<WeightChartWidget> {
),
),
Stack(
alignment: Alignment.bottomRight,
alignment: Alignment.center,
children: [
SfCartesianChart(
margin: EdgeInsets.symmetric(horizontal: 8),
@@ -112,99 +112,104 @@ class _WeightChartWidgetState extends State<WeightChartWidget> {
tooltipBehavior: TooltipBehavior(enable: true),
),
if (widget.profileCubit != null)
FloatingActionButton.small(
heroTag: 'addWeight',
onPressed: () {
if (widget.weightPoints.isNotEmpty) {
try {
weightKilo = int.parse(widget.weightPoints.last.weight.toString().split('.')[0]);
weightGrams = int.parse(widget.weightPoints.last.weight.toString().split('.')[1][0]);
} catch (e) {
weightGrams = 0;
Positioned(
right: 16,
bottom: 16,
child: FloatingActionButton.small(
heroTag: 'addWeight',
onPressed: () {
if (widget.weightPoints.isNotEmpty) {
try {
weightKilo = int.parse(widget.weightPoints.last.weight.toString().split('.')[0]);
weightGrams = int.parse(widget.weightPoints.last.weight.toString().split('.')[1][0]);
} catch (e) {
weightGrams = 0;
}
weightKiloController = FixedExtentScrollController(initialItem: weightKilo - 20);
weightGramsController = FixedExtentScrollController(initialItem: weightGrams);
} else {
weightKiloController = FixedExtentScrollController();
weightGramsController = FixedExtentScrollController();
}
weightKiloController = FixedExtentScrollController(initialItem: weightKilo - 20);
weightGramsController = FixedExtentScrollController(initialItem: weightGrams);
} else {
weightKiloController = FixedExtentScrollController();
weightGramsController = FixedExtentScrollController();
}
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightKiloController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightKilo = value + 20;
},
children: [
for (int i = 20; i < 300; i++) Text('$i'),
],
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightKiloController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightKilo = value + 20;
},
children: [
for (int i = 20; i < 300; i++) Text('$i'),
],
),
),
),
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightGramsController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightGrams = value;
},
children: [
for (int i = 0; i < 10; i++) Text('$i'),
],
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightGramsController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightGrams = value;
},
children: [
for (int i = 0; i < 10; i++) Text('$i'),
],
),
),
),
],
),
),
InkWell(
onTap: () {
widget.profileCubit?.addWeight(weight: double.parse('$weightKilo.$weightGrams'));
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
],
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
InkWell(
onTap: () {
widget.profileCubit?.addWeight(weight: double.parse('$weightKilo.$weightGrams'));
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
),
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
),
),
),
if (widget.weightPoints.isEmpty) Text('Добавьте Ваш вес'),
],
),
],

View File

@@ -0,0 +1,37 @@
import 'package:eatvio_app/features/recipes/models/ingredient.dart';
import 'package:eatvio_app/features/recipes/models/step.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'recipe_create_model.freezed.dart';
part 'recipe_create_model.g.dart';
enum RecipeType {
first_meals,
second_meals,
salads,
snacks,
sweets,
drinks,
other
}
@freezed
class RecipeCreateModel with _$RecipeCreateModel {
const factory RecipeCreateModel({
required String title,
required String state,
required String description,
required RecipeType type,
@JsonKey(name: 'video_url') String? videoUrl,
@JsonKey(name: 'cooking_time') String? cookingTime,
@JsonKey(name: 'active_time') String? activeTime,
required String servings,
@JsonKey(name: 'energy_per_serving') required String energyPerServing,
required List<String> tags,
required List<Ingredient> ingredients,
required List<Step> steps,
}) = _RecipeCreateModel;
factory RecipeCreateModel.fromJson(Map<String, Object?> json) => _$RecipeCreateModelFromJson(json);
}

View File

@@ -0,0 +1,442 @@
// 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 'recipe_create_model.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');
RecipeCreateModel _$RecipeCreateModelFromJson(Map<String, dynamic> json) {
return _RecipeCreateModel.fromJson(json);
}
/// @nodoc
mixin _$RecipeCreateModel {
String get title => throw _privateConstructorUsedError;
String get state => throw _privateConstructorUsedError;
String get description => throw _privateConstructorUsedError;
RecipeType get type => throw _privateConstructorUsedError;
@JsonKey(name: 'video_url')
String? get videoUrl => throw _privateConstructorUsedError;
@JsonKey(name: 'cooking_time')
String? get cookingTime => throw _privateConstructorUsedError;
@JsonKey(name: 'active_time')
String? get activeTime => throw _privateConstructorUsedError;
String get servings => throw _privateConstructorUsedError;
@JsonKey(name: 'energy_per_serving')
String get energyPerServing => throw _privateConstructorUsedError;
List<String> get tags => throw _privateConstructorUsedError;
List<Ingredient> get ingredients => throw _privateConstructorUsedError;
List<Step> get steps => throw _privateConstructorUsedError;
/// Serializes this RecipeCreateModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of RecipeCreateModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$RecipeCreateModelCopyWith<RecipeCreateModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $RecipeCreateModelCopyWith<$Res> {
factory $RecipeCreateModelCopyWith(
RecipeCreateModel value, $Res Function(RecipeCreateModel) then) =
_$RecipeCreateModelCopyWithImpl<$Res, RecipeCreateModel>;
@useResult
$Res call(
{String title,
String state,
String description,
RecipeType type,
@JsonKey(name: 'video_url') String? videoUrl,
@JsonKey(name: 'cooking_time') String? cookingTime,
@JsonKey(name: 'active_time') String? activeTime,
String servings,
@JsonKey(name: 'energy_per_serving') String energyPerServing,
List<String> tags,
List<Ingredient> ingredients,
List<Step> steps});
}
/// @nodoc
class _$RecipeCreateModelCopyWithImpl<$Res, $Val extends RecipeCreateModel>
implements $RecipeCreateModelCopyWith<$Res> {
_$RecipeCreateModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of RecipeCreateModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? title = null,
Object? state = null,
Object? description = null,
Object? type = null,
Object? videoUrl = freezed,
Object? cookingTime = freezed,
Object? activeTime = freezed,
Object? servings = null,
Object? energyPerServing = null,
Object? tags = null,
Object? ingredients = null,
Object? steps = null,
}) {
return _then(_value.copyWith(
title: null == title
? _value.title
: title // ignore: cast_nullable_to_non_nullable
as String,
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String,
description: null == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String,
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
as RecipeType,
videoUrl: freezed == videoUrl
? _value.videoUrl
: videoUrl // ignore: cast_nullable_to_non_nullable
as String?,
cookingTime: freezed == cookingTime
? _value.cookingTime
: cookingTime // ignore: cast_nullable_to_non_nullable
as String?,
activeTime: freezed == activeTime
? _value.activeTime
: activeTime // ignore: cast_nullable_to_non_nullable
as String?,
servings: null == servings
? _value.servings
: servings // ignore: cast_nullable_to_non_nullable
as String,
energyPerServing: null == energyPerServing
? _value.energyPerServing
: energyPerServing // ignore: cast_nullable_to_non_nullable
as String,
tags: null == tags
? _value.tags
: tags // ignore: cast_nullable_to_non_nullable
as List<String>,
ingredients: null == ingredients
? _value.ingredients
: ingredients // ignore: cast_nullable_to_non_nullable
as List<Ingredient>,
steps: null == steps
? _value.steps
: steps // ignore: cast_nullable_to_non_nullable
as List<Step>,
) as $Val);
}
}
/// @nodoc
abstract class _$$RecipeCreateModelImplCopyWith<$Res>
implements $RecipeCreateModelCopyWith<$Res> {
factory _$$RecipeCreateModelImplCopyWith(_$RecipeCreateModelImpl value,
$Res Function(_$RecipeCreateModelImpl) then) =
__$$RecipeCreateModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{String title,
String state,
String description,
RecipeType type,
@JsonKey(name: 'video_url') String? videoUrl,
@JsonKey(name: 'cooking_time') String? cookingTime,
@JsonKey(name: 'active_time') String? activeTime,
String servings,
@JsonKey(name: 'energy_per_serving') String energyPerServing,
List<String> tags,
List<Ingredient> ingredients,
List<Step> steps});
}
/// @nodoc
class __$$RecipeCreateModelImplCopyWithImpl<$Res>
extends _$RecipeCreateModelCopyWithImpl<$Res, _$RecipeCreateModelImpl>
implements _$$RecipeCreateModelImplCopyWith<$Res> {
__$$RecipeCreateModelImplCopyWithImpl(_$RecipeCreateModelImpl _value,
$Res Function(_$RecipeCreateModelImpl) _then)
: super(_value, _then);
/// Create a copy of RecipeCreateModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? title = null,
Object? state = null,
Object? description = null,
Object? type = null,
Object? videoUrl = freezed,
Object? cookingTime = freezed,
Object? activeTime = freezed,
Object? servings = null,
Object? energyPerServing = null,
Object? tags = null,
Object? ingredients = null,
Object? steps = null,
}) {
return _then(_$RecipeCreateModelImpl(
title: null == title
? _value.title
: title // ignore: cast_nullable_to_non_nullable
as String,
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String,
description: null == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String,
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
as RecipeType,
videoUrl: freezed == videoUrl
? _value.videoUrl
: videoUrl // ignore: cast_nullable_to_non_nullable
as String?,
cookingTime: freezed == cookingTime
? _value.cookingTime
: cookingTime // ignore: cast_nullable_to_non_nullable
as String?,
activeTime: freezed == activeTime
? _value.activeTime
: activeTime // ignore: cast_nullable_to_non_nullable
as String?,
servings: null == servings
? _value.servings
: servings // ignore: cast_nullable_to_non_nullable
as String,
energyPerServing: null == energyPerServing
? _value.energyPerServing
: energyPerServing // ignore: cast_nullable_to_non_nullable
as String,
tags: null == tags
? _value._tags
: tags // ignore: cast_nullable_to_non_nullable
as List<String>,
ingredients: null == ingredients
? _value._ingredients
: ingredients // ignore: cast_nullable_to_non_nullable
as List<Ingredient>,
steps: null == steps
? _value._steps
: steps // ignore: cast_nullable_to_non_nullable
as List<Step>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$RecipeCreateModelImpl implements _RecipeCreateModel {
const _$RecipeCreateModelImpl(
{required this.title,
required this.state,
required this.description,
required this.type,
@JsonKey(name: 'video_url') this.videoUrl,
@JsonKey(name: 'cooking_time') this.cookingTime,
@JsonKey(name: 'active_time') this.activeTime,
required this.servings,
@JsonKey(name: 'energy_per_serving') required this.energyPerServing,
required final List<String> tags,
required final List<Ingredient> ingredients,
required final List<Step> steps})
: _tags = tags,
_ingredients = ingredients,
_steps = steps;
factory _$RecipeCreateModelImpl.fromJson(Map<String, dynamic> json) =>
_$$RecipeCreateModelImplFromJson(json);
@override
final String title;
@override
final String state;
@override
final String description;
@override
final RecipeType type;
@override
@JsonKey(name: 'video_url')
final String? videoUrl;
@override
@JsonKey(name: 'cooking_time')
final String? cookingTime;
@override
@JsonKey(name: 'active_time')
final String? activeTime;
@override
final String servings;
@override
@JsonKey(name: 'energy_per_serving')
final String energyPerServing;
final List<String> _tags;
@override
List<String> get tags {
if (_tags is EqualUnmodifiableListView) return _tags;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_tags);
}
final List<Ingredient> _ingredients;
@override
List<Ingredient> get ingredients {
if (_ingredients is EqualUnmodifiableListView) return _ingredients;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_ingredients);
}
final List<Step> _steps;
@override
List<Step> get steps {
if (_steps is EqualUnmodifiableListView) return _steps;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_steps);
}
@override
String toString() {
return 'RecipeCreateModel(title: $title, state: $state, description: $description, type: $type, videoUrl: $videoUrl, cookingTime: $cookingTime, activeTime: $activeTime, servings: $servings, energyPerServing: $energyPerServing, tags: $tags, ingredients: $ingredients, steps: $steps)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RecipeCreateModelImpl &&
(identical(other.title, title) || other.title == title) &&
(identical(other.state, state) || other.state == state) &&
(identical(other.description, description) ||
other.description == description) &&
(identical(other.type, type) || other.type == type) &&
(identical(other.videoUrl, videoUrl) ||
other.videoUrl == videoUrl) &&
(identical(other.cookingTime, cookingTime) ||
other.cookingTime == cookingTime) &&
(identical(other.activeTime, activeTime) ||
other.activeTime == activeTime) &&
(identical(other.servings, servings) ||
other.servings == servings) &&
(identical(other.energyPerServing, energyPerServing) ||
other.energyPerServing == energyPerServing) &&
const DeepCollectionEquality().equals(other._tags, _tags) &&
const DeepCollectionEquality()
.equals(other._ingredients, _ingredients) &&
const DeepCollectionEquality().equals(other._steps, _steps));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
title,
state,
description,
type,
videoUrl,
cookingTime,
activeTime,
servings,
energyPerServing,
const DeepCollectionEquality().hash(_tags),
const DeepCollectionEquality().hash(_ingredients),
const DeepCollectionEquality().hash(_steps));
/// Create a copy of RecipeCreateModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$RecipeCreateModelImplCopyWith<_$RecipeCreateModelImpl> get copyWith =>
__$$RecipeCreateModelImplCopyWithImpl<_$RecipeCreateModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$RecipeCreateModelImplToJson(
this,
);
}
}
abstract class _RecipeCreateModel implements RecipeCreateModel {
const factory _RecipeCreateModel(
{required final String title,
required final String state,
required final String description,
required final RecipeType type,
@JsonKey(name: 'video_url') final String? videoUrl,
@JsonKey(name: 'cooking_time') final String? cookingTime,
@JsonKey(name: 'active_time') final String? activeTime,
required final String servings,
@JsonKey(name: 'energy_per_serving')
required final String energyPerServing,
required final List<String> tags,
required final List<Ingredient> ingredients,
required final List<Step> steps}) = _$RecipeCreateModelImpl;
factory _RecipeCreateModel.fromJson(Map<String, dynamic> json) =
_$RecipeCreateModelImpl.fromJson;
@override
String get title;
@override
String get state;
@override
String get description;
@override
RecipeType get type;
@override
@JsonKey(name: 'video_url')
String? get videoUrl;
@override
@JsonKey(name: 'cooking_time')
String? get cookingTime;
@override
@JsonKey(name: 'active_time')
String? get activeTime;
@override
String get servings;
@override
@JsonKey(name: 'energy_per_serving')
String get energyPerServing;
@override
List<String> get tags;
@override
List<Ingredient> get ingredients;
@override
List<Step> get steps;
/// Create a copy of RecipeCreateModel
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$RecipeCreateModelImplCopyWith<_$RecipeCreateModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,55 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'recipe_create_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$RecipeCreateModelImpl _$$RecipeCreateModelImplFromJson(
Map<String, dynamic> json) =>
_$RecipeCreateModelImpl(
title: json['title'] as String,
state: json['state'] as String,
description: json['description'] as String,
type: $enumDecode(_$RecipeTypeEnumMap, json['type']),
videoUrl: json['video_url'] as String?,
cookingTime: json['cooking_time'] as String?,
activeTime: json['active_time'] as String?,
servings: json['servings'] as String,
energyPerServing: json['energy_per_serving'] as String,
tags: (json['tags'] as List<dynamic>).map((e) => e as String).toList(),
ingredients: (json['ingredients'] as List<dynamic>)
.map((e) => Ingredient.fromJson(e as Map<String, dynamic>))
.toList(),
steps: (json['steps'] as List<dynamic>)
.map((e) => Step.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$RecipeCreateModelImplToJson(
_$RecipeCreateModelImpl instance) =>
<String, dynamic>{
'title': instance.title,
'state': instance.state,
'description': instance.description,
'type': _$RecipeTypeEnumMap[instance.type]!,
'video_url': instance.videoUrl,
'cooking_time': instance.cookingTime,
'active_time': instance.activeTime,
'servings': instance.servings,
'energy_per_serving': instance.energyPerServing,
'tags': instance.tags,
'ingredients': instance.ingredients,
'steps': instance.steps,
};
const _$RecipeTypeEnumMap = {
RecipeType.first_meals: 'first_meals',
RecipeType.second_meals: 'second_meals',
RecipeType.salads: 'salads',
RecipeType.snacks: 'snacks',
RecipeType.sweets: 'sweets',
RecipeType.drinks: 'drinks',
RecipeType.other: 'other',
};

View File

@@ -41,7 +41,6 @@ class _AdditionalInformationScreenState extends State<AdditionalInformationScree
SizedBox(height: 4),
CustomTextFormField(
controller: editTextController,
hintText: "У меня крепкое здоровье, но последнее время часто утомляюсь, однако, это мне не мешает радоваться жизни",
textInputAction: TextInputAction.done,
maxLines: 8,
inputFormatters: [

View File

@@ -37,8 +37,6 @@ class _FavoriteSportsScreenState extends State<FavoriteSportsScreen> {
SizedBox(height: 4),
CustomTextFormField(
controller: enterInformationController,
hintText: "Я занимаюсь плаванием , почти каждый вечер прогулки на свежем воздухе, пару раз в месяц играю в волейбол. Стараюсь не сидеть на месте!",
textInputAction: TextInputAction.done,
focusNode: infoFocusNode,
autofocus: true,
maxLines: 8,

View File

@@ -15,7 +15,12 @@ class SupportScreen extends StatelessWidget {
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Text('Если у вас есть вопросы по работе нашего приложения, вы можете задать их, перейдя по ссылке:'),
child: Text(
'Если у вас есть вопросы по работе нашего приложения, вы можете задать их, перейдя по ссылке:',
style: TextStyle(
fontSize: 16,
),
),
),
InkWell(
onTap: () {
@@ -35,7 +40,12 @@ class SupportScreen extends StatelessWidget {
colorFilter: ColorFilter.mode(Colors.black, BlendMode.srcIn),
),
const SizedBox(width: 12),
Text('Telegram'),
Text(
'Telegram',
style: TextStyle(
fontSize: 16,
),
),
],
),
),
@@ -56,7 +66,12 @@ class SupportScreen extends StatelessWidget {
children: [
Icon(Icons.alternate_email_rounded),
const SizedBox(width: 12),
Text('E-mail'),
Text(
'E-mail',
style: TextStyle(
fontSize: 16,
),
),
],
),
),