forked from eatvio/eatvio_app
Merge pull request 'mso7nueh' (#156) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#156
This commit is contained in:
@@ -159,7 +159,7 @@ class AppRouter {
|
||||
GoRoute(
|
||||
path: '/blog-post-create-screen',
|
||||
name: 'blogPostCreateScreen',
|
||||
builder: (context, state) => BlogPostCreateScreen.builder(context),
|
||||
builder: (context, state) => BlogPostCreateScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/blog-post-screen',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:eatvio_app/old/feed/blog_post_create_screen/bloc/blog_post_create_bloc.dart';
|
||||
import 'package:eatvio_app/old/feed/blog_post_create_screen/models/blog_post_create_model.dart';
|
||||
import 'package:eatvio_app/theme/app_decoration.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
||||
@@ -13,22 +13,13 @@ import 'package:image_picker/image_picker.dart';
|
||||
class BlogPostCreateScreen extends StatefulWidget {
|
||||
const BlogPostCreateScreen({Key? key}) : super(key: key);
|
||||
|
||||
static Widget builder(BuildContext context) {
|
||||
final blog_postID = ModalRoute.of(context)!.settings.arguments;
|
||||
return BlocProvider<BlogPostCreateBloc>(
|
||||
create: (context) => BlogPostCreateBloc(BlogPostCreateState(blog_postModelObj: BlogPostCreateModel(blog_postID: blog_postID.toString())))
|
||||
..add(BlogPostCreateInitialEvent()),
|
||||
child: BlogPostCreateScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
State<BlogPostCreateScreen> createState() => _BlogPostCreateScreenState();
|
||||
}
|
||||
|
||||
class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
final blogPostCreateBloc = BlogPostCreateBloc(BlogPostCreateState())..add(BlogPostCreateInitialEvent());
|
||||
bool shrinkImage = false;
|
||||
|
||||
late StreamSubscription<bool> keyboardSubscription;
|
||||
|
||||
@override
|
||||
@@ -49,24 +40,72 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<BlogPostCreateBloc, BlogPostCreateState>(
|
||||
builder: (context, state) {
|
||||
if (state is BlogPostCreateInitialState) {
|
||||
// Это начальное состояние, данные ещё не загружены.
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
);
|
||||
} else if (state is BlogPostCreateLoadedState) {
|
||||
// Данные загружены, можно строить экран.
|
||||
return _buildBlogPostCreate(context, state);
|
||||
} else if (state is BlogPostCreateErrorState) {
|
||||
// Произошла ошибка при загрузке данных.
|
||||
return Center(child: Text(state.errorMessage));
|
||||
} else {
|
||||
// Другие состояния, если они есть.
|
||||
return Container(); // Пустой контейнер для необработанных состояний.
|
||||
}
|
||||
},
|
||||
return BlocProvider<BlogPostCreateBloc>(
|
||||
create: (BuildContext context) => blogPostCreateBloc,
|
||||
child: BlocBuilder<BlogPostCreateBloc, BlogPostCreateState>(
|
||||
builder: (context, state) {
|
||||
if (state is BlogPostCreateInitialState) {
|
||||
// Это начальное состояние, данные ещё не загружены.
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
);
|
||||
} else if (state is BlogPostCreateLoadedState) {
|
||||
// Данные загружены, можно строить экран.
|
||||
return _buildBlogPostCreate(context, state);
|
||||
} else if (state is BlogPostCreateErrorState) {
|
||||
// Произошла ошибка при загрузке данных.
|
||||
return Center(child: Text(state.errorMessage));
|
||||
} else {
|
||||
// Другие состояния, если они есть.
|
||||
return Container(); // Пустой контейнер для необработанных состояний.
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_showImagePicker() {
|
||||
showCupertinoModalPopup<void>(
|
||||
context: context,
|
||||
builder: (context) => CupertinoActionSheet(
|
||||
actions: [
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () async {
|
||||
final picker = ImagePicker();
|
||||
XFile? image = await picker.pickImage(source: ImageSource.camera);
|
||||
if (image != null) blogPostCreateBloc.add(UploadImages(image));
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Row(
|
||||
children: const [
|
||||
Icon(Icons.photo_camera),
|
||||
SizedBox(width: 8),
|
||||
Text('Фото'),
|
||||
],
|
||||
),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () async {
|
||||
final picker = ImagePicker();
|
||||
XFile? image = await picker.pickImage(source: ImageSource.gallery);
|
||||
if (image != null) blogPostCreateBloc.add(UploadImages(image));
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Row(
|
||||
children: const [
|
||||
Icon(Icons.photo),
|
||||
SizedBox(width: 8),
|
||||
Text('Галерея'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
isDestructiveAction: true,
|
||||
child: const Text('Отмена'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -164,15 +203,15 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
),
|
||||
),
|
||||
if (state.image != null)
|
||||
AnimatedContainer(
|
||||
Container(
|
||||
width: shrinkImage ? 52 : MediaQuery.of(context).size.width - 32,
|
||||
curve: Curves.easeIn,
|
||||
duration: Duration(milliseconds: 150),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Image(
|
||||
image: FileImage(
|
||||
File(state.image!.path),
|
||||
File(
|
||||
state.image!.path,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -181,6 +220,14 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
addImage(BuildContext context, bool isLoading) {
|
||||
if (!isLoading) {
|
||||
return () {
|
||||
_showImagePicker();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_submitForm(
|
||||
@@ -191,15 +238,3 @@ _submitForm(
|
||||
) async {
|
||||
context.read<BlogPostCreateBloc>().add(CreateBlogPost());
|
||||
}
|
||||
|
||||
addImage(BuildContext context, bool isLoading) {
|
||||
if (!isLoading) {
|
||||
return () async {
|
||||
final picker = ImagePicker();
|
||||
XFile? image = await picker.pickImage(source: ImageSource.gallery);
|
||||
if (image != null) {
|
||||
context.read<BlogPostCreateBloc>().add(UploadImages(image));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
|
||||
return Scaffold(
|
||||
body: widget.child,
|
||||
bottomNavigationBar: SizedBox(
|
||||
height: 58,
|
||||
height: 80,
|
||||
child: BottomNavigationBar(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
onTap: _onItemTapped,
|
||||
|
||||
@@ -130,7 +130,7 @@ class _DiaryScreenState extends State<DiaryScreen> {
|
||||
state.diary,
|
||||
state.currentSelectedSatietyRating,
|
||||
),
|
||||
if (state is DiaryStateLoaded) _chart(state.nutrition),
|
||||
if (state is DiaryStateLoaded && _selectedDay!.compareTo(today!) != 1) _chart(state.nutrition),
|
||||
if (state is DiaryStateLoaded && state.diary.closed == 0 && _selectedDay == today)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
@@ -278,23 +278,25 @@ class _DiaryScreenState extends State<DiaryScreen> {
|
||||
_mealButton(5),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_divider(context),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Время приема пищи',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF323F4B),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
_selectedDay!.compareTo(today!) == 1 ? const SizedBox.shrink() : const SizedBox(height: 12),
|
||||
_selectedDay!.compareTo(today!) == 1 ? const SizedBox.shrink() : _divider(context),
|
||||
_selectedDay!.compareTo(today!) == 1 ? const SizedBox.shrink() : const SizedBox(height: 12),
|
||||
_selectedDay!.compareTo(today!) == 1
|
||||
? const SizedBox.shrink()
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Время приема пищи',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF323F4B),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
_timeOfMeal(time),
|
||||
],
|
||||
),
|
||||
),
|
||||
_timeOfMeal(time),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_divider(context),
|
||||
const SizedBox(height: 12),
|
||||
@@ -303,21 +305,25 @@ class _DiaryScreenState extends State<DiaryScreen> {
|
||||
_addProductButton(diaryDay),
|
||||
const SizedBox(height: 24),
|
||||
if (diaryDay.meals[currentSelectedMealNumber - 1].photos.isEmpty)
|
||||
GestureDetector(
|
||||
onTap: () => _showImagePicker(diaryDay),
|
||||
child: SvgPicture.asset(
|
||||
width: MediaQuery.of(context).size.width - 32,
|
||||
'assets/no_one_image_was_added.svg',
|
||||
),
|
||||
),
|
||||
_selectedDay!.compareTo(today!) == 1
|
||||
? const SizedBox.shrink()
|
||||
: GestureDetector(
|
||||
onTap: () => _showImagePicker(diaryDay),
|
||||
child: SvgPicture.asset(
|
||||
width: MediaQuery.of(context).size.width - 32,
|
||||
'assets/no_one_image_was_added.svg',
|
||||
),
|
||||
),
|
||||
if (diaryDay.meals[currentSelectedMealNumber - 1].photos.isNotEmpty)
|
||||
_photoGallery(
|
||||
diaryDay.meals[currentSelectedMealNumber - 1].photos,
|
||||
diaryDay,
|
||||
),
|
||||
SatietyRatingWidget(
|
||||
currentSelectedSatietyRating: currentSelectedSatietyRating,
|
||||
),
|
||||
_selectedDay!.compareTo(today!) == 1
|
||||
? const SizedBox.shrink()
|
||||
: SatietyRatingWidget(
|
||||
currentSelectedSatietyRating: currentSelectedSatietyRating,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -1057,6 +1063,7 @@ class _DiaryScreenState extends State<DiaryScreen> {
|
||||
}
|
||||
|
||||
_addProductButton(DiaryDayModel diaryDay) {
|
||||
if (_selectedDay!.compareTo(today!) == 1) return const SizedBox.shrink();
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class OtherInfoScreen extends StatefulWidget {
|
||||
@@ -60,6 +59,7 @@ class _OtherInfoScreenState extends State<OtherInfoScreen> {
|
||||
autofocus: true,
|
||||
minLines: 2,
|
||||
maxLines: 8,
|
||||
maxLength: 250,
|
||||
onChanged: (newValue) {},
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
@@ -70,6 +70,7 @@ class _OtherInfoScreenState extends State<OtherInfoScreen> {
|
||||
hintText: s.enter_information,
|
||||
autofocus: true,
|
||||
minLines: 2,
|
||||
maxLength: 250,
|
||||
maxLines: 8,
|
||||
onChanged: (newValue) {},
|
||||
),
|
||||
@@ -82,6 +83,7 @@ class _OtherInfoScreenState extends State<OtherInfoScreen> {
|
||||
"Я занимаюсь плаванием , почти каждый вечер прогулки на свежем воздухе, пару раз в месяц играю в волейбол. Стараюсь не сидеть на месте!",
|
||||
autofocus: true,
|
||||
maxLines: 8,
|
||||
maxLength: 250,
|
||||
onChanged: (newValue) {},
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
@@ -92,6 +94,7 @@ class _OtherInfoScreenState extends State<OtherInfoScreen> {
|
||||
hintText: s.enter_information,
|
||||
maxLines: 7,
|
||||
minLines: 2,
|
||||
maxLength: 250,
|
||||
onChanged: (newValue) {},
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
@@ -102,6 +105,7 @@ class _OtherInfoScreenState extends State<OtherInfoScreen> {
|
||||
hintText: s.enter_information,
|
||||
maxLines: 7,
|
||||
minLines: 2,
|
||||
maxLength: 250,
|
||||
onChanged: (newValue) {},
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
@@ -114,9 +118,7 @@ class _OtherInfoScreenState extends State<OtherInfoScreen> {
|
||||
SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
controller: additionalInfoController,
|
||||
inputFormatters: [
|
||||
new LengthLimitingTextInputFormatter(250),
|
||||
],
|
||||
maxLength: 250,
|
||||
hintText: "У меня крепкое здоровье, но последнее время часто утомляюсь, однако, это мне не мешает радоваться жизни",
|
||||
maxLines: 8,
|
||||
onChanged: (newValue) {},
|
||||
|
||||
@@ -34,6 +34,7 @@ class CustomTextFormField extends StatelessWidget {
|
||||
this.onChanged,
|
||||
this.onEditingComplete,
|
||||
this.minLines = 1,
|
||||
this.maxLength,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@@ -67,6 +68,7 @@ class CustomTextFormField extends StatelessWidget {
|
||||
final Function()? onEditingComplete;
|
||||
final void Function(String?)? onSaved;
|
||||
final void Function(String)? onChanged;
|
||||
final int? maxLength;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -74,6 +76,7 @@ class CustomTextFormField extends StatelessWidget {
|
||||
alignment: alignment ?? Alignment.center,
|
||||
child: TextFormField(
|
||||
minLines: minLines,
|
||||
maxLength: maxLength,
|
||||
onChanged: onChanged,
|
||||
controller: controller,
|
||||
focusNode: focusNode ?? null,
|
||||
|
||||
Reference in New Issue
Block a user