diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml
index e8e16098..a6d70a2a 100644
--- a/.gitea/workflows/build.yml
+++ b/.gitea/workflows/build.yml
@@ -1,15 +1,15 @@
-name: Android Release
+name: Eatvio App Android Test
-on: [ push, pull_request ]
+on: [ pull_request ]
env:
- flutter_version: "3.22.0"
- java_version: "12.x"
+ flutter_version: "3.24.5"
+ java_version: "21.x"
flutter_channel: "stable"
jobs:
build:
- runs-on: ubuntu-latest
+ runs-on: [ dev-office ]
steps:
- uses: actions/checkout@v3
@@ -17,9 +17,9 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v3
with:
- distribution: 'zulu'
+ distribution: "zulu"
java-version: ${{ env.java_version }}
- cache: 'gradle'
+ id: setup-jdk
- name: Install Android SDK
run: |
@@ -31,18 +31,17 @@ jobs:
mv cmdline-tools/* $HOME/Android/Sdk/cmdline-tools/latest/
export ANDROID_SDK_ROOT=$HOME/Android/Sdk
export PATH=$PATH:$HOME/Android/Sdk/cmdline-tools/latest/bin
- sdkmanager "platform-tools" "platforms;android-30" "build-tools;30.0.3"
+ yes | sdkmanager --licenses 2>/dev/null || true
- name: Set up Android environment variables
run: |
echo "ANDROID_SDK_ROOT=$HOME/Android/Sdk" >> $GITHUB_ENV
- echo "PATH=$PATH:$HOME/Android/Sdk/platform-tools:$HOME/Android/Sdk/build-tools/30.0.3" >> $GITHUB_ENV
- echo "ANDROID_HOME=$HOME/Android/Sdk" >> $GITHUB_ENV
+ echo "PATH=$PATH:$HOME/Android/Sdk/cmdline-tools/latest/bin:$HOME/Android/Sdk/platform-tools:$HOME/Android/Sdk/build-tools/30.0.3" >> $GITHUB_ENV
+ echo "ANDROID_HOME=$HOME/Android/Sdk" >> $GITHUB_ENV
- - uses: actions/cache@v2
- with:
- path: ${{ runner.tool_cache }}/flutter
- key: flutter-${{ env.flutter_version }}-${{ env.flutter_channel }}
+ - name: Install jq
+ run: |
+ apt-get install -y jq
- id: flutter-action
uses: actions/flutter-action@v2
@@ -51,21 +50,11 @@ jobs:
flutter-version: ${{ env.flutter_version }}
cache: true
- - name: show cache keys
- run: |
- echo CACHE-PATH=${{ steps.flutter-action.outputs.CACHE-PATH }}
- echo CACHE-KEY=${{ steps.flutter-action.outputs.CACHE-KEY }}
- echo CHANNEL=${{ steps.flutter-action.outputs.CHANNEL }}
- echo VERSION=${{ steps.flutter-action.outputs.VERSION }}
- echo ARCHITECTURE=${{ steps.flutter-action.outputs.ARCHITECTURE }}
- echo PUB-CACHE-PATH=${{ steps.flutter-action.outputs.PUB-CACHE-PATH }}
- echo PUB-CACHE-KEY=${{ steps.flutter-action.outputs.PUB-CACHE-KEY }}
- shell: bash
-
- - name: fix dir permissions
+ - name: Fix dir permissions
run: |
git config --global --add safe.directory /opt/hostedtoolcache/flutter/${{ env.flutter_channel }}-${{ env.flutter_version }}-${{ steps.flutter-action.outputs.ARCHITECTURE }}
- flutter --version
+ flutter config --android-sdk="$ANDROID_HOME"
+ flutter doctor -v
- name: Get dependencies
run: flutter pub get
@@ -73,15 +62,13 @@ jobs:
- name: Native Analyze
run: flutter analyze
- - name: Run Code Metrics
- run: flutter pub run dart_code_metrics:metrics lib --disable-sunset-warning --fatal-warnings --fatal-performance
-
- name: Test
run: |
- flutter test
+ flutter test
- name: Build apk
- run: flutter build apk
+ run: |
+ flutter build apk
- name: Rename and move apk
run: |
@@ -89,3 +76,10 @@ jobs:
APK_NAME="eatvio_app_${TIMESTAMP}.apk"
mv build/app/outputs/flutter-apk/app-release.apk $APK_NAME
echo "APK build finished $APK_NAME"
+ echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
+
+ - name: Upload APK artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: ${{ env.APK_NAME }}
+ path: ${{ env.APK_NAME }}
diff --git a/.gitea/workflows/docker-run-tests.yml b/.gitea/workflows/docker-run-tests.yml
new file mode 100644
index 00000000..99cc866e
--- /dev/null
+++ b/.gitea/workflows/docker-run-tests.yml
@@ -0,0 +1,57 @@
+name: Eatvio App Android Test on custom docker
+
+on: [ pull_request ]
+
+env:
+ flutter_version: "3.24.5"
+ java_version: "21.x"
+ flutter_channel: "stable"
+ my_local_cache_dir: "/opt/hostedtoolcache/"
+ ANDROID_SDK_ROOT: "/opt/hostedtoolcache/Android/Sdk"
+ PUB_CACHE: "/opt/hostedtoolcache/.pub-cache"
+
+jobs:
+ build:
+ runs-on: [ dev-office-flutter ]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Set up Android environment variables
+ id: "android-env-setup"
+ run: |
+ echo "ANDROID_SDK_ROOT=${{ env.my_local_cache_dir }}Android/Sdk" >> $GITHUB_ENV
+ echo "PATH=$PATH:${{ env.my_local_cache_dir }}Android/Sdk/cmdline-tools/latest/bin:${{ env.my_local_cache_dir }}Android/Sdk/platform-tools:${{ env.my_local_cache_dir }}Android/Sdk/build-tools/30.0.3:${{ env.my_local_cache_dir }}Android/Sdk/build-tools/34.0.0" >> $GITHUB_ENV
+ echo "ANDROID_HOME=${{ env.my_local_cache_dir }}Android/Sdk" >> $GITHUB_ENV
+
+ - name: Fix dir permissions
+ run: |
+ git config --global --add safe.directory /opt/hostedtoolcache/flutter/${{ env.flutter_channel }}-${{ env.flutter_version }}-${{ steps.flutter-action.outputs.ARCHITECTURE }}
+ flutter config --android-sdk="$ANDROID_HOME"
+ flutter doctor -v
+
+ - name: Get dependencies
+ run: flutter pub get
+
+ - name: Native Analyze
+ run: flutter analyze
+
+ - name: Test
+ run: flutter test
+
+ # - name: Build apk
+ # run: flutter build apk
+
+ # - name: Rename and move apk
+ # run: |
+ # TIMESTAMP=$(TZ=Europe/Moscow date +'%Y-%m-%d-%H-%M')
+ # APK_NAME="eatvio_app_${TIMESTAMP}.apk"
+ # mv build/app/outputs/flutter-apk/app-release.apk $APK_NAME
+ # echo "APK build finished $APK_NAME"
+ # echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
+
+ # - name: Upload APK artifact
+ # uses: actions/upload-artifact@v3
+ # with:
+ # name: ${{ env.APK_NAME }}
+ # path: ${{ env.APK_NAME }}
diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml
index 0b639038..24078471 100644
--- a/.gitea/workflows/test.yml
+++ b/.gitea/workflows/test.yml
@@ -3,56 +3,61 @@ name: Eatvio App Android Test
on: [ pull_request ]
env:
- flutter_version: "3.24.4"
+ flutter_version: "3.24.5"
java_version: "21.x"
flutter_channel: "stable"
+ my_local_cache_dir: "/opt/hostedtoolcache/"
+ ANDROID_SDK_ROOT: "/opt/hostedtoolcache/Android/Sdk"
jobs:
build:
- runs-on: ubuntu-latest
+ runs-on: [ dev-office ]
steps:
- uses: actions/checkout@v3
+ - name: Cache Android SDK
+ id: cache-sdk
+ uses: "https://gitea.com/actions/cache@v4"
+ with:
+ path: ${{ env.my_local_cache_dir }}
+ key: ${{ runner.os }}-cache-sdk
+
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: "zulu"
java-version: ${{ env.java_version }}
- cache: "gradle"
+ cache: gradle
- - name: Install Android SDK
+ - name: Install utils for Android SDK
run: |
apt-get update
- apt-get install -y openjdk-11-jdk wget
+ apt-get install -y openjdk-11-jdk wget jq clang cmake ninja-build libgtk-3-dev
+
+ - name: Install Android SDK
+ if: steps.cache-sdk.outputs.cache-hit != 'true'
+ run: |
wget https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip -O commandlinetools.zip
unzip commandlinetools.zip
- mkdir -p $HOME/Android/Sdk/cmdline-tools/latest
- mv cmdline-tools/* $HOME/Android/Sdk/cmdline-tools/latest/
- export ANDROID_SDK_ROOT=$HOME/Android/Sdk
- export PATH=$PATH:$HOME/Android/Sdk/cmdline-tools/latest/bin
+ mkdir -p ${{ env.my_local_cache_dir }}Android/Sdk/cmdline-tools/latest
+ mv cmdline-tools/* ${{ env.my_local_cache_dir }}Android/Sdk/cmdline-tools/latest/
+ export ANDROID_SDK_ROOT=${{ env.my_local_cache_dir }}Android/Sdk
+ export PATH=$PATH:${{ env.my_local_cache_dir }}Android/Sdk/cmdline-tools/latest/bin
yes | sdkmanager --licenses 2>/dev/null || true
+ sdkmanager --list | egrep "platform-tools|build-tools|ndk"
+ sdkmanager "platform-tools"
+ sdkmanager "platform-tools" "platforms;android-35" "platforms;android-34" "platforms;android-33" "platforms;android-31"
+ sdkmanager "build-tools;34.0.0"
+ sdkmanager "ndk;25.1.8937393"
+ sdkmanager --install "cmake;3.22.1"
- name: Set up Android environment variables
+ id: "android-env-setup"
run: |
- echo "ANDROID_SDK_ROOT=$HOME/Android/Sdk" >> $GITHUB_ENV
- echo "PATH=$PATH:$HOME/Android/Sdk/cmdline-tools/latest/bin:$HOME/Android/Sdk/platform-tools:$HOME/Android/Sdk/build-tools/30.0.3" >> $GITHUB_ENV
- echo "ANDROID_HOME=$HOME/Android/Sdk" >> $GITHUB_ENV
-
- - name: Debug Environment Variables
- run: |
- echo "ANDROID_SDK_ROOT: $ANDROID_SDK_ROOT"
- echo "ANDROID_HOME: $ANDROID_HOME"
- echo "PATH: $PATH"
-
- - uses: actions/cache@v2
- with:
- path: ${{ runner.tool_cache }}/flutter
- key: flutter-${{ env.flutter_version }}-${{ env.flutter_channel }}
-
- - name: Install jq
- run: |
- apt-get install -y jq
+ echo "ANDROID_SDK_ROOT=${{ env.my_local_cache_dir }}Android/Sdk" >> $GITHUB_ENV
+ echo "PATH=$PATH:${{ env.my_local_cache_dir }}Android/Sdk/cmdline-tools/latest/bin:${{ env.my_local_cache_dir }}Android/Sdk/platform-tools:${{ env.my_local_cache_dir }}Android/Sdk/build-tools/30.0.3:${{ env.my_local_cache_dir }}Android/Sdk/build-tools/34.0.0" >> $GITHUB_ENV
+ echo "ANDROID_HOME=${{ env.my_local_cache_dir }}Android/Sdk" >> $GITHUB_ENV
- id: flutter-action
uses: actions/flutter-action@v2
@@ -60,23 +65,30 @@ jobs:
channel: ${{ env.flutter_channel }}
flutter-version: ${{ env.flutter_version }}
cache: true
+ cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" # optional, change this to force refresh cache
+ cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:" # optional, change this to specify the cache path
+ pub-cache-key: "flutter-pub:os:-:channel:-:version:-:arch:-:hash:" # optional, change this to force refresh cache of dart pub get dependencies
+ pub-cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:" # optional, change this to specify the cache path
- - name: Show cache keys
- run: |
- echo CACHE-PATH=${{ steps.flutter-action.outputs.CACHE-PATH }}
- echo CACHE-KEY=${{ steps.flutter-action.outputs.CACHE-KEY }}
- echo CHANNEL=${{ steps.flutter-action.outputs.CHANNEL }}
- echo VERSION=${{ steps.flutter-action.outputs.VERSION }}
- echo ARCHITECTURE=${{ steps.flutter-action.outputs.ARCHITECTURE }}
- echo PUB-CACHE-PATH=${{ steps.flutter-action.outputs.PUB-CACHE-PATH }}
- echo PUB-CACHE-KEY=${{ steps.flutter-action.outputs.PUB-CACHE-KEY }}
- shell: bash
+ # - name: Print flutter-action outputs
+ # shell: bash
+ # run: |
+ # echo CACHE-PATH=${{ steps.flutter-action.outputs.CACHE-PATH }}
+ # echo CACHE-KEY=${{ steps.flutter-action.outputs.CACHE-KEY }}
+ # echo CHANNEL=${{ steps.flutter-action.outputs.CHANNEL }}
+ # echo VERSION=${{ steps.flutter-action.outputs.VERSION }}
+ # echo ARCHITECTURE=${{ steps.flutter-action.outputs.ARCHITECTURE }}
+ # echo PUB-CACHE-PATH=${{ steps.flutter-action.outputs.PUB-CACHE-PATH }}
+ # echo PUB-CACHE-KEY=${{ steps.flutter-action.outputs.PUB-CACHE-KEY }}
+ # echo "PATH is $PATH"
+ # echo "ANDROID_SDK_ROOT is $ANDROID_SDK_ROOT"
+ # echo "ANDROID_HOME is $ANDROID_HOME"
- name: Fix dir permissions
run: |
git config --global --add safe.directory /opt/hostedtoolcache/flutter/${{ env.flutter_channel }}-${{ env.flutter_version }}-${{ steps.flutter-action.outputs.ARCHITECTURE }}
flutter config --android-sdk="$ANDROID_HOME"
- flutter doctor -v
+ flutter doctor -v
- name: Get dependencies
run: flutter pub get
@@ -84,24 +96,19 @@ jobs:
- name: Native Analyze
run: flutter analyze
- #- name: Run Code Metrics
- # run: flutter pub run dart_code_metrics:metrics lib --disable-sunset-warning --fatal-warnings --fatal-performance
-
- name: Test
- run: |
- flutter test
+ run: flutter test
- name: Build apk
- run: |
- flutter build apk
+ run: flutter build apk
- name: Rename and move apk
run: |
- TIMESTAMP=$(date +'%Y-%m-%d-%H-%M')
+ TIMESTAMP=$(TZ=Europe/Moscow date +'%Y-%m-%d-%H-%M')
APK_NAME="eatvio_app_${TIMESTAMP}.apk"
mv build/app/outputs/flutter-apk/app-release.apk $APK_NAME
echo "APK build finished $APK_NAME"
- echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
+ echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
- name: Upload APK artifact
uses: actions/upload-artifact@v3
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 5841cc1f..2496707b 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,3 @@
-#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 7454c98b..b335af4e 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -361,7 +361,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CURRENT_PROJECT_VERSION = 16;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -369,6 +369,8 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = Eatvio;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -377,6 +379,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
+ MARKETING_VERSION = 2.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -504,7 +507,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CURRENT_PROJECT_VERSION = 16;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -512,6 +515,8 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = Eatvio;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -520,6 +525,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
+ MARKETING_VERSION = 2.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -535,7 +541,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CURRENT_PROJECT_VERSION = 16;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -543,6 +549,8 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = Eatvio;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -551,6 +559,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
+ MARKETING_VERSION = 2.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 8795a89d..9efe0f5f 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -27,7 +27,9 @@
UIMainStoryboardFile
Main
NSPhotoLibraryUsageDescription
- UserPhotoUpload
+ Нужно для загрузки фото
+ NSCameraUsageDescription
+ Нужно для загрузки фото
UIBackgroundModes
fetch
diff --git a/lib/app_router.dart b/lib/app_router.dart
index 43c2e357..9d4df0ba 100644
--- a/lib/app_router.dart
+++ b/lib/app_router.dart
@@ -160,7 +160,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',
diff --git a/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart b/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart
index d76b7bd4..d41a1967 100644
--- a/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart
+++ b/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart
@@ -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(
- create: (context) => BlogPostCreateBloc(BlogPostCreateState(blog_postModelObj: BlogPostCreateModel(blog_postID: blog_postID.toString())))
- ..add(BlogPostCreateInitialEvent()),
- child: BlogPostCreateScreen(),
- );
- }
-
@override
State createState() => _BlogPostCreateScreenState();
}
class _BlogPostCreateScreenState extends State {
+ final blogPostCreateBloc = BlogPostCreateBloc(BlogPostCreateState())..add(BlogPostCreateInitialEvent());
bool shrinkImage = false;
-
late StreamSubscription keyboardSubscription;
@override
@@ -49,24 +40,72 @@ class _BlogPostCreateScreenState extends State {
}
Widget build(BuildContext context) {
- return BlocBuilder(
- 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(
+ create: (BuildContext context) => blogPostCreateBloc,
+ child: BlocBuilder(
+ 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(
+ 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 {
),
),
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 {
),
);
}
+
+ addImage(BuildContext context, bool isLoading) {
+ if (!isLoading) {
+ return () {
+ _showImagePicker();
+ };
+ }
+ }
}
_submitForm(
@@ -191,15 +238,3 @@ _submitForm(
) async {
context.read().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().add(UploadImages(image));
- }
- };
- }
-}
diff --git a/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart b/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart
index ce8a8bca..ebab1850 100644
--- a/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart
+++ b/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart
@@ -62,157 +62,154 @@ class _BottomNavigationBarWidgetState extends State {
final s = S.of(context);
return Scaffold(
body: widget.child,
- bottomNavigationBar: SizedBox(
- height: 58,
- child: BottomNavigationBar(
- type: BottomNavigationBarType.fixed,
- onTap: _onItemTapped,
- selectedFontSize: 10,
- unselectedFontSize: 10,
- selectedItemColor: appTheme.blueA400,
- currentIndex: currentBottomNavBarIndex,
- items: [
- BottomNavigationBarItem(
- label: '',
- icon: BlocProvider(
- create: (context) => sl()..getMyProfile(),
- child: BlocBuilder(
- builder: (BuildContext context, ProfileAvatarState state) {
- if (state is ProfileAvatarStateLoaded) {
- return CircleAvatar(
- backgroundImage: NetworkImage(state.profile.profilePhotoUrl),
- radius: 16,
- );
- }
+ bottomNavigationBar: BottomNavigationBar(
+ type: BottomNavigationBarType.fixed,
+ onTap: _onItemTapped,
+ selectedFontSize: 10,
+ unselectedFontSize: 10,
+ selectedItemColor: appTheme.blueA400,
+ currentIndex: currentBottomNavBarIndex,
+ items: [
+ BottomNavigationBarItem(
+ label: '',
+ icon: BlocProvider(
+ create: (context) => sl()..getMyProfile(),
+ child: BlocBuilder(
+ builder: (BuildContext context, ProfileAvatarState state) {
+ if (state is ProfileAvatarStateLoaded) {
return CircleAvatar(
+ backgroundImage: NetworkImage(state.profile.profilePhotoUrl),
radius: 16,
- backgroundColor: Colors.black12,
);
- },
- ),
- ),
- ),
- BottomNavigationBarItem(
- label: 'Лента',
- icon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- width: 20,
- height: 20,
- ImageConstant.icnFeed,
- ),
- ),
- activeIcon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnFeed,
- width: 20,
- height: 20,
- colorFilter: ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- ),
- ),
- ),
- ),
- BottomNavigationBarItem(
- label: s.diary,
- icon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- ImageConstant.icnDiary,
- width: 20,
- height: 20,
- ),
- ),
- activeIcon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnDiary,
- width: 20,
- height: 20,
- colorFilter: ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- ),
- ),
- ),
- ),
- BottomNavigationBarItem(
- label: s.chat,
- icon: BlocBuilder(
- builder: (BuildContext context, NewMessagesState state) {
- return badges.Badge(
- position: badges.BadgePosition.topEnd(),
- badgeAnimation: badges.BadgeAnimation.fade(),
- badgeContent: Text(
- (state is NewMessagesStateLoaded) ? state.messagesCount.toString() : '0',
- style: TextStyle(
- color: Colors.white,
- fontSize: 8,
- ),
- ),
- child: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnChat,
- width: 20,
- height: 20,
- colorFilter: currentBottomNavBarIndex == 3
- ? ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- )
- : ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- ),
- ),
+ }
+ return CircleAvatar(
+ radius: 16,
+ backgroundColor: Colors.black12,
);
},
),
),
- BottomNavigationBarItem(
- label: 'Уведомления',
- icon: BlocBuilder(
- builder: (BuildContext context, NotificationsState state) {
- return badges.Badge(
- position: badges.BadgePosition.topEnd(),
- badgeAnimation: badges.BadgeAnimation.fade(),
- badgeContent: Text(
- (state is NotificationsStateLoaded) ? state.notificationsCount.toString() : '0',
- style: TextStyle(
- color: Colors.white,
- fontSize: 8,
- ),
- ),
- child: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnBell,
- colorFilter: currentBottomNavBarIndex == 4
- ? ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- )
- : ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- width: 20,
- height: 20,
- ),
- ),
- );
- },
+ ),
+ BottomNavigationBarItem(
+ label: 'Лента',
+ icon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
+ width: 20,
+ height: 20,
+ ImageConstant.icnFeed,
),
),
- BottomNavigationBarItem(
- label: '',
- icon: SvgPicture.asset(
- ImageConstant.imgLogo,
- height: 32,
+ activeIcon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ ImageConstant.icnFeed,
+ width: 20,
+ height: 20,
+ colorFilter: ColorFilter.mode(
+ appTheme.blueA400,
+ BlendMode.srcIn,
+ ),
),
),
- ],
- ),
+ ),
+ BottomNavigationBarItem(
+ label: s.diary,
+ icon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
+ ImageConstant.icnDiary,
+ width: 20,
+ height: 20,
+ ),
+ ),
+ activeIcon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ ImageConstant.icnDiary,
+ width: 20,
+ height: 20,
+ colorFilter: ColorFilter.mode(
+ appTheme.blueA400,
+ BlendMode.srcIn,
+ ),
+ ),
+ ),
+ ),
+ BottomNavigationBarItem(
+ label: s.chat,
+ icon: BlocBuilder(
+ builder: (BuildContext context, NewMessagesState state) {
+ return badges.Badge(
+ position: badges.BadgePosition.topEnd(),
+ badgeAnimation: badges.BadgeAnimation.fade(),
+ badgeContent: Text(
+ (state is NewMessagesStateLoaded) ? state.messagesCount.toString() : '0',
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 8,
+ ),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ ImageConstant.icnChat,
+ width: 20,
+ height: 20,
+ colorFilter: currentBottomNavBarIndex == 3
+ ? ColorFilter.mode(
+ appTheme.blueA400,
+ BlendMode.srcIn,
+ )
+ : ColorFilter.mode(Colors.grey, BlendMode.srcIn),
+ ),
+ ),
+ );
+ },
+ ),
+ ),
+ BottomNavigationBarItem(
+ label: 'Уведомления',
+ icon: BlocBuilder(
+ builder: (BuildContext context, NotificationsState state) {
+ return badges.Badge(
+ position: badges.BadgePosition.topEnd(),
+ badgeAnimation: badges.BadgeAnimation.fade(),
+ badgeContent: Text(
+ (state is NotificationsStateLoaded) ? state.notificationsCount.toString() : '0',
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 8,
+ ),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ ImageConstant.icnBell,
+ colorFilter: currentBottomNavBarIndex == 4
+ ? ColorFilter.mode(
+ appTheme.blueA400,
+ BlendMode.srcIn,
+ )
+ : ColorFilter.mode(Colors.grey, BlendMode.srcIn),
+ width: 20,
+ height: 20,
+ ),
+ ),
+ );
+ },
+ ),
+ ),
+ BottomNavigationBarItem(
+ label: '',
+ icon: SvgPicture.asset(
+ ImageConstant.imgLogo,
+ height: 32,
+ ),
+ ),
+ ],
),
);
}
diff --git a/lib/features/diary/models/product_moderation_model.dart b/lib/features/diary/models/product_moderation_model.dart
new file mode 100644
index 00000000..c28ffe64
--- /dev/null
+++ b/lib/features/diary/models/product_moderation_model.dart
@@ -0,0 +1,21 @@
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'product_moderation_model.freezed.dart';
+part 'product_moderation_model.g.dart';
+
+@freezed
+class ProductModerationModel with _$ProductModerationModel {
+ const factory ProductModerationModel({
+ required String name,
+ @JsonKey(name: 'energy_on_100gr')
+ required int energy,
+ @JsonKey(name: 'proteins_on_100gr')
+ required int proteins,
+ @JsonKey(name: 'fats_on_100gr')
+ required int fats,
+ @JsonKey(name: 'carbohydrates_on_100gr')
+ required int carbohydrates,
+ }) = _ProductModerationModel;
+
+ factory ProductModerationModel.fromJson(Map json) => _$ProductModerationModelFromJson(json);
+}
diff --git a/lib/features/diary/models/product_moderation_model.freezed.dart b/lib/features/diary/models/product_moderation_model.freezed.dart
new file mode 100644
index 00000000..9566e207
--- /dev/null
+++ b/lib/features/diary/models/product_moderation_model.freezed.dart
@@ -0,0 +1,270 @@
+// 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 'product_moderation_model.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+T _$identity(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');
+
+ProductModerationModel _$ProductModerationModelFromJson(
+ Map json) {
+ return _ProductModerationModel.fromJson(json);
+}
+
+/// @nodoc
+mixin _$ProductModerationModel {
+ String get name => throw _privateConstructorUsedError;
+ @JsonKey(name: 'energy_on_100gr')
+ int get energy => throw _privateConstructorUsedError;
+ @JsonKey(name: 'proteins_on_100gr')
+ int get proteins => throw _privateConstructorUsedError;
+ @JsonKey(name: 'fats_on_100gr')
+ int get fats => throw _privateConstructorUsedError;
+ @JsonKey(name: 'carbohydrates_on_100gr')
+ int get carbohydrates => throw _privateConstructorUsedError;
+
+ /// Serializes this ProductModerationModel to a JSON map.
+ Map toJson() => throw _privateConstructorUsedError;
+
+ /// Create a copy of ProductModerationModel
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ $ProductModerationModelCopyWith get copyWith =>
+ throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $ProductModerationModelCopyWith<$Res> {
+ factory $ProductModerationModelCopyWith(ProductModerationModel value,
+ $Res Function(ProductModerationModel) then) =
+ _$ProductModerationModelCopyWithImpl<$Res, ProductModerationModel>;
+ @useResult
+ $Res call(
+ {String name,
+ @JsonKey(name: 'energy_on_100gr') int energy,
+ @JsonKey(name: 'proteins_on_100gr') int proteins,
+ @JsonKey(name: 'fats_on_100gr') int fats,
+ @JsonKey(name: 'carbohydrates_on_100gr') int carbohydrates});
+}
+
+/// @nodoc
+class _$ProductModerationModelCopyWithImpl<$Res,
+ $Val extends ProductModerationModel>
+ implements $ProductModerationModelCopyWith<$Res> {
+ _$ProductModerationModelCopyWithImpl(this._value, this._then);
+
+ // ignore: unused_field
+ final $Val _value;
+ // ignore: unused_field
+ final $Res Function($Val) _then;
+
+ /// Create a copy of ProductModerationModel
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? name = null,
+ Object? energy = null,
+ Object? proteins = null,
+ Object? fats = null,
+ Object? carbohydrates = null,
+ }) {
+ return _then(_value.copyWith(
+ name: null == name
+ ? _value.name
+ : name // ignore: cast_nullable_to_non_nullable
+ as String,
+ energy: null == energy
+ ? _value.energy
+ : energy // ignore: cast_nullable_to_non_nullable
+ as int,
+ proteins: null == proteins
+ ? _value.proteins
+ : proteins // ignore: cast_nullable_to_non_nullable
+ as int,
+ fats: null == fats
+ ? _value.fats
+ : fats // ignore: cast_nullable_to_non_nullable
+ as int,
+ carbohydrates: null == carbohydrates
+ ? _value.carbohydrates
+ : carbohydrates // ignore: cast_nullable_to_non_nullable
+ as int,
+ ) as $Val);
+ }
+}
+
+/// @nodoc
+abstract class _$$ProductModerationModelImplCopyWith<$Res>
+ implements $ProductModerationModelCopyWith<$Res> {
+ factory _$$ProductModerationModelImplCopyWith(
+ _$ProductModerationModelImpl value,
+ $Res Function(_$ProductModerationModelImpl) then) =
+ __$$ProductModerationModelImplCopyWithImpl<$Res>;
+ @override
+ @useResult
+ $Res call(
+ {String name,
+ @JsonKey(name: 'energy_on_100gr') int energy,
+ @JsonKey(name: 'proteins_on_100gr') int proteins,
+ @JsonKey(name: 'fats_on_100gr') int fats,
+ @JsonKey(name: 'carbohydrates_on_100gr') int carbohydrates});
+}
+
+/// @nodoc
+class __$$ProductModerationModelImplCopyWithImpl<$Res>
+ extends _$ProductModerationModelCopyWithImpl<$Res,
+ _$ProductModerationModelImpl>
+ implements _$$ProductModerationModelImplCopyWith<$Res> {
+ __$$ProductModerationModelImplCopyWithImpl(
+ _$ProductModerationModelImpl _value,
+ $Res Function(_$ProductModerationModelImpl) _then)
+ : super(_value, _then);
+
+ /// Create a copy of ProductModerationModel
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? name = null,
+ Object? energy = null,
+ Object? proteins = null,
+ Object? fats = null,
+ Object? carbohydrates = null,
+ }) {
+ return _then(_$ProductModerationModelImpl(
+ name: null == name
+ ? _value.name
+ : name // ignore: cast_nullable_to_non_nullable
+ as String,
+ energy: null == energy
+ ? _value.energy
+ : energy // ignore: cast_nullable_to_non_nullable
+ as int,
+ proteins: null == proteins
+ ? _value.proteins
+ : proteins // ignore: cast_nullable_to_non_nullable
+ as int,
+ fats: null == fats
+ ? _value.fats
+ : fats // ignore: cast_nullable_to_non_nullable
+ as int,
+ carbohydrates: null == carbohydrates
+ ? _value.carbohydrates
+ : carbohydrates // ignore: cast_nullable_to_non_nullable
+ as int,
+ ));
+ }
+}
+
+/// @nodoc
+@JsonSerializable()
+class _$ProductModerationModelImpl implements _ProductModerationModel {
+ const _$ProductModerationModelImpl(
+ {required this.name,
+ @JsonKey(name: 'energy_on_100gr') required this.energy,
+ @JsonKey(name: 'proteins_on_100gr') required this.proteins,
+ @JsonKey(name: 'fats_on_100gr') required this.fats,
+ @JsonKey(name: 'carbohydrates_on_100gr') required this.carbohydrates});
+
+ factory _$ProductModerationModelImpl.fromJson(Map json) =>
+ _$$ProductModerationModelImplFromJson(json);
+
+ @override
+ final String name;
+ @override
+ @JsonKey(name: 'energy_on_100gr')
+ final int energy;
+ @override
+ @JsonKey(name: 'proteins_on_100gr')
+ final int proteins;
+ @override
+ @JsonKey(name: 'fats_on_100gr')
+ final int fats;
+ @override
+ @JsonKey(name: 'carbohydrates_on_100gr')
+ final int carbohydrates;
+
+ @override
+ String toString() {
+ return 'ProductModerationModel(name: $name, energy: $energy, proteins: $proteins, fats: $fats, carbohydrates: $carbohydrates)';
+ }
+
+ @override
+ bool operator ==(Object other) {
+ return identical(this, other) ||
+ (other.runtimeType == runtimeType &&
+ other is _$ProductModerationModelImpl &&
+ (identical(other.name, name) || other.name == name) &&
+ (identical(other.energy, energy) || other.energy == energy) &&
+ (identical(other.proteins, proteins) ||
+ other.proteins == proteins) &&
+ (identical(other.fats, fats) || other.fats == fats) &&
+ (identical(other.carbohydrates, carbohydrates) ||
+ other.carbohydrates == carbohydrates));
+ }
+
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ @override
+ int get hashCode =>
+ Object.hash(runtimeType, name, energy, proteins, fats, carbohydrates);
+
+ /// Create a copy of ProductModerationModel
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ @override
+ @pragma('vm:prefer-inline')
+ _$$ProductModerationModelImplCopyWith<_$ProductModerationModelImpl>
+ get copyWith => __$$ProductModerationModelImplCopyWithImpl<
+ _$ProductModerationModelImpl>(this, _$identity);
+
+ @override
+ Map toJson() {
+ return _$$ProductModerationModelImplToJson(
+ this,
+ );
+ }
+}
+
+abstract class _ProductModerationModel implements ProductModerationModel {
+ const factory _ProductModerationModel(
+ {required final String name,
+ @JsonKey(name: 'energy_on_100gr') required final int energy,
+ @JsonKey(name: 'proteins_on_100gr') required final int proteins,
+ @JsonKey(name: 'fats_on_100gr') required final int fats,
+ @JsonKey(name: 'carbohydrates_on_100gr')
+ required final int carbohydrates}) = _$ProductModerationModelImpl;
+
+ factory _ProductModerationModel.fromJson(Map json) =
+ _$ProductModerationModelImpl.fromJson;
+
+ @override
+ String get name;
+ @override
+ @JsonKey(name: 'energy_on_100gr')
+ int get energy;
+ @override
+ @JsonKey(name: 'proteins_on_100gr')
+ int get proteins;
+ @override
+ @JsonKey(name: 'fats_on_100gr')
+ int get fats;
+ @override
+ @JsonKey(name: 'carbohydrates_on_100gr')
+ int get carbohydrates;
+
+ /// Create a copy of ProductModerationModel
+ /// with the given fields replaced by the non-null parameter values.
+ @override
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ _$$ProductModerationModelImplCopyWith<_$ProductModerationModelImpl>
+ get copyWith => throw _privateConstructorUsedError;
+}
diff --git a/lib/features/diary/models/product_moderation_model.g.dart b/lib/features/diary/models/product_moderation_model.g.dart
new file mode 100644
index 00000000..2199a5f6
--- /dev/null
+++ b/lib/features/diary/models/product_moderation_model.g.dart
@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'product_moderation_model.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+_$ProductModerationModelImpl _$$ProductModerationModelImplFromJson(
+ Map json) =>
+ _$ProductModerationModelImpl(
+ name: json['name'] as String,
+ energy: (json['energy_on_100gr'] as num).toInt(),
+ proteins: (json['proteins_on_100gr'] as num).toInt(),
+ fats: (json['fats_on_100gr'] as num).toInt(),
+ carbohydrates: (json['carbohydrates_on_100gr'] as num).toInt(),
+ );
+
+Map _$$ProductModerationModelImplToJson(
+ _$ProductModerationModelImpl instance) =>
+ {
+ 'name': instance.name,
+ 'energy_on_100gr': instance.energy,
+ 'proteins_on_100gr': instance.proteins,
+ 'fats_on_100gr': instance.fats,
+ 'carbohydrates_on_100gr': instance.carbohydrates,
+ };
diff --git a/lib/features/diary/presentation/bloc/diary_cubit.dart b/lib/features/diary/presentation/bloc/diary_cubit.dart
index 74df5385..976d16e6 100644
--- a/lib/features/diary/presentation/bloc/diary_cubit.dart
+++ b/lib/features/diary/presentation/bloc/diary_cubit.dart
@@ -25,7 +25,7 @@ class DiaryCubit extends Cubit {
emit(
DiaryState.loaded(
diary: await diaryRepository.getDiaryByDate(date),
- nutrition: await getNutrition(await diaryRepository.getDiaryIndexByDate(date)),
+ nutrition: await getNutrition((await diaryRepository.getDiaryByDate(date)).id),
currentSelectedSatietyRating: currentSelectedSatietyRating,
),
);
@@ -140,4 +140,20 @@ class DiaryCubit extends Cubit {
currentSelectedSatietyRating = value;
emit((state as DiaryStateLoaded).copyWith(currentSelectedSatietyRating: currentSelectedSatietyRating));
}
+
+ sendProductToModeration({
+ required String name,
+ required int energy,
+ required int proteins,
+ required int fats,
+ required int carbohydrates,
+ }) async {
+ return await diaryRepository.sendProductToModeration(
+ name: name,
+ energy: energy,
+ proteins: proteins,
+ fats: fats,
+ carbohydrates: carbohydrates,
+ );
+ }
}
diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart
index cfd571cf..6c19ceb6 100644
--- a/lib/features/diary/presentation/pages/diary_screen.dart
+++ b/lib/features/diary/presentation/pages/diary_screen.dart
@@ -130,7 +130,7 @@ class _DiaryScreenState extends State {
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 {
_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 {
_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,
+ ),
],
),
),
@@ -1017,7 +1023,10 @@ class _DiaryScreenState extends State {
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
- child: GlossaryModerationRequestModalWidget(productName: productNameController.text),
+ child: GlossaryModerationRequestModalWidget(
+ productName: productNameController.text,
+ diaryCubit: diaryCubit,
+ ),
),
);
}
@@ -1057,6 +1066,7 @@ class _DiaryScreenState extends State {
}
_addProductButton(DiaryDayModel diaryDay) {
+ if (_selectedDay!.compareTo(today!) == 1) return const SizedBox.shrink();
return InkWell(
onTap: () {
setState(() {
diff --git a/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart b/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart
index 956a9113..57896321 100644
--- a/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart
+++ b/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart
@@ -1,29 +1,38 @@
+import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.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:lottie/lottie.dart';
class GlossaryModerationRequestModalWidget extends StatefulWidget {
+ final DiaryCubit diaryCubit;
final String productName;
const GlossaryModerationRequestModalWidget({
super.key,
- required this.productName,
+ required this.productName, required this.diaryCubit,
});
@override
State createState() => _GlossaryModerationRequestModalWidgetState();
}
-enum GlossaryState { alert, addNewProduct, finish }
+enum GlossaryState { alert, addNewProduct, success }
class _GlossaryModerationRequestModalWidgetState extends State {
GlossaryState glossaryState = GlossaryState.alert;
final productNameController = TextEditingController();
+ final energyController = TextEditingController();
+ final proteinsController = TextEditingController();
+ final fatsController = TextEditingController();
+ final carbohydratesController = TextEditingController();
@override
Widget build(BuildContext context) {
if (glossaryState == GlossaryState.alert) {
return _alert();
+ } else if (glossaryState == GlossaryState.success) {
+ return _success();
} else {
return _addNewGlossaryProduct();
}
@@ -126,6 +135,58 @@ class _GlossaryModerationRequestModalWidgetState extends State getDiaryByDate(String date) async {
- return (await diaryService.getDiaryDay(
- index: await getDiaryIndexByDate(date),
- ))
- .diary;
+ return (await getDiaryIndexByDate(date)).last;
}
- Future getDiaryIndexByDate(String date) async {
- return (await diaryService.getDiaryIndexByDate(date: date)).id;
+ Future> getDiaryIndexByDate(String date) async {
+ return (await diaryService.getDiaryIndexByDate(date: date));
}
Future getNutritionData(int index) async {
@@ -123,4 +121,22 @@ class DiaryRepository {
// ),
);
}
+
+ Future sendProductToModeration({
+ required String name,
+ required int energy,
+ required int proteins,
+ required int fats,
+ required int carbohydrates,
+ }) async {
+ return await diaryService.sendProductToModeration(
+ data: ProductModerationModel(
+ name: name,
+ energy: energy,
+ proteins: proteins,
+ fats: fats,
+ carbohydrates: carbohydrates,
+ ).toJson(),
+ );
+ }
}
diff --git a/lib/features/diary/services/diary_service.dart b/lib/features/diary/services/diary_service.dart
index 833f9604..4ff8b2e1 100644
--- a/lib/features/diary/services/diary_service.dart
+++ b/lib/features/diary/services/diary_service.dart
@@ -1,7 +1,6 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
-import 'package:eatvio_app/features/diary/models/diary_index_model.dart';
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
import 'package:retrofit/retrofit.dart';
@@ -12,7 +11,7 @@ abstract class DiaryService {
factory DiaryService(Dio dio, {String baseUrl}) = _DiaryService;
@GET('/api/diary/index/{date}')
- Future getDiaryIndexByDate({
+ Future> getDiaryIndexByDate({
@Path('date') required String date, // yyyy-mm-dd
});
@@ -71,4 +70,9 @@ abstract class DiaryService {
@Path('diary_id') required int diaryId,
// @Body() required FinishDiaryDayModel finishDiaryDayModel,
});
+
+ @POST('/api/diary/product_nutritional_values/sendToModeration')
+ Future sendProductToModeration({
+ @Body() required Map data,
+ });
}
diff --git a/lib/features/diary/services/diary_service.g.dart b/lib/features/diary/services/diary_service.g.dart
index 03fa20ed..b9327c5f 100644
--- a/lib/features/diary/services/diary_service.g.dart
+++ b/lib/features/diary/services/diary_service.g.dart
@@ -22,12 +22,13 @@ class _DiaryService implements DiaryService {
final ParseErrorLogger? errorLogger;
@override
- Future getDiaryIndexByDate({required String date}) async {
+ Future> getDiaryIndexByDate(
+ {required String date}) async {
final _extra = {};
final queryParameters = {};
final _headers = {};
const Map? _data = null;
- final _options = _setStreamType(Options(
+ final _options = _setStreamType>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
@@ -43,10 +44,12 @@ class _DiaryService implements DiaryService {
_dio.options.baseUrl,
baseUrl,
)));
- final _result = await _dio.fetch