Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Username1548
2024-11-12 19:10:59 +07:00
29 changed files with 1754 additions and 56 deletions

View File

@@ -24,7 +24,8 @@ jobs:
- name: Install Android SDK
run: |
apt-get update
https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip -O commandlinetools.zip
apt-get install -y openjdk-11-jdk wget
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/

329
android/.idea/caches/deviceStreaming.xml generated Normal file
View File

@@ -0,0 +1,329 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceStreaming">
<option name="deviceSelectionList">
<list>
<PersistentDeviceSelectionData>
<option name="api" value="27" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="F01L" />
<option name="id" value="F01L" />
<option name="manufacturer" value="FUJITSU" />
<option name="name" value="F-01L" />
<option name="screenDensity" value="360" />
<option name="screenX" value="720" />
<option name="screenY" value="1280" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="28" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="SH-01L" />
<option name="id" value="SH-01L" />
<option name="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="Lenovo" />
<option name="codename" value="TB370FU" />
<option name="id" value="TB370FU" />
<option name="manufacturer" value="Lenovo" />
<option name="name" value="Tab P12" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1840" />
<option name="screenY" value="2944" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="samsung" />
<option name="codename" value="a51" />
<option name="id" value="a51" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy A51" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="b0q" />
<option name="id" value="b0q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S22 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="caiman" />
<option name="id" value="caiman" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro" />
<option name="screenDensity" value="360" />
<option name="screenX" value="960" />
<option name="screenY" value="2142" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="comet" />
<option name="id" value="comet" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro Fold" />
<option name="screenDensity" value="390" />
<option name="screenX" value="2076" />
<option name="screenY" value="2152" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="crownqlteue" />
<option name="id" value="crownqlteue" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2220" />
<option name="screenY" value="1080" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm3q" />
<option name="id" value="dm3q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S23 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e1q" />
<option name="id" value="e1q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix_camera" />
<option name="id" value="felix_camera" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold (Camera-enabled)" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8uwifi" />
<option name="id" value="gts8uwifi" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8 Ultra" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1848" />
<option name="screenY" value="2960" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="husky" />
<option name="id" value="husky" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8 Pro" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="java" />
<option name="id" value="java" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro XL" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="google" />
<option name="codename" value="oriole" />
<option name="id" value="oriole" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="panther" />
<option name="id" value="panther" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q5q" />
<option name="id" value="q5q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold5" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1812" />
<option name="screenY" value="2176" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q6q" />
<option name="id" value="q6q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-F956B" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1856" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="r11" />
<option name="id" value="r11" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Watch" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
<option name="type" value="WEAR_OS" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 5" />
<option name="screenDensity" value="440" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="shiba" />
<option name="id" value="shiba" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="tangorpro" />
<option name="id" value="tangorpro" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Tablet" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="id" value="tokay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>

14
android/.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="23" />
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
<option name="parallelModelFetch" value="true" />
</component>
</project>

10
android/.idea/migrations.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

9
android/.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

8
android/.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/modules/android.iml" filepath="$PROJECT_DIR$/.idea/modules/android.iml" />
</modules>
</component>
</project>

9
android/.idea/modules/android.iml generated Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

17
android/.idea/runConfigurations.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

6
android/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

65
android/.idea/workspace.xml generated Normal file
View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="NONE" />
</component>
<component name="ChangeListManager">
<list default="true" id="48538bf9-f01e-4931-b825-e9023d9f83f3" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/app/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/app/build.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/settings.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/settings.gradle" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 0
}]]></component>
<component name="ProjectId" id="2ogeByQ5QpkVqOhNR7IKHeDp4Dx" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.cidr.known.project.marker": "true",
"RunOnceActivity.readMode.enableVisualFormatting": "true",
"android.gradle.sync.needed": "true",
"cf.first.check.clang-format": "false",
"cidr.known.project.marker": "true",
"dart.analysis.tool.window.visible": "false",
"git-widget-placeholder": "main",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "C:/Users/mso7nueh/eatvio_app/android",
"project.structure.last.edited": "Suggestions",
"project.structure.proportion": "0.17",
"project.structure.side.proportion": "0.2",
"settings.editor.selected.configurable": "reference.settingsdialog.project.gradle",
"show.migrate.to.gradle.popup": "false"
}
}]]></component>
<component name="PsdUISettings">
<option name="MODULE_TAB" value="Signing Configs" />
<option name="LAST_EDITED_SIGNING_CONFIG" value="debug" />
<option name="LAST_EDITED_BUILD_TYPE" value="release" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="48538bf9-f01e-4931-b825-e9023d9f83f3" name="Changes" comment="" />
<created>1731295514828</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1731295514828</updated>
</task>
<servers />
</component>
</project>

View File

@@ -7,7 +7,7 @@ plugins {
android {
namespace = "com.eatvioapp.app"
compileSdk = flutter.compileSdkVersion
ndkVersion = "28.0.12433566"
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_21

View File

@@ -18,8 +18,8 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.3.2" apply false
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
id "com.android.application" version "8.7.2" apply false
id "org.jetbrains.kotlin.android" version "2.0.21" apply false
}
include ":app"

View File

@@ -0,0 +1,7 @@
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 0C6.71667 0 0 6.71667 0 15C0 20.0425 2.49667 24.4933 6.31167 27.2125C6.39833 21.8475 4.4475 15.8333 1.17 15.8333C0.783333 15.8333 0.47 15.8883 0.209167 15.9858C0.461667 15.355 1.00917 15 2.03333 15C5.59167 15 7.58833 22.0883 7.11 27.74C9.405 29.1642 12.1017 30 15 30C17.8992 30 20.5967 29.1633 22.8917 27.7392C22.4108 22.0667 24.4067 15 27.9675 15C28.995 15 29.5442 15.355 29.7942 15.9858C29.5325 15.8883 29.2183 15.8333 28.83 15.8333C25.5483 15.8333 23.5983 21.8325 23.6883 27.2125C27.5042 24.4933 30 20.0425 30 15C30 6.71667 23.2842 0 15 0Z" fill="#FFCC4D"/>
<path d="M15 0C6.71667 0 0 6.71667 0 15C0 15.9933 0.1025 16.9633 0.286667 17.9033C0.481667 17.1842 0.786667 16.4942 1.16833 15.8333C0.7825 15.8333 0.47 15.8883 0.21 15.9858C0.43 15.4367 0.895 15.1125 1.68333 15.0342C4.17667 11.5517 9.1975 9.16667 15 9.16667C20.8033 9.16667 25.8233 11.5508 28.3167 15.0333C29.1083 15.1117 29.575 15.435 29.7933 15.9858C29.5333 15.8883 29.2192 15.8333 28.8325 15.8333C29.2142 16.4942 29.5183 17.1842 29.7142 17.9033C29.8983 16.9633 30 15.9933 30 15C30 6.71667 23.2842 0 15 0Z" fill="#BDDDF4"/>
<path d="M6.12144 9.92495C5.3331 12.5716 6.2106 15.1691 8.08227 15.7266C9.95394 16.2849 12.1106 14.5916 12.8981 11.9449C13.6864 9.29911 12.8098 6.70078 10.9389 6.14328C9.06727 5.58578 6.9106 7.27911 6.12144 9.92495ZM23.8756 9.92495C24.6639 12.5716 23.7864 15.1691 21.9156 15.7266C20.0439 16.2849 17.8873 14.5916 17.0998 11.9449C16.3114 9.29911 17.1889 6.70078 19.0589 6.14328C20.9298 5.58578 23.0864 7.27911 23.8756 9.92495Z" fill="#F5F8FA"/>
<path d="M14.9987 15C12.7012 15 10.832 16.8692 10.832 19.1667V24.1667C10.832 26.4642 12.7012 28.3333 14.9987 28.3333C17.2962 28.3333 19.1654 26.4642 19.1654 24.1667V19.1667C19.1654 16.8692 17.2962 15 14.9987 15Z" fill="#664500"/>
<path d="M1.17111 15.8335C0.784443 15.8335 0.47111 15.8885 0.210277 15.986C0.270277 15.8369 0.349443 15.706 0.444443 15.5894C-1.10722 17.4985 2.37528 23.7835 0.682777 30.0002H6.06611C7.05778 24.2002 5.03694 15.8335 1.17111 15.8335ZM29.7953 15.986C29.5336 15.8885 29.2194 15.8335 28.8311 15.8335C24.9636 15.8335 22.9436 24.1685 23.9369 30.0002H29.3203C27.7319 24.1294 30.7003 18.2594 29.7953 15.986Z" fill="#FCAB40"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,11 @@
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.9878 30.2021C25.3279 30.2021 32.0888 23.4411 32.0888 15.1011C32.0888 6.76097 25.3279 0 16.9878 0C8.64769 0 1.88672 6.76097 1.88672 15.1011C1.88672 23.4411 8.64769 30.2021 16.9878 30.2021Z" fill="#FFCC4D"/>
<path d="M10.708 19.8169C10.7458 19.9671 11.6879 23.4906 16.9876 23.4906C22.288 23.4906 23.2293 19.9671 23.2671 19.8169C23.3132 19.6348 23.231 19.4461 23.0682 19.3521C22.9047 19.259 22.6999 19.2867 22.5649 19.4167C22.5489 19.4326 20.9256 20.9738 16.9876 20.9738C13.0495 20.9738 11.4253 19.4326 11.4102 19.4175C11.3297 19.3378 11.2223 19.2959 11.1149 19.2959C11.0445 19.2959 10.9731 19.3135 10.9085 19.3496C10.7441 19.4436 10.6619 19.634 10.708 19.8169Z" fill="#664500"/>
<path d="M11.9528 14.2623C13.1112 14.2623 14.0502 12.9476 14.0502 11.326C14.0502 9.70428 13.1112 8.38965 11.9528 8.38965C10.7945 8.38965 9.85547 9.70428 9.85547 11.326C9.85547 12.9476 10.7945 14.2623 11.9528 14.2623Z" fill="#664500"/>
<path d="M22.0192 14.2623C23.1776 14.2623 24.1166 12.9476 24.1166 11.326C24.1166 9.70428 23.1776 8.38965 22.0192 8.38965C20.8609 8.38965 19.9219 9.70428 19.9219 11.326C19.9219 12.9476 20.8609 14.2623 22.0192 14.2623Z" fill="#664500"/>
<path d="M2.72313 24.7491C0.20629 20.5543 2.30366 14.2622 2.30366 14.2622L11.9516 28.9438C11.9516 28.9438 5.23998 28.9438 2.72313 24.7491Z" fill="#FFCC4D" stroke="#FFCC4D"/>
<path d="M16.3648 31.9261C11.4769 31.7286 7.36752 26.5226 7.36752 26.5226L24.9354 26.5128C24.9354 26.5128 21.2527 32.1237 16.3648 31.9261Z" fill="#FFCC4D" stroke="#FFCC4D"/>
<path d="M31.0574 25.2319C28.1005 29.129 21.1818 29.3629 21.1818 29.3629L31.2492 14.2618C31.2492 14.2618 34.0144 21.3349 31.0574 25.2319Z" fill="#FFCC4D" stroke="#FFCC4D"/>
<path d="M2.30503 13.4233C2.30503 13.4233 -0.631285 20.1349 2.30503 24.7491C5.24134 29.3633 11.9529 29.3633 11.9529 29.3633" stroke="#664500" stroke-width="0.2"/>
<path d="M20.3429 29.7829C20.3429 29.7829 28.3129 29.3634 31.2492 25.5882C34.1855 21.8129 31.6687 14.2624 31.6687 14.2624" stroke="#664500" stroke-width="0.2"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,27 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'nutrition_model.freezed.dart';
part 'nutrition_model.g.dart';
@freezed
class NutritionDataModel with _$NutritionDataModel {
const factory NutritionDataModel({
required NutritionModel dailyNutritionIntake,
required NutritionModel dailyNutritionRecommendation,
}) = _NutritionDataModel;
factory NutritionDataModel.fromJson(Map<String, Object?> json) => _$NutritionDataModelFromJson(json);
}
@freezed
class NutritionModel with _$NutritionModel {
const factory NutritionModel({
required double energy,
required double proteins,
required double fats,
required double carbohydrates,
}) = _NutritionModel;
factory NutritionModel.fromJson(Map<String, Object?> json) => _$NutritionModelFromJson(json);
}

View File

@@ -0,0 +1,437 @@
// 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 'nutrition_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');
NutritionDataModel _$NutritionDataModelFromJson(Map<String, dynamic> json) {
return _NutritionDataModel.fromJson(json);
}
/// @nodoc
mixin _$NutritionDataModel {
NutritionModel get dailyNutritionIntake => throw _privateConstructorUsedError;
NutritionModel get dailyNutritionRecommendation =>
throw _privateConstructorUsedError;
/// Serializes this NutritionDataModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of NutritionDataModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$NutritionDataModelCopyWith<NutritionDataModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $NutritionDataModelCopyWith<$Res> {
factory $NutritionDataModelCopyWith(
NutritionDataModel value, $Res Function(NutritionDataModel) then) =
_$NutritionDataModelCopyWithImpl<$Res, NutritionDataModel>;
@useResult
$Res call(
{NutritionModel dailyNutritionIntake,
NutritionModel dailyNutritionRecommendation});
$NutritionModelCopyWith<$Res> get dailyNutritionIntake;
$NutritionModelCopyWith<$Res> get dailyNutritionRecommendation;
}
/// @nodoc
class _$NutritionDataModelCopyWithImpl<$Res, $Val extends NutritionDataModel>
implements $NutritionDataModelCopyWith<$Res> {
_$NutritionDataModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of NutritionDataModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? dailyNutritionIntake = null,
Object? dailyNutritionRecommendation = null,
}) {
return _then(_value.copyWith(
dailyNutritionIntake: null == dailyNutritionIntake
? _value.dailyNutritionIntake
: dailyNutritionIntake // ignore: cast_nullable_to_non_nullable
as NutritionModel,
dailyNutritionRecommendation: null == dailyNutritionRecommendation
? _value.dailyNutritionRecommendation
: dailyNutritionRecommendation // ignore: cast_nullable_to_non_nullable
as NutritionModel,
) as $Val);
}
/// Create a copy of NutritionDataModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$NutritionModelCopyWith<$Res> get dailyNutritionIntake {
return $NutritionModelCopyWith<$Res>(_value.dailyNutritionIntake, (value) {
return _then(_value.copyWith(dailyNutritionIntake: value) as $Val);
});
}
/// Create a copy of NutritionDataModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$NutritionModelCopyWith<$Res> get dailyNutritionRecommendation {
return $NutritionModelCopyWith<$Res>(_value.dailyNutritionRecommendation,
(value) {
return _then(
_value.copyWith(dailyNutritionRecommendation: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$NutritionDataModelImplCopyWith<$Res>
implements $NutritionDataModelCopyWith<$Res> {
factory _$$NutritionDataModelImplCopyWith(_$NutritionDataModelImpl value,
$Res Function(_$NutritionDataModelImpl) then) =
__$$NutritionDataModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{NutritionModel dailyNutritionIntake,
NutritionModel dailyNutritionRecommendation});
@override
$NutritionModelCopyWith<$Res> get dailyNutritionIntake;
@override
$NutritionModelCopyWith<$Res> get dailyNutritionRecommendation;
}
/// @nodoc
class __$$NutritionDataModelImplCopyWithImpl<$Res>
extends _$NutritionDataModelCopyWithImpl<$Res, _$NutritionDataModelImpl>
implements _$$NutritionDataModelImplCopyWith<$Res> {
__$$NutritionDataModelImplCopyWithImpl(_$NutritionDataModelImpl _value,
$Res Function(_$NutritionDataModelImpl) _then)
: super(_value, _then);
/// Create a copy of NutritionDataModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? dailyNutritionIntake = null,
Object? dailyNutritionRecommendation = null,
}) {
return _then(_$NutritionDataModelImpl(
dailyNutritionIntake: null == dailyNutritionIntake
? _value.dailyNutritionIntake
: dailyNutritionIntake // ignore: cast_nullable_to_non_nullable
as NutritionModel,
dailyNutritionRecommendation: null == dailyNutritionRecommendation
? _value.dailyNutritionRecommendation
: dailyNutritionRecommendation // ignore: cast_nullable_to_non_nullable
as NutritionModel,
));
}
}
/// @nodoc
@JsonSerializable()
class _$NutritionDataModelImpl implements _NutritionDataModel {
const _$NutritionDataModelImpl(
{required this.dailyNutritionIntake,
required this.dailyNutritionRecommendation});
factory _$NutritionDataModelImpl.fromJson(Map<String, dynamic> json) =>
_$$NutritionDataModelImplFromJson(json);
@override
final NutritionModel dailyNutritionIntake;
@override
final NutritionModel dailyNutritionRecommendation;
@override
String toString() {
return 'NutritionDataModel(dailyNutritionIntake: $dailyNutritionIntake, dailyNutritionRecommendation: $dailyNutritionRecommendation)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$NutritionDataModelImpl &&
(identical(other.dailyNutritionIntake, dailyNutritionIntake) ||
other.dailyNutritionIntake == dailyNutritionIntake) &&
(identical(other.dailyNutritionRecommendation,
dailyNutritionRecommendation) ||
other.dailyNutritionRecommendation ==
dailyNutritionRecommendation));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType, dailyNutritionIntake, dailyNutritionRecommendation);
/// Create a copy of NutritionDataModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$NutritionDataModelImplCopyWith<_$NutritionDataModelImpl> get copyWith =>
__$$NutritionDataModelImplCopyWithImpl<_$NutritionDataModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$NutritionDataModelImplToJson(
this,
);
}
}
abstract class _NutritionDataModel implements NutritionDataModel {
const factory _NutritionDataModel(
{required final NutritionModel dailyNutritionIntake,
required final NutritionModel dailyNutritionRecommendation}) =
_$NutritionDataModelImpl;
factory _NutritionDataModel.fromJson(Map<String, dynamic> json) =
_$NutritionDataModelImpl.fromJson;
@override
NutritionModel get dailyNutritionIntake;
@override
NutritionModel get dailyNutritionRecommendation;
/// Create a copy of NutritionDataModel
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$NutritionDataModelImplCopyWith<_$NutritionDataModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}
NutritionModel _$NutritionModelFromJson(Map<String, dynamic> json) {
return _NutritionModel.fromJson(json);
}
/// @nodoc
mixin _$NutritionModel {
double get energy => throw _privateConstructorUsedError;
double get proteins => throw _privateConstructorUsedError;
double get fats => throw _privateConstructorUsedError;
double get carbohydrates => throw _privateConstructorUsedError;
/// Serializes this NutritionModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of NutritionModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$NutritionModelCopyWith<NutritionModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $NutritionModelCopyWith<$Res> {
factory $NutritionModelCopyWith(
NutritionModel value, $Res Function(NutritionModel) then) =
_$NutritionModelCopyWithImpl<$Res, NutritionModel>;
@useResult
$Res call(
{double energy, double proteins, double fats, double carbohydrates});
}
/// @nodoc
class _$NutritionModelCopyWithImpl<$Res, $Val extends NutritionModel>
implements $NutritionModelCopyWith<$Res> {
_$NutritionModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of NutritionModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? energy = null,
Object? proteins = null,
Object? fats = null,
Object? carbohydrates = null,
}) {
return _then(_value.copyWith(
energy: null == energy
? _value.energy
: energy // ignore: cast_nullable_to_non_nullable
as double,
proteins: null == proteins
? _value.proteins
: proteins // ignore: cast_nullable_to_non_nullable
as double,
fats: null == fats
? _value.fats
: fats // ignore: cast_nullable_to_non_nullable
as double,
carbohydrates: null == carbohydrates
? _value.carbohydrates
: carbohydrates // ignore: cast_nullable_to_non_nullable
as double,
) as $Val);
}
}
/// @nodoc
abstract class _$$NutritionModelImplCopyWith<$Res>
implements $NutritionModelCopyWith<$Res> {
factory _$$NutritionModelImplCopyWith(_$NutritionModelImpl value,
$Res Function(_$NutritionModelImpl) then) =
__$$NutritionModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{double energy, double proteins, double fats, double carbohydrates});
}
/// @nodoc
class __$$NutritionModelImplCopyWithImpl<$Res>
extends _$NutritionModelCopyWithImpl<$Res, _$NutritionModelImpl>
implements _$$NutritionModelImplCopyWith<$Res> {
__$$NutritionModelImplCopyWithImpl(
_$NutritionModelImpl _value, $Res Function(_$NutritionModelImpl) _then)
: super(_value, _then);
/// Create a copy of NutritionModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? energy = null,
Object? proteins = null,
Object? fats = null,
Object? carbohydrates = null,
}) {
return _then(_$NutritionModelImpl(
energy: null == energy
? _value.energy
: energy // ignore: cast_nullable_to_non_nullable
as double,
proteins: null == proteins
? _value.proteins
: proteins // ignore: cast_nullable_to_non_nullable
as double,
fats: null == fats
? _value.fats
: fats // ignore: cast_nullable_to_non_nullable
as double,
carbohydrates: null == carbohydrates
? _value.carbohydrates
: carbohydrates // ignore: cast_nullable_to_non_nullable
as double,
));
}
}
/// @nodoc
@JsonSerializable()
class _$NutritionModelImpl implements _NutritionModel {
const _$NutritionModelImpl(
{required this.energy,
required this.proteins,
required this.fats,
required this.carbohydrates});
factory _$NutritionModelImpl.fromJson(Map<String, dynamic> json) =>
_$$NutritionModelImplFromJson(json);
@override
final double energy;
@override
final double proteins;
@override
final double fats;
@override
final double carbohydrates;
@override
String toString() {
return 'NutritionModel(energy: $energy, proteins: $proteins, fats: $fats, carbohydrates: $carbohydrates)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$NutritionModelImpl &&
(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, energy, proteins, fats, carbohydrates);
/// Create a copy of NutritionModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$NutritionModelImplCopyWith<_$NutritionModelImpl> get copyWith =>
__$$NutritionModelImplCopyWithImpl<_$NutritionModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$NutritionModelImplToJson(
this,
);
}
}
abstract class _NutritionModel implements NutritionModel {
const factory _NutritionModel(
{required final double energy,
required final double proteins,
required final double fats,
required final double carbohydrates}) = _$NutritionModelImpl;
factory _NutritionModel.fromJson(Map<String, dynamic> json) =
_$NutritionModelImpl.fromJson;
@override
double get energy;
@override
double get proteins;
@override
double get fats;
@override
double get carbohydrates;
/// Create a copy of NutritionModel
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$NutritionModelImplCopyWith<_$NutritionModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,40 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'nutrition_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$NutritionDataModelImpl _$$NutritionDataModelImplFromJson(
Map<String, dynamic> json) =>
_$NutritionDataModelImpl(
dailyNutritionIntake: NutritionModel.fromJson(
json['dailyNutritionIntake'] as Map<String, dynamic>),
dailyNutritionRecommendation: NutritionModel.fromJson(
json['dailyNutritionRecommendation'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$NutritionDataModelImplToJson(
_$NutritionDataModelImpl instance) =>
<String, dynamic>{
'dailyNutritionIntake': instance.dailyNutritionIntake,
'dailyNutritionRecommendation': instance.dailyNutritionRecommendation,
};
_$NutritionModelImpl _$$NutritionModelImplFromJson(Map<String, dynamic> json) =>
_$NutritionModelImpl(
energy: (json['energy'] as num).toDouble(),
proteins: (json['proteins'] as num).toDouble(),
fats: (json['fats'] as num).toDouble(),
carbohydrates: (json['carbohydrates'] as num).toDouble(),
);
Map<String, dynamic> _$$NutritionModelImplToJson(
_$NutritionModelImpl instance) =>
<String, dynamic>{
'energy': instance.energy,
'proteins': instance.proteins,
'fats': instance.fats,
'carbohydrates': instance.carbohydrates,
};

View File

@@ -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/presentation/bloc/diary_state.dart';
import 'package:eatvio_app/features/diary/repositories/diary_repository.dart';
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
@@ -10,6 +11,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
class DiaryCubit extends Cubit<DiaryState> {
final DiaryRepository diaryRepository;
final GlossaryRepository glossaryRepository;
double currentSelectedSatietyRating = 3;
DiaryCubit({
required this.diaryRepository,
@@ -19,13 +21,23 @@ class DiaryCubit extends Cubit<DiaryState> {
getDiaryDay(String date, [bool needLoading = true]) async {
if (needLoading) emit(const DiaryState.loading());
try {
emit(DiaryState.loaded(diary: await diaryRepository.getDiaryByDate(date)));
emit(
DiaryState.loaded(
diary: await diaryRepository.getDiaryByDate(date),
nutrition: await getNutrition(await diaryRepository.getDiaryIndexByDate(date)),
currentSelectedSatietyRating: currentSelectedSatietyRating,
),
);
} catch (e) {
emit(DiaryState.error(errorMessage: e.toString()));
throw e;
}
}
Future<NutritionDataModel> getNutrition(int index) async {
return (await diaryRepository.getNutritionData(index));
}
addProductToMeal({
required int diaryId,
required int mealId,
@@ -109,4 +121,9 @@ class DiaryCubit extends Cubit<DiaryState> {
);
await getDiaryDay(date, false);
}
updateCurrentSelectedSatietyRating(double value) {
currentSelectedSatietyRating = value;
emit((state as DiaryStateLoaded).copyWith(currentSelectedSatietyRating: currentSelectedSatietyRating));
}
}

View File

@@ -1,4 +1,5 @@
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'diary_state.freezed.dart';
@@ -15,5 +16,7 @@ class DiaryState with _$DiaryState {
const factory DiaryState.loaded({
required DiaryDayModel diary,
required NutritionDataModel nutrition,
required double currentSelectedSatietyRating,
}) = DiaryStateLoaded;
}

View File

@@ -21,7 +21,9 @@ mixin _$DiaryState {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(String errorMessage) error,
required TResult Function(DiaryDayModel diary) loaded,
required TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)
loaded,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
@@ -29,7 +31,9 @@ mixin _$DiaryState {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(String errorMessage)? error,
TResult? Function(DiaryDayModel diary)? loaded,
TResult? Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
@@ -37,7 +41,9 @@ mixin _$DiaryState {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(String errorMessage)? error,
TResult Function(DiaryDayModel diary)? loaded,
TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@@ -133,7 +139,9 @@ class _$DiaryStateImpl implements _DiaryState {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(String errorMessage) error,
required TResult Function(DiaryDayModel diary) loaded,
required TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)
loaded,
}) {
return $default();
}
@@ -144,7 +152,9 @@ class _$DiaryStateImpl implements _DiaryState {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(String errorMessage)? error,
TResult? Function(DiaryDayModel diary)? loaded,
TResult? Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
}) {
return $default?.call();
}
@@ -155,7 +165,9 @@ class _$DiaryStateImpl implements _DiaryState {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(String errorMessage)? error,
TResult Function(DiaryDayModel diary)? loaded,
TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
required TResult orElse(),
}) {
if ($default != null) {
@@ -250,7 +262,9 @@ class _$DiaryStateLoadingImpl implements DiaryStateLoading {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(String errorMessage) error,
required TResult Function(DiaryDayModel diary) loaded,
required TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)
loaded,
}) {
return loading();
}
@@ -261,7 +275,9 @@ class _$DiaryStateLoadingImpl implements DiaryStateLoading {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(String errorMessage)? error,
TResult? Function(DiaryDayModel diary)? loaded,
TResult? Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
}) {
return loading?.call();
}
@@ -272,7 +288,9 @@ class _$DiaryStateLoadingImpl implements DiaryStateLoading {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(String errorMessage)? error,
TResult Function(DiaryDayModel diary)? loaded,
TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
required TResult orElse(),
}) {
if (loading != null) {
@@ -396,7 +414,9 @@ class _$DiaryStateErrorImpl implements DiaryStateError {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(String errorMessage) error,
required TResult Function(DiaryDayModel diary) loaded,
required TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)
loaded,
}) {
return error(errorMessage);
}
@@ -407,7 +427,9 @@ class _$DiaryStateErrorImpl implements DiaryStateError {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(String errorMessage)? error,
TResult? Function(DiaryDayModel diary)? loaded,
TResult? Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
}) {
return error?.call(errorMessage);
}
@@ -418,7 +440,9 @@ class _$DiaryStateErrorImpl implements DiaryStateError {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(String errorMessage)? error,
TResult Function(DiaryDayModel diary)? loaded,
TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
required TResult orElse(),
}) {
if (error != null) {
@@ -484,9 +508,13 @@ abstract class _$$DiaryStateLoadedImplCopyWith<$Res> {
$Res Function(_$DiaryStateLoadedImpl) then) =
__$$DiaryStateLoadedImplCopyWithImpl<$Res>;
@useResult
$Res call({DiaryDayModel diary});
$Res call(
{DiaryDayModel diary,
NutritionDataModel nutrition,
double currentSelectedSatietyRating});
$DiaryDayModelCopyWith<$Res> get diary;
$NutritionDataModelCopyWith<$Res> get nutrition;
}
/// @nodoc
@@ -503,12 +531,22 @@ class __$$DiaryStateLoadedImplCopyWithImpl<$Res>
@override
$Res call({
Object? diary = null,
Object? nutrition = null,
Object? currentSelectedSatietyRating = null,
}) {
return _then(_$DiaryStateLoadedImpl(
diary: null == diary
? _value.diary
: diary // ignore: cast_nullable_to_non_nullable
as DiaryDayModel,
nutrition: null == nutrition
? _value.nutrition
: nutrition // ignore: cast_nullable_to_non_nullable
as NutritionDataModel,
currentSelectedSatietyRating: null == currentSelectedSatietyRating
? _value.currentSelectedSatietyRating
: currentSelectedSatietyRating // ignore: cast_nullable_to_non_nullable
as double,
));
}
@@ -521,19 +559,36 @@ class __$$DiaryStateLoadedImplCopyWithImpl<$Res>
return _then(_value.copyWith(diary: value));
});
}
/// Create a copy of DiaryState
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$NutritionDataModelCopyWith<$Res> get nutrition {
return $NutritionDataModelCopyWith<$Res>(_value.nutrition, (value) {
return _then(_value.copyWith(nutrition: value));
});
}
}
/// @nodoc
class _$DiaryStateLoadedImpl implements DiaryStateLoaded {
const _$DiaryStateLoadedImpl({required this.diary});
const _$DiaryStateLoadedImpl(
{required this.diary,
required this.nutrition,
required this.currentSelectedSatietyRating});
@override
final DiaryDayModel diary;
@override
final NutritionDataModel nutrition;
@override
final double currentSelectedSatietyRating;
@override
String toString() {
return 'DiaryState.loaded(diary: $diary)';
return 'DiaryState.loaded(diary: $diary, nutrition: $nutrition, currentSelectedSatietyRating: $currentSelectedSatietyRating)';
}
@override
@@ -541,11 +596,18 @@ class _$DiaryStateLoadedImpl implements DiaryStateLoaded {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$DiaryStateLoadedImpl &&
(identical(other.diary, diary) || other.diary == diary));
(identical(other.diary, diary) || other.diary == diary) &&
(identical(other.nutrition, nutrition) ||
other.nutrition == nutrition) &&
(identical(other.currentSelectedSatietyRating,
currentSelectedSatietyRating) ||
other.currentSelectedSatietyRating ==
currentSelectedSatietyRating));
}
@override
int get hashCode => Object.hash(runtimeType, diary);
int get hashCode =>
Object.hash(runtimeType, diary, nutrition, currentSelectedSatietyRating);
/// Create a copy of DiaryState
/// with the given fields replaced by the non-null parameter values.
@@ -562,9 +624,11 @@ class _$DiaryStateLoadedImpl implements DiaryStateLoaded {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(String errorMessage) error,
required TResult Function(DiaryDayModel diary) loaded,
required TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)
loaded,
}) {
return loaded(diary);
return loaded(diary, nutrition, currentSelectedSatietyRating);
}
@override
@@ -573,9 +637,11 @@ class _$DiaryStateLoadedImpl implements DiaryStateLoaded {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(String errorMessage)? error,
TResult? Function(DiaryDayModel diary)? loaded,
TResult? Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
}) {
return loaded?.call(diary);
return loaded?.call(diary, nutrition, currentSelectedSatietyRating);
}
@override
@@ -584,11 +650,13 @@ class _$DiaryStateLoadedImpl implements DiaryStateLoaded {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(String errorMessage)? error,
TResult Function(DiaryDayModel diary)? loaded,
TResult Function(DiaryDayModel diary, NutritionDataModel nutrition,
double currentSelectedSatietyRating)?
loaded,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(diary);
return loaded(diary, nutrition, currentSelectedSatietyRating);
}
return orElse();
}
@@ -632,10 +700,15 @@ class _$DiaryStateLoadedImpl implements DiaryStateLoaded {
}
abstract class DiaryStateLoaded implements DiaryState {
const factory DiaryStateLoaded({required final DiaryDayModel diary}) =
const factory DiaryStateLoaded(
{required final DiaryDayModel diary,
required final NutritionDataModel nutrition,
required final double currentSelectedSatietyRating}) =
_$DiaryStateLoadedImpl;
DiaryDayModel get diary;
NutritionDataModel get nutrition;
double get currentSelectedSatietyRating;
/// Create a copy of DiaryState
/// with the given fields replaced by the non-null parameter values.

View File

@@ -2,8 +2,11 @@ import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:eatvio_app/core/const.dart';
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/presentation/bloc/diary_cubit.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
import 'package:eatvio_app/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart';
import 'package:eatvio_app/features/diary/presentation/widgets/satiety_rating_widget.dart';
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:eatvio_app/theme/theme_helper.dart';
@@ -15,6 +18,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:image_picker/image_picker.dart';
import 'package:rive/rive.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
import 'package:table_calendar/table_calendar.dart';
class DiaryScreen extends StatefulWidget {
@@ -34,6 +38,65 @@ class _DiaryScreenState extends State<DiaryScreen> {
final productNameController = TextEditingController();
final quantityController = TextEditingController();
int currentSelectedPhotoIndex = 0;
String time = "${DateTime.now().hour.toString().padLeft(2, '0')}:${DateTime.now().minute.toString().padLeft(2, '0')}";
DateTime _time = DateTime.now();
_showDatePicker() {
showModalBottomSheet<void>(
context: context,
useRootNavigator: true,
builder: (context) => SizedBox(
height: MediaQuery.of(context).copyWith().size.height / 3,
child: Column(
children: [
Expanded(
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.time,
use24hFormat: true,
initialDateTime: DateTime.now(),
onDateTimeChanged: (newTime) {
setState(() {
_time = newTime;
time = "${_time.hour.toString().padLeft(2, '0')}:${_time.minute.toString().padLeft(2, '0')}";
});
},
),
),
InkWell(
onTap: () {
Navigator.of(context).pop();
showModalBottomSheet(
useRootNavigator: true,
useSafeArea: false,
context: context,
builder: (context) => GlossaryModerationRequestModalWidget(),
);
},
borderRadius: BorderRadius.circular(20),
child: Ink(
width: MediaQuery.of(context).size.width - 16,
height: 52,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: appTheme.blueA400,
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
@@ -59,7 +122,12 @@ class _DiaryScreenState extends State<DiaryScreen> {
children: [
_calendar(state),
if (state is DiaryStateLoading) _loader(),
if (state is DiaryStateLoaded) _meals(state.diary),
if (state is DiaryStateLoaded)
_meals(
state.diary,
state.currentSelectedSatietyRating,
),
if (state is DiaryStateLoaded) _chart(state.nutrition),
const SizedBox(height: 32),
],
),
@@ -70,13 +138,47 @@ class _DiaryScreenState extends State<DiaryScreen> {
);
}
_timeOfMeal(String time) {
return InkWell(
onTap: () => _showDatePicker(),
borderRadius: BorderRadius.circular(100),
child: Ink(
height: 32,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: Color(0xFFF1F2F6),
),
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 16),
child: Text(
time,
style: TextStyle(
color: Color(0xFF6D6F71),
fontSize: 17,
fontWeight: FontWeight.w500,
),
),
),
),
);
}
_arrowDown() {
return Container(
padding: const EdgeInsets.only(top: 8, bottom: 16),
width: double.infinity,
child: Icon(
_calendarFormat == CalendarFormat.month ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded,
color: Colors.grey.shade600,
return GestureDetector(
behavior: HitTestBehavior.translucent,
onVerticalDragStart: (_) {
setState(() {
_calendarFormat = CalendarFormat.values[(_calendarFormat.index - 1) % CalendarFormat.values.length];
});
},
child: Container(
width: double.infinity,
padding: const EdgeInsets.only(top: 8, bottom: 16),
child: Icon(
_calendarFormat == CalendarFormat.month ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded,
color: Colors.grey.shade600,
),
),
);
}
@@ -130,7 +232,10 @@ class _DiaryScreenState extends State<DiaryScreen> {
);
}
_meals(DiaryDayModel diaryDay) {
_meals(
DiaryDayModel diaryDay,
double currentSelectedSatietyRating,
) {
return Material(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
@@ -161,13 +266,19 @@ class _DiaryScreenState extends State<DiaryScreen> {
const SizedBox(height: 12),
_divider(context),
const SizedBox(height: 12),
Text(
'Время приема пищи',
style: TextStyle(
color: Color(0xFF323F4B),
fontSize: 16,
fontWeight: FontWeight.w500,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Время приема пищи',
style: TextStyle(
color: Color(0xFF323F4B),
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
_timeOfMeal(time),
],
),
const SizedBox(height: 12),
_divider(context),
@@ -189,12 +300,254 @@ class _DiaryScreenState extends State<DiaryScreen> {
diaryDay.meals[currentSelectedMealNumber - 1].photos,
diaryDay,
),
SatietyRatingWidget(
currentSelectedSatietyRating: currentSelectedSatietyRating,
),
],
),
),
);
}
_chart(NutritionDataModel nutrition) {
final List<ChartData> chartData = [
ChartData(
nutrition.dailyNutritionIntake.carbohydrates,
nutrition.dailyNutritionRecommendation.carbohydrates,
),
ChartData(
nutrition.dailyNutritionIntake.fats,
nutrition.dailyNutritionRecommendation.fats,
),
ChartData(
nutrition.dailyNutritionIntake.proteins,
nutrition.dailyNutritionRecommendation.proteins,
),
ChartData(
nutrition.dailyNutritionIntake.energy,
nutrition.dailyNutritionRecommendation.energy,
),
];
return Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(top: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Ваш КБЖУ от дневной\nсуточной нормы',
textAlign: TextAlign.center,
style: TextStyle(
color: Color(0xFF323F4B),
fontWeight: FontWeight.w500,
fontSize: 18,
height: 1,
),
),
const SizedBox(height: 48),
Stack(
alignment: Alignment.bottomCenter,
children: [
SfRadialGauge(
axes: <RadialAxis>[
RadialAxis(
startAngle: 180,
endAngle: 0,
minimum: 0,
maximum: 100,
showLabels: false,
showTicks: false,
radiusFactor: 0.7,
showAxisLine: false,
pointers: <GaugePointer>[
RangePointer(
value: 100,
width: 0.16,
animationDuration: 2000,
color: Color(0xFFF6FAFF),
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
),
RangePointer(
value: (chartData[0].intake / chartData[0].recommendation) * 100,
width: 0.16,
color: chartData[0].intake < chartData[0].recommendation ? appTheme.blueA400 : Colors.red,
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
),
RangePointer(
value: 100,
width: 0.16,
animationDuration: 2000,
color: Color(0xFFF6FAFF),
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
pointerOffset: -0.18,
),
RangePointer(
value: (chartData[1].intake / chartData[1].recommendation) * 100,
width: 0.16,
color: chartData[1].intake < chartData[1].recommendation ? appTheme.blueA400 : Colors.red,
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
pointerOffset: -0.18,
),
RangePointer(
value: 100,
width: 0.16,
animationDuration: 2000,
color: Color(0xFFF6FAFF),
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
pointerOffset: -0.36,
),
RangePointer(
value: (chartData[2].intake / chartData[2].recommendation) * 100,
width: 0.16,
color: chartData[2].intake < chartData[2].recommendation ? appTheme.blueA400 : Colors.red,
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
pointerOffset: -0.36,
),
RangePointer(
value: 100,
width: 0.16,
animationDuration: 2000,
color: Color(0xFFF6FAFF),
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
pointerOffset: -0.54,
),
RangePointer(
value: (chartData[3].intake / chartData[3].recommendation) * 100,
width: 0.16,
color: chartData[3].intake < chartData[3].recommendation ? appTheme.blueA400 : Colors.red,
sizeUnit: GaugeSizeUnit.factor,
enableAnimation: true,
cornerStyle: CornerStyle.bothCurve,
pointerOffset: -0.54,
),
],
annotations: <GaugeAnnotation>[
GaugeAnnotation(
widget: Transform.rotate(
angle: 30.1,
child: Text(
'Углеводы',
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
),
angle: 198,
positionFactor: 0.92,
),
GaugeAnnotation(
widget: Transform.rotate(
angle: 30,
child: Text(
'Жиры',
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
),
angle: 190,
positionFactor: 1.1,
),
GaugeAnnotation(
widget: Transform.rotate(
angle: 30,
child: Text(
'Белки',
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
),
angle: 190,
positionFactor: 1.27,
),
GaugeAnnotation(
widget: Transform.rotate(
angle: 30,
child: Text(
'Калории',
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
),
angle: 192,
positionFactor: 1.46,
),
],
),
],
),
Column(
children: [
_chartData('Калории',
'${nutrition.dailyNutritionIntake.energy.toStringAsFixed(0)} из ${nutrition.dailyNutritionRecommendation.energy.toStringAsFixed(0)} ккал'),
const SizedBox(height: 8),
_chartData('Белки',
'${nutrition.dailyNutritionIntake.proteins.toStringAsFixed(0)} из ${nutrition.dailyNutritionRecommendation.proteins.toStringAsFixed(0)} грамм'),
const SizedBox(height: 8),
_chartData('Жиры',
'${nutrition.dailyNutritionIntake.fats.toStringAsFixed(0)} из ${nutrition.dailyNutritionRecommendation.fats.toStringAsFixed(0)} грамм'),
const SizedBox(height: 8),
_chartData('Углеводы',
'${nutrition.dailyNutritionIntake.carbohydrates.toStringAsFixed(0)} из ${nutrition.dailyNutritionRecommendation.carbohydrates.toStringAsFixed(0)} грамм'),
],
),
],
),
],
),
);
}
_chartData(String title, String value) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Color(0xFF323F4B),
),
),
Text(
value,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Color(0xFF323F4B),
),
),
],
);
}
_showImagePicker(DiaryDayModel diaryDay) {
showCupertinoModalPopup<void>(
context: context,
@@ -271,19 +624,20 @@ class _DiaryScreenState extends State<DiaryScreen> {
child: IconButton.filled(
style: IconButton.styleFrom(
backgroundColor: Colors.white,
elevation: 0,
),
onPressed: () {
setState(() {
if (currentSelectedPhotoIndex == photos.length - 1 && currentSelectedPhotoIndex != 0) {
currentSelectedPhotoIndex = photos.length - 2;
}
});
diaryCubit.deletePhoto(
onPressed: () async {
await diaryCubit.deletePhoto(
photo: photos[currentSelectedPhotoIndex],
diaryId: diaryDay.id,
mealId: diaryDay.meals[currentSelectedMealNumber - 1].id,
date: _selectedDay.toString(),
);
setState(() {
if (currentSelectedPhotoIndex == photos.length - 1 && currentSelectedPhotoIndex != 0) {
currentSelectedPhotoIndex = photos.length - 2;
}
});
},
icon: Icon(
Icons.close_rounded,
@@ -372,7 +726,7 @@ class _DiaryScreenState extends State<DiaryScreen> {
child: Text(
'$mealNumber',
style: TextStyle(
color: isActive ? Colors.white : Colors.black,
color: isActive ? Colors.white : Color(0xFF6D6F71),
fontSize: 16,
fontWeight: FontWeight.w600,
),
@@ -669,3 +1023,13 @@ class _DiaryScreenState extends State<DiaryScreen> {
);
}
}
class ChartData {
final double intake;
final double recommendation;
ChartData(
this.intake,
this.recommendation,
);
}

View File

@@ -0,0 +1,17 @@
import 'package:flutter/material.dart';
class GlossaryModerationRequestModalWidget extends StatefulWidget {
const GlossaryModerationRequestModalWidget({super.key});
@override
State<GlossaryModerationRequestModalWidget> createState() => _GlossaryModerationRequestModalWidgetState();
}
class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModerationRequestModalWidget> {
@override
Widget build(BuildContext context) {
return Dialog(
child: Column(),
);
}
}

View File

@@ -0,0 +1,179 @@
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:flutter_svg/flutter_svg.dart';
class SatietyRatingWidget extends StatefulWidget {
final double currentSelectedSatietyRating;
const SatietyRatingWidget({
super.key,
required this.currentSelectedSatietyRating,
});
@override
State<SatietyRatingWidget> createState() => _SatietyRatingWidgetState();
}
class _SatietyRatingWidgetState extends State<SatietyRatingWidget> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Ваша сытость после приёма пищи',
style: TextStyle(
fontSize: 16,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
'assets/icons/satiety_emoji_left.svg',
height: 32,
width: 32,
),
RatingBar.builder(
initialRating: 3,
itemCount: 6,
itemSize: MediaQuery.of(context).size.width / 6 - (124 / 6),
updateOnDrag: true,
itemBuilder: (context, index) {
switch (index) {
case 0:
return Container(
width: MediaQuery.of(context).size.width / 6,
height: 24,
margin: widget.currentSelectedSatietyRating == 1 ? EdgeInsets.symmetric(horizontal: 2) : null,
decoration: BoxDecoration(
color: Color(0xFFC82222),
border: widget.currentSelectedSatietyRating == 1
? Border.all(
width: 2,
color: Color(0xFFAA3333),
strokeAlign: BorderSide.strokeAlignOutside,
)
: null,
borderRadius: widget.currentSelectedSatietyRating == 1
? BorderRadius.horizontal(
left: Radius.circular(8),
right: Radius.circular(2),
)
: BorderRadius.horizontal(
left: Radius.circular(8),
),
),
);
case 1:
return Container(
width: MediaQuery.of(context).size.width / 6,
height: 24,
margin: widget.currentSelectedSatietyRating == 2 ? EdgeInsets.symmetric(horizontal: 2) : null,
decoration: BoxDecoration(
color: Color(0xFFFF3E3E),
border: widget.currentSelectedSatietyRating == 2
? Border.all(
width: 2,
color: Color(0xFF550000),
strokeAlign: BorderSide.strokeAlignOutside,
)
: null,
borderRadius: widget.currentSelectedSatietyRating == 2 ? BorderRadius.circular(2) : null,
),
);
case 2:
return Container(
width: MediaQuery.of(context).size.width / 6,
height: 24,
margin: widget.currentSelectedSatietyRating == 3 ? EdgeInsets.symmetric(horizontal: 2) : null,
decoration: BoxDecoration(
color: Color(0xFFF8C926),
border: widget.currentSelectedSatietyRating == 3
? Border.all(
width: 2,
color: Color(0xFF8C5D00),
strokeAlign: BorderSide.strokeAlignOutside,
)
: null,
borderRadius: widget.currentSelectedSatietyRating == 3 ? BorderRadius.circular(2) : null,
),
);
case 3:
return Container(
width: MediaQuery.of(context).size.width / 6,
height: 24,
margin: widget.currentSelectedSatietyRating == 4 ? EdgeInsets.symmetric(horizontal: 2) : null,
decoration: BoxDecoration(
color: Color(0xFFFFF3BF),
border: widget.currentSelectedSatietyRating == 4
? Border.all(
width: 2,
color: Color(0xFFB5911B),
strokeAlign: BorderSide.strokeAlignOutside,
)
: null,
borderRadius: widget.currentSelectedSatietyRating == 4 ? BorderRadius.circular(2) : null,
),
);
case 4:
return Container(
width: MediaQuery.of(context).size.width / 6,
height: 24,
margin: widget.currentSelectedSatietyRating == 5 ? EdgeInsets.symmetric(horizontal: 2) : null,
decoration: BoxDecoration(
color: Color(0xFF62E833),
border: widget.currentSelectedSatietyRating == 5
? Border.all(
width: 2,
color: Color(0xFF276918),
strokeAlign: BorderSide.strokeAlignOutside,
)
: null,
borderRadius: widget.currentSelectedSatietyRating == 5 ? BorderRadius.circular(2) : null,
),
);
default:
return Container(
width: MediaQuery.of(context).size.width / 6,
height: 24,
margin: widget.currentSelectedSatietyRating == 6 ? EdgeInsets.symmetric(horizontal: 2) : null,
decoration: BoxDecoration(
color: Color(0xFF4DCE20),
border: widget.currentSelectedSatietyRating == 6
? Border.all(
width: 2,
color: Color(0xFF184D12),
strokeAlign: BorderSide.strokeAlignOutside,
)
: null,
borderRadius: widget.currentSelectedSatietyRating == 6
? BorderRadius.horizontal(
left: Radius.circular(2),
right: Radius.circular(8),
)
: BorderRadius.horizontal(
right: Radius.circular(8),
),
),
);
}
},
onRatingUpdate: (value) => context.read<DiaryCubit>().updateCurrentSelectedSatietyRating(value),
),
SvgPicture.asset(
'assets/icons/satiety_emoji_right.svg',
height: 32,
width: 32,
),
],
),
],
),
);
}
}

View File

@@ -1,5 +1,6 @@
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/services/diary_service.dart';
class DiaryRepository {
@@ -11,15 +12,19 @@ class DiaryRepository {
Future<DiaryDayModel> getDiaryByDate(String date) async {
return (await diaryService.getDiaryDay(
index: await _getDiaryIndexByDate(date),
index: await getDiaryIndexByDate(date),
))
.diary;
}
Future<int> _getDiaryIndexByDate(String date) async {
Future<int> getDiaryIndexByDate(String date) async {
return (await diaryService.getDiaryIndexByDate(date: date)).id;
}
Future<NutritionDataModel> getNutritionData(int index) async {
return await diaryService.getNutrition(index: index);
}
Future<void> addPortionToMeal({
required int diaryId,
required int mealId,

View File

@@ -2,6 +2,7 @@ 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';
part 'diary_service.g.dart';
@@ -20,6 +21,11 @@ abstract class DiaryService {
@Path('diary_id') required int index,
});
@GET('/api/diary/{diary_id}/dailyNutritionData')
Future<NutritionDataModel> getNutrition({
@Path('diary_id') required int index,
});
@POST('/api/diary/{diary_id}/meal/{meal_id}/photo/upload')
@MultiPart()
Future<void> uploadPhotoOfMeal({

View File

@@ -87,6 +87,39 @@ class _DiaryService implements DiaryService {
return _value;
}
@override
Future<NutritionDataModel> getNutrition({required int index}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<NutritionDataModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${index}/dailyNutritionData',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late NutritionDataModel _value;
try {
_value = NutritionDataModel.fromJson(_result.data!);
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
rethrow;
}
return _value;
}
@override
Future<void> uploadPhotoOfMeal({
required int diaryId,

View File

@@ -8,6 +8,7 @@ import 'package:flutter_svg/svg.dart';
class TypeBadges extends StatefulWidget {
const TypeBadges({super.key, required this.type});
final DietType type;
@override
@@ -16,6 +17,7 @@ class TypeBadges extends StatefulWidget {
class _TypeBadgesState extends State<TypeBadges> {
final List<bool> overlaysVisibilityState = [false, false, false, false];
@override
Widget build(BuildContext context) {
final s = S.of(context);
@@ -117,11 +119,18 @@ class _TypeBadgesState extends State<TypeBadges> {
}
class _InfoOverlayEntry extends StatelessWidget {
const _InfoOverlayEntry({required this.title, required this.description, required this.assetPath, required this.onClose});
const _InfoOverlayEntry({
required this.title,
required this.description,
required this.assetPath,
required this.onClose,
});
final String title;
final String description;
final assetPath;
final void Function() onClose;
@override
Widget build(BuildContext context) {
return MainBackgroundBouble(

View File

@@ -12,7 +12,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
Future<void> main() async {
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await di.init();
runApp(MyApp());

View File

@@ -40,6 +40,7 @@ dependencies:
google_fonts: ^6.2.1
location: ^7.0.1
syncfusion_flutter_charts: ^27.1.55
syncfusion_flutter_gauges: ^27.1.58
table_calendar: ^3.1.2
flutter_keyboard_visibility: ^6.0.0
share_plus: ^10.1.0
@@ -52,6 +53,7 @@ dependencies:
lottie: ^3.1.3
flutter_portal: ^1.1.4
fluttertoast: ^8.2.8
flutter_rating_bar: ^4.0.1
dev_dependencies:
build_runner: ^2.4.13