forked from eatvio/eatvio_app
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@@ -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 }}
|
||||
|
||||
57
.gitea/workflows/docker-run-tests.yml
Normal file
57
.gitea/workflows/docker-run-tests.yml
Normal file
@@ -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 }}
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>UserPhotoUpload</string>
|
||||
<string>Нужно для загрузки фото</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Нужно для загрузки фото</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,157 +62,154 @@ class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
|
||||
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<ProfileAvatarCubit>(
|
||||
create: (context) => sl<ProfileAvatarCubit>()..getMyProfile(),
|
||||
child: BlocBuilder<ProfileAvatarCubit, ProfileAvatarState>(
|
||||
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<ProfileAvatarCubit>(
|
||||
create: (context) => sl<ProfileAvatarCubit>()..getMyProfile(),
|
||||
child: BlocBuilder<ProfileAvatarCubit, ProfileAvatarState>(
|
||||
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<NewMessagesCubit, NewMessagesState>(
|
||||
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<NotificationsCubit, NotificationsState>(
|
||||
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<NewMessagesCubit, NewMessagesState>(
|
||||
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<NotificationsCubit, NotificationsState>(
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
21
lib/features/diary/models/product_moderation_model.dart
Normal file
21
lib/features/diary/models/product_moderation_model.dart
Normal file
@@ -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<String, Object?> json) => _$ProductModerationModelFromJson(json);
|
||||
}
|
||||
270
lib/features/diary/models/product_moderation_model.freezed.dart
Normal file
270
lib/features/diary/models/product_moderation_model.freezed.dart
Normal file
@@ -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>(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<String, dynamic> 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<String, dynamic> 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<ProductModerationModel> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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;
|
||||
}
|
||||
27
lib/features/diary/models/product_moderation_model.g.dart
Normal file
27
lib/features/diary/models/product_moderation_model.g.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'product_moderation_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$ProductModerationModelImpl _$$ProductModerationModelImplFromJson(
|
||||
Map<String, dynamic> 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<String, dynamic> _$$ProductModerationModelImplToJson(
|
||||
_$ProductModerationModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'energy_on_100gr': instance.energy,
|
||||
'proteins_on_100gr': instance.proteins,
|
||||
'fats_on_100gr': instance.fats,
|
||||
'carbohydrates_on_100gr': instance.carbohydrates,
|
||||
};
|
||||
@@ -25,7 +25,7 @@ class DiaryCubit extends Cubit<DiaryState> {
|
||||
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<DiaryState> {
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -1017,7 +1023,10 @@ class _DiaryScreenState extends State<DiaryScreen> {
|
||||
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<DiaryScreen> {
|
||||
}
|
||||
|
||||
_addProductButton(DiaryDayModel diaryDay) {
|
||||
if (_selectedDay!.compareTo(today!) == 1) return const SizedBox.shrink();
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
|
||||
@@ -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<GlossaryModerationRequestModalWidget> createState() => _GlossaryModerationRequestModalWidgetState();
|
||||
}
|
||||
|
||||
enum GlossaryState { alert, addNewProduct, finish }
|
||||
enum GlossaryState { alert, addNewProduct, success }
|
||||
|
||||
class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModerationRequestModalWidget> {
|
||||
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<GlossaryModeratio
|
||||
);
|
||||
}
|
||||
|
||||
_success() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Продукт успешно отправлен\nна модерацию',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Color(0xFF323F4B),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Lottie.asset(
|
||||
'assets/lottie_animations/success.json',
|
||||
width: 160,
|
||||
height: 160,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'Закрыть',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_addNewGlossaryProduct() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -163,12 +224,16 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
||||
Expanded(
|
||||
child: CustomTextFormField(
|
||||
hintText: 'Калории',
|
||||
controller: energyController,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: CustomTextFormField(
|
||||
hintText: 'Белки',
|
||||
controller: proteinsController,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -180,19 +245,34 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
||||
Expanded(
|
||||
child: CustomTextFormField(
|
||||
hintText: 'Жиры',
|
||||
controller: fatsController,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: CustomTextFormField(
|
||||
hintText: 'Углеводы',
|
||||
controller: carbohydratesController,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
InkWell(
|
||||
onTap: () {},
|
||||
onTap: () {
|
||||
widget.diaryCubit.sendProductToModeration(
|
||||
name: productNameController.text,
|
||||
energy: int.parse(energyController.text),
|
||||
proteins: int.parse(proteinsController.text),
|
||||
fats: int.parse(fatsController.text),
|
||||
carbohydrates: int.parse(carbohydratesController.text),
|
||||
);
|
||||
setState(() {
|
||||
glossaryState = GlossaryState.success;
|
||||
});
|
||||
},
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: Ink(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
||||
import 'package:eatvio_app/features/diary/models/product_moderation_model.dart';
|
||||
import 'package:eatvio_app/features/diary/services/diary_service.dart';
|
||||
|
||||
class DiaryRepository {
|
||||
@@ -11,14 +12,11 @@ class DiaryRepository {
|
||||
});
|
||||
|
||||
Future<DiaryDayModel> getDiaryByDate(String date) async {
|
||||
return (await diaryService.getDiaryDay(
|
||||
index: await getDiaryIndexByDate(date),
|
||||
))
|
||||
.diary;
|
||||
return (await getDiaryIndexByDate(date)).last;
|
||||
}
|
||||
|
||||
Future<int> getDiaryIndexByDate(String date) async {
|
||||
return (await diaryService.getDiaryIndexByDate(date: date)).id;
|
||||
Future<List<DiaryDayModel>> getDiaryIndexByDate(String date) async {
|
||||
return (await diaryService.getDiaryIndexByDate(date: date));
|
||||
}
|
||||
|
||||
Future<NutritionDataModel> getNutritionData(int index) async {
|
||||
@@ -123,4 +121,22 @@ class DiaryRepository {
|
||||
// ),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> 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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<DiaryIndexModel> getDiaryIndexByDate({
|
||||
Future<List<DiaryDayModel>> 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<void> sendProductToModeration({
|
||||
@Body() required Map<String, dynamic> data,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,12 +22,13 @@ class _DiaryService implements DiaryService {
|
||||
final ParseErrorLogger? errorLogger;
|
||||
|
||||
@override
|
||||
Future<DiaryIndexModel> getDiaryIndexByDate({required String date}) async {
|
||||
Future<List<DiaryDayModel>> getDiaryIndexByDate(
|
||||
{required String date}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<DiaryIndexModel>(Options(
|
||||
final _options = _setStreamType<List<DiaryDayModel>>(Options(
|
||||
method: 'GET',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
@@ -43,10 +44,12 @@ class _DiaryService implements DiaryService {
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
)));
|
||||
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||
late DiaryIndexModel _value;
|
||||
final _result = await _dio.fetch<List<dynamic>>(_options);
|
||||
late List<DiaryDayModel> _value;
|
||||
try {
|
||||
_value = DiaryIndexModel.fromJson(_result.data!);
|
||||
_value = _result.data!
|
||||
.map((dynamic i) => DiaryDayModel.fromJson(i as Map<String, dynamic>))
|
||||
.toList();
|
||||
} on Object catch (e, s) {
|
||||
errorLogger?.logError(e, s, _options);
|
||||
rethrow;
|
||||
@@ -317,6 +320,33 @@ class _DiaryService implements DiaryService {
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendProductToModeration(
|
||||
{required Map<String, dynamic> data}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = <String, dynamic>{};
|
||||
_data.addAll(data);
|
||||
final _options = _setStreamType<void>(Options(
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/diary/product_nutritional_values/sendToModeration',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(
|
||||
baseUrl: _combineBaseUrls(
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
)));
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
|
||||
@@ -124,7 +124,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
if (widget.author == null) const SizedBox(height: 16),
|
||||
_activePlans(state),
|
||||
if (widget.author == null) const SizedBox(height: 16),
|
||||
_newBlogPostButton(),
|
||||
if (widget.author == null) _newBlogPostButton(),
|
||||
_blogPosts(state),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: eatvio_app
|
||||
description: A new Flutter project.
|
||||
version: 0.0.0+1
|
||||
version: 1.0.2+17
|
||||
publish_to: "none"
|
||||
|
||||
environment:
|
||||
|
||||
Reference in New Issue
Block a user