diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73d61cb --- /dev/null +++ b/.gitignore @@ -0,0 +1,74 @@ +# Created by https://www.toptal.com/developers/gitignore/api/flutter,vscode +# Edit at https://www.toptal.com/developers/gitignore?templates=flutter,vscode + +### Flutter ### +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.fvm/ +.packages +.pub-cache/ +.pub/ +build/ +lib/generated_plugin_registrant.dart + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/key.properties +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/.last_build_id +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages + +### vscode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Misc. +.DS_Store + +# End of https://www.toptal.com/developers/gitignore/api/flutter,vscode diff --git a/README.md b/README.md new file mode 100644 index 0000000..02f58f1 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..1c91652 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,93 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + + +android { + compileSdkVersion 29 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + checkReleaseBuilds false + } + + defaultConfig { + applicationId "com.huynh.listar_flutter" + minSdkVersion 21 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + multiDexEnabled true + } + +// signingConfigs { +// release { +// keyAlias keystoreProperties['keyAlias'] +// keyPassword keystoreProperties['keyPassword'] +// storeFile file(keystoreProperties['storeFile']?keystoreProperties['storeFile']:'') +// storePassword keystoreProperties['storePassword'] +// } +// } + + buildTypes { +// release { +// signingConfig signingConfigs.release +// } + debug { + signingConfig signingConfigs.debug + } +// signingConfig signingConfigs.debug +// + } +} + +flutter { + source '../..' +} + +apply plugin: 'com.android.application' + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.google.firebase:firebase-analytics:17.2.1' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + +} + +apply plugin: 'com.google.gms.google-services' diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..a160a91 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,47 @@ +{ + "project_info": { + "project_number": "254789615258", + "firebase_url": "https://listarflutter.firebaseio.com", + "project_id": "listarflutter", + "storage_bucket": "listarflutter.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:254789615258:android:d186e35569214101f8a923", + "android_client_info": { + "package_name": "com.huynh.listar_flutter" + } + }, + "oauth_client": [ + { + "client_id": "254789615258-p9n1rlm99m0jb4jk4pc5ftnupbcd13i2.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyC9garNK6h2IGgZ74ocFXHVXLknC9bUCws" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "254789615258-p9n1rlm99m0jb4jk4pc5ftnupbcd13i2.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "254789615258-qbpjmknq1u9473imrnnh2chlbcs6i2b1.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.huynh.listarFlutter" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..22fbccc --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..fd7c4fb --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/huynh/listar_flutter/MainActivity.kt b/android/app/src/main/kotlin/com/huynh/listar_flutter/MainActivity.kt new file mode 100644 index 0000000..efbb449 --- /dev/null +++ b/android/app/src/main/kotlin/com/huynh/listar_flutter/MainActivity.kt @@ -0,0 +1,12 @@ +package com.huynh.listar_flutter + +import android.os.Bundle + +import io.flutter.app.FlutterActivity +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } +} diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/logo.png b/android/app/src/main/res/drawable/logo.png new file mode 100644 index 0000000..5b57585 Binary files /dev/null and b/android/app/src/main/res/drawable/logo.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..3588730 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..7e6c11c Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6a750cf Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..7d257e5 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2db4362 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..83de459 --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,13 @@ + + Mahaas Sports + + + 430258564493822 + fb430258564493822 + + + AIzaSyDSNYVC-8DU9BTcyqkeN9c5pgVhwOBAvGg + + + ca-app-pub-7432665165146018~2664444130 + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..3d1e88d --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,19 @@ + + + #2eb0fe + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..22fbccc --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..7d9dd06 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,32 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.google.gms:google-services:4.3.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..a5965ab --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true \ No newline at end of file diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e4994ef --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Dec 08 21:46:38 ICT 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip diff --git a/android/keystore.jks b/android/keystore.jks new file mode 100644 index 0000000..b9c6aa9 Binary files /dev/null and b/android/keystore.jks differ diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..5a2f14f --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/assets/data/home.json b/assets/data/home.json new file mode 100644 index 0000000..e76f645 --- /dev/null +++ b/assets/data/home.json @@ -0,0 +1,78 @@ +{ + "success": true, + "data": { + "banner": [ + { + "id": 1, + "image": "assets/images/hurricane-banner.jpg" + }, + { + "id": 2, + "image": "assets/images/storm-banner.jpg" + }, + { + "id": 3, + "image": "assets/images/tornado-banner.jpg" + } + ], + "category": [ + { + "id": 1, + "title": "Storm Tracking", + "icon": "shopping_basket", + "color": "#ff8a65", + "type": "shop" + }, + { + "id": 2, + "title": "Personal Safety", + "icon": "local_drink", + "color": "#5d6d7e", + "type": "drink" + }, + { + "id": 3, + "title": "Personal Risk", + "icon": "event_available", + "color": "#a569bd", + "type": "event" + }, + { + "id": 4, + "title": "Property Safety", + "icon": "all_inclusive", + "color": "#5dade2", + "type": "estate" + }, + { + "id": 5, + "title": "Property Risk", + "icon": "card_travel", + "color": "#4a90a4", + "type": "job" + }, + { + "id": 6, + "title": "Supplies", + "icon": "restaurant", + "color": "#58d68d", + "type": "restaurant" + }, + { + "id": 7, + "title": "Evacuation", + "icon": "directions_car", + "color": "#fdc60a", + "type": "automotive" + }, + { + "id": 8, + "title": "Stay in Touch", + "icon": "hotel", + "color": "#ff8a65", + "type": "hotel" + } + ] + }, + "message": "get data success" +} \ No newline at end of file diff --git a/assets/data/location.json b/assets/data/location.json new file mode 100644 index 0000000..8213b7f --- /dev/null +++ b/assets/data/location.json @@ -0,0 +1,38 @@ +{ + "success": true, + "data": { + "location": [ + { + "id": 1, + "name": "Bridgeport", + "lat": 37.774929, + "long": -122.419418 + }, + { + "id": 2, + "name": "Milford", + "lat": 37.774929, + "long": -122.419418 + }, + { + "id": 3, + "name": "New Haven", + "lat": 37.774929, + "long": -122.419418 + }, + { + "id": 4, + "name": "New London", + "lat": 37.774929, + "long": -122.419418 + }, + { + "id": 5, + "name": "Norwalk", + "lat": 37.774929, + "long": -122.419418 + } + ] + }, + "message": "get data success" +} \ No newline at end of file diff --git a/assets/fonts/Merriweather-Black.ttf b/assets/fonts/Merriweather-Black.ttf new file mode 100644 index 0000000..555f892 Binary files /dev/null and b/assets/fonts/Merriweather-Black.ttf differ diff --git a/assets/fonts/Merriweather-BlackItalic.ttf b/assets/fonts/Merriweather-BlackItalic.ttf new file mode 100644 index 0000000..01ab074 Binary files /dev/null and b/assets/fonts/Merriweather-BlackItalic.ttf differ diff --git a/assets/fonts/Merriweather-Bold.ttf b/assets/fonts/Merriweather-Bold.ttf new file mode 100644 index 0000000..c6374c0 Binary files /dev/null and b/assets/fonts/Merriweather-Bold.ttf differ diff --git a/assets/fonts/Merriweather-BoldItalic.ttf b/assets/fonts/Merriweather-BoldItalic.ttf new file mode 100644 index 0000000..b2e7663 Binary files /dev/null and b/assets/fonts/Merriweather-BoldItalic.ttf differ diff --git a/assets/fonts/Merriweather-Italic.ttf b/assets/fonts/Merriweather-Italic.ttf new file mode 100644 index 0000000..179acf3 Binary files /dev/null and b/assets/fonts/Merriweather-Italic.ttf differ diff --git a/assets/fonts/Merriweather-Light.ttf b/assets/fonts/Merriweather-Light.ttf new file mode 100644 index 0000000..843b8a8 Binary files /dev/null and b/assets/fonts/Merriweather-Light.ttf differ diff --git a/assets/fonts/Merriweather-LightItalic.ttf b/assets/fonts/Merriweather-LightItalic.ttf new file mode 100644 index 0000000..16ea25e Binary files /dev/null and b/assets/fonts/Merriweather-LightItalic.ttf differ diff --git a/assets/fonts/Merriweather-Regular.ttf b/assets/fonts/Merriweather-Regular.ttf new file mode 100644 index 0000000..18da9e5 Binary files /dev/null and b/assets/fonts/Merriweather-Regular.ttf differ diff --git a/assets/fonts/Raleway-Black.ttf b/assets/fonts/Raleway-Black.ttf new file mode 100644 index 0000000..fa0be3b Binary files /dev/null and b/assets/fonts/Raleway-Black.ttf differ diff --git a/assets/fonts/Raleway-BlackItalic.ttf b/assets/fonts/Raleway-BlackItalic.ttf new file mode 100644 index 0000000..f879014 Binary files /dev/null and b/assets/fonts/Raleway-BlackItalic.ttf differ diff --git a/assets/fonts/Raleway-Bold.ttf b/assets/fonts/Raleway-Bold.ttf new file mode 100644 index 0000000..156d4a1 Binary files /dev/null and b/assets/fonts/Raleway-Bold.ttf differ diff --git a/assets/fonts/Raleway-BoldItalic.ttf b/assets/fonts/Raleway-BoldItalic.ttf new file mode 100644 index 0000000..d2db573 Binary files /dev/null and b/assets/fonts/Raleway-BoldItalic.ttf differ diff --git a/assets/fonts/Raleway-ExtraBold.ttf b/assets/fonts/Raleway-ExtraBold.ttf new file mode 100644 index 0000000..045f204 Binary files /dev/null and b/assets/fonts/Raleway-ExtraBold.ttf differ diff --git a/assets/fonts/Raleway-ExtraBoldItalic.ttf b/assets/fonts/Raleway-ExtraBoldItalic.ttf new file mode 100644 index 0000000..6780461 Binary files /dev/null and b/assets/fonts/Raleway-ExtraBoldItalic.ttf differ diff --git a/assets/fonts/Raleway-ExtraLight.ttf b/assets/fonts/Raleway-ExtraLight.ttf new file mode 100644 index 0000000..aa11269 Binary files /dev/null and b/assets/fonts/Raleway-ExtraLight.ttf differ diff --git a/assets/fonts/Raleway-ExtraLightItalic.ttf b/assets/fonts/Raleway-ExtraLightItalic.ttf new file mode 100644 index 0000000..0e7581b Binary files /dev/null and b/assets/fonts/Raleway-ExtraLightItalic.ttf differ diff --git a/assets/fonts/Raleway-Italic.ttf b/assets/fonts/Raleway-Italic.ttf new file mode 100644 index 0000000..a0157a5 Binary files /dev/null and b/assets/fonts/Raleway-Italic.ttf differ diff --git a/assets/fonts/Raleway-Light.ttf b/assets/fonts/Raleway-Light.ttf new file mode 100644 index 0000000..b5ec486 Binary files /dev/null and b/assets/fonts/Raleway-Light.ttf differ diff --git a/assets/fonts/Raleway-LightItalic.ttf b/assets/fonts/Raleway-LightItalic.ttf new file mode 100644 index 0000000..f844efb Binary files /dev/null and b/assets/fonts/Raleway-LightItalic.ttf differ diff --git a/assets/fonts/Raleway-Medium.ttf b/assets/fonts/Raleway-Medium.ttf new file mode 100644 index 0000000..070ac76 Binary files /dev/null and b/assets/fonts/Raleway-Medium.ttf differ diff --git a/assets/fonts/Raleway-MediumItalic.ttf b/assets/fonts/Raleway-MediumItalic.ttf new file mode 100644 index 0000000..bd61842 Binary files /dev/null and b/assets/fonts/Raleway-MediumItalic.ttf differ diff --git a/assets/fonts/Raleway-Regular.ttf b/assets/fonts/Raleway-Regular.ttf new file mode 100644 index 0000000..746c242 Binary files /dev/null and b/assets/fonts/Raleway-Regular.ttf differ diff --git a/assets/fonts/Raleway-SemiBold.ttf b/assets/fonts/Raleway-SemiBold.ttf new file mode 100644 index 0000000..34db420 Binary files /dev/null and b/assets/fonts/Raleway-SemiBold.ttf differ diff --git a/assets/fonts/Raleway-SemiBoldItalic.ttf b/assets/fonts/Raleway-SemiBoldItalic.ttf new file mode 100644 index 0000000..ade9ca6 Binary files /dev/null and b/assets/fonts/Raleway-SemiBoldItalic.ttf differ diff --git a/assets/fonts/Raleway-Thin.ttf b/assets/fonts/Raleway-Thin.ttf new file mode 100644 index 0000000..f623aba Binary files /dev/null and b/assets/fonts/Raleway-Thin.ttf differ diff --git a/assets/fonts/Raleway-ThinItalic.ttf b/assets/fonts/Raleway-ThinItalic.ttf new file mode 100644 index 0000000..6abf43e Binary files /dev/null and b/assets/fonts/Raleway-ThinItalic.ttf differ diff --git a/assets/fonts/Roboto-Black.ttf b/assets/fonts/Roboto-Black.ttf new file mode 100644 index 0000000..2d45238 Binary files /dev/null and b/assets/fonts/Roboto-Black.ttf differ diff --git a/assets/fonts/Roboto-BlackItalic.ttf b/assets/fonts/Roboto-BlackItalic.ttf new file mode 100644 index 0000000..29a4359 Binary files /dev/null and b/assets/fonts/Roboto-BlackItalic.ttf differ diff --git a/assets/fonts/Roboto-Bold.ttf b/assets/fonts/Roboto-Bold.ttf new file mode 100644 index 0000000..d998cf5 Binary files /dev/null and b/assets/fonts/Roboto-Bold.ttf differ diff --git a/assets/fonts/Roboto-BoldItalic.ttf b/assets/fonts/Roboto-BoldItalic.ttf new file mode 100644 index 0000000..b4e2210 Binary files /dev/null and b/assets/fonts/Roboto-BoldItalic.ttf differ diff --git a/assets/fonts/Roboto-Italic.ttf b/assets/fonts/Roboto-Italic.ttf new file mode 100644 index 0000000..5b390ff Binary files /dev/null and b/assets/fonts/Roboto-Italic.ttf differ diff --git a/assets/fonts/Roboto-Light.ttf b/assets/fonts/Roboto-Light.ttf new file mode 100644 index 0000000..3526798 Binary files /dev/null and b/assets/fonts/Roboto-Light.ttf differ diff --git a/assets/fonts/Roboto-LightItalic.ttf b/assets/fonts/Roboto-LightItalic.ttf new file mode 100644 index 0000000..46e9bf7 Binary files /dev/null and b/assets/fonts/Roboto-LightItalic.ttf differ diff --git a/assets/fonts/Roboto-Medium.ttf b/assets/fonts/Roboto-Medium.ttf new file mode 100644 index 0000000..f714a51 Binary files /dev/null and b/assets/fonts/Roboto-Medium.ttf differ diff --git a/assets/fonts/Roboto-MediumItalic.ttf b/assets/fonts/Roboto-MediumItalic.ttf new file mode 100644 index 0000000..5dc6a2d Binary files /dev/null and b/assets/fonts/Roboto-MediumItalic.ttf differ diff --git a/assets/fonts/Roboto-Regular.ttf b/assets/fonts/Roboto-Regular.ttf new file mode 100644 index 0000000..2b6392f Binary files /dev/null and b/assets/fonts/Roboto-Regular.ttf differ diff --git a/assets/fonts/Roboto-Thin.ttf b/assets/fonts/Roboto-Thin.ttf new file mode 100644 index 0000000..4e797cf Binary files /dev/null and b/assets/fonts/Roboto-Thin.ttf differ diff --git a/assets/fonts/Roboto-ThinItalic.ttf b/assets/fonts/Roboto-ThinItalic.ttf new file mode 100644 index 0000000..eea836f Binary files /dev/null and b/assets/fonts/Roboto-ThinItalic.ttf differ diff --git a/assets/images/beach.png b/assets/images/beach.png new file mode 100644 index 0000000..2f950b0 Binary files /dev/null and b/assets/images/beach.png differ diff --git a/assets/images/boat.png b/assets/images/boat.png new file mode 100644 index 0000000..16f1b3a Binary files /dev/null and b/assets/images/boat.png differ diff --git a/assets/images/burger.png b/assets/images/burger.png new file mode 100644 index 0000000..074056d Binary files /dev/null and b/assets/images/burger.png differ diff --git a/assets/images/care.png b/assets/images/care.png new file mode 100644 index 0000000..598b338 Binary files /dev/null and b/assets/images/care.png differ diff --git a/assets/images/category-4.jpg b/assets/images/category-4.jpg new file mode 100755 index 0000000..19dd266 Binary files /dev/null and b/assets/images/category-4.jpg differ diff --git a/assets/images/ct-alert.png b/assets/images/ct-alert.png new file mode 100644 index 0000000..63aade2 Binary files /dev/null and b/assets/images/ct-alert.png differ diff --git a/assets/images/ct-map.png b/assets/images/ct-map.png new file mode 100644 index 0000000..137bad6 Binary files /dev/null and b/assets/images/ct-map.png differ diff --git a/assets/images/dashboard.png b/assets/images/dashboard.png new file mode 100644 index 0000000..6272d9f Binary files /dev/null and b/assets/images/dashboard.png differ diff --git a/assets/images/documents.png b/assets/images/documents.png new file mode 100644 index 0000000..fe563a5 Binary files /dev/null and b/assets/images/documents.png differ diff --git a/assets/images/drainage.png b/assets/images/drainage.png new file mode 100644 index 0000000..3857884 Binary files /dev/null and b/assets/images/drainage.png differ diff --git a/assets/images/emergency-service.png b/assets/images/emergency-service.png new file mode 100644 index 0000000..35315dc Binary files /dev/null and b/assets/images/emergency-service.png differ diff --git a/assets/images/emergency.png b/assets/images/emergency.png new file mode 100644 index 0000000..b736fdc Binary files /dev/null and b/assets/images/emergency.png differ diff --git a/assets/images/flood-zone.png b/assets/images/flood-zone.png new file mode 100644 index 0000000..06f72d9 Binary files /dev/null and b/assets/images/flood-zone.png differ diff --git a/assets/images/food.png b/assets/images/food.png new file mode 100644 index 0000000..e73f994 Binary files /dev/null and b/assets/images/food.png differ diff --git a/assets/images/green-check.png b/assets/images/green-check.png new file mode 100644 index 0000000..0300d5c Binary files /dev/null and b/assets/images/green-check.png differ diff --git a/assets/images/home-flooding.png b/assets/images/home-flooding.png new file mode 100644 index 0000000..5dadd22 Binary files /dev/null and b/assets/images/home-flooding.png differ diff --git a/assets/images/house.png b/assets/images/house.png new file mode 100644 index 0000000..e915dd0 Binary files /dev/null and b/assets/images/house.png differ diff --git a/assets/images/hurricane-banner.jpg b/assets/images/hurricane-banner.jpg new file mode 100644 index 0000000..e2b4075 Binary files /dev/null and b/assets/images/hurricane-banner.jpg differ diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000..59a42e4 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/images/map.png b/assets/images/map.png new file mode 100644 index 0000000..2c68a2b Binary files /dev/null and b/assets/images/map.png differ diff --git a/assets/images/medical.png b/assets/images/medical.png new file mode 100644 index 0000000..73dd809 Binary files /dev/null and b/assets/images/medical.png differ diff --git a/assets/images/nhc.png b/assets/images/nhc.png new file mode 100644 index 0000000..8b40345 Binary files /dev/null and b/assets/images/nhc.png differ diff --git a/assets/images/phone.png b/assets/images/phone.png new file mode 100644 index 0000000..a00457d Binary files /dev/null and b/assets/images/phone.png differ diff --git a/assets/images/police.png b/assets/images/police.png new file mode 100644 index 0000000..eebc490 Binary files /dev/null and b/assets/images/police.png differ diff --git a/assets/images/power.png b/assets/images/power.png new file mode 100644 index 0000000..ce499f4 Binary files /dev/null and b/assets/images/power.png differ diff --git a/assets/images/property-risk.png b/assets/images/property-risk.png new file mode 100644 index 0000000..bf4ebf8 Binary files /dev/null and b/assets/images/property-risk.png differ diff --git a/assets/images/report.png b/assets/images/report.png new file mode 100644 index 0000000..2108601 Binary files /dev/null and b/assets/images/report.png differ diff --git a/assets/images/resources.png b/assets/images/resources.png new file mode 100644 index 0000000..67bae51 Binary files /dev/null and b/assets/images/resources.png differ diff --git a/assets/images/safety.png b/assets/images/safety.png new file mode 100644 index 0000000..ddeb86c Binary files /dev/null and b/assets/images/safety.png differ diff --git a/assets/images/social_media.png b/assets/images/social_media.png new file mode 100644 index 0000000..a284218 Binary files /dev/null and b/assets/images/social_media.png differ diff --git a/assets/images/storm-banner.jpg b/assets/images/storm-banner.jpg new file mode 100644 index 0000000..f9b21d1 Binary files /dev/null and b/assets/images/storm-banner.jpg differ diff --git a/assets/images/storm.png b/assets/images/storm.png new file mode 100644 index 0000000..70f5aa3 Binary files /dev/null and b/assets/images/storm.png differ diff --git a/assets/images/structure.png b/assets/images/structure.png new file mode 100644 index 0000000..e764558 Binary files /dev/null and b/assets/images/structure.png differ diff --git a/assets/images/tools.png b/assets/images/tools.png new file mode 100644 index 0000000..131f843 Binary files /dev/null and b/assets/images/tools.png differ diff --git a/assets/images/tornado-banner.jpg b/assets/images/tornado-banner.jpg new file mode 100644 index 0000000..761e711 Binary files /dev/null and b/assets/images/tornado-banner.jpg differ diff --git a/assets/images/tv.png b/assets/images/tv.png new file mode 100644 index 0000000..f6d5f8b Binary files /dev/null and b/assets/images/tv.png differ diff --git a/assets/images/water.png b/assets/images/water.png new file mode 100644 index 0000000..f32ac32 Binary files /dev/null and b/assets/images/water.png differ diff --git a/assets/locale/ar.json b/assets/locale/ar.json new file mode 100644 index 0000000..9915eca --- /dev/null +++ b/assets/locale/ar.json @@ -0,0 +1,132 @@ +{ + "home": "الصفحة الرئيسية", + "wish_list": "قائمة الرغبات", + "message": "الرسائل", + "notification": "تنبيه", + "account": "الحساب", + "change_language": "تغيير اللغة", + "dynamic_theme": "هاتف النظام", + "always_on": "دائما متاح", + "always_off": "دائما خارج", + "about_us": "معلومات عنا", + "who_we_are": "من نحن ؟", + "what_we_do": "الذي نفعله ؟", + "meet_our_team": "التق بفريقنا", + "category": "الفئة", + "search": "بحث ...", + "category_not_found": "لم يتم العثور على الفئة", + "password": "كلمه السر", + "change_password": "تغيير كلمة المرور", + "input_your_password": "أدخل كلمة المرور الخاصة بك", + "confirm_password": "تأكيد كلمة المرور", + "confirm_your_password": "أكد رقمك السري", + "confirm": "تؤكد", + "type_something": "اطبع شيئا...", + "location": "موقعك", + "apply": "تطبيق", + "contact_us": "اتصل بنا", + "send": "إرسال", + "name": "اسم", + "input_name": "أدخل اسمك", + "email": "البريد الإلكتروني", + "input_email": "أدخل بريدك الإلكتروني", + "information": "معلومات", + "input_information": "أدخل معلوماتك", + "value_not_empty": "الإدخال ليس فارغًا", + "value_not_valid_range": "الإدخال ليس نطاقًا صالحًا", + "value_not_valid_email": "الإدخال غير صالح", + "value_not_valid_phone": "الإدخال غير صالح", + "value_not_valid_password": "الإدخال غير صالح لكلمة المرور", + "value_not_valid_id": "الإدخال غير صالح", + "edit_profile": "تعديل الملف الشخصي", + "address": "عنوان", + "input_address": "أدخل عنوانك", + "website": "موقع الكتروني", + "input_website": "أدخل موقع الويب الخاص بك", + "feedback": "ردود الفعل", + "replay": "إعادة", + "tap_rate": "انقر على نجمة للتقييم", + "title": "عنوان", + "input_title": "أدخل عنوانك", + "description": "وصف", + "input_feedback": "أدخل تعليقاتك", + "filter": "منقي", + "facilities": "مرافق", + "area": "منطقة", + "select_location": "اختر موقعا", + "price_range": "نطاق السعر", + "avg_price": "متوسط السعر", + "business_color": "لون الأعمال", + "open_time": "وقت متاح", + "start_time": "وقت البدء", + "end_time": "وقت النهاية", + "rating": "تقييم", + "font": "الخط", + "forgot_password": "هل نسيت كلمة المرور", + "reset_password": "إعادة تعيين كلمة المرور", + "search_location": "موقع البحث", + "more": "أكثر", + "popular_location": "موقع شعبي", + "let_find_interesting": "دعنا نكتشف الأشياء الأكثر إثارة للاهتمام", + "recent_location": "الموقع الأخير", + "what_happen": "ماذا يمكن أن يحدث", + "shopping": "التسوق", + "shopping_intro": "العلامات التجارية المفضلة والاتجاهات الأكثر سخونة.", + "payment": "دفع", + "payment_intro": "شريكك الاستراتيجي عبر الإنترنت.", + "location_intro": "الموقع ، المجتمع ، جودة المعيشة. يبدأ هنا!", + "lasted_post": "مشاركة مشاركة", + "oldest_post": "أقدم وظيفة", + "most_view": "معظم المشاهدات", + "review_rating": "تقييم المراجعة", + "delete": "حذف", + "image": "صورة", + "phone": "هاتف", + "date_established": "تحدد الموعد", + "featured": "متميز", + "nearly": "تقريبا", + "related": "ذات صلة", + "profile": "الملف الشخصي", + "sign_in": "تسجيل الدخول", + "sign_out": "خروج", + "setting": "ضبط", + "review": "المراجعات", + "write": "كتابة", + "out_of": "بعيدا عن المكان", + "loading": "جار التحميل...", + "search_title": "بحث", + "search_history": "سجل البحث", + "discover_more": "إكتشف أكثر", + "recently_viewed": "شوهدت مؤخرا", + "clear": "واضح", + "language": "لغة", + "theme": "موضوع", + "dark_mode": "الوضع الداكن", + "version": "الإصدار", + "post": "بريد", + "follower": "تابع", + "sign_up": "سجل", + "input_id": "أدخل حسابك", + "default": "إفتراضي", + "brown": "بنى", + "pink": "زهري", + "orange": "البرتقالي", + "green": "أخضر", + "monday": "يوم الاثنين", + "tuesday": "الثلاثاء", + "wednesday": "الأربعاء", + "thursday": "الخميس", + "friday": "يوم الجمعة", + "saturday": "يوم السبت", + "sunday": "الأحد", + "day_off": "يوم عطلة", + "close": "قريب", + "pull_down_refresh": "سحب التحديث لأسفل", + "refreshing": "منعش...", + "refresh_completed": "اكتمل التحديث", + "release_to_refresh": "حرر للتحديث", + "release_to_load_more": "حرر لتحميل المزيد", + "pull_to_load_more": "اسحب لتحميل المزيد", + "explore_product": "استكشاف المنتج", + "view_list": "عرض القائمة" +} diff --git a/assets/locale/da.json b/assets/locale/da.json new file mode 100644 index 0000000..387c0ba --- /dev/null +++ b/assets/locale/da.json @@ -0,0 +1,132 @@ +{ + "home": "Hjem", + "wish_list": "ønskeliste", + "message": "Beskeder", + "notification": "Notifikation", + "account": "Konto", + "change_language": "Skift sprog", + "dynamic_theme": "Systemtelefon", + "always_on": "Altid på", + "always_off": "Altid slukket", + "about_us": "Om os", + "who_we_are": "HVEM VI ER ?", + "what_we_do": "HVAD VI GØR ?", + "meet_our_team": "Mød Vores team", + "category": "Kategori", + "search": "Søg ...", + "category_not_found": "Kategori ikke fundet", + "password": "Adgangskode", + "change_password": "Skift kodeord", + "input_your_password": "Indtast din adgangskode", + "confirm_password": "Bekræft kodeord", + "confirm_your_password": "Bekræft dit kodeord", + "confirm": "Bekræfte", + "type_something": "Skriv noget ...", + "location": "Beliggenhed", + "apply": "ansøge", + "contact_us": "Kontakt os", + "send": "Sende", + "name": "Navn", + "input_name": "Indtast dit navn", + "email": "E-mail", + "input_email": "Indtast din e-mail", + "information": "Information", + "input_information": "Indtast dine oplysninger", + "value_not_empty": "Input er ikke tom", + "value_not_valid_range": "Input ikke gyldigt interval", + "value_not_valid_email": "Input ikke gyldig e-mail", + "value_not_valid_phone": "Input ikke gyldig telefon", + "value_not_valid_password": "Input ikke gyldigt kodeord", + "value_not_valid_id": "Input ikke gyldigt ID", + "edit_profile": "Rediger profil", + "address": "Adresse", + "input_address": "Indtast din adresse", + "website": "Internet side", + "input_website": "Indtast dit websted", + "feedback": "Feedback", + "replay": "Replay", + "tap_rate": "Tryk på en stjerne for at vurdere", + "title": "Titel", + "input_title": "Indtast din titel", + "description": "Beskrivelse", + "input_feedback": "Indtast din feedback", + "filter": "Filter", + "facilities": "Faciliteter", + "area": "Areal", + "select_location": "Vælg placering", + "price_range": "Prisklasse", + "avg_price": "AVG-pris", + "business_color": "Virksomhedsfarve", + "open_time": "Åben tid", + "start_time": "Starttidspunkt", + "end_time": "Sluttid", + "rating": "Bedømmelse", + "font": "Skrifttype", + "forgot_password": "Glemt kodeord", + "reset_password": "Nulstille kodeord", + "search_location": "Søg efter placering", + "more": "Mere", + "popular_location": "Populær placering", + "let_find_interesting": "Lad os finde ud af, hvad der er mest interessante ting", + "recent_location": "Seneste placering", + "what_happen": "Hvad der kunne ske", + "shopping": "Handle ind", + "shopping_intro": "Favoritmærker og hotteste trends.", + "payment": "Betaling", + "payment_intro": "Din strategiske online forretningspartner.", + "location_intro": "Beliggenhed, samfund, kvalitetsleje. Det begynder her!", + "lasted_post": "Sidste post", + "oldest_post": "Ældste post", + "most_view": "De fleste visninger", + "review_rating": "Gennemgå vurdering", + "delete": "Slet", + "image": "Billede", + "phone": "telefon", + "date_established": "Dato fastlagt", + "featured": "Udvalgte", + "nearly": "Næsten", + "related": "Relaterede", + "profile": "Profil", + "sign_in": "Log ind", + "sign_out": "Log ud", + "setting": "Indstilling", + "review": "Anmeldelser", + "write": "Skrive", + "out_of": "Ud af", + "loading": "Indlæser...", + "search_title": "Søg", + "search_history": "Søgningshistorie", + "discover_more": "Oplev mere", + "recently_viewed": "Senest set", + "clear": "Klar", + "language": "Sprog", + "theme": "Tema", + "dark_mode": "Mørk tilstand", + "version": "Version", + "post": "Stolpe", + "follower": "Follower", + "sign_up": "Tilmelde", + "input_id": "Indtast din konto", + "default": "Standard", + "brown": "Brun", + "pink": "Lyserød", + "orange": "orange", + "green": "Grøn", + "monday": "Mandag", + "tuesday": "tirsdag", + "wednesday": "onsdag", + "thursday": "torsdag", + "friday": "Fredag", + "saturday": "lørdag", + "sunday": "Søndag", + "day_off": "Fridag", + "close": "Tæt", + "pull_down_refresh": "Træk opdateringen ned", + "refreshing": "Forfriskende ...", + "refresh_completed": "Opdatering afsluttet", + "release_to_refresh": "Slip for at opdatere", + "release_to_load_more": "Slip for at indlæse mere", + "pull_to_load_more": "Træk op for at indlæse mere", + "explore_product": "Udforsk produkt", + "view_list": "Vis liste" +} diff --git a/assets/locale/de.json b/assets/locale/de.json new file mode 100644 index 0000000..4788991 --- /dev/null +++ b/assets/locale/de.json @@ -0,0 +1,132 @@ +{ + "home": "Zuhause", + "wish_list": "Wunschzettel", + "message": "Mitteilungen", + "notification": "Benachrichtigung", + "account": "Konto", + "change_language": "Sprache ändern", + "dynamic_theme": "Systemtelefon", + "always_on": "Immer auf", + "always_off": "Immer aus", + "about_us": "Über uns", + "who_we_are": "WER WIR SIND ?", + "what_we_do": "WAS WIR TUN ?", + "meet_our_team": "TRIFF UNSER TEAM", + "category": "Kategorie", + "search": "Suche ...", + "category_not_found": "Kategorie nicht gefunden", + "password": "Passwort", + "change_password": "Ändere das Passwort", + "input_your_password": "Geben Sie Ihr Passwort ein", + "confirm_password": "Kennwort bestätigen", + "confirm_your_password": "Bestätigen Sie Ihr Passwort", + "confirm": "Bestätigen", + "type_something": "Schreibe etwas...", + "location": "Lage", + "apply": "Anwenden", + "contact_us": "Kontaktiere uns", + "send": "Senden", + "name": "Name", + "input_name": "Geben Sie Ihren Namen ein", + "email": "Email", + "input_email": "Geben Sie Ihre E-Mail-Adresse ein", + "information": "Information", + "input_information": "Geben Sie Ihre Daten ein", + "value_not_empty": "Eingabe ist nicht leer", + "value_not_valid_range": "Geben Sie keinen gültigen Bereich ein", + "value_not_valid_email": "Geben Sie keine gültige E-Mail-Adresse ein", + "value_not_valid_phone": "Geben Sie ein ungültiges Telefon ein", + "value_not_valid_password": "Geben Sie ein ungültiges Passwort ein", + "value_not_valid_id": "Geben Sie keine gültige ID ein", + "edit_profile": "Profil bearbeiten", + "address": "Adresse", + "input_address": "Geben Sie Ihre Adresse ein", + "website": "Webseite", + "input_website": "Geben Sie Ihre Website ein", + "feedback": "Feedback", + "replay": "Wiederholung", + "tap_rate": "Tippen Sie auf einen Stern, um ihn zu bewerten", + "title": "Titel", + "input_title": "Geben Sie Ihren Titel ein", + "description": "Beschreibung", + "input_feedback": "Geben Sie Ihr Feedback ein", + "filter": "Filter", + "facilities": "Anlagen", + "area": "Bereich", + "select_location": "Ort auswählen", + "price_range": "Preisklasse", + "avg_price": "AVG Preis", + "business_color": "Geschäftsfarbe", + "open_time": "Offene Zeit", + "start_time": "Startzeit", + "end_time": "Endzeit", + "rating": "Bewertung", + "font": "Schriftart", + "forgot_password": "Passwort vergessen", + "reset_password": "Passwort zurücksetzen", + "search_location": "Ort suchen", + "more": "Mehr", + "popular_location": "Beliebte Lage", + "let_find_interesting": "Lassen Sie uns herausfinden, was am interessantesten ist", + "recent_location": "Letzter Standort", + "what_happen": "Was könnte das passieren?", + "shopping": "Einkaufen", + "shopping_intro": "Lieblingsmarken und heißeste Trends.", + "payment": "Zahlung", + "payment_intro": "Ihr strategischer Online-Geschäftspartner.", + "location_intro": "Lage, Gemeinschaft, Lebensqualität. Hier fängt es an!", + "lasted_post": "Lasted Post", + "oldest_post": "Ältester Beitrag", + "most_view": "Die meisten Ansichten", + "review_rating": "Bewertung bewerten", + "delete": "Löschen", + "image": "Bild", + "phone": "Telefon", + "date_established": "Gründungsdatum", + "featured": "Vorgestellt", + "nearly": "Fast", + "related": "verbunden", + "profile": "Profil", + "sign_in": "Einloggen", + "sign_out": "Ausloggen", + "setting": "Rahmen", + "review": "Bewertungen", + "write": "Schreiben", + "out_of": "Aus", + "loading": "Wird geladen...", + "search_title": "Suche", + "search_history": "Suchverlauf", + "discover_more": "Entdecke mehr", + "recently_viewed": "zuletzt angesehen", + "clear": "klar", + "language": "Sprache", + "theme": "Thema", + "dark_mode": "Dunkler Modus", + "version": "Ausführung", + "post": "Post", + "follower": "Anhänger", + "sign_up": "Anmelden", + "input_id": "Geben Sie Ihr Konto ein", + "default": "Standard", + "brown": "Braun", + "pink": "Rosa", + "orange": "Orange", + "green": "Grün", + "monday": "Montag", + "tuesday": "Dienstag", + "wednesday": "Mittwoch", + "thursday": "Donnerstag", + "friday": "Freitag", + "saturday": "Samstag", + "sunday": "Sonntag", + "day_off": "Freier Tag", + "close": "Schließen", + "pull_down_refresh": "Aktualisierung nach unten ziehen", + "refreshing": "Erfrischend...", + "refresh_completed": "Aktualisierung abgeschlossen", + "release_to_refresh": "Zum Aktualisieren loslassen", + "release_to_load_more": "Lassen Sie los, um mehr zu laden", + "pull_to_load_more": "Ziehen Sie nach oben, um mehr zu laden", + "explore_product": "Produkt entdecken", + "view_list": "Liste anzeigen" +} diff --git a/assets/locale/el.json b/assets/locale/el.json new file mode 100644 index 0000000..b0fbc9e --- /dev/null +++ b/assets/locale/el.json @@ -0,0 +1,132 @@ +{ + "home": "Σπίτι", + "wish_list": "Λίστα επιθυμιών", + "message": "Μηνύματα", + "notification": "Γνωστοποίηση", + "account": "λογαριασμός", + "change_language": "Αλλαξε γλώσσα", + "dynamic_theme": "Τηλέφωνο συστήματος", + "always_on": "Πάντα ανοιχτό", + "always_off": "Πάντα εκτός λειτουργίας", + "about_us": "Σχετικά με εμάς", + "who_we_are": "ΠΟΙΟΙ ΕΙΜΑΣΤΕ ?", + "what_we_do": "ΑΥΤΟ ΠΟΥ ΚΑΝΟΥΜΕ ?", + "meet_our_team": "ΣΥΝΕΧΕΤΕ ΤΗΝ ΟΜΑΔΑ ΜΑΣ", + "category": "Κατηγορία", + "search": "Αναζήτηση ...", + "category_not_found": "Η κατηγορία δεν βρέθηκε", + "password": "Κωδικός πρόσβασης", + "change_password": "Άλλαξε κωδικό", + "input_your_password": "Εισάγετε τον κωδικό πρόσβασής σας", + "confirm_password": "Επιβεβαίωση Κωδικού", + "confirm_your_password": "Επιβεβαιώστε τον κωδικό πρόσβασής σας", + "confirm": "Επιβεβαιώνω", + "type_something": "Πληκτρολόγησε κάτι...", + "location": "Τοποθεσία", + "apply": "Ισχύουν", + "contact_us": "Επικοινωνήστε μαζί μας", + "send": "Στείλετε", + "name": "Ονομα", + "input_name": "Εισάγετε το όνομά σας", + "email": "ΗΛΕΚΤΡΟΝΙΚΗ ΔΙΕΥΘΥΝΣΗ", + "input_email": "Εισάγετε το email σας", + "information": "Πληροφορίες", + "input_information": "Εισάγετε τις πληροφορίες σας", + "value_not_empty": "Η είσοδος δεν είναι κενή", + "value_not_valid_range": "Η είσοδος δεν είναι έγκυρη", + "value_not_valid_email": "Μη εισαγωγή έγκυρου μηνύματος ηλεκτρονικού ταχυδρομείου", + "value_not_valid_phone": "Μη εισαγωγή έγκυρου τηλεφώνου", + "value_not_valid_password": "Εισαγωγή δεν είναι έγκυρος κωδικός πρόσβασης", + "value_not_valid_id": "Η εισαγωγή δεν είναι έγκυρη ταυτότητα", + "edit_profile": "Επεξεργασία προφίλ", + "address": "Διεύθυνση", + "input_address": "Εισαγάγετε τη διεύθυνσή σας", + "website": "Δικτυακός τόπος", + "input_website": "Εισάγετε τον ιστότοπό σας", + "feedback": "Ανατροφοδότηση", + "replay": "Επανάληψη", + "tap_rate": "Αγγίξτε ένα αστέρι για να αξιολογήσετε", + "title": "Τίτλος", + "input_title": "Εισάγετε τον τίτλο σας", + "description": "Περιγραφή", + "input_feedback": "Εισάγετε τα σχόλιά σας", + "filter": "Φίλτρο", + "facilities": "Εγκαταστάσεις", + "area": "Περιοχή", + "select_location": "Επιλέξτε Τοποθεσία", + "price_range": "Εύρος τιμών", + "avg_price": "AVG Τιμή", + "business_color": "Επιχειρηματικό χρώμα", + "open_time": "Άνοιγμα ώρας", + "start_time": "Ωρα έναρξης", + "end_time": "Τέλος χρόνου", + "rating": "Εκτίμηση", + "font": "Γραμματοσειρά", + "forgot_password": "Ξεχάσατε τον κωδικό", + "reset_password": "Επαναφέρετε τον κωδικό πρόσβασης", + "search_location": "Τοποθεσία αναζήτησης", + "more": "Περισσότερο", + "popular_location": "Δημοφιλής τοποθεσία", + "let_find_interesting": "Ας μάθουμε ποια είναι τα πιο ενδιαφέροντα πράγματα", + "recent_location": "Πρόσφατη τοποθεσία", + "what_happen": "Τι μπορεί να συμβεί αυτό", + "shopping": "Ψώνια", + "shopping_intro": "Αγαπημένες μάρκες και πιο καυτές τάσεις.", + "payment": "Πληρωμή", + "payment_intro": "Ο στρατηγικός συνεργάτης σας στο διαδίκτυο.", + "location_intro": "Τοποθεσία, Κοινότητα, Ποιότητα Ζωής. Ξεκινά εδώ!", + "lasted_post": "Δημοσίευση", + "oldest_post": "Παλαιότερη Δημοσίευση", + "most_view": "Οι περισσότερες προβολές", + "review_rating": "Αξιολόγηση αξιολόγησης", + "delete": "Διαγράφω", + "image": "Εικόνα", + "phone": "Τηλέφωνο", + "date_established": "Η ημερομηνία καθιερώθηκε", + "featured": "Προτεινόμενα", + "nearly": "Σχεδόν", + "related": "Σχετίζεται με", + "profile": "Προφίλ", + "sign_in": "Συνδεθείτε", + "sign_out": "Αποσύνδεση", + "setting": "Σύνθεση", + "review": "Κριτικές", + "write": "Γράφω", + "out_of": "Εκτός", + "loading": "Φόρτωση...", + "search_title": "Αναζήτηση", + "search_history": "Ιστορικό αναζήτησης", + "discover_more": "Ανακάλυψε περισσότερα", + "recently_viewed": "Πρόσφατα προβεβλημένα", + "clear": "Σαφή", + "language": "Γλώσσα", + "theme": "Θέμα", + "dark_mode": "Σκοτεινή λειτουργία", + "version": "Εκδοχή", + "post": "Θέση", + "follower": "Οπαδός", + "sign_up": "Εγγραφείτε", + "input_id": "Εισαγάγετε το λογαριασμό σας", + "default": "Προκαθορισμένο", + "brown": "καφέ", + "pink": "Ροζ", + "orange": "Πορτοκάλι", + "green": "Πράσινος", + "monday": "Δευτέρα", + "tuesday": "Τρίτη", + "wednesday": "Τετάρτη", + "thursday": "Πέμπτη", + "friday": "Παρασκευή", + "saturday": "Σάββατο", + "sunday": "Κυριακή", + "day_off": "Ρεπό", + "close": "Κλείσε", + "pull_down_refresh": "Τραβήξτε προς τα κάτω την ανανέωση", + "refreshing": "Δροσιστικός...", + "refresh_completed": "Η ανανέωση ολοκληρώθηκε", + "release_to_refresh": "Απελευθερώστε για ανανέωση", + "release_to_load_more": "Απελευθερώστε για να φορτώσετε περισσότερο", + "pull_to_load_more": "Τραβήξτε προς τα πάνω για να φορτώσετε περισσότερο", + "explore_product": "Εξερευνήστε το προϊόν", + "view_list": "Προβολή λίστας" +} diff --git a/assets/locale/en.json b/assets/locale/en.json new file mode 100644 index 0000000..cc08346 --- /dev/null +++ b/assets/locale/en.json @@ -0,0 +1,137 @@ +{ + "home": "Home", + "wish_list": "Wishlist", + "message": "Messages", + "notification": "Notification", + "account": "Account", + "change_language": "Change Language", + "dynamic_theme": "System", + "always_on": "Dark Mode", + "always_off": "Light Mode", + "about_us": "About Us", + "who_we_are": "WHO WE ARE ?", + "what_we_do": "WHAT WE DO ?", + "meet_our_team": "MEET OUR TEAM", + "category": "Category", + "search": "Search ...", + "category_not_found": "Category not found", + "password": "Password", + "change_password": "Change Password", + "input_your_password": "Input your password", + "confirm_password": "Confirm Password", + "confirm_your_password": "Confirm your password", + "confirm": "Confirm", + "type_something": "Type Something...", + "location": "Select Location", + "apply": "Apply", + "contact_us": "Contact Us", + "send": "Send", + "name": "Name", + "input_name": "Input your name", + "email": "Email", + "input_email": "Input your email", + "information": "Information", + "input_information": "Input your information", + "value_not_empty": "Input is not empty", + "value_not_valid_range": "Input not valid range", + "value_not_valid_email": "Input not valid email", + "value_not_valid_phone": "Input not valid phone", + "value_not_valid_password": "Input not valid password", + "value_not_valid_id": "Input not valid ID", + "edit_profile": "Edit Profile", + "address": "Address", + "input_address": "Input your address", + "website": "Website", + "input_website": "Input your website", + "feedback": "Feedback", + "replay": "Replay", + "tap_rate": "Tap a star to rate", + "title": "Title", + "input_title": "Input your title", + "description": "Description", + "input_feedback": "Input your feedback", + "filter": "Filter", + "facilities": "Facilities", + "area": "Area", + "select_location": "Select Location", + "price_range": "Price Range", + "avg_price": "AVG Price", + "business_color": "Business Color", + "open_time": "Open Time", + "start_time": "Start Time", + "end_time": "End Time", + "rating": "Rating", + "font": "Font", + "forgot_password": "Forgot Password", + "reset_password": "Reset Password", + "search_location": "Search Location", + "more": "More", + "popular_location": "Popular Locations", + "quick_lookups": "Quick Lookups", + "get_info": "Get the safety information for any of the locations below.", + "recent_location": "Recent Location", + "what_happen": "What’s that could happen", + "shopping": "Shopping", + "shopping_intro": "Favorite brands and hottest trends.", + "payment": "Payment", + "payment_intro": "Your strategic online business partner.", + "location_intro": "Location, Community, Quality Living. It Starts Here!", + "lasted_post": "Lasted Post", + "oldest_post": "Oldest Post", + "most_view": "Most Views", + "review_rating": "Review Rating", + "delete": "Delete", + "image": "Image", + "phone": "Phone", + "date_established": "Date Established", + "featured": "Featured", + "nearly": "Nearly", + "related": "Related", + "profile": "Profile", + "sign_in": "Sign In", + "sign_out": "Sign Out", + "settings": "Settings", + "review": "Reviews", + "write": "Write", + "out_of": "Out of", + "loading": "Loading...", + "search_title": "Search", + "search_history": "Search History", + "discover_more": "Discover More", + "recently_viewed": "Recently Viewed", + "clear": "Clear", + "language": "Language", + "theme": "Theme", + "dark_mode": "Appearance", + "version": "Version", + "post": "Post", + "follower": "Follower", + "sign_up": "Sign Up", + "input_id": "Input your account", + "default": "Default", + "brown": "Brown", + "pink": "Pink", + "orange": "Orange", + "green": "Green", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sunday": "Sunday", + "day_off": "Day Off", + "close": "Close", + "pull_down_refresh": "Pull down refresh", + "refreshing": "Refreshing...", + "refresh_completed": "Refresh completed", + "release_to_refresh": "Release to refresh", + "release_to_load_more": "Release to load more", + "pull_to_load_more": "Pull up to load more", + "explore_product": "Explore Product", + "view_list": "View List", + "more_options": "Explore More Options", + "pref": "Preferences", + "general": "General", + "terms_of_use": "Terms of Use" +} \ No newline at end of file diff --git a/assets/locale/fa.json b/assets/locale/fa.json new file mode 100644 index 0000000..fcf55c6 --- /dev/null +++ b/assets/locale/fa.json @@ -0,0 +1,132 @@ +{ + "home": "خانه", + "wish_list": "لیست علاقه مندیها", + "message": "پیام ها", + "notification": "اطلاع", + "account": "حساب", + "change_language": "تغییر زبان", + "dynamic_theme": "تلفن تلفن", + "always_on": "همیشه روشن است", + "always_off": "همیشه خاموش", + "about_us": "درباره ما", + "who_we_are": "ما کی هستیم ؟", + "what_we_do": "چه کاری انجام می دهیم؟", + "meet_our_team": "دیدار با تیم ما", + "category": "دسته بندی", + "search": "جستجو کردن ...", + "category_not_found": "دسته یافت نشد", + "password": "کلمه عبور", + "change_password": "تغییر رمز عبور", + "input_your_password": "گذرواژه خود را وارد کنید", + "confirm_password": "رمز عبور را تأیید کنید", + "confirm_your_password": "رمز عبور خود را تأیید کنید", + "confirm": "تایید", + "type_something": "چیزی بنویسید ...", + "location": "محل", + "apply": "درخواست دادن", + "contact_us": "با ما تماس بگیرید", + "send": "ارسال", + "name": "نام", + "input_name": "نام خود را وارد کنید", + "email": "پست الکترونیک", + "input_email": "ایمیل خود را وارد کنید", + "information": "اطلاعات", + "input_information": "اطلاعات خود را وارد کنید", + "value_not_empty": "ورودی خالی نیست", + "value_not_valid_range": "دامنه ورودی معتبر نیست", + "value_not_valid_email": "ایمیل ورودی معتبر نیست", + "value_not_valid_phone": "ورودی تلفن معتبر نیست", + "value_not_valid_password": "رمز ورود معتبر نیست", + "value_not_valid_id": "شناسه معتبر ورودی نیست", + "edit_profile": "ویرایش نمایه", + "address": "نشانی", + "input_address": "آدرس خود را وارد کنید", + "website": "سایت اینترنتی", + "input_website": "وب سایت خود را وارد کنید", + "feedback": "بازخورد", + "replay": "بازپخش", + "tap_rate": "برای امتیاز دادن به یک ستاره ضربه بزنید", + "title": "عنوان", + "input_title": "عنوان خود را وارد کنید", + "description": "شرح", + "input_feedback": "بازخورد خود را وارد کنید", + "filter": "فیلتر", + "facilities": "امکانات", + "area": "حوزه", + "select_location": "موقعیت مکانی را انتخاب کنید", + "price_range": "حدود قیمت", + "avg_price": "قیمت AVG", + "business_color": "رنگ کسب و کار", + "open_time": "زمان باز", + "start_time": "زمان شروع", + "end_time": "زمان پایان", + "rating": "رتبه بندی", + "font": "قلم", + "forgot_password": "رمز عبور را فراموش کرده اید", + "reset_password": "بازنشانی گذرواژه", + "search_location": "جستجوی موقعیت مکانی", + "more": "بیشتر", + "popular_location": "موقعیت مکانی محبوب", + "let_find_interesting": "بگذارید دریابید که جالب ترین چیزها چیست", + "recent_location": "موقعیت مکانی اخیر", + "what_happen": "چه اتفاقی می افتد", + "shopping": "خريد كردن", + "shopping_intro": "مارک های مورد علاقه و داغترین روند.", + "payment": "پرداخت", + "payment_intro": "شریک استراتژیک تجارت آنلاین شما", + "location_intro": "مکان ، اجتماع ، کیفیت زندگی. از اینجا شروع می شود!", + "lasted_post": "ارسال طولانی شد", + "oldest_post": "قدیمی ترین پست", + "most_view": "بیشترین بازدیدها", + "review_rating": "بررسی رتبه بندی", + "delete": "حذف", + "image": "تصویر", + "phone": "تلفن", + "date_established": "تاریخ تأسیس", + "featured": "ویژه", + "nearly": "تقریبا", + "related": "مربوط", + "profile": "مشخصات", + "sign_in": "ورود", + "sign_out": "خروج از سیستم", + "setting": "تنظیمات", + "review": "بررسی ها", + "write": "نوشتن", + "out_of": "بیرون از", + "loading": "بارگذاری...", + "search_title": "جستجو کردن", + "search_history": "تاریخچه جستجو", + "discover_more": "بیشتر پیدا کن", + "recently_viewed": "به تازگی بازدید شده", + "clear": "پاک کردن", + "language": "زبان", + "theme": "موضوع", + "dark_mode": "حالت تاریک", + "version": "نسخه", + "post": "پست", + "follower": "دنباله رو", + "sign_up": "ثبت نام", + "input_id": "وارد حساب کاربری خود شوید", + "default": "پیش فرض", + "brown": "رنگ قهوه ای", + "pink": "رنگ صورتی", + "orange": "نارنجی", + "green": "سبز", + "monday": "دوشنبه", + "tuesday": "سهشنبه", + "wednesday": "چهار شنبه", + "thursday": "پنج شنبه", + "friday": "جمعه", + "saturday": "شنبه", + "sunday": "یکشنبه", + "day_off": "مرخصی روزانه", + "close": "نزدیک", + "pull_down_refresh": "تازه کردن را پایین بیاورید", + "refreshing": "طراوت ...", + "refresh_completed": "تازه کردن به پایان رسید", + "release_to_refresh": "انتشار برای تازه کردن", + "release_to_load_more": "برای بارگیری بیشتر رها کنید", + "pull_to_load_more": "برای بارگیری بیشتر بکشید", + "explore_product": "کاوش محصول", + "view_list": "لیست نمایش" +} diff --git a/assets/locale/fr.json b/assets/locale/fr.json new file mode 100644 index 0000000..c022f72 --- /dev/null +++ b/assets/locale/fr.json @@ -0,0 +1,132 @@ +{ + "home": "Accueil", + "wish_list": "Liste de souhaits", + "message": "messages", + "notification": "Notification", + "account": "Compte", + "change_language": "Changer de langue", + "dynamic_theme": "Téléphone système", + "always_on": "Toujours allumé", + "always_off": "Toujours désactivé", + "about_us": "À propos de nous", + "who_we_are": "QUI NOUS SOMMES ?", + "what_we_do": "CE QUE NOUS FAISONS", + "meet_our_team": "RENCONTREZ NOTRE ÉQUIPE", + "category": "Catégorie", + "search": "Chercher ...", + "category_not_found": "Catégorie non trouvée", + "password": "Mot de passe", + "change_password": "Changer le mot de passe", + "input_your_password": "Saisissez votre mot de passe", + "confirm_password": "Confirmez le mot de passe", + "confirm_your_password": "Confirmer votre mot de passe", + "confirm": "Confirmer", + "type_something": "Tapez quelque chose ...", + "location": "Emplacement", + "apply": "Appliquer", + "contact_us": "Nous contacter", + "send": "Envoyer", + "name": "Nom", + "input_name": "Entrez votre nom", + "email": "Email", + "input_email": "Saisissez votre email", + "information": "Information", + "input_information": "Entrez vos informations", + "value_not_empty": "L'entrée n'est pas vide", + "value_not_valid_range": "Plage d'entrée non valide", + "value_not_valid_email": "E-mail non valide", + "value_not_valid_phone": "Saisie d'un téléphone non valide", + "value_not_valid_password": "Saisissez un mot de passe non valide", + "value_not_valid_id": "ID d'entrée non valide", + "edit_profile": "Editer le profil", + "address": "Adresse", + "input_address": "Entrez votre adresse", + "website": "Site Internet", + "input_website": "Saisissez votre site Web", + "feedback": "Retour d'information", + "replay": "Rejouer", + "tap_rate": "Appuyez sur une étoile pour noter", + "title": "Titre", + "input_title": "Entrez votre titre", + "description": "La description", + "input_feedback": "Entrez vos commentaires", + "filter": "Filtre", + "facilities": "Installations", + "area": "Surface", + "select_location": "Sélectionnez l'emplacement", + "price_range": "Échelle des prix", + "avg_price": "Prix AVG", + "business_color": "Couleur de l'entreprise", + "open_time": "Temps ouvert", + "start_time": "Heure de début", + "end_time": "Heure de fin", + "rating": "Évaluation", + "font": "Font", + "forgot_password": "Mot de passe oublié", + "reset_password": "réinitialiser le mot de passe", + "search_location": "Lieu de recherche", + "more": "Plus", + "popular_location": "Emplacement populaire", + "let_find_interesting": "Voyons quelles sont les choses les plus intéressantes", + "recent_location": "Lieu récent", + "what_happen": "Qu'est-ce qui pourrait arriver", + "shopping": "Achats", + "shopping_intro": "Marques préférées et tendances les plus en vogue.", + "payment": "Paiement", + "payment_intro": "Votre partenaire commercial stratégique en ligne.", + "location_intro": "Emplacement, communauté, qualité de vie. Ça commence ici!", + "lasted_post": "Message duré", + "oldest_post": "Post le plus ancien", + "most_view": "Les plus vus", + "review_rating": "Évaluation des avis", + "delete": "Effacer", + "image": "Image", + "phone": "Téléphone", + "date_established": "Date établie", + "featured": "En vedette", + "nearly": "Presque", + "related": "en relation", + "profile": "Profil", + "sign_in": "Se connecter", + "sign_out": "Déconnexion", + "setting": "Réglage", + "review": "Commentaires", + "write": "Écrire", + "out_of": "Hors de", + "loading": "Chargement...", + "search_title": "Chercher", + "search_history": "Historique des recherches", + "discover_more": "Découvrir plus", + "recently_viewed": "vu récemment", + "clear": "Clair", + "language": "Langue", + "theme": "Thème", + "dark_mode": "Mode sombre", + "version": "Version", + "post": "Publier", + "follower": "Disciple", + "sign_up": "S'inscrire", + "input_id": "Saisissez votre compte", + "default": "Défaut", + "brown": "marron", + "pink": "Rose", + "orange": "Orange", + "green": "vert", + "monday": "Lundi", + "tuesday": "Mardi", + "wednesday": "Mercredi", + "thursday": "Jeudi", + "friday": "Vendredi", + "saturday": "samedi", + "sunday": "dimanche", + "day_off": "Jour de congé", + "close": "Fermer", + "pull_down_refresh": "Rafraîchir vers le bas", + "refreshing": "Rafraîchissant...", + "refresh_completed": "Actualisation terminée", + "release_to_refresh": "Relâcher pour rafraîchir", + "release_to_load_more": "Relâchez pour charger plus", + "pull_to_load_more": "Tirez pour charger plus", + "explore_product": "Découvrir le produit", + "view_list": "Afficher la liste" +} diff --git a/assets/locale/he.json b/assets/locale/he.json new file mode 100644 index 0000000..119fe68 --- /dev/null +++ b/assets/locale/he.json @@ -0,0 +1,132 @@ +{ + "home": "בית", + "wish_list": "רשימת משאלות", + "message": "הודעות", + "notification": "הודעה", + "account": "חשבון", + "change_language": "שנה שפה", + "dynamic_theme": "טלפון מערכת", + "always_on": "תמיד פועל", + "always_off": "תמיד כבוי", + "about_us": "עלינו", + "who_we_are": "מי אנחנו ?", + "what_we_do": "מה אנחנו עושים ?", + "meet_our_team": "פגש את הצוות שלנו", + "category": "קטגוריה", + "search": "לחפש ...", + "category_not_found": "הקטגוריה לא נמצאה", + "password": "סיסמה", + "change_password": "שנה סיסמא", + "input_your_password": "הזן את הסיסמה שלך", + "confirm_password": "אשר סיסמה", + "confirm_your_password": "אמת סיסמתך", + "confirm": "אשר", + "type_something": "הקלד משהו...", + "location": "מקום", + "apply": "להגיש מועמדות", + "contact_us": "צור קשר", + "send": "שלח", + "name": "שם", + "input_name": "הזן את שמך", + "email": "אימייל", + "input_email": "הזן את הדוא"ל שלך", + "information": "מידע", + "input_information": "הזן את המידע שלך", + "value_not_empty": "הקלט אינו ריק", + "value_not_valid_range": "הקלט אינו תקף", + "value_not_valid_email": "הקלט אינו דוא"ל חוקי", + "value_not_valid_phone": "הקלט לא חוקי טלפון", + "value_not_valid_password": "הקלט אינו סיסמא חוקית", + "value_not_valid_id": "הקלט אינו מזהה חוקי", + "edit_profile": "ערוך פרופיל", + "address": "כתובת", + "input_address": "הזן את הכתובת שלך", + "website": "אתר אינטרנט", + "input_website": "הזן את האתר שלך", + "feedback": "משוב", + "replay": "שידור חוזר", + "tap_rate": "הקש על כוכב כדי לדרג", + "title": "כותרת", + "input_title": "הזן את הכותרת שלך", + "description": "תיאור", + "input_feedback": "הזן את המשוב שלך", + "filter": "סנן", + "facilities": "מתקנים", + "area": "אזור", + "select_location": "תבחר מיקום", + "price_range": "טווח מחירים", + "avg_price": "מחיר ממוצע", + "business_color": "צבע עסקי", + "open_time": "זמן הפתיחה", + "start_time": "שעת התחלה", + "end_time": "זמן סיום", + "rating": "דירוג", + "font": "גופן", + "forgot_password": "שכחת ססמא", + "reset_password": "לאפס את הסיסמה", + "search_location": "חיפוש מיקום", + "more": "יותר", + "popular_location": "מיקום פופולרי", + "let_find_interesting": "בואו לגלות מה הדברים המעניינים ביותר", + "recent_location": "מיקום אחרון", + "what_happen": "מה זה יכול לקרות", + "shopping": "קניות", + "shopping_intro": "מותגים אהובים וטרנדים הכי חמים.", + "payment": "תשלום", + "payment_intro": "השותף העסקי המקוון האסטרטגי שלך.", + "location_intro": "מיקום, קהילה, מגורים איכותיים. זה מתחיל כאן!", + "lasted_post": "הודעה אחרונה", + "oldest_post": "הפוסט העתיק ביותר", + "most_view": "רוב הנופים", + "review_rating": "דירוג סקירה", + "delete": "מחק", + "image": "תמונה", + "phone": "מכשיר טלפון", + "date_established": "נקבע תאריך", + "featured": "מומלצים", + "nearly": "כמעט", + "related": "קשורים", + "profile": "פרופיל", + "sign_in": "להתחבר", + "sign_out": "התנתק", + "setting": "הגדרה", + "review": "ביקורות", + "write": "כתוב", + "out_of": "מתוך", + "loading": "טוען...", + "search_title": "לחפש", + "search_history": "חפש היסטוריה", + "discover_more": "לגלות עוד", + "recently_viewed": "נראה לאחרונה", + "clear": "ברור", + "language": "שפה", + "theme": "נושא", + "dark_mode": "מצב אפל", + "version": "גרסה", + "post": "הודעה", + "follower": "עוקב", + "sign_up": "הירשם", + "input_id": "הזן את חשבונך", + "default": "ברירת מחדל", + "brown": "חום", + "pink": "ורוד", + "orange": "תפוז", + "green": "ירוק", + "monday": "יום שני", + "tuesday": "יום שלישי", + "wednesday": "יום רביעי", + "thursday": "יום חמישי", + "friday": "יום שישי", + "saturday": "יום שבת", + "sunday": "יום ראשון", + "day_off": "יום חופש", + "close": "סגור", + "pull_down_refresh": "הורד את הרענון", + "refreshing": "מרענן ...", + "refresh_completed": "הרענון הושלם", + "release_to_refresh": "שחרר כדי לרענן", + "release_to_load_more": "שחרר כדי לטעון יותר", + "pull_to_load_more": "משוך למעלה כדי לטעון יותר", + "explore_product": "חקור את המוצר", + "view_list": "רשימת צפיה" +} diff --git a/assets/locale/id.json b/assets/locale/id.json new file mode 100644 index 0000000..76f5d3f --- /dev/null +++ b/assets/locale/id.json @@ -0,0 +1,132 @@ +{ + "home": "Rumah", + "wish_list": "Wishlist", + "message": "Pesan", + "notification": "Pemberitahuan", + "account": "Akun", + "change_language": "Ganti BAHASA", + "dynamic_theme": "Telepon Sistem", + "always_on": "Selalu Aktif", + "always_off": "Selalu Mati", + "about_us": "Tentang kami", + "who_we_are": "SIAPA KITA ?", + "what_we_do": "APA YANG KITA LAKUKAN ?", + "meet_our_team": "RAPAT TIM KAMI", + "category": "Kategori", + "search": "Cari ...", + "category_not_found": "Kategori tidak ditemukan", + "password": "Kata sandi", + "change_password": "Ganti kata sandi", + "input_your_password": "Masukkan kata sandi Anda", + "confirm_password": "konfirmasi sandi", + "confirm_your_password": "Konfirmasi password Anda", + "confirm": "Konfirmasi", + "type_something": "Ketik Sesuatu ...", + "location": "Lokasi", + "apply": "Menerapkan", + "contact_us": "Hubungi kami", + "send": "Kirim", + "name": "Nama", + "input_name": "Masukkan nama Anda", + "email": "Surel", + "input_email": "Masukkan email Anda", + "information": "Informasi", + "input_information": "Masukkan informasi Anda", + "value_not_empty": "Masukan tidak kosong", + "value_not_valid_range": "Input bukan rentang yang valid", + "value_not_valid_email": "Masukan bukan email yang valid", + "value_not_valid_phone": "Masukan telepon tidak valid", + "value_not_valid_password": "Masukkan bukan kata sandi yang valid", + "value_not_valid_id": "Masukkan bukan ID yang valid", + "edit_profile": "Sunting profil", + "address": "Alamat", + "input_address": "Masukkan alamat Anda", + "website": "Situs web", + "input_website": "Masukkan situs web Anda", + "feedback": "Umpan balik", + "replay": "Ulangan", + "tap_rate": "Ketuk bintang untuk memberi peringkat", + "title": "Judul", + "input_title": "Masukkan judul Anda", + "description": "Deskripsi", + "input_feedback": "Masukkan umpan balik Anda", + "filter": "Saring", + "facilities": "Fasilitas", + "area": "Daerah", + "select_location": "Pilih lokasi", + "price_range": "Kisaran harga", + "avg_price": "Harga AVG", + "business_color": "Warna Bisnis", + "open_time": "Waktu Terbuka", + "start_time": "Waktu mulai", + "end_time": "Akhir waktu", + "rating": "Peringkat", + "font": "Font", + "forgot_password": "Tidak ingat kata sandi", + "reset_password": "Setel Ulang Kata Sandi", + "search_location": "Lokasi Pencarian", + "more": "Lebih", + "popular_location": "Lokasi Populer", + "let_find_interesting": "Biarkan mencari tahu hal-hal apa yang paling menarik", + "recent_location": "Lokasi Terbaru", + "what_happen": "Apa yang bisa terjadi?", + "shopping": "Perbelanjaan", + "shopping_intro": "Merek favorit dan tren terpanas.", + "payment": "Pembayaran", + "payment_intro": "Mitra bisnis online strategis Anda.", + "location_intro": "Lokasi, Komunitas, Kualitas Hidup. Mulai Di Sini!", + "lasted_post": "Posting Terakhir", + "oldest_post": "Pos Tertua", + "most_view": "Kebanyakan Tampilan", + "review_rating": "Peringkat Ulasan", + "delete": "Menghapus", + "image": "Gambar", + "phone": "Telepon", + "date_established": "Tanggal Didirikan", + "featured": "Unggulan", + "nearly": "Hampir", + "related": "Terkait", + "profile": "Profil", + "sign_in": "Masuk", + "sign_out": "Keluar", + "setting": "Pengaturan", + "review": "Ulasan", + "write": "Menulis", + "out_of": "Dari", + "loading": "Memuat...", + "search_title": "Cari", + "search_history": "Sejarah pencarian", + "discover_more": "Temukan Lebih Banyak", + "recently_viewed": "baru saja dilihat", + "clear": "Bersih", + "language": "Bahasa", + "theme": "Tema", + "dark_mode": "Mode Gelap", + "version": "Versi: kapan", + "post": "Pos", + "follower": "Pengikut", + "sign_up": "Daftar", + "input_id": "Masukkan akun Anda", + "default": "Default", + "brown": "cokelat", + "pink": "Merah Jambu", + "orange": "jeruk", + "green": "hijau", + "monday": "Senin", + "tuesday": "Selasa", + "wednesday": "Rabu", + "thursday": "Kamis", + "friday": "Jumat", + "saturday": "Sabtu", + "sunday": "Minggu", + "day_off": "Libur", + "close": "Menutup", + "pull_down_refresh": "Tarik penyegaran ke bawah", + "refreshing": "Segar...", + "refresh_completed": "Segarkan selesai", + "release_to_refresh": "Lepaskan untuk menyegarkan", + "release_to_load_more": "Lepaskan untuk memuat lebih banyak", + "pull_to_load_more": "Tarik ke atas untuk memuat lebih banyak", + "explore_product": "Jelajahi Produk", + "view_list": "Lihat Daftar" +} diff --git a/assets/locale/ja.json b/assets/locale/ja.json new file mode 100644 index 0000000..4726cf0 --- /dev/null +++ b/assets/locale/ja.json @@ -0,0 +1,132 @@ +{ + "home": "ホーム", + "wish_list": "ウィッシュリスト", + "message": "メッセージ", + "notification": "お知らせ", + "account": "アカウント", + "change_language": "言語を変えてください", + "dynamic_theme": "システム電話", + "always_on": "常にオン", + "always_off": "常にオフ", + "about_us": "私たちに関しては", + "who_we_are": "私たちは誰ですか?", + "what_we_do": "私達がすること ?", + "meet_our_team": "私たちのチームに会う", + "category": "カテゴリー", + "search": "探す ...", + "category_not_found": "カテゴリが見つかりません", + "password": "パスワード", + "change_password": "パスワードを変更する", + "input_your_password": "パスワードを入力してください", + "confirm_password": "パスワードを認証する", + "confirm_your_password": "あなたのパスワードを確認", + "confirm": "確認", + "type_something": "何かを入力...", + "location": "ロケーション", + "apply": "申し込む", + "contact_us": "お問い合わせ", + "send": "送る", + "name": "名前", + "input_name": "名前を入力してください", + "email": "Eメール", + "input_email": "メールアドレスを入力してください", + "information": "情報", + "input_information": "情報を入力してください", + "value_not_empty": "入力が空ではありません", + "value_not_valid_range": "入力が無効な範囲です", + "value_not_valid_email": "無効なメールアドレスを入力してください", + "value_not_valid_phone": "入力が無効な電話", + "value_not_valid_password": "無効なパスワードを入力してください", + "value_not_valid_id": "入力したIDが無効です", + "edit_profile": "プロファイル編集", + "address": "住所", + "input_address": "住所を入力してください", + "website": "ウェブサイト", + "input_website": "あなたのウェブサイトを入力してください", + "feedback": "フィードバック", + "replay": "リプレイ", + "tap_rate": "星をタップして評価", + "title": "題名", + "input_title": "タイトルを入力してください", + "description": "説明文", + "input_feedback": "フィードバックを入力してください", + "filter": "フィルタ", + "facilities": "施設紹介", + "area": "範囲", + "select_location": "場所を選択", + "price_range": "価格帯", + "avg_price": "AVG価格", + "business_color": "ビジネスカラー", + "open_time": "オープンタイム", + "start_time": "始まる時間", + "end_time": "終了時間", + "rating": "評価", + "font": "書体", + "forgot_password": "パスワードをお忘れですか", + "reset_password": "パスワードを再設定する", + "search_location": "場所を検索", + "more": "もっと", + "popular_location": "人気の場所", + "let_find_interesting": "最も興味深いものを見つけましょう", + "recent_location": "最近の場所", + "what_happen": "何が起こる可能性がありますか", + "shopping": "ショッピング", + "shopping_intro": "お気に入りのブランドと最も人気のあるトレンド。", + "payment": "支払い", + "payment_intro": "戦略的なオンラインビジネスパートナー。", + "location_intro": "場所、コミュニティ、質の高い生活。ここから始まります!", + "lasted_post": "長続きする投稿", + "oldest_post": "最古の投稿", + "most_view": "ほとんどのビュー", + "review_rating": "レビューの評価", + "delete": "削除する", + "image": "画像", + "phone": "電話", + "date_established": "設立日", + "featured": "特徴", + "nearly": "ほぼ", + "related": "関連した", + "profile": "プロフィール", + "sign_in": "サインイン", + "sign_out": "サインアウト", + "setting": "設定", + "review": "レビュー", + "write": "書く", + "out_of": "のうち", + "loading": "読み込んでいます...", + "search_title": "探す", + "search_history": "検索履歴", + "discover_more": "もっと知る", + "recently_viewed": "最近見た", + "clear": "晴れ", + "language": "言語", + "theme": "テーマ", + "dark_mode": "ダークモード", + "version": "バージョン", + "post": "役職", + "follower": "フォロワー", + "sign_up": "サインアップ", + "input_id": "アカウントを入力してください", + "default": "デフォルト", + "brown": "褐色", + "pink": "ピンク", + "orange": "オレンジ", + "green": "緑", + "monday": "月曜", + "tuesday": "火曜日", + "wednesday": "水曜日", + "thursday": "木曜日", + "friday": "金曜日", + "saturday": "土曜日", + "sunday": "日曜日", + "day_off": "休みの日", + "close": "閉じる", + "pull_down_refresh": "プルダウンリフレッシュ", + "refreshing": "更新しています...", + "refresh_completed": "更新が完了しました", + "release_to_refresh": "リリースして更新", + "release_to_load_more": "解放してさらに読み込む", + "pull_to_load_more": "引き上げてさらにロード", + "explore_product": "製品を探す", + "view_list": "リストを表示" +} diff --git a/assets/locale/km.json b/assets/locale/km.json new file mode 100644 index 0000000..265b742 --- /dev/null +++ b/assets/locale/km.json @@ -0,0 +1,132 @@ +{ + "home": "ផ្ទះ", + "wish_list": "បញ្ជីប្រាថ្នា", + "message": "សារ", + "notification": "ការជូនដំណឹង", + "account": "គណនី", + "change_language": "ប្ដូរ​ភាសា", + "dynamic_theme": "ទូរស័ព្ទប្រព័ន្ធ", + "always_on": "បើកជានិច្ច", + "always_off": "បិទជានិច្ច", + "about_us": "អំពី​ពួក​យើង", + "who_we_are": "យើង​ជា​នរណា ?", + "what_we_do": "តើយើងធ្វើអ្វី?", + "meet_our_team": "ជួបជាមួយក្រុមរបស់យើង", + "category": "ប្រភេទ", + "search": "ស្វែងរក", + "category_not_found": "រកមិនឃើញចំណាត់ថ្នាក់", + "password": "ពាក្យសម្ងាត់", + "change_password": "ផ្លាស់ប្តូរពាក្យសម្ងាត់", + "input_your_password": "បញ្ចូលពាក្យសម្ងាត់របស់អ្នក", + "confirm_password": "បញ្ជាក់ពាក្យសម្ងាត់", + "confirm_your_password": "បញ្ជាក់ពាក្យសម្ងាត់របស់អ្នក", + "confirm": "បញ្ជាក់", + "type_something": "វាយអ្វីមួយ ...", + "location": "ទីតាំង", + "apply": "អនុវត្ត", + "contact_us": "ទាក់ទង​មក​ពួក​យើង", + "send": "ផ្ញើ", + "name": "ឈ្មោះ", + "input_name": "បញ្ចូលឈ្មោះរបស់អ្នក", + "email": "អ៊ីមែល", + "input_email": "បញ្ចូលអ៊ីមែលរបស់អ្នក", + "information": "ព័ត៌មាន", + "input_information": "បញ្ចូលព័ត៌មានរបស់អ្នក", + "value_not_empty": "ការបញ្ចូលមិនទទេ", + "value_not_valid_range": "ការបញ្ចូលជួរមិនត្រឹមត្រូវ", + "value_not_valid_email": "ការបញ្ចូលមិនមានអ៊ីមែលត្រឹមត្រូវ", + "value_not_valid_phone": "ការបញ្ចូលមិនមានទូរស័ព្ទត្រឹមត្រូវ", + "value_not_valid_password": "ការបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវ", + "value_not_valid_id": "ការបញ្ចូលមិនមានអត្តសញ្ញាណប័ណ្ណត្រឹមត្រូវ", + "edit_profile": "កែប្រែពត៌មាន", + "address": "អាសយដ្ឋាន", + "input_address": "បញ្ចូលអាសយដ្ឋានរបស់អ្នក", + "website": "គេហទំព័រ", + "input_website": "បញ្ចូលគេហទំព័ររបស់អ្នក", + "feedback": "មតិប្រតិកម្ម", + "replay": "ចាក់ឡើងវិញ", + "tap_rate": "ប៉ះផ្កាយដើម្បីវាយតម្លៃ", + "title": "ចំណងជើង", + "input_title": "បញ្ចូលចំណងជើងរបស់អ្នក", + "description": "ការពិពណ៌នា", + "input_feedback": "បញ្ចូលមតិត្រឡប់របស់អ្នក", + "filter": "ត្រង", + "facilities": "គ្រឿងបរិក្ខារ", + "area": "តំបន់", + "select_location": "ជ្រើសរើសទីតាំង", + "price_range": "ជួរតម្លៃ", + "avg_price": "តម្លៃ AVG", + "business_color": "ពណ៌អាជីវកម្ម", + "open_time": "ពេលវេលាបើកចំហ", + "start_time": "ពេលវេលាចាប់ផ្តើម", + "end_time": "ពេលវេលាបញ្ចប់", + "rating": "ការវាយតម្លៃ", + "font": "ពុម្ពអក្សរ", + "forgot_password": "ភ្លេច​លេខសំងាត់​", + "reset_password": "កំណត់ពាក្យសម្ងាត់ឡើងវិញ", + "search_location": "ស្វែងរកទីតាំង", + "more": "ច្រើនទៀត", + "popular_location": "ទីតាំងពេញនិយម", + "let_find_interesting": "សូមស្វែងយល់នូវអ្វីដែលគួរឱ្យចាប់អារម្មណ៍បំផុត", + "recent_location": "ទីតាំងថ្មីៗ", + "what_happen": "អ្វីដែលអាចកើតឡើង", + "shopping": "ដើរទិញឥវ៉ាន់", + "shopping_intro": "យីហោដែលខ្ញុំចូលចិត្តនិងនិន្នាការពេញនិយមបំផុត។", + "payment": "ការទូទាត់", + "payment_intro": "ដៃគូអាជីវកម្មតាមអ៊ិនធរណេតរបស់អ្នក។", + "location_intro": "ទីតាំងសហគមន៍ការរស់នៅប្រកបដោយគុណភាព។ វាចាប់ផ្តើមនៅទីនេះ!", + "lasted_post": "ប្រកាសចុងក្រោយ", + "oldest_post": "ប៉ុស្តិ៍ចាស់ជាងគេ", + "most_view": "ការមើលច្រើនបំផុត", + "review_rating": "ការវាយតម្លៃឡើងវិញ", + "delete": "លុប", + "image": "រូបភាព", + "phone": "ទូរស័ព្ទ", + "date_established": "កាលបរិច្ឆេទបង្កើតឡើង", + "featured": "លក្ខណៈពិសេស", + "nearly": "ជិតហើយ", + "related": "ពាក់ព័ន្ធ", + "profile": "ប្រវត្តិរូប", + "sign_in": "ចូល", + "sign_out": "ចាកចេញ", + "setting": "ការកំណត់", + "review": "ការពិនិត្យឡើងវិញ", + "write": "សរសេរ", + "out_of": "ចេញ​ពី", + "loading": "កំពុងផ្ទុក ...", + "search_title": "ស្វែងរក", + "search_history": "ប្រវត្តិស្វែងរក", + "discover_more": "ស្វែងយល់បន្ថែម", + "recently_viewed": "បានមើលថ្មីៗ", + "clear": "ច្បាស់", + "language": "ភាសា", + "theme": "ស្បែក", + "dark_mode": "របៀបងងឹត", + "version": "កំណែ", + "post": "ប្រកាស", + "follower": "អ្នកតាម", + "sign_up": "ចុះ​ឈ្មោះ", + "input_id": "បញ្ចូលគណនីរបស់អ្នក", + "default": "លំនាំដើម", + "brown": "ត្នោត", + "pink": "ពណ៌ផ្កាឈូក", + "orange": "ទឹកក្រូច", + "green": "បៃតង", + "monday": "ថ្ងៃច័ន្ទ", + "tuesday": "ថ្ងៃអង្គារ", + "wednesday": "ថ្ងៃពុធ", + "thursday": "ថ្ងៃព្រហស្បតិ៍", + "friday": "ថ្ងៃសុក្រ", + "saturday": "ថ្ងៃសៅរ៍", + "sunday": "ថ្ងៃអាទិត្យ", + "day_off": "ថ្ងៃ​ឈប់សម្រាក", + "close": "បិទ", + "pull_down_refresh": "ទាញធ្វើឱ្យស្រស់", + "refreshing": "កំពុងធ្វើឱ្យស្រស់ ...", + "refresh_completed": "បានបញ្ចប់ការផ្ទុកឡើងវិញ", + "release_to_refresh": "ដោះលែងដើម្បីធ្វើឱ្យស្រស់", + "release_to_load_more": "ចេញផ្សាយដើម្បីផ្ទុកបន្ថែមទៀត", + "pull_to_load_more": "ទាញឡើងដើម្បីផ្ទុកបន្ថែម", + "explore_product": "ស្វែងរកផលិតផល", + "view_list": "មើលបញ្ជី" +} diff --git a/assets/locale/ko.json b/assets/locale/ko.json new file mode 100644 index 0000000..89c27b6 --- /dev/null +++ b/assets/locale/ko.json @@ -0,0 +1,132 @@ +{ + "home": "집", + "wish_list": "위시리스트", + "message": "메시지", + "notification": "공고", + "account": "계정", + "change_language": "언어 변경", + "dynamic_theme": "시스템 전화", + "always_on": "항상 켜기", + "always_off": "항상 끄기", + "about_us": "회사 소개", + "who_we_are": "우리는 누구입니까?", + "what_we_do": "우리는 무엇을합니까?", + "meet_our_team": "우리의 팀을 만나", + "category": "범주", + "search": "검색 ...", + "category_not_found": "카테고리를 찾을 수 없습니다", + "password": "암호", + "change_password": "비밀번호 변경", + "input_your_password": "비밀번호를 입력하십시오", + "confirm_password": "비밀번호 확인", + "confirm_your_password": "암호를 확인", + "confirm": "확인", + "type_something": "뭔가를 입력하십시오 ...", + "location": "위치", + "apply": "대다", + "contact_us": "문의하기", + "send": "보내다", + "name": "이름", + "input_name": "당신의 이름을 입력", + "email": "이메일", + "input_email": "이메일을 입력하십시오", + "information": "정보", + "input_information": "정보를 입력하십시오", + "value_not_empty": "입력이 비어 있지 않습니다", + "value_not_valid_range": "유효하지 않은 입력 범위", + "value_not_valid_email": "유효하지 않은 이메일 입력", + "value_not_valid_phone": "잘못된 전화 번호를 입력했습니다", + "value_not_valid_password": "유효하지 않은 비밀번호를 입력했습니다", + "value_not_valid_id": "유효하지 않은 ID를 입력했습니다", + "edit_profile": "프로필 수정", + "address": "주소", + "input_address": "주소를 입력하십시오", + "website": "웹 사이트", + "input_website": "귀하의 웹 사이트를 입력하십시오", + "feedback": "피드백", + "replay": "다시 하다", + "tap_rate": "별표를 탭하여 평가", + "title": "표제", + "input_title": "제목을 입력하십시오", + "description": "기술", + "input_feedback": "의견을 입력하세요", + "filter": "필터", + "facilities": "시설", + "area": "지역", + "select_location": "위치를 선택하십시오", + "price_range": "가격 범위", + "avg_price": "AVG 가격", + "business_color": "비즈니스 컬러", + "open_time": "영업 시간", + "start_time": "시작 시간", + "end_time": "종료 시간", + "rating": "평가", + "font": "폰트", + "forgot_password": "비밀번호를 잊으 셨나요", + "reset_password": "암호를 재설정", + "search_location": "위치 검색", + "more": "더", + "popular_location": "인기있는 위치", + "let_find_interesting": "가장 흥미로운 것들을 찾아 보자", + "recent_location": "최근 위치", + "what_happen": "일어날 수있는 일", + "shopping": "쇼핑", + "shopping_intro": "좋아하는 브랜드와 인기 트렌드.", + "payment": "지불", + "payment_intro": "전략적 온라인 비즈니스 파트너.", + "location_intro": "위치, 지역 사회, 양질의 생활. 여기에서 시작합니다!", + "lasted_post": "지속 된 게시물", + "oldest_post": "가장 오래된 포스트", + "most_view": "대부분의 조회수", + "review_rating": "평가 등급", + "delete": "지우다", + "image": "영상", + "phone": "전화", + "date_established": "설립일", + "featured": "특집", + "nearly": "거의", + "related": "관련", + "profile": "프로필", + "sign_in": "로그인", + "sign_out": "로그 아웃", + "setting": "환경", + "review": "리뷰", + "write": "쓰다", + "out_of": "밖으로", + "loading": "불러오는 중 ...", + "search_title": "검색", + "search_history": "검색 기록", + "discover_more": "더 발견하다", + "recently_viewed": "최근에 본", + "clear": "명확한", + "language": "언어", + "theme": "테마", + "dark_mode": "다크 모드", + "version": "버전", + "post": "게시하다", + "follower": "수행원", + "sign_up": "가입하기", + "input_id": "계정을 입력하십시오", + "default": "기본", + "brown": "갈색", + "pink": "분홍", + "orange": "주황색", + "green": "초록", + "monday": "월요일", + "tuesday": "화요일", + "wednesday": "수요일", + "thursday": "목요일", + "friday": "금요일", + "saturday": "토요일", + "sunday": "일요일", + "day_off": "휴일", + "close": "닫기", + "pull_down_refresh": "새로 고침 풀다운", + "refreshing": "새로 고침 중 ...", + "refresh_completed": "새로 고침 완료", + "release_to_refresh": "새로 고침하려면 놓습니다", + "release_to_load_more": "더로드하려면 놓으십시오", + "pull_to_load_more": "더로드하려면 위로 당기십시오", + "explore_product": "제품 둘러보기", + "view_list": "리스트보기" +} diff --git a/assets/locale/lo.json b/assets/locale/lo.json new file mode 100644 index 0000000..f4ea5b0 --- /dev/null +++ b/assets/locale/lo.json @@ -0,0 +1,132 @@ +{ + "home": "ເຮືອນ", + "wish_list": "ລາຍການທີ່ຕ້ອງການ", + "message": "ຂໍ້ຄວາມ", + "notification": "ແຈ້ງການ", + "account": "ບັນຊີ", + "change_language": "ປ່ຽນ​ພາ​ສາ", + "dynamic_theme": "ໂທລະສັບລະບົບ", + "always_on": "ສະເຫມີໄປ", + "always_off": "ເບີຢູ່ສະ ເໝີ", + "about_us": "ກ່ຽວ​ກັບ​ພວກ​ເຮົາ", + "who_we_are": "ພວກ​ເຮົາ​ແມ່ນ​ໃຜ ?", + "what_we_do": "ພວກ​ເຮົາ​ເຮັດ​ຫຍັງ ?", + "meet_our_team": "ພົບກັບທິມງານຂອງພວກເຮົາ", + "category": "ໝວດ", + "search": "ຄົ້ນຫາ ...", + "category_not_found": "ບໍ່ພົບ ໝວດ ໝູ່", + "password": "ລະຫັດຜ່ານ", + "change_password": "ປ່ຽນ​ລະ​ຫັດ​ຜ່ານ", + "input_your_password": "ປ້ອນລະຫັດຜ່ານຂອງທ່ານ", + "confirm_password": "ຢືນ​ຢັນ​ລະ​ຫັດ", + "confirm_your_password": "ຢືນຢັນລະຫັດຜ່ານຂອງທ່ານ", + "confirm": "ຢືນຢັນ", + "type_something": "ພິມບາງສິ່ງບາງຢ່າງ ...", + "location": "ສະຖານທີ່", + "apply": "ສະ ໝັກ", + "contact_us": "ຕິດ​ຕໍ່​ພວກ​ເຮົາ", + "send": "ສົ່ງ", + "name": "ຊື່", + "input_name": "ປ້ອນຊື່ຂອງທ່ານ", + "email": "ອີເມວ", + "input_email": "ປ້ອນອີເມວຂອງທ່ານ", + "information": "ຂໍ້ມູນ", + "input_information": "ປ້ອນຂໍ້ມູນຂອງທ່ານ", + "value_not_empty": "ການປ້ອນຂໍ້ມູນບໍ່ແມ່ນວ່າງເປົ່າ", + "value_not_valid_range": "ການປ້ອນຂໍ້ມູນບໍ່ມີລະດັບທີ່ຖືກຕ້ອງ", + "value_not_valid_email": "ການປ້ອນຂໍ້ມູນບໍ່ແມ່ນອີເມວທີ່ຖືກຕ້ອງ", + "value_not_valid_phone": "ການປ້ອນຂໍ້ມູນໂທລະສັບບໍ່ຖືກຕ້ອງ", + "value_not_valid_password": "ການປ້ອນຂໍ້ມູນບໍ່ຖືກຕ້ອງລະຫັດຜ່ານ", + "value_not_valid_id": "ການປ້ອນຂໍ້ມູນບໍ່ຖືກຕ້ອງ", + "edit_profile": "ແກ້ໄຂຂໍ້ມູນ", + "address": "ທີ່ຢູ່", + "input_address": "ປ້ອນທີ່ຢູ່ຂອງທ່ານ", + "website": "ເວບໄຊທ໌", + "input_website": "ປ້ອນເວັບໄຊທ໌ຂອງທ່ານ", + "feedback": "ຄຳ ຕິຊົມ", + "replay": "ເປີດ ໃໝ່", + "tap_rate": "ແຕະດາວເພື່ອໃຫ້ຄະແນນ", + "title": "ຫົວຂໍ້", + "input_title": "ປ້ອນຫົວຂໍ້ຂອງທ່ານ", + "description": "ລາຍລະອຽດ", + "input_feedback": "ໃສ່ ຄຳ ຕິຊົມຂອງທ່ານ", + "filter": "ການກັ່ນຕອງ", + "facilities": "ສິ່ງ ອຳ ນວຍຄວາມສະດວກ", + "area": "ພື້ນທີ່", + "select_location": "ເລືອກສະຖານທີ່", + "price_range": "ລະ​ດັບ​ລາ​ຄາ", + "avg_price": "ລາຄາ AVG", + "business_color": "ສີທຸລະກິດ", + "open_time": "ເວລາເປີດ", + "start_time": "ເວລາເລີ່ມຕົ້ນ", + "end_time": "ເວລາສິ້ນສຸດ", + "rating": "ການໃຫ້ຄະແນນ", + "font": "ຕົວອັກສອນ", + "forgot_password": "ລືມລະຫັດຜ່ານ", + "reset_password": "ຕັ້ງລະຫັດຜ່ານຄືນ", + "search_location": "ສະຖານທີ່ຄົ້ນຫາ", + "more": "ຫຼາຍ", + "popular_location": "ສະຖານທີ່ທີ່ນິຍົມ", + "let_find_interesting": "ໃຫ້ເຮົາຄົ້ນຫາສິ່ງທີ່ ໜ້າ ສົນໃຈທີ່ສຸດ", + "recent_location": "ສະຖານທີ່ທີ່ຜ່ານມາ", + "what_happen": "ສິ່ງທີ່ອາດຈະເກີດຂື້ນ", + "shopping": "ຊື້ເຄື່ອງ", + "shopping_intro": "ຍີ່ຫໍ້ທີ່ມັກແລະແນວໂນ້ມທີ່ຮ້ອນທີ່ສຸດ.", + "payment": "ການຈ່າຍເງິນ", + "payment_intro": "ຄູ່ຮ່ວມທຸລະກິດທາງຍຸດທະສາດຂອງທ່ານ.", + "location_intro": "ສະຖານທີ່, ຊຸມຊົນ, ການ ດຳ ລົງຊີວິດທີ່ມີຄຸນນະພາບ. ມັນເລີ່ມຕົ້ນທີ່ນີ້!", + "lasted_post": "ຕອບຫຼ້າສຸດ", + "oldest_post": "Post ເກົ່າແກ່ທີ່ສຸດ", + "most_view": "ການເບິ່ງຫລາຍທີ່ສຸດ", + "review_rating": "ການໃຫ້ຄະແນນການທົບທວນຄືນ", + "delete": "ລົບ", + "image": "ຮູບພາບ", + "phone": "ໂທລະສັບ", + "date_established": "ວັນສ້າງຕັ້ງ", + "featured": "ທີ່ໂດດເດັ່ນ", + "nearly": "ເກືອບ", + "related": "ທີ່ກ່ຽວຂ້ອງ", + "profile": "ຂໍ້ມູນ", + "sign_in": "ເຂົ້າ​ສູ່​ລະ​ບົບ", + "sign_out": "ອອກ​ຈາກ​ລະ​ບົບ", + "setting": "ການຕັ້ງຄ່າ", + "review": "ການທົບທວນຄືນ", + "write": "ຂຽນ", + "out_of": "ອອກຈາກ", + "loading": "ກຳ ລັງໂຫລດ ...", + "search_title": "ຄົ້ນຫາ", + "search_history": "ປະຫວັດການຄົ້ນຫາ", + "discover_more": "ຄົ້ນພົບຕື່ມອີກ", + "recently_viewed": "ເມື່ອມໍ່ໆມານີ້ເບິ່ງ", + "clear": "ແຈ້ງ", + "language": "ພາສາ", + "theme": "ຫົວຂໍ້", + "dark_mode": "ຮູບແບບມືດ", + "version": "ຮຸ່ນ", + "post": "ໂພສ", + "follower": "ຜູ້ຕິດຕາມ", + "sign_up": "ລົງ​ທະ​ບຽນ", + "input_id": "ປ້ອນບັນຊີຂອງທ່ານ", + "default": "ເລີ່ມຕົ້ນ", + "brown": "ສີນ້ ຳ ຕານ", + "pink": "ສີບົວ", + "orange": "ສົ້ມ", + "green": "ສີຂຽວ", + "monday": "ວັນຈັນ", + "tuesday": "ວັນອັງຄານ", + "wednesday": "ວັນພຸດ", + "thursday": "ວັນພະຫັດ", + "friday": "ວັນ​ສຸກ", + "saturday": "ວັນເສົາ", + "sunday": "ວັນອາທິດ", + "day_off": "ມື້​ພັກ", + "close": "ປິດ", + "pull_down_refresh": "ດຶງການໂຫຼດຫນ້າຈໍຄືນ", + "refreshing": "ກຳ ລັງ ໃໝ່ ...", + "refresh_completed": "ການໂຫຼດ ໜ້າ ຈໍ ສຳ ເລັດແລ້ວ", + "release_to_refresh": "ປ່ອຍເພື່ອສົດຊື່ນ", + "release_to_load_more": "ປ່ອຍເພື່ອໃຫ້ໂຫລດຫຼາຍ", + "pull_to_load_more": "ດຶງຂຶ້ນມາເພື່ອໂຫຼດຫຼາຍ", + "explore_product": "ສຳ ຫຼວດຜະລິດຕະພັນ", + "view_list": "ເບິ່ງບັນຊີລາຍຊື່" +} diff --git a/assets/locale/nl.json b/assets/locale/nl.json new file mode 100644 index 0000000..3484c08 --- /dev/null +++ b/assets/locale/nl.json @@ -0,0 +1,132 @@ +{ + "home": "Huis", + "wish_list": "Verlanglijst", + "message": "Berichten", + "notification": "Kennisgeving", + "account": "Account", + "change_language": "Wijzig taal", + "dynamic_theme": "Systeemtelefoon", + "always_on": "Altijd aan", + "always_off": "Altijd uit", + "about_us": "Over ons", + "who_we_are": "WIE WE ZIJN ?", + "what_we_do": "WAT WE DOEN ?", + "meet_our_team": "ONTMOET ONS TEAM", + "category": "Categorie", + "search": "Zoeken ...", + "category_not_found": "Categorie niet gevonden", + "password": "Wachtwoord", + "change_password": "Verander wachtwoord", + "input_your_password": "Voer uw wachtwoord in", + "confirm_password": "bevestig wachtwoord", + "confirm_your_password": "Bevestig je wachtwoord", + "confirm": "Bevestigen", + "type_something": "Typ iets...", + "location": "Plaats", + "apply": "Van toepassing zijn", + "contact_us": "Neem contact op", + "send": "Sturen", + "name": "Naam", + "input_name": "Voer uw naam in", + "email": "E-mail", + "input_email": "Voer uw e-mailadres in", + "information": "Informatie", + "input_information": "Voer uw gegevens in", + "value_not_empty": "Invoer is niet leeg", + "value_not_valid_range": "Invoer niet geldig bereik", + "value_not_valid_email": "Voer geen geldige e-mail in", + "value_not_valid_phone": "Invoer ongeldige telefoon", + "value_not_valid_password": "Voer een ongeldig wachtwoord in", + "value_not_valid_id": "Voer een ongeldige ID in", + "edit_profile": "Bewerk profiel", + "address": "Adres", + "input_address": "Voer uw adres in", + "website": "Website", + "input_website": "Voer uw website in", + "feedback": "Feedback", + "replay": "Herhaling", + "tap_rate": "Tik op een ster om te beoordelen", + "title": "Titel", + "input_title": "Voer uw titel in", + "description": "Beschrijving", + "input_feedback": "Voer uw feedback in", + "filter": "Filter", + "facilities": "Voorzieningen", + "area": "Oppervlakte", + "select_location": "Selecteer een locatie", + "price_range": "Prijsklasse", + "avg_price": "AVG-prijs", + "business_color": "Zakelijke kleur", + "open_time": "Openingsuren", + "start_time": "Starttijd", + "end_time": "Eindtijd", + "rating": "Beoordeling", + "font": "Lettertype", + "forgot_password": "Wachtwoord vergeten", + "reset_password": "Wachtwoord opnieuw instellen", + "search_location": "Zoek locatie", + "more": "Meer", + "popular_location": "Populaire locatie", + "let_find_interesting": "Laten we eens kijken wat de meest interessante dingen zijn", + "recent_location": "Recente locatie", + "what_happen": "Wat kan er gebeuren?", + "shopping": "Boodschappen doen", + "shopping_intro": "Favoriete merken en populairste trends.", + "payment": "Betaling", + "payment_intro": "Uw strategische online zakenpartner.", + "location_intro": "Locatie, gemeenschap, kwaliteit van leven. Het begint hier!", + "lasted_post": "Duurde bericht", + "oldest_post": "Oudste bericht", + "most_view": "De meeste weergaven", + "review_rating": "Beoordeling beoordelen", + "delete": "Verwijderen", + "image": "Beeld", + "phone": "Telefoon", + "date_established": "datum Opgericht", + "featured": "Aanbevolen", + "nearly": "Bijna", + "related": "Verwant", + "profile": "Profiel", + "sign_in": "Log in", + "sign_out": "Afmelden", + "setting": "Omgeving", + "review": "Recensies", + "write": "Schrijven", + "out_of": "Uit", + "loading": "Bezig met laden...", + "search_title": "Zoeken", + "search_history": "Zoek geschiedenis", + "discover_more": "Ontdek meer", + "recently_viewed": "Recent bekeken", + "clear": "Doorzichtig", + "language": "Taal", + "theme": "Thema", + "dark_mode": "Donkere modus", + "version": "Versie", + "post": "Post", + "follower": "Volger", + "sign_up": "Inschrijven", + "input_id": "Voer uw account in", + "default": "Standaard", + "brown": "Bruin", + "pink": "Roze", + "orange": "Oranje", + "green": "Groen", + "monday": "maandag", + "tuesday": "dinsdag", + "wednesday": "woensdag", + "thursday": "donderdag", + "friday": "vrijdag", + "saturday": "zaterdag", + "sunday": "zondag", + "day_off": "Vrije dag", + "close": "Dichtbij", + "pull_down_refresh": "Trek vernieuwen naar beneden", + "refreshing": "Verfrissend...", + "refresh_completed": "Vernieuwen voltooid", + "release_to_refresh": "Laat los om te verversen", + "release_to_load_more": "Laat los om meer te laden", + "pull_to_load_more": "Trek omhoog om meer te laden", + "explore_product": "Ontdek Product", + "view_list": "Weergave lijst" +} diff --git a/assets/locale/vi.json b/assets/locale/vi.json new file mode 100644 index 0000000..82a2a71 --- /dev/null +++ b/assets/locale/vi.json @@ -0,0 +1,132 @@ +{ + "home": "Trang Chủ", + "wish_list": "Danh sách mong muốn", + "message": "Tin nhắn", + "notification": "Thông báo", + "account": "Tài khoản", + "change_language": "Thay đổi ngôn ngữ", + "dynamic_theme": "Điện thoại hệ thống", + "always_on": "Luôn luôn", + "always_off": "Luôn luôn tắt", + "about_us": "Về chúng tôi", + "who_we_are": "CHÚNG TA LÀ AI ?", + "what_we_do": "CHÚNG TA LÀM GÌ ?", + "meet_our_team": "GẶP ĐỘI CỦA CHÚNG TÔI", + "category": "thể loại", + "search": "Tìm kiếm ...", + "category_not_found": "Không tìm thấy danh mục", + "password": "Mật khẩu", + "change_password": "Đổi mật khẩu", + "input_your_password": "Nhập mật khẩu của bạn", + "confirm_password": "Xác nhận mật khẩu", + "confirm_your_password": "Xác nhận mật khẩu của bạn", + "confirm": "Xác nhận", + "type_something": "Nhập một cái gì đó ...", + "location": "Vị trí", + "apply": "Ứng dụng", + "contact_us": "Liên hệ chúng tôi", + "send": "Gửi", + "name": "Tên", + "input_name": "Nhập tên của bạn", + "email": "E-mail", + "input_email": "Nhập email của bạn", + "information": "Thông tin", + "input_information": "Nhập thông tin của bạn", + "value_not_empty": "Đầu vào không trống", + "value_not_valid_range": "Phạm vi đầu vào không hợp lệ", + "value_not_valid_email": "Đầu vào email không hợp lệ", + "value_not_valid_phone": "Điện thoại nhập không hợp lệ", + "value_not_valid_password": "Nhập mật khẩu không hợp lệ", + "value_not_valid_id": "ID không hợp lệ", + "edit_profile": "Chỉnh sửa hồ sơ", + "address": "Địa chỉ", + "input_address": "Nhập địa chỉ của bạn", + "website": "Trang mạng", + "input_website": "Nhập trang web của bạn", + "feedback": "Phản hồi", + "replay": "phát lại", + "tap_rate": "Nhấn vào một ngôi sao để xếp hạng", + "title": "Tiêu đề", + "input_title": "Nhập tiêu đề của bạn", + "description": "Sự miêu tả", + "input_feedback": "Nhập phản hồi của bạn", + "filter": "Bộ lọc", + "facilities": "Cơ sở vật chất", + "area": "Khu vực", + "select_location": "Chọn địa điểm", + "price_range": "Phạm vi giá", + "avg_price": "Giá AVG", + "business_color": "Màu kinh doanh", + "open_time": "Thời gian mở", + "start_time": "Thời gian bắt đầu", + "end_time": "Thời gian kết thúc", + "rating": "Xếp hạng", + "font": "Phông chữ", + "forgot_password": "Quên mật khẩu", + "reset_password": "Đặt lại mật khẩu", + "search_location": "Địa điểm tìm kiếm", + "more": "Hơn", + "popular_location": "Địa điểm nổi tiếng", + "let_find_interesting": "Hãy tìm hiểu những điều thú vị nhất", + "recent_location": "Địa điểm gần đây", + "what_happen": "Điều gì có thể xảy ra", + "shopping": "Mua sắm", + "shopping_intro": "Thương hiệu yêu thích và xu hướng nóng nhất.", + "payment": "Thanh toán", + "payment_intro": "Đối tác kinh doanh trực tuyến chiến lược của bạn.", + "location_intro": "Địa điểm, Cộng đồng, Cuộc sống Chất lượng. Nó bắt đầu từ đây!", + "lasted_post": "Bài cuối", + "oldest_post": "Bài cũ nhất", + "most_view": "Lượt xem nhiều nhất", + "review_rating": "Đánh giá xếp hạng", + "delete": "Xóa bỏ", + "image": "Hình ảnh", + "phone": "Điện thoại", + "date_established": "Ngày thành lập", + "featured": "Đặc sắc", + "nearly": "Gần", + "related": "Liên quan", + "profile": "Hồ sơ", + "sign_in": "Đăng nhập", + "sign_out": "Đăng xuất", + "setting": "Cài đặt", + "review": "Nhận xét", + "write": "Viết", + "out_of": "Hết", + "loading": "Đang tải...", + "search_title": "Tìm kiếm", + "search_history": "Lịch sử tìm kiếm", + "discover_more": "Khám phá nhiều hơn", + "recently_viewed": "Đã xem gần đây", + "clear": "Thông thoáng", + "language": "Ngôn ngữ", + "theme": "Chủ đề", + "dark_mode": "Chế độ tối", + "version": "Phiên bản", + "post": "Bài đăng", + "follower": "Người theo dõi", + "sign_up": "Đăng ký", + "input_id": "Nhập tài khoản của bạn", + "default": "Mặc định", + "brown": "nâu", + "pink": "Hồng", + "orange": "trái cam", + "green": "màu xanh lá", + "monday": "Thứ hai", + "tuesday": "Thứ ba", + "wednesday": "Thứ tư", + "thursday": "Thứ năm", + "friday": "Thứ sáu", + "saturday": "ngày thứ bảy", + "sunday": "chủ nhật", + "day_off": "Ngày nghỉ", + "close": "Đóng", + "pull_down_refresh": "Kéo xuống làm mới", + "refreshing": "Làm mới ...", + "refresh_completed": "Làm mới hoàn thành", + "release_to_refresh": "Phát hành để làm mới", + "release_to_load_more": "Phát hành để tải thêm", + "pull_to_load_more": "Kéo lên để tải thêm", + "explore_product": "Khám phá sản phẩm", + "view_list": "Xem danh sách" +} diff --git a/assets/locale/zh.json b/assets/locale/zh.json new file mode 100644 index 0000000..2e7581b --- /dev/null +++ b/assets/locale/zh.json @@ -0,0 +1,132 @@ +{ + "home": "家", + "wish_list": "心愿单", + "message": "留言内容", + "notification": "通知", + "account": "帐户", + "change_language": "改变语言", + "dynamic_theme": "系统电话", + "always_on": "永远在线", + "always_off": "总是关闭", + "about_us": "关于我们", + "who_we_are": "我们是谁 ?", + "what_we_do": "我们所做的 ?", + "meet_our_team": "认识我们的团队", + "category": "类别", + "search": "搜索...", + "category_not_found": "找不到类别", + "password": "密码", + "change_password": "更改密码", + "input_your_password": "输入密码", + "confirm_password": "确认密码", + "confirm_your_password": "确认你的密码", + "confirm": "确认", + "type_something": "输入一些东西...", + "location": "位置", + "apply": "应用", + "contact_us": "联系我们", + "send": "发送", + "name": "名称", + "input_name": "输入你的名字", + "email": "电子邮件", + "input_email": "输入您的电子邮件", + "information": "信息", + "input_information": "输入您的信息", + "value_not_empty": "输入不为空", + "value_not_valid_range": "输入无效范围", + "value_not_valid_email": "输入无效的电子邮件", + "value_not_valid_phone": "输入的电话无效", + "value_not_valid_password": "输入的密码无效", + "value_not_valid_id": "输入无效的ID", + "edit_profile": "编辑个人资料", + "address": "地址", + "input_address": "输入你的地址", + "website": "网站", + "input_website": "输入您的网站", + "feedback": "反馈", + "replay": "重播", + "tap_rate": "点按星星即可评分", + "title": "标题", + "input_title": "输入您的标题", + "description": "描述", + "input_feedback": "输入您的反馈", + "filter": "过滤", + "facilities": "设备", + "area": "区域", + "select_location": "选择位置", + "price_range": "价格范围", + "avg_price": "平均价格", + "business_color": "商业色彩", + "open_time": "开放时间", + "start_time": "开始时间", + "end_time": "时间结束", + "rating": "评分", + "font": "字形", + "forgot_password": "忘记密码", + "reset_password": "重设密码", + "search_location": "搜索位置", + "more": "更多", + "popular_location": "热门地点", + "let_find_interesting": "让我们找出最有趣的事情", + "recent_location": "最近位置", + "what_happen": "那会发生什么", + "shopping": "购物", + "shopping_intro": "最喜欢的品牌和最热门的趋势。", + "payment": "付款", + "payment_intro": "您的战略在线业务合作伙伴。", + "location_intro": "位置,社区,优质生活。它从这里开始!", + "lasted_post": "持续发布", + "oldest_post": "最旧的帖子", + "most_view": "大多数观看", + "review_rating": "评价等级", + "delete": "删除", + "image": "图片", + "phone": "电话", + "date_established": "成立日期", + "featured": "精选", + "nearly": "几乎", + "related": "有关", + "profile": "轮廓", + "sign_in": "登入", + "sign_out": "登出", + "setting": "设置", + "review": "评论", + "write": "写", + "out_of": "在......之外", + "loading": "载入中...", + "search_title": "搜索", + "search_history": "搜索历史记录", + "discover_more": "发现更多", + "recently_viewed": "最近浏览过的", + "clear": "明确", + "language": "语言", + "theme": "主题", + "dark_mode": "暗模式", + "version": "版", + "post": "发布", + "follower": "追随者", + "sign_up": "注册", + "input_id": "输入您的帐号", + "default": "默认", + "brown": "棕色", + "pink": "粉", + "orange": "橙子", + "green": "绿色", + "monday": "星期一", + "tuesday": "星期二", + "wednesday": "星期三", + "thursday": "星期四", + "friday": "星期五", + "saturday": "星期六", + "sunday": "星期日", + "day_off": "休假", + "close": "关", + "pull_down_refresh": "下拉刷新", + "refreshing": "正在刷新...", + "refresh_completed": "刷新完成", + "release_to_refresh": "释放刷新", + "release_to_load_more": "释放以加载更多", + "pull_to_load_more": "拉起以加载更多", + "explore_product": "探索产品", + "view_list": "查看清单" +} diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..6b4c0f7 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..e8efba1 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..399e934 --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..1e8c3c9 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..b5d1b7f --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,34 @@ +PODS: + - Flutter (1.0.0) + - image_picker (0.0.1): + - Flutter + - shared_preferences (0.0.1): + - Flutter + - url_launcher (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - image_picker (from `.symlinks/plugins/image_picker/ios`) + - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + image_picker: + :path: ".symlinks/plugins/image_picker/ios" + shared_preferences: + :path: ".symlinks/plugins/shared_preferences/ios" + url_launcher: + :path: ".symlinks/plugins/url_launcher/ios" + +SPEC CHECKSUMS: + Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c + image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09 + shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d + url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.10.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fa95b1f --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,595 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 923E169924431AA200D35845 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 923E169824431AA200D35845 /* GoogleService-Info.plist */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + CBEB752E65FC6CB6D6A71AD6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B60CB223184C5ED24B84A49 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 263764E540538D053E7E47F3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7EBF5206239B9AEC00FA3132 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 8B60CB223184C5ED24B84A49 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 923E169824431AA200D35845 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D3F9A3F4084D93F1D35D44BD /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + DB8F105C2156385117CE16BE /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CBEB752E65FC6CB6D6A71AD6 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 419E50F7F167742DA13D404A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8B60CB223184C5ED24B84A49 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + D47ECCD636798EBF7154A1EA /* Pods */, + 419E50F7F167742DA13D404A /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 7EBF5206239B9AEC00FA3132 /* Runner.entitlements */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + 923E169824431AA200D35845 /* GoogleService-Info.plist */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D47ECCD636798EBF7154A1EA /* Pods */ = { + isa = PBXGroup; + children = ( + 263764E540538D053E7E47F3 /* Pods-Runner.debug.xcconfig */, + DB8F105C2156385117CE16BE /* Pods-Runner.release.xcconfig */, + D3F9A3F4084D93F1D35D44BD /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + CD483E5625382251E9C790C3 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 389916D673969572A174367F /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1240; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = 3C2ZJ87Z72; + LastSwiftMigration = 0910; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + 923E169924431AA200D35845 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 389916D673969572A174367F /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + CD483E5625382251E9C790C3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = 2; + DEVELOPMENT_TEAM = 3C2ZJ87Z72; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + MARKETING_VERSION = 1.0.3; + PRODUCT_BUNDLE_IDENTIFIER = com.huynh.listarFlutter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = 2; + DEVELOPMENT_TEAM = 3C2ZJ87Z72; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + MARKETING_VERSION = 1.0.3; + PRODUCT_BUNDLE_IDENTIFIER = com.huynh.listarFlutter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = 2; + DEVELOPMENT_TEAM = 3C2ZJ87Z72; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + MARKETING_VERSION = 1.0.3; + PRODUCT_BUNDLE_IDENTIFIER = com.huynh.listarFlutter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..46d2d0d --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..cea67b1 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,20 @@ +import UIKit +import Flutter +// import Firebase +// import GoogleMaps + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + // FirebaseApp.configure() //Firebase + // GMSServices.provideAPIKey("AIzaSyBRB5_8rkANX4dYFkqQ8hIDE60ELN4TCt8") //Google API key + if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate + } //Request permistion notification + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000..c88f9d7 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000..c2f6659 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000..31f4f25 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000..cb0f385 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png new file mode 100644 index 0000000..1249890 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000..f5bce2f Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000..f84b9a6 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 0000000..c1c9d38 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png new file mode 100644 index 0000000..1bfefe4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000..6c50f80 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000..f4a0f99 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png new file mode 100644 index 0000000..4c6a3b5 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png new file mode 100644 index 0000000..719fb6d Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000..1055500 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000..87f8e1b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png new file mode 100644 index 0000000..7864b07 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png new file mode 100644 index 0000000..bdb7bc1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 0000000..848c760 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000..796ee1b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..65b74d7 --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1 @@ +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/icon.imageset/icon.png b/ios/Runner/Assets.xcassets/icon.imageset/icon.png new file mode 100644 index 0000000..5b1b72b Binary files /dev/null and b/ios/Runner/Assets.xcassets/icon.imageset/icon.png differ diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..0c9fe7f --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..15b7426 --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 254789615258-qbpjmknq1u9473imrnnh2chlbcs6i2b1.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.254789615258-qbpjmknq1u9473imrnnh2chlbcs6i2b1 + API_KEY + AIzaSyC-hfYmzFW_hF2JMYF1tOkYHfcwE2xyJwY + GCM_SENDER_ID + 254789615258 + PLIST_VERSION + 1 + BUNDLE_ID + com.huynh.listarFlutter + PROJECT_ID + listarflutter + STORAGE_BUCKET + listarflutter.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:254789615258:ios:6a158b7c95902906f8a923 + DATABASE_URL + https://listarflutter.firebaseio.com + + \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..9454169 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Safer + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + FirebaseAppDelegateProxyEnabled + + LSRequiresIPhoneOS + + NSCameraUsageDescription + Would like to access your camera roll to upload your photo. + NSLocationAlwaysUsageDescription + We need access to your location to show you relevant place result. + NSLocationWhenInUseUsageDescription + We need access to your location to show you relevant place result. + NSMicrophoneUsageDescription + Would like to access your microphone to upload your video. + NSPhotoLibraryUsageDescription + Would like to access your photo to upload photo. + UIBackgroundModes + + fetch + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + io.flutter.embedded_views_preview + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..7335fdf --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..903def2 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/lib/api/api.dart b/lib/api/api.dart new file mode 100644 index 0000000..0b88105 --- /dev/null +++ b/lib/api/api.dart @@ -0,0 +1,29 @@ +import 'dart:async'; + +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class Api { + ///Get Home + static Future getHome() async { + await Future.delayed(Duration(seconds: 1)); + final result = await UtilAsset.loadJson("assets/data/home.json"); + return ResultApiModel.fromJson(result); + } + + ///Get Location List + static Future getLocationList() async { + await Future.delayed(Duration(seconds: 1)); + final result = await UtilAsset.loadJson("assets/data/location.json"); + return ResultApiModel.fromJson(result); + } + + ///Singleton factory + static final Api _instance = Api._internal(); + + factory Api() { + return _instance; + } + + Api._internal(); +} diff --git a/lib/app.dart b/lib/app.dart new file mode 100644 index 0000000..3ba0d2a --- /dev/null +++ b/lib/app.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:listar_flutter/blocs/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/main_navigation.dart'; +import 'package:listar_flutter/screens/screen.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class App extends StatefulWidget { + @override + _AppState createState() => _AppState(); +} + +class _AppState extends State { + final Routes route = Routes(); + + ApplicationBloc _applicationBloc; + LanguageBloc _languageBloc; + ThemeBloc _themeBloc; + + @override + void initState() { + ///Bloc business logic + _languageBloc = LanguageBloc(); + _themeBloc = ThemeBloc(); + _applicationBloc = ApplicationBloc( + themeBloc: _themeBloc, + languageBloc: _languageBloc, + ); + super.initState(); + } + + @override + void dispose() { + _applicationBloc.close(); + _languageBloc.close(); + _themeBloc.close(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => _applicationBloc, + ), + BlocProvider( + create: (context) => _languageBloc, + ), + BlocProvider( + create: (context) => _themeBloc, + ), + ], + child: BlocBuilder( + builder: (context, lang) { + return BlocBuilder( + builder: (context, theme) { + return MaterialApp( + debugShowCheckedModeBanner: false, + theme: AppTheme.lightTheme, + darkTheme: AppTheme.darkTheme, + onGenerateRoute: route.generateRoute, + locale: AppLanguage.defaultLanguage, + localizationsDelegates: [ + Translate.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + supportedLocales: AppLanguage.supportLanguage, + home: BlocBuilder( + builder: (context, app) { + if (app is ApplicationSetupCompleted) { + return MainNavigation(); + } + if (app is ApplicationIntroView) { + return MainNavigation(); + } + return SplashScreen(); + }, + ), + ); + }, + ); + }, + ), + ); + } +} diff --git a/lib/app_locale_delegate.dart b/lib/app_locale_delegate.dart new file mode 100644 index 0000000..8ea7375 --- /dev/null +++ b/lib/app_locale_delegate.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class AppLocaleDelegate extends LocalizationsDelegate { + const AppLocaleDelegate(); + + @override + bool isSupported(Locale locale) { + return AppLanguage.supportLanguage.contains(locale); + } + + @override + Future load(Locale locale) async { + Translate localizations = Translate(locale); + await localizations.load(); + return localizations; + } + + @override + bool shouldReload(AppLocaleDelegate old) => false; +} diff --git a/lib/blocs/application/application_bloc.dart b/lib/blocs/application/application_bloc.dart new file mode 100644 index 0000000..865233c --- /dev/null +++ b/lib/blocs/application/application_bloc.dart @@ -0,0 +1,116 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:listar_flutter/blocs/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class ApplicationBloc extends Bloc { + final ThemeBloc themeBloc; + final LanguageBloc languageBloc; + + ApplicationBloc({ + @required this.themeBloc, + @required this.languageBloc, + }); + + @override + ApplicationState get initialState => InitialApplicationState(); + + @override + Stream mapEventToState(event) async* { + if (event is SetupApplication) { + ///Pending loading to UI + yield ApplicationWaiting(); + + ///Setup SharedPreferences + Application.preferences = await SharedPreferences.getInstance(); + + ///Get old Theme & Font & Language + final oldTheme = UtilPreferences.getString(Preferences.theme); + final oldFont = UtilPreferences.getString(Preferences.font); + final oldLanguage = UtilPreferences.getString(Preferences.language); + final oldDarkOption = UtilPreferences.getString(Preferences.darkOption); + + ThemeModel theme; + String font; + DarkOption darkOption; + + ///Setup Language + if (oldLanguage != null) { + languageBloc.add( + ChangeLanguage(Locale(oldLanguage)), + ); + } + + ///Find font support available + final fontAvailable = AppTheme.fontSupport.where((item) { + return item == oldFont; + }).toList(); + + ///Find theme support available + final themeAvailable = AppTheme.themeSupport.where((item) { + return item.name == oldTheme; + }).toList(); + + ///Check theme and font available + if (fontAvailable.isNotEmpty) { + font = fontAvailable[0]; + } + + if (themeAvailable.isNotEmpty) { + theme = themeAvailable[0]; + } + + ///check old dark option + + if (oldDarkOption != null) { + switch (oldDarkOption) { + case DARK_ALWAYS_OFF: + darkOption = DarkOption.alwaysOff; + break; + case DARK_ALWAYS_ON: + darkOption = DarkOption.alwaysOn; + break; + default: + darkOption = DarkOption.alwaysOff; + } + } + + ///Setup Theme & Font with dark Option + themeBloc.add( + ChangeTheme( + theme: theme ?? AppTheme.currentTheme, + font: font ?? AppTheme.currentFont, + darkOption: darkOption ?? AppTheme.darkThemeOption, + ), + ); + + ///First or After upgrade version show intro preview app + final hasReview = UtilPreferences.containsKey( + '${Preferences.reviewIntro}.${Application.version}', + ); + if (hasReview) { + ///Become app + yield ApplicationSetupCompleted(); + } else { + ///Pending preview intro + yield ApplicationIntroView(); + } + } + + ///Event Completed IntroView + if (event is OnCompletedIntro) { + await UtilPreferences.setBool( + '${Preferences.reviewIntro}.${Application.version}', + true, + ); + + ///Become app + yield ApplicationSetupCompleted(); + } + } +} diff --git a/lib/blocs/application/application_event.dart b/lib/blocs/application/application_event.dart new file mode 100644 index 0000000..eac63d5 --- /dev/null +++ b/lib/blocs/application/application_event.dart @@ -0,0 +1,10 @@ +import 'package:meta/meta.dart'; + +@immutable +abstract class ApplicationEvent {} + +///Event notification setup application +class SetupApplication extends ApplicationEvent {} + +///Event notification completed preview intro +class OnCompletedIntro extends ApplicationEvent {} diff --git a/lib/blocs/application/application_state.dart b/lib/blocs/application/application_state.dart new file mode 100644 index 0000000..42f7ca1 --- /dev/null +++ b/lib/blocs/application/application_state.dart @@ -0,0 +1,12 @@ +import 'package:meta/meta.dart'; + +@immutable +abstract class ApplicationState {} + +class InitialApplicationState extends ApplicationState {} + +class ApplicationWaiting extends ApplicationState {} + +class ApplicationSetupCompleted extends ApplicationState {} + +class ApplicationIntroView extends ApplicationState {} diff --git a/lib/blocs/application/bloc.dart b/lib/blocs/application/bloc.dart new file mode 100644 index 0000000..d5ac72b --- /dev/null +++ b/lib/blocs/application/bloc.dart @@ -0,0 +1,3 @@ +export 'application_bloc.dart'; +export 'application_event.dart'; +export 'application_state.dart'; diff --git a/lib/blocs/bloc.dart b/lib/blocs/bloc.dart new file mode 100644 index 0000000..33a3148 --- /dev/null +++ b/lib/blocs/bloc.dart @@ -0,0 +1,3 @@ +export 'application/bloc.dart'; +export 'language/bloc.dart'; +export 'theme/bloc.dart'; diff --git a/lib/blocs/language/bloc.dart b/lib/blocs/language/bloc.dart new file mode 100644 index 0000000..5456908 --- /dev/null +++ b/lib/blocs/language/bloc.dart @@ -0,0 +1,3 @@ +export 'language_bloc.dart'; +export 'language_event.dart'; +export 'language_state.dart'; diff --git a/lib/blocs/language/language_bloc.dart b/lib/blocs/language/language_bloc.dart new file mode 100644 index 0000000..fcfcd23 --- /dev/null +++ b/lib/blocs/language/language_bloc.dart @@ -0,0 +1,31 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:listar_flutter/blocs/language/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class LanguageBloc extends Bloc { + @override + LanguageState get initialState => InitialLanguageState(); + + @override + Stream mapEventToState(event) async* { + if (event is ChangeLanguage) { + if (event.locale == AppLanguage.defaultLanguage) { + yield LanguageUpdated(); + } else { + yield LanguageUpdating(); + AppLanguage.defaultLanguage = event.locale; + + ///Preference save + UtilPreferences.setString( + Preferences.language, + event.locale.languageCode, + ); + + yield LanguageUpdated(); + } + } + } +} diff --git a/lib/blocs/language/language_event.dart b/lib/blocs/language/language_event.dart new file mode 100644 index 0000000..5266289 --- /dev/null +++ b/lib/blocs/language/language_event.dart @@ -0,0 +1,9 @@ +import 'package:flutter/cupertino.dart'; + +abstract class LanguageEvent {} + +class ChangeLanguage extends LanguageEvent { + final Locale locale; + + ChangeLanguage(this.locale); +} diff --git a/lib/blocs/language/language_state.dart b/lib/blocs/language/language_state.dart new file mode 100644 index 0000000..d82db62 --- /dev/null +++ b/lib/blocs/language/language_state.dart @@ -0,0 +1,7 @@ +abstract class LanguageState {} + +class InitialLanguageState extends LanguageState {} + +class LanguageUpdating extends LanguageState {} + +class LanguageUpdated extends LanguageState {} diff --git a/lib/blocs/theme/bloc.dart b/lib/blocs/theme/bloc.dart new file mode 100644 index 0000000..766b199 --- /dev/null +++ b/lib/blocs/theme/bloc.dart @@ -0,0 +1,3 @@ +export 'theme_bloc.dart'; +export 'theme_event.dart'; +export 'theme_state.dart'; diff --git a/lib/blocs/theme/theme_bloc.dart b/lib/blocs/theme/theme_bloc.dart new file mode 100644 index 0000000..94ab1cc --- /dev/null +++ b/lib/blocs/theme/theme_bloc.dart @@ -0,0 +1,98 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:listar_flutter/blocs/theme/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +const DARK_DYNAMIC = 'dynamic'; +const DARK_ALWAYS_OFF = 'off'; +const DARK_ALWAYS_ON = 'on'; + +class ThemeBloc extends Bloc { + @override + ThemeState get initialState => InitialThemeState(); + + @override + Stream mapEventToState(event) async* { + ///Update theme style and font + if (event is ChangeTheme) { + yield ThemeUpdating(); + + AppTheme.currentTheme = event.theme ?? AppTheme.currentTheme; + AppTheme.currentFont = event.font ?? AppTheme.currentFont; + AppTheme.darkThemeOption = event.darkOption ?? AppTheme.darkThemeOption; + + ///Setup Theme with setting darkOption + switch (AppTheme.darkThemeOption) { + case DarkOption.dynamic: + AppTheme.lightTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.lightTheme, + font: AppTheme.currentFont, + ); + AppTheme.darkTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.darkTheme, + font: AppTheme.currentFont, + ); + break; + case DarkOption.alwaysOn: + AppTheme.lightTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.darkTheme, + font: AppTheme.currentFont, + ); + AppTheme.darkTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.darkTheme, + font: AppTheme.currentFont, + ); + break; + case DarkOption.alwaysOff: + AppTheme.lightTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.lightTheme, + font: AppTheme.currentFont, + ); + AppTheme.darkTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.lightTheme, + font: AppTheme.currentFont, + ); + break; + default: + AppTheme.lightTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.lightTheme, + font: AppTheme.currentFont, + ); + AppTheme.darkTheme = CollectionTheme.getCollectionTheme( + theme: AppTheme.currentTheme.darkTheme, + font: AppTheme.currentFont, + ); + break; + } + + ///Preference save + UtilPreferences.setString(Preferences.location, AppTheme.currentLocation); + + ///Preference save + UtilPreferences.setString(Preferences.theme, AppTheme.currentTheme.name); + + ///Preference save + UtilPreferences.setString(Preferences.font, AppTheme.currentFont); + + ///Preference save + switch (AppTheme.darkThemeOption) { + case DarkOption.dynamic: + UtilPreferences.setString(Preferences.darkOption, DARK_DYNAMIC); + break; + case DarkOption.alwaysOn: + UtilPreferences.setString(Preferences.darkOption, DARK_ALWAYS_ON); + break; + case DarkOption.alwaysOff: + UtilPreferences.setString(Preferences.darkOption, DARK_ALWAYS_OFF); + break; + default: + break; + } + + ///Notification UI + yield ThemeUpdated(); + } + } +} diff --git a/lib/blocs/theme/theme_event.dart b/lib/blocs/theme/theme_event.dart new file mode 100644 index 0000000..5d52bd5 --- /dev/null +++ b/lib/blocs/theme/theme_event.dart @@ -0,0 +1,24 @@ +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:meta/meta.dart'; + +@immutable +abstract class ThemeEvent {} + +class ChangeTheme extends ThemeEvent { + final ThemeModel theme; + final String font; + final DarkOption darkOption; + + ChangeTheme({ + this.theme, + this.font, + this.darkOption, + }); +} + +class ChangeDarkOption extends ThemeEvent { + final DarkOption darkOption; + + ChangeDarkOption({this.darkOption}); +} diff --git a/lib/blocs/theme/theme_state.dart b/lib/blocs/theme/theme_state.dart new file mode 100644 index 0000000..aa75411 --- /dev/null +++ b/lib/blocs/theme/theme_state.dart @@ -0,0 +1,10 @@ +import 'package:meta/meta.dart'; + +@immutable +abstract class ThemeState {} + +class InitialThemeState extends ThemeState {} + +class ThemeUpdating extends ThemeState {} + +class ThemeUpdated extends ThemeState {} diff --git a/lib/configs/application.dart b/lib/configs/application.dart new file mode 100644 index 0000000..19117a9 --- /dev/null +++ b/lib/configs/application.dart @@ -0,0 +1,19 @@ +import 'package:listar_flutter/models/model.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class Application { + static bool debug = false; + static String version = '1.0.0'; + static SharedPreferences preferences; + static UserModel user; + static String pushToken; + + ///Singleton factory + static final Application _instance = Application._internal(); + + factory Application() { + return _instance; + } + + Application._internal(); +} diff --git a/lib/configs/config.dart b/lib/configs/config.dart new file mode 100644 index 0000000..f44aa5a --- /dev/null +++ b/lib/configs/config.dart @@ -0,0 +1,8 @@ +export 'application.dart'; +export 'image.dart'; +export 'language.dart'; +export 'preferences.dart'; +export 'routes.dart'; +export 'sort.dart'; +export 'theme.dart'; +export 'theme_collection.dart'; diff --git a/lib/configs/image.dart b/lib/configs/image.dart new file mode 100644 index 0000000..c7effea --- /dev/null +++ b/lib/configs/image.dart @@ -0,0 +1,73 @@ +class Images { + static const String Intro1 = "assets/images/intro_1.png"; + static const String Intro2 = "assets/images/intro_2.png"; + static const String Intro3 = "assets/images/intro_3.png"; + static const String Logo = "assets/images/logo.png"; + static const String Slide = "assets/images/slide.png"; + static const String Avatar1 = "assets/images/avata-01.jpeg"; + static const String Avatar2 = "assets/images/avata-02.jpeg"; + static const String Avatar3 = "assets/images/avata-03.jpeg"; + static const String Avatar4 = "assets/images/avata-04.png"; + static const String Profile1 = "assets/images/profile-1.jpg"; + static const String Profile2 = "assets/images/profile-2.jpg"; + static const String Profile3 = "assets/images/profile-3.jpg"; + static const String Profile4 = "assets/images/profile-4.jpg"; + static const String Profile5 = "assets/images/profile-5.jpg"; + static const String Profile6 = "assets/images/profile-6.jpg"; + static const String Profile7 = "assets/images/profile-7.jpg"; + static const String Profile8 = "assets/images/profile-8.jpg"; + static const String Trip1 = "assets/images/trip-1.jpg"; + static const String Trip2 = "assets/images/trip-2.jpg"; + static const String Trip3 = "assets/images/trip-3.jpg"; + static const String Trip4 = "assets/images/trip-4.jpg"; + static const String Trip5 = "assets/images/trip-5.jpg"; + static const String Trip6 = "assets/images/trip-6.jpg"; + static const String Trip7 = "assets/images/trip-7.jpg"; + static const String Trip8 = "assets/images/trip-8.jpg"; + static const String Trip9 = "assets/images/trip-9.jpg"; + static const String Room1 = "assets/images/room-1.jpg"; + static const String Room2 = "assets/images/room-2.jpg"; + static const String Room3 = "assets/images/room-3.jpg"; + static const String Room4 = "assets/images/room-4.jpg"; + static const String Room5 = "assets/images/room-5.jpg"; + static const String Room6 = "assets/images/room-6.jpg"; + static const String Room7 = "assets/images/room-7.jpg"; + static const String Room8 = "assets/images/room-8.jpg"; + static const String Room9 = "assets/images/room-9.jpg"; + static const String Room10 = "assets/images/room-10.jpg"; + static const String Room11 = "assets/images/room-11.jpg"; + static const String Banner1 = "assets/images/banner-1.jpg"; + static const String Banner2 = "assets/images/banner-2.jpg"; + static const String Banner3 = "assets/images/banner-3.jpg"; + static const String Category1 = "assets/images/category-1.jpg"; + static const String Category2 = "assets/images/category-2.jpg"; + static const String Category3 = "assets/images/category-3.jpg"; + static const String Category4 = "assets/images/category-4.jpg"; + static const String Gallery1 = "assets/images/gallery-1.jpg"; + static const String Gallery2 = "assets/images/gallery-2.jpg"; + static const String Location1 = "assets/images/location-1.jpg"; + static const String Location2 = "assets/images/location-2.jpg"; + static const String Location3 = "assets/images/location-3.jpg"; + static const String Location4 = "assets/images/location-4.jpg"; + static const String Location5 = "assets/images/location-5.jpg"; + static const String Location6 = "assets/images/location-6.jpg"; + static const String Location7 = "assets/images/location-7.jpg"; + static const String Place1 = "assets/images/place-1.jpg"; + static const String Place2 = "assets/images/place-2.jpg"; + static const String Service1 = "assets/images/service-shopping.jpg"; + static const String Service2 = "assets/images/service-automotive.jpg"; + static const String Service3 = "assets/images/service-coffee.jpg"; + static const String Service4 = "assets/images/service-event.jpg"; + static const String Service5 = "assets/images/service-housing.jpg"; + static const String Service6 = "assets/images/service-job.jpg"; + static const String Service7 = "assets/images/service-restaurant.jpg"; + + ///Singleton factory + static final Images _instance = Images._internal(); + + factory Images() { + return _instance; + } + + Images._internal(); +} diff --git a/lib/configs/language.dart b/lib/configs/language.dart new file mode 100644 index 0000000..744d9b8 --- /dev/null +++ b/lib/configs/language.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class AppLanguage { + ///Default Language + static Locale defaultLanguage = Locale("en"); + + ///List Language support in Application + static List supportLanguage = [ + Locale("en"), + Locale("vi"), + ]; + + ///Singleton factory + static final AppLanguage _instance = AppLanguage._internal(); + + factory AppLanguage() { + return _instance; + } + + AppLanguage._internal(); +} diff --git a/lib/configs/preferences.dart b/lib/configs/preferences.dart new file mode 100644 index 0000000..0e308eb --- /dev/null +++ b/lib/configs/preferences.dart @@ -0,0 +1,19 @@ +class Preferences { + static String reviewIntro = 'review'; + static String user = 'user'; + static String language = 'language'; + static String notification = 'notification'; + static String theme = 'theme'; + static String darkOption = 'darkOption'; + static String font = 'font'; + static String location = 'location'; + + ///Singleton factory + static final Preferences _instance = Preferences._internal(); + + factory Preferences() { + return _instance; + } + + Preferences._internal(); +} diff --git a/lib/configs/routes.dart b/lib/configs/routes.dart new file mode 100644 index 0000000..ff34dba --- /dev/null +++ b/lib/configs/routes.dart @@ -0,0 +1,172 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:listar_flutter/screens/choose_location/choose_location.dart'; +import 'package:listar_flutter/screens/safer_main_menu/storm_tracking.dart'; +import 'package:listar_flutter/screens/screen.dart'; +import 'package:listar_flutter/screens/terms_of_use/terms_of_use.dart'; + +class Routes { + static const String signIn = "/signIn"; + static const String signUp = "/signUp"; + static const String forgotPassword = "/forgotPassword"; + static const String productDetail = "/productDetail"; + static const String productDetailTab = "ProductDetailTab"; + static const String searchHistory = "/searchHistory"; + static const String category = "/category"; + static const String editProfile = "/editProfile"; + static const String changePassword = "/changePassword"; + static const String changeLanguage = "/changeLanguage"; + static const String contactUs = "/contactUs"; + static const String chat = "/chat"; + static const String aboutUs = "/aboutUs"; + static const String gallery = "/gallery"; + static const String photoPreview = "/photoPreview"; + static const String themeSetting = "/themeSetting"; + static const String listProduct = "/listProduct"; + static const String filter = "/filter"; + static const String review = "/review"; + static const String writeReview = "/writeReview"; + static const String location = "/location"; + static const String setting = "/setting"; + static const String fontSetting = "/fontSetting"; + static const String chooseLocation = "/chooseLocation"; + + static const String stormTracking = "/stormTracking"; + static const String personalSafety = "/personalSafety"; + static const String personalRisk = "/personalRisk"; + static const String propertySafety = "/propertySafety"; + static const String propertyRisk = "/propertyRisk"; + static const String supplies = "/supplies"; + static const String evacuation = "/evacuation"; + static const String stayInTouch = "/stayInTouch"; + + static const String termsOfUse = "/termsOfUse"; + + Route generateRoute(RouteSettings settings) { + switch (settings.name) { + case termsOfUse: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return TermsOfUse(title: category); + }, + ); + + case chooseLocation: + final location = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return ChooseLocation(location: location); + }, + ); + + case stormTracking: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return StormTracking(title: category); + }, + ); + + case personalSafety: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return PersonalSafety(title: category); + }, + ); + + case personalRisk: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return PersonalRisk(title: category); + }, + ); + + case propertySafety: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return PropertySafety(title: category); + }, + ); + + case propertyRisk: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return PropertyRisk(title: category); + }, + ); + + case supplies: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return Supplies(title: category); + }, + ); + + case evacuation: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return Evacuation(title: category); + }, + ); + + case stayInTouch: + final category = settings.arguments; + return MaterialPageRoute( + builder: (context) { + return StayInTouch(title: category); + }, + ); + + case changeLanguage: + return MaterialPageRoute( + builder: (context) { + return LanguageSetting(); + }, + ); + + case themeSetting: + return MaterialPageRoute( + builder: (context) { + return ThemeSetting(); + }, + ); + + case fontSetting: + return MaterialPageRoute( + builder: (context) { + return FontSetting(); + }, + ); + + default: + return MaterialPageRoute( + builder: (context) { + return Scaffold( + appBar: AppBar( + title: Text("Not Found"), + ), + body: Center( + child: Text('No path for ${settings.name}'), + ), + ); + }, + ); + } + } + + ///Singleton factory + static final Routes _instance = Routes._internal(); + + factory Routes() { + return _instance; + } + + Routes._internal(); +} diff --git a/lib/configs/sort.dart b/lib/configs/sort.dart new file mode 100644 index 0000000..b442216 --- /dev/null +++ b/lib/configs/sort.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; + +class AppSort { + ///Default Sort + static SortModel defaultSort = SortModel.fromJson( + { + "code": "lasted", + "name": "lasted_post", + "icon": Icons.swap_vert, + }, + ); + + ///List Sort support in Application + static List listSortDefault = [ + { + "code": "lasted", + "name": "lasted_post", + "icon": Icons.swap_vert, + }, + { + "code": "oldest", + "name": "oldest_post", + "icon": Icons.swap_vert, + }, + { + "code": "most_view", + "name": "most_view", + "icon": Icons.swap_vert, + }, + { + "code": "rating", + "name": "review_rating", + "icon": Icons.swap_vert, + }, + ].map((item) => SortModel.fromJson(item)).toList(); + + ///Singleton factory + static final AppSort _instance = AppSort._internal(); + + factory AppSort() { + return _instance; + } + + AppSort._internal(); +} diff --git a/lib/configs/theme.dart b/lib/configs/theme.dart new file mode 100644 index 0000000..a313614 --- /dev/null +++ b/lib/configs/theme.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; + +enum DarkOption { dynamic, alwaysOn, alwaysOff } + +class AppTheme { + ///Optional Color + static Color blueColor = Color.fromRGBO(93, 173, 226, 1); + static Color pinkColor = Color.fromRGBO(165, 105, 189, 1); + static Color greenColor = Color.fromRGBO(88, 214, 141, 1); + static Color yellowColor = Color.fromRGBO(253, 198, 10, 1); + static Color kashmirColor = Color.fromRGBO(93, 109, 126, 1); + + ///Default location + static String currentLocation = "Bridgeport"; + + ///Default font + static String currentFont = "Raleway"; + + ///List Font support + static List fontSupport = ["Raleway", "Roboto", "Merriweather"]; + + ///Default Theme + static ThemeModel currentTheme = ThemeModel.fromJson({ + "name": "default", + "color": Color(0xffe5634d), + "light": "primaryLight", + "dark": "primaryDark", + }); + + ///List Theme Support in Application + static List themeSupport = [ + { + "name": "default", + "color": Color(0xffe5634d), + "light": "primaryLight", + "dark": "primaryDark", + }, + { + "name": "brown", + "color": Color(0xffa0877e), + "light": "brownLight", + "dark": "brownDark", + }, + { + "name": "pink", + "color": Color(0xffe0a6c1), + "light": "pinkLight", + "dark": "pinkDark", + }, + { + "name": "orange", + "color": Color(0xfff6bb41), + "light": "pastelOrangeLight", + "dark": "pastelOrangeDark", + }, + { + "name": "green", + "color": Color(0xff93b7b0), + "light": "greenLight", + "dark": "greenDark", + }, + ].map((item) => ThemeModel.fromJson(item)).toList(); + + ///Dark Theme option + static DarkOption darkThemeOption = DarkOption.dynamic; + + static ThemeData lightTheme = CollectionTheme.getCollectionTheme( + theme: currentTheme.lightTheme, + ); + + static ThemeData darkTheme = CollectionTheme.getCollectionTheme( + theme: currentTheme.darkTheme, + ); + + ///Singleton factory + static final AppTheme _instance = AppTheme._internal(); + + factory AppTheme() { + return _instance; + } + + AppTheme._internal(); +} diff --git a/lib/configs/theme_collection.dart b/lib/configs/theme_collection.dart new file mode 100644 index 0000000..c83f0cf --- /dev/null +++ b/lib/configs/theme_collection.dart @@ -0,0 +1,1378 @@ +import 'package:flutter/material.dart'; + +class CollectionTheme { + ///Get collection theme + /// + /// primaryLight/primaryDark/brownLight/brownDark/pinkLight/pinkDark + static ThemeData getCollectionTheme( + {String theme = "primaryLight", String font = "Raleway"}) { + switch (theme) { + case "primaryLight": + return ThemeData( + primarySwatch: MaterialColor(4293223245, { + 50: Color(0xfffcebe9), + 100: Color(0xfff9d8d3), + 200: Color(0xfff2b1a6), + 300: Color(0xffec8a79), + 400: Color(0xffe5634d), + 500: Color(0xffdf3c20), + 600: Color(0xffb2301a), + 700: Color(0xff862413), + 800: Color(0xff59180d), + 900: Color(0xff2d0c06) + }), + fontFamily: font, + brightness: Brightness.light, + primaryColor: Color(0xffe5634d), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xffFF8A65), + primaryColorDark: Color(0xff862413), + accentColor: Color(0xff4A90A4), + accentColorBrightness: Brightness.dark, + canvasColor: Color(0xfffafafa), + scaffoldBackgroundColor: Color(0xfffafafa), + bottomAppBarColor: Color(0xffffffff), + cardColor: Color(0xffffffff), + dividerColor: Color(0x1f000000), + highlightColor: Color(0x66bcbcbc), + splashColor: Color(0x66c8c8c8), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0x8a000000), + disabledColor: Color(0x61000000), + buttonColor: Color(0xffe5634d), + toggleableActiveColor: Color(0xff4A90A4), + secondaryHeaderColor: Color(0xfffcebe9), + textSelectionColor: Color(0xff4A90A4), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xff4A90A4), + backgroundColor: Color(0xfff2b1a6), + dialogBackgroundColor: Color(0xffffffff), + indicatorColor: Color(0xff4A90A4), + hintColor: Color(0x8a000000), + errorColor: Color(0xffd32f2f), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + buttonColor: Color(0xffe5634d), + disabledColor: Color(0x61000000), + highlightColor: Color(0x29000000), + splashColor: Color(0x1f000000), + focusColor: Color(0x1f000000), + hoverColor: Color(0x0a000000), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1f000000), + brightness: Brightness.light, + deleteIconColor: Color(0xffdf3c20), + disabledColor: Color(0x0c000000), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.all(4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3de5634d), + selectedColor: Color(0x3de5634d), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "primaryDark": + return ThemeData( + primarySwatch: MaterialColor(4280361249, { + 50: Color(0xfff2f2f2), + 100: Color(0xffe6e6e6), + 200: Color(0xffcccccc), + 300: Color(0xffb3b3b3), + 400: Color(0xff999999), + 500: Color(0xff808080), + 600: Color(0xff666666), + 700: Color(0xff4d4d4d), + 800: Color(0xff333333), + 900: Color(0xff191919) + }), + fontFamily: font, + brightness: Brightness.dark, + primaryColor: Color(0xffe5634d), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xffFF8A65), + primaryColorDark: Color(0xff000000), + accentColor: Color(0xff4A90A4), + accentColorBrightness: Brightness.light, + canvasColor: Colors.grey[900], + scaffoldBackgroundColor: Color(0xff303030), + bottomAppBarColor: Color(0xff424242), + cardColor: Color(0xff424242), + dividerColor: Color(0x1fffffff), + highlightColor: Color(0x40cccccc), + splashColor: Color(0x40cccccc), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0xb3ffffff), + disabledColor: Color(0x62ffffff), + buttonColor: Color(0xffe5634d), + toggleableActiveColor: Color(0xff4A90A4), + secondaryHeaderColor: Color(0xff616161), + textSelectionColor: Color(0xff4A90A4), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xff4A90A4), + backgroundColor: Color(0xff616161), + dialogBackgroundColor: Color(0xff424242), + indicatorColor: Color(0xff4A90A4), + hintColor: Color(0x80ffffff), + errorColor: Color(0xffd32f2f), + appBarTheme: AppBarTheme( + brightness: Brightness.dark, + color: Colors.grey[900], + ), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + buttonColor: Color(0xffe5634d), + disabledColor: Color(0x61ffffff), + highlightColor: Color(0x29ffffff), + splashColor: Color(0x1fffffff), + focusColor: Color(0x1fffffff), + hoverColor: Color(0x0affffff), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1fffffff), + brightness: Brightness.dark, + deleteIconColor: Color(0xdeffffff), + disabledColor: Color(0x0cffffff), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0xb3ffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.all(4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0xb3ffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3d212121), + selectedColor: Color(0x3dffffff), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + sliderTheme: SliderThemeData.fromPrimaryColors( + primaryColor: Color(0xffe5634d), + primaryColorLight: Color(0xfff9d8d3), + primaryColorDark: Color(0xff862413), + valueIndicatorTextStyle: TextStyle( + color: Color(0xffffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "brownLight": + return ThemeData( + primarySwatch: MaterialColor(4288776319, { + 50: Color(0xfff4f1f0), + 100: Color(0xffe9e4e2), + 200: Color(0xffd4c8c4), + 300: Color(0xffbeada7), + 400: Color(0xffa99289), + 500: Color(0xff93766c), + 600: Color(0xff765f56), + 700: Color(0xff584741), + 800: Color(0xff3b2f2b), + 900: Color(0xff1d1816) + }), + fontFamily: font, + brightness: Brightness.light, + primaryColor: Color(0xffa1887f), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xffe9e4e2), + primaryColorDark: Color(0xff584741), + accentColor: Color(0xff93766c), + accentColorBrightness: Brightness.dark, + canvasColor: Color(0xfffafafa), + scaffoldBackgroundColor: Color(0xfffafafa), + bottomAppBarColor: Color(0xffffffff), + cardColor: Color(0xffffffff), + dividerColor: Color(0x1f000000), + highlightColor: Color(0x66bcbcbc), + splashColor: Color(0x66c8c8c8), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0x8a000000), + disabledColor: Color(0x61000000), + buttonColor: Color(0xffa1887f), + toggleableActiveColor: Color(0xff765f56), + secondaryHeaderColor: Color(0xfff4f1f0), + textSelectionColor: Color(0xffd4c8c4), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xffbeada7), + backgroundColor: Color(0xffd4c8c4), + dialogBackgroundColor: Color(0xffffffff), + indicatorColor: Color(0xff93766c), + hintColor: Color(0x8a000000), + errorColor: Color(0xffd32f2f), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + buttonColor: Color(0xffa1887f), + disabledColor: Color(0x61000000), + highlightColor: Color(0x29000000), + splashColor: Color(0x1f000000), + focusColor: Color(0x1f000000), + hoverColor: Color(0x0a000000), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1f000000), + brightness: Brightness.light, + deleteIconColor: Color(0xff93766c), + disabledColor: Color(0x0c000000), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.all(4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3da1887f), + selectedColor: Color(0x3da1887f), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "brownDark": + return ThemeData( + primarySwatch: MaterialColor(4280361249, { + 50: Color(0xfff2f2f2), + 100: Color(0xffe6e6e6), + 200: Color(0xffcccccc), + 300: Color(0xffb3b3b3), + 400: Color(0xff999999), + 500: Color(0xff808080), + 600: Color(0xff666666), + 700: Color(0xff4d4d4d), + 800: Color(0xff333333), + 900: Color(0xff191919) + }), + fontFamily: font, + brightness: Brightness.dark, + primaryColor: Color(0xffa1887f), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xff9e9e9e), + primaryColorDark: Color(0xff000000), + accentColor: Color(0xff93766c), + accentColorBrightness: Brightness.light, + canvasColor: Colors.grey[900], + scaffoldBackgroundColor: Color(0xff303030), + bottomAppBarColor: Color(0xff424242), + cardColor: Color(0xff424242), + dividerColor: Color(0x1fffffff), + highlightColor: Color(0x40cccccc), + splashColor: Color(0x40cccccc), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0xb3ffffff), + disabledColor: Color(0x62ffffff), + buttonColor: Color(0xffa1887f), + toggleableActiveColor: Color(0xff765f56), + secondaryHeaderColor: Color(0xff616161), + textSelectionColor: Color(0xffd4c8c4), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xffbeada7), + backgroundColor: Color(0xff616161), + dialogBackgroundColor: Color(0xff424242), + indicatorColor: Color(0xff93766c), + hintColor: Color(0x80ffffff), + errorColor: Color(0xffd32f2f), + appBarTheme: AppBarTheme( + brightness: Brightness.dark, + color: Colors.grey[900], + ), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + buttonColor: Color(0xffa1887f), + disabledColor: Color(0x61ffffff), + highlightColor: Color(0x29ffffff), + splashColor: Color(0x1fffffff), + focusColor: Color(0x1fffffff), + hoverColor: Color(0x0affffff), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1fffffff), + brightness: Brightness.dark, + deleteIconColor: Color(0xdeffffff), + disabledColor: Color(0x0cffffff), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0xdeffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.all(4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0x3dffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3d212121), + selectedColor: Color(0x3dffffff), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + sliderTheme: SliderThemeData.fromPrimaryColors( + primaryColor: Color(0xffa1887f), + primaryColorLight: Color(0xffe9e4e2), + primaryColorDark: Color(0xff584741), + valueIndicatorTextStyle: TextStyle( + color: Color(0xffffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "pinkLight": + return ThemeData( + primarySwatch: MaterialColor(4292912833, { + 50: Color(0xfff8ecf2), + 100: Color(0xfff2d9e5), + 200: Color(0xffe5b3ca), + 300: Color(0xffd78eb0), + 400: Color(0xffca6896), + 500: Color(0xffbd427b), + 600: Color(0xff973563), + 700: Color(0xff71284a), + 800: Color(0xff4c1a31), + 900: Color(0xff260d19) + }), + fontFamily: font, + brightness: Brightness.light, + primaryColor: Color(0xffe0a6c1), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xfff2d9e5), + primaryColorDark: Color(0xff71284a), + accentColor: Color(0xffbd427b), + accentColorBrightness: Brightness.dark, + canvasColor: Color(0xfffafafa), + scaffoldBackgroundColor: Color(0xfffafafa), + bottomAppBarColor: Color(0xffffffff), + cardColor: Color(0xffffffff), + dividerColor: Color(0x1f000000), + highlightColor: Color(0x66bcbcbc), + splashColor: Color(0x66c8c8c8), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0x8a000000), + disabledColor: Color(0x61000000), + buttonColor: Color(0xffe0a6c1), + toggleableActiveColor: Color(0xff973563), + secondaryHeaderColor: Color(0xfff8ecf2), + textSelectionColor: Color(0xffe5b3ca), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xffd78eb0), + backgroundColor: Color(0xffe5b3ca), + dialogBackgroundColor: Color(0xffffffff), + indicatorColor: Color(0xffbd427b), + hintColor: Color(0x8a000000), + errorColor: Color(0xffd32f2f), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + buttonColor: Color(0xffe0a6c1), + disabledColor: Color(0x61000000), + highlightColor: Color(0x29000000), + splashColor: Color(0x1f000000), + focusColor: Color(0x1f000000), + hoverColor: Color(0x0a000000), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1f000000), + brightness: Brightness.light, + deleteIconColor: Color(0xffbd427b), + disabledColor: Color(0x0c000000), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.all(4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3de5634d), + selectedColor: Color(0x3de5634d), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "pinkDark": + return ThemeData( + primarySwatch: MaterialColor(4280361249, { + 50: Color(0xfff2f2f2), + 100: Color(0xffe6e6e6), + 200: Color(0xffcccccc), + 300: Color(0xffb3b3b3), + 400: Color(0xff999999), + 500: Color(0xff808080), + 600: Color(0xff666666), + 700: Color(0xff4d4d4d), + 800: Color(0xff333333), + 900: Color(0xff191919) + }), + fontFamily: font, + brightness: Brightness.dark, + primaryColor: Color(0xffe0a6c1), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xff9e9e9e), + primaryColorDark: Color(0xff000000), + accentColor: Color(0xffbd427b), + accentColorBrightness: Brightness.light, + canvasColor: Colors.grey[900], + scaffoldBackgroundColor: Color(0xff303030), + bottomAppBarColor: Color(0xff424242), + cardColor: Color(0xff424242), + dividerColor: Color(0x1fffffff), + highlightColor: Color(0x40cccccc), + splashColor: Color(0x40cccccc), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0xb3ffffff), + disabledColor: Color(0x62ffffff), + buttonColor: Color(0xffe0a6c1), + toggleableActiveColor: Color(0xffbd427b), + secondaryHeaderColor: Color(0xff616161), + textSelectionColor: Color(0xfff2b1a6), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xffec8a79), + backgroundColor: Color(0xff616161), + dialogBackgroundColor: Color(0xff424242), + indicatorColor: Color(0xffbd427b), + hintColor: Color(0x80ffffff), + errorColor: Color(0xffd32f2f), + appBarTheme: AppBarTheme( + brightness: Brightness.dark, + color: Colors.grey[900], + ), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + buttonColor: Color(0xffe0a6c1), + disabledColor: Color(0x61ffffff), + highlightColor: Color(0x29ffffff), + splashColor: Color(0x1fffffff), + focusColor: Color(0x1fffffff), + hoverColor: Color(0x0affffff), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1fffffff), + brightness: Brightness.dark, + deleteIconColor: Color(0xdeffffff), + disabledColor: Color(0x0cffffff), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0xb3ffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.all(0), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0xb3ffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3d212121), + selectedColor: Color(0x3dffffff), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + sliderTheme: SliderThemeData.fromPrimaryColors( + primaryColor: Color(0xffe0a6c1), + primaryColorLight: Color(0xfff2d9e5), + primaryColorDark: Color(0xff71284a), + valueIndicatorTextStyle: TextStyle( + color: Color(0xffffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "pastelOrangeLight": + return ThemeData( + primarySwatch: MaterialColor(4294359873, { + 50: Color(0xfffef6e7), + 100: Color(0xfffdeece), + 200: Color(0xfffadc9e), + 300: Color(0xfff8cb6d), + 400: Color(0xfff6b93c), + 500: Color(0xfff3a80c), + 600: Color(0xffc38609), + 700: Color(0xff926507), + 800: Color(0xff614305), + 900: Color(0xff312202) + }), + fontFamily: font, + brightness: Brightness.light, + primaryColor: Color(0xfff6bb41), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xfffdeece), + primaryColorDark: Color(0xff926507), + accentColor: Color(0xfff3a80c), + accentColorBrightness: Brightness.dark, + canvasColor: Color(0xfffafafa), + scaffoldBackgroundColor: Color(0xfffafafa), + bottomAppBarColor: Color(0xffffffff), + cardColor: Color(0xffffffff), + dividerColor: Color(0x1f000000), + highlightColor: Color(0x66bcbcbc), + splashColor: Color(0x66c8c8c8), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0x8a000000), + disabledColor: Color(0x61000000), + buttonColor: Color(0xfff6bb41), + toggleableActiveColor: Color(0xffc38609), + secondaryHeaderColor: Color(0xfffef6e7), + textSelectionColor: Color(0xfffadc9e), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xfff8cb6d), + backgroundColor: Color(0xfffadc9e), + dialogBackgroundColor: Color(0xffffffff), + indicatorColor: Color(0xfff3a80c), + hintColor: Color(0x8a000000), + errorColor: Color(0xffd32f2f), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + buttonColor: Color(0xfff6bb41), + disabledColor: Color(0x61000000), + highlightColor: Color(0x29000000), + splashColor: Color(0x1f000000), + focusColor: Color(0x1f000000), + hoverColor: Color(0x0a000000), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1f000000), + brightness: Brightness.light, + deleteIconColor: Color(0xfff6bb41), + disabledColor: Color(0x0c000000), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3df6bb41), + selectedColor: Color(0x3df6bb41), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "pastelOrangeDark": + return ThemeData( + primarySwatch: MaterialColor(4280361249, { + 50: Color(0xfff2f2f2), + 100: Color(0xffe6e6e6), + 200: Color(0xffcccccc), + 300: Color(0xffb3b3b3), + 400: Color(0xff999999), + 500: Color(0xff808080), + 600: Color(0xff666666), + 700: Color(0xff4d4d4d), + 800: Color(0xff333333), + 900: Color(0xff191919) + }), + fontFamily: font, + brightness: Brightness.dark, + primaryColor: Color(0xfff6bb41), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xff9e9e9e), + primaryColorDark: Color(0xff000000), + accentColor: Color(0xfff3a80c), + accentColorBrightness: Brightness.light, + canvasColor: Colors.grey[900], + scaffoldBackgroundColor: Color(0xff303030), + bottomAppBarColor: Color(0xff424242), + cardColor: Color(0xff424242), + dividerColor: Color(0x1fffffff), + highlightColor: Color(0x40cccccc), + splashColor: Color(0x40cccccc), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0xb3ffffff), + disabledColor: Color(0x62ffffff), + buttonColor: Color(0xffc38609), + toggleableActiveColor: Color(0xfff3a80c), + secondaryHeaderColor: Color(0xff616161), + textSelectionColor: Color(0xfff3a80c), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xfff3a80c), + backgroundColor: Color(0xff616161), + dialogBackgroundColor: Color(0xff424242), + indicatorColor: Color(0xfff3a80c), + hintColor: Color(0x80ffffff), + errorColor: Color(0xffd32f2f), + appBarTheme: AppBarTheme( + brightness: Brightness.dark, + color: Colors.grey[900], + ), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + buttonColor: Color(0xfff6bb41), + disabledColor: Color(0x61ffffff), + highlightColor: Color(0x29ffffff), + splashColor: Color(0x1fffffff), + focusColor: Color(0x1fffffff), + hoverColor: Color(0x0affffff), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + sliderTheme: SliderThemeData.fromPrimaryColors( + primaryColor: Color(0xfff6bb41), + primaryColorLight: Color(0xfffdeece), + primaryColorDark: Color(0xff926507), + valueIndicatorTextStyle: TextStyle( + color: Color(0xffffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1fffffff), + brightness: Brightness.dark, + deleteIconColor: Color(0xdeffffff), + disabledColor: Color(0x0cffffff), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + color: Color(0xdeffffff), + fontSize: 12, + fontFamily: font, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 4), + secondaryLabelStyle: TextStyle( + color: Color(0x3dffffff), + fontSize: 12, + fontFamily: font, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3d212121), + selectedColor: Color(0x3dffffff), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + )), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "greenLight": + return ThemeData( + primarySwatch: MaterialColor(4287870896, { + 50: Color(0xfff0f5f4), + 100: Color(0xffe0ebe9), + 200: Color(0xffc2d6d2), + 300: Color(0xffa3c2bc), + 400: Color(0xff85ada5), + 500: Color(0xff66998f), + 600: Color(0xff527a72), + 700: Color(0xff3d5c56), + 800: Color(0xff293d39), + 900: Color(0xff141f1d) + }), + fontFamily: font, + brightness: Brightness.light, + primaryColor: Color(0xff93b7b0), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xffe0ebe9), + primaryColorDark: Color(0xff3d5c56), + accentColor: Color(0xff66998f), + accentColorBrightness: Brightness.dark, + canvasColor: Color(0xfffafafa), + scaffoldBackgroundColor: Color(0xfffafafa), + bottomAppBarColor: Color(0xffffffff), + cardColor: Color(0xffffffff), + dividerColor: Color(0x1f000000), + highlightColor: Color(0x66bcbcbc), + splashColor: Color(0x66c8c8c8), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0x8a000000), + disabledColor: Color(0x61000000), + buttonColor: Color(0xff93b7b0), + toggleableActiveColor: Color(0xff527a72), + secondaryHeaderColor: Color(0xfff0f5f4), + textSelectionColor: Color(0xffc2d6d2), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xffa3c2bc), + backgroundColor: Color(0xffc2d6d2), + dialogBackgroundColor: Color(0xffffffff), + indicatorColor: Color(0xff66998f), + hintColor: Color(0x8a000000), + errorColor: Color(0xffd32f2f), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + buttonColor: Color(0xff93b7b0), + disabledColor: Color(0x61000000), + highlightColor: Color(0x29000000), + splashColor: Color(0x1f000000), + focusColor: Color(0x1f000000), + hoverColor: Color(0x0a000000), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1f000000), + brightness: Brightness.light, + deleteIconColor: Color(0xde000000), + disabledColor: Color(0x0c000000), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3d93b7b0), + selectedColor: Color(0x3d93b7b0), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + case "greenDark": + return ThemeData( + primarySwatch: MaterialColor(4280361249, { + 50: Color(0xfff2f2f2), + 100: Color(0xffe6e6e6), + 200: Color(0xffcccccc), + 300: Color(0xffb3b3b3), + 400: Color(0xff999999), + 500: Color(0xff808080), + 600: Color(0xff666666), + 700: Color(0xff4d4d4d), + 800: Color(0xff333333), + 900: Color(0xff191919) + }), + fontFamily: font, + brightness: Brightness.dark, + primaryColor: Color(0xff93b7b0), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xff9e9e9e), + primaryColorDark: Color(0xff000000), + accentColor: Color(0xff3d5c56), + accentColorBrightness: Brightness.light, + canvasColor: Colors.grey[900], + scaffoldBackgroundColor: Color(0xff303030), + bottomAppBarColor: Color(0xff424242), + cardColor: Color(0xff424242), + dividerColor: Color(0x1fffffff), + highlightColor: Color(0x40cccccc), + splashColor: Color(0x40cccccc), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0xb3ffffff), + disabledColor: Color(0x62ffffff), + buttonColor: Color(0xff93b7b0), + toggleableActiveColor: Color(0xff3d5c56), + secondaryHeaderColor: Color(0xff616161), + textSelectionColor: Color(0xff3d5c56), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xff3d5c56), + backgroundColor: Color(0xff616161), + dialogBackgroundColor: Color(0xff424242), + indicatorColor: Color(0xff3d5c56), + hintColor: Color(0x80ffffff), + errorColor: Color(0xffd32f2f), + appBarTheme: AppBarTheme( + brightness: Brightness.dark, + color: Colors.grey[900], + ), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + buttonColor: Color(0xff93b7b0), + disabledColor: Color(0x61ffffff), + highlightColor: Color(0x29ffffff), + splashColor: Color(0x1fffffff), + focusColor: Color(0x1fffffff), + hoverColor: Color(0x0affffff), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + sliderTheme: SliderThemeData.fromPrimaryColors( + primaryColor: Color(0xff93b7b0), + primaryColorLight: Color(0xffe0ebe9), + primaryColorDark: Color(0xff3d5c56), + valueIndicatorTextStyle: TextStyle( + color: Color(0xffffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1fffffff), + brightness: Brightness.dark, + deleteIconColor: Color(0xdeffffff), + disabledColor: Color(0x0cffffff), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0xb3ffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Color(0xb3ffffff), + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3d212121), + selectedColor: Color(0x3dffffff), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + + default: + return ThemeData( + primarySwatch: MaterialColor(4293223245, { + 50: Color(0xfffcebe9), + 100: Color(0xfff9d8d3), + 200: Color(0xfff2b1a6), + 300: Color(0xffec8a79), + 400: Color(0xffe5634d), + 500: Color(0xffdf3c20), + 600: Color(0xffb2301a), + 700: Color(0xff862413), + 800: Color(0xff59180d), + 900: Color(0xff2d0c06) + }), + fontFamily: font, + brightness: Brightness.light, + primaryColor: Color(0xffe5634d), + primaryColorBrightness: Brightness.dark, + primaryColorLight: Color(0xffFF8A65), + primaryColorDark: Color(0xff862413), + accentColor: Color(0xff4A90A4), + accentColorBrightness: Brightness.dark, + canvasColor: Color(0xfffafafa), + scaffoldBackgroundColor: Color(0xfffafafa), + bottomAppBarColor: Color(0xffffffff), + cardColor: Color(0xffffffff), + dividerColor: Color(0x1f000000), + highlightColor: Color(0x66bcbcbc), + splashColor: Color(0x66c8c8c8), + selectedRowColor: Color(0xfff5f5f5), + unselectedWidgetColor: Color(0x8a000000), + disabledColor: Color(0x61000000), + buttonColor: Color(0xffe5634d), + toggleableActiveColor: Color(0xff4A90A4), + secondaryHeaderColor: Color(0xfffcebe9), + textSelectionColor: Color(0xff4A90A4), + cursorColor: Color(0xff4285f4), + textSelectionHandleColor: Color(0xff4A90A4), + backgroundColor: Color(0xfff2b1a6), + dialogBackgroundColor: Color(0xffffffff), + indicatorColor: Color(0xff4A90A4), + hintColor: Color(0x8a000000), + errorColor: Color(0xffd32f2f), + buttonTheme: ButtonThemeData( + textTheme: ButtonTextTheme.accent, + minWidth: 88, + height: 48, + padding: EdgeInsets.only(left: 16, right: 16), + shape: RoundedRectangleBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + buttonColor: Color(0xffe5634d), + disabledColor: Color(0x61000000), + highlightColor: Color(0x29000000), + splashColor: Color(0x1f000000), + focusColor: Color(0x1f000000), + hoverColor: Color(0x0a000000), + ), + inputDecorationTheme: InputDecorationTheme( + contentPadding: EdgeInsets.only( + top: 12, + bottom: 12, + left: 15, + right: 15, + ), + ), + chipTheme: ChipThemeData( + backgroundColor: Color(0x1f000000), + brightness: Brightness.light, + deleteIconColor: Color(0xffdf3c20), + disabledColor: Color(0x0c000000), + labelPadding: EdgeInsets.only(left: 8, right: 8), + labelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + padding: EdgeInsets.all(4), + secondaryLabelStyle: TextStyle( + fontSize: 12, + fontFamily: font, + color: Colors.black, + fontWeight: FontWeight.w400, + fontStyle: FontStyle.normal, + ), + secondarySelectedColor: Color(0x3de5634d), + selectedColor: Color(0x3de5634d), + shape: StadiumBorder( + side: BorderSide( + color: Color(0xff000000), + width: 0, + style: BorderStyle.none, + ), + ), + ), + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + ), + cardTheme: CardTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ); + } + } + + ///Singleton factory + static final CollectionTheme _instance = CollectionTheme._internal(); + + factory CollectionTheme() { + return _instance; + } + + CollectionTheme._internal(); +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..e1da049 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,33 @@ +import 'package:bloc/bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:listar_flutter/app.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class AppDelegate extends BlocDelegate { + ///Support Development + @override + void onEvent(Bloc bloc, Object event) { + super.onEvent(bloc, event); + UtilLogger.log('BLOC EVENT', event); + } + + ///Support Development + @override + void onTransition(Bloc bloc, Transition transition) { + super.onTransition(bloc, transition); + UtilLogger.log('BLOC TRANSITION', transition); + } + + ///Support Development + @override + void onError(Bloc bloc, Object error, StackTrace stacktrace) { + super.onError(bloc, error, stacktrace); + UtilLogger.log('BLOC ERROR', error); + } +} + +void main() { + BlocSupervisor.delegate = AppDelegate(); + runApp(App()); +} diff --git a/lib/main_navigation.dart b/lib/main_navigation.dart new file mode 100644 index 0000000..cf56b22 --- /dev/null +++ b/lib/main_navigation.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/screens/profile/profile.dart'; +import 'package:listar_flutter/screens/screen.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class MainNavigation extends StatefulWidget { + MainNavigation({Key key}) : super(key: key); + + @override + _MainNavigationState createState() { + return _MainNavigationState(); + } +} + +class _MainNavigationState extends State { + int _selectedIndex = 0; + + @override + void initState() { + super.initState(); + } + + ///On change tab bottom menu + void _onItemTapped(int index) { + setState(() { + _selectedIndex = index; + }); + } + + ///List bottom menu + List _bottomBarItem(BuildContext context) { + return [ + BottomNavigationBarItem( + icon: Icon(Icons.home), + title: Padding( + padding: EdgeInsets.only(top: 3), + child: Text(Translate.of(context).translate('home')), + ), + ), + BottomNavigationBarItem( + icon: Icon(Icons.account_circle), + title: Padding( + padding: EdgeInsets.only(top: 3), + child: Text(Translate.of(context).translate('pref')), + ), + ), + ]; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: IndexedStack( + index: _selectedIndex, + children: [ + Home(), + Profile(), + ], + ), + bottomNavigationBar: BottomNavigationBar( + items: _bottomBarItem(context), + currentIndex: _selectedIndex, + type: BottomNavigationBarType.fixed, + unselectedItemColor: Theme.of(context).unselectedWidgetColor, + selectedItemColor: Theme.of(context).primaryColor, + showUnselectedLabels: true, + onTap: _onItemTapped, + ), + ); + } +} diff --git a/lib/models/model.dart b/lib/models/model.dart new file mode 100644 index 0000000..ca0f75a --- /dev/null +++ b/lib/models/model.dart @@ -0,0 +1,16 @@ +export 'model_banner.dart'; +export 'model_category.dart'; +export 'model_comment.dart'; +export 'model_hour.dart'; +export 'model_icon.dart'; +export 'model_location.dart'; +export 'model_message.dart'; +export 'model_notification.dart'; +export 'model_product.dart'; +export 'model_rate.dart'; +export 'model_result_api.dart'; +export 'model_sort.dart'; +export 'model_tab.dart'; +export 'model_tag.dart'; +export 'model_theme.dart'; +export 'model_user.dart'; diff --git a/lib/models/model_banner.dart b/lib/models/model_banner.dart new file mode 100644 index 0000000..b6df070 --- /dev/null +++ b/lib/models/model_banner.dart @@ -0,0 +1,23 @@ +class ImageModel { + final int id; + final String image; + + ImageModel( + this.id, + this.image, + ); + + factory ImageModel.fromJson(Map json) { + return ImageModel( + json['id'] as int ?? 0, + json['image'] as String ?? "Unknown", + ); + } + + Map toJson() { + return { + 'id': id, + 'image': image, + }; + } +} diff --git a/lib/models/model_category.dart b/lib/models/model_category.dart new file mode 100644 index 0000000..8b63b62 --- /dev/null +++ b/lib/models/model_category.dart @@ -0,0 +1,60 @@ +import 'package:flutter/cupertino.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class CategoryModel { + final int id; + final String title; + final int count; + final String image; + final IconData icon; + final Color color; + final ProductType type; + + CategoryModel({ + this.id, + this.title, + this.count, + this.image, + this.icon, + this.color, + this.type, + }); + + static ProductType _setType(String type) { + switch (type) { + case 'shop': + return ProductType.shop; + case 'drink': + return ProductType.drink; + case 'event': + return ProductType.event; + case 'estate': + return ProductType.estate; + case 'job': + return ProductType.job; + case 'restaurant': + return ProductType.restaurant; + case 'automotive': + return ProductType.automotive; + case 'hotel': + return ProductType.hotel; + default: + return ProductType.more; + } + } + + factory CategoryModel.fromJson(Map json) { + final icon = UtilIcon.getIconData(json['icon'] ?? "Unknown"); + final color = UtilColor.getColorFromHex(json['color'] ?? "#ff8a65"); + return CategoryModel( + id: json['id'] as int ?? 0, + title: json['title'] as String ?? 'Unknown', + count: json['count'] as int ?? 0, + image: json['image'] as String ?? 'Unknown', + icon: icon, + color: color, + type: _setType(json['type'] as String ?? "Unknown"), + ); + } +} diff --git a/lib/models/model_comment.dart b/lib/models/model_comment.dart new file mode 100644 index 0000000..5f7f965 --- /dev/null +++ b/lib/models/model_comment.dart @@ -0,0 +1,30 @@ +import 'package:listar_flutter/models/model.dart'; + +class CommentModel { + final int id; + final UserModel user; + final String title; + final String comment; + final String createDate; + final num rate; + + CommentModel( + this.id, + this.user, + this.title, + this.comment, + this.createDate, + this.rate, + ); + + factory CommentModel.fromJson(Map json) { + return CommentModel( + json['id'] as int ?? 0, + UserModel.fromJson(json['user']), + json['title'] as String ?? 'Unknown', + json['comment'] as String ?? 'Unknown', + json['created_date'] as String ?? 'Unknown', + json['rate'] as num ?? 0.0, + ); + } +} diff --git a/lib/models/model_hour.dart b/lib/models/model_hour.dart new file mode 100644 index 0000000..793f97c --- /dev/null +++ b/lib/models/model_hour.dart @@ -0,0 +1,16 @@ +class HourModel { + final String title; + final String time; + + HourModel( + this.title, + this.time, + ); + + factory HourModel.fromJson(Map json) { + return HourModel( + json['title'] as String ?? "Unknown", + json['time'] as String ?? "Unknown", + ); + } +} diff --git a/lib/models/model_icon.dart b/lib/models/model_icon.dart new file mode 100644 index 0000000..9271f2e --- /dev/null +++ b/lib/models/model_icon.dart @@ -0,0 +1,16 @@ +class IconModel { + final String title; + final String icon; + + IconModel( + this.title, + this.icon, + ); + + factory IconModel.fromJson(Map json) { + return IconModel( + json['title'] as String ?? "Unknown", + json['icon'] as String ?? "Unknown", + ); + } +} diff --git a/lib/models/model_location.dart b/lib/models/model_location.dart new file mode 100644 index 0000000..8194f83 --- /dev/null +++ b/lib/models/model_location.dart @@ -0,0 +1,22 @@ +class LocationModel { + final int id; + final String name; + final double lat; + final double long; + + LocationModel( + this.id, + this.name, + this.lat, + this.long, + ); + + factory LocationModel.fromJson(Map json) { + return LocationModel( + json['id'] as int ?? 0, + json['name'] as String ?? "Unknown", + json['lat'] as double ?? 0.0, + json['long'] as double ?? 0.0, + ); + } +} diff --git a/lib/models/model_message.dart b/lib/models/model_message.dart new file mode 100644 index 0000000..85a8c56 --- /dev/null +++ b/lib/models/model_message.dart @@ -0,0 +1,70 @@ +import 'dart:io'; + +import 'package:listar_flutter/models/model.dart'; + +enum Status { sent, received } +enum Type { textMessage, photo } + +class MessageModel { + final int id; + final String roomName; + final List member; + final UserModel from; + final String message; + final DateTime date; + final Status status; + final File file; + final Type type; + + MessageModel( + this.id, + this.roomName, + this.member, + this.from, + this.message, + this.date, + this.status, + this.file, + this.type, + ); + + factory MessageModel.fromJson(Map json) { + Status status = Status.sent; + File file; + Type type = Type.textMessage; + List member; + UserModel from; + + if (json['status'] == 'received') { + status = Status.received; + } + + if (json['file'] != null) { + file = File(json['file']); + type = Type.photo; + } + + if (json['member'] != null) { + final Iterable convertUser = json['member'] ?? []; + member = convertUser.map((item) { + return UserModel.fromJson(item); + }).toList(); + } + + if (json['from'] != null) { + from = UserModel.fromJson(json['from']); + } + + return MessageModel( + json['id'] as int ?? 0, + json['room_name'] as String ?? '', + member, + from, + json['message'] as String ?? 'Unknown', + DateTime.tryParse(json['date']) ?? DateTime.now(), + status, + file, + type, + ); + } +} diff --git a/lib/models/model_notification.dart b/lib/models/model_notification.dart new file mode 100644 index 0000000..653c53f --- /dev/null +++ b/lib/models/model_notification.dart @@ -0,0 +1,27 @@ +import 'model.dart'; + +class NotificationModel { + final int id; + final String title; + final String subtitle; + final DateTime date; + final CategoryModel category; + + NotificationModel( + this.id, + this.title, + this.subtitle, + this.date, + this.category, + ); + + factory NotificationModel.fromJson(Map json) { + return NotificationModel( + json['id'] as int, + json['title'] as String, + json['subtitle'] as String, + DateTime.tryParse(json['date']) ?? DateTime.now(), + new CategoryModel.fromJson(json['category']), + ); + } +} diff --git a/lib/models/model_product.dart b/lib/models/model_product.dart new file mode 100644 index 0000000..f885bd0 --- /dev/null +++ b/lib/models/model_product.dart @@ -0,0 +1,193 @@ +import 'package:listar_flutter/models/model.dart'; + +enum ProductType { + place, + hotel, + shop, + drink, + event, + estate, + job, + restaurant, + automotive, + more +} + +class ProductModel { + final int id; + final String title; + final String subtitle; + final String image; + final String createDate; + final bool like; + final num rate; + final num numRate; + final String rateText; + final String status; + final bool favorite; + final String address; + final String phone; + final String email; + final String website; + final String hour; + final String description; + final String date; + final String priceRange; + final List photo; + final List hourDetail; + final List service; + final List feature; + final List related; + final LocationModel location; + final UserModel author; + final ProductType type; + + ProductModel( + this.id, + this.title, + this.subtitle, + this.image, + this.createDate, + this.like, + this.rate, + this.numRate, + this.rateText, + this.status, + this.favorite, + this.address, + this.phone, + this.email, + this.website, + this.hour, + this.description, + this.date, + this.priceRange, + this.hourDetail, + this.service, + this.photo, + this.feature, + this.related, + this.location, + this.author, + this.type, + ); + + static List _setHourDetail(hour) { + if (hour != null) { + final Iterable refactorHour = hour; + return refactorHour.map((item) { + return HourModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setService(icon) { + if (icon != null) { + final Iterable refactorService = icon; + return refactorService.map((item) { + return IconModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setPhoto(photo) { + if (photo != null) { + final Iterable refactorPhoto = photo; + return refactorPhoto.map((item) { + return ImageModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setFeature(feature) { + if (feature != null) { + final Iterable refactorFeature = feature; + return refactorFeature.map((item) { + return ProductModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setRelated(related) { + if (related != null) { + final Iterable refactorRelated = related; + return refactorRelated.map((item) { + return ProductModel.fromJson(item); + }).toList(); + } + return null; + } + + static LocationModel _setLocation(Map location) { + if (location != null) { + return LocationModel.fromJson(location); + } + return null; + } + + static UserModel _setAuthor(Map author) { + if (author != null) { + return UserModel.fromJson(author); + } + return null; + } + + static ProductType _setType(String type) { + switch (type) { + case 'hotel': + return ProductType.hotel; + case 'shop': + return ProductType.shop; + case 'drink': + return ProductType.drink; + case 'event': + return ProductType.event; + case 'estate': + return ProductType.estate; + case 'job': + return ProductType.job; + case 'restaurant': + return ProductType.restaurant; + case 'automotive': + return ProductType.automotive; + default: + return ProductType.place; + } + } + + factory ProductModel.fromJson(Map json) { + return ProductModel( + json['id'] as int ?? 0, + json['title'] as String ?? 'Unknown', + json['subtitle'] as String ?? 'Unknown', + json['image'] as String ?? 'Unknown', + json['created_date'] as String ?? 'Unknown', + json['like'] as bool ?? false, + json['rate'] as num ?? 0, + json['num_rate'] as num ?? 0, + json['rate_text'] as String ?? 'Unknown', + json['status'] as String ?? null, + json['favorite'] as bool ?? false, + json['address'] as String ?? 'Unknown', + json['phone'] as String ?? 'Unknown', + json['email'] as String ?? 'Unknown', + json['website'] as String ?? 'Unknown', + json['hour'] as String ?? 'Unknown', + json['description'] as String ?? 'Unknown', + json['date'] as String ?? 'Unknown', + json['price_range'] as String ?? 'Unknown', + _setHourDetail(json['hour_detail']), + _setService(json['service']), + _setPhoto(json['photo']), + _setFeature(json['feature']), + _setRelated(json['related']), + _setLocation(json['location']), + _setAuthor(json['author']), + _setType(json['type']), + ); + } +} diff --git a/lib/models/model_product_hotel.dart b/lib/models/model_product_hotel.dart new file mode 100644 index 0000000..34238f8 --- /dev/null +++ b/lib/models/model_product_hotel.dart @@ -0,0 +1,194 @@ +import 'package:listar_flutter/models/model.dart'; + +class HotelProductModel extends ProductModel { + final List nearly; + + HotelProductModel( + int id, + String title, + String subtitle, + String image, + String createDate, + bool like, + num rate, + num numRate, + String rateText, + String status, + bool favorite, + String address, + String phone, + String email, + String website, + String hour, + String description, + String date, + String priceRange, + List hourDetail, + List service, + List photo, + List feature, + List related, + LocationModel location, + UserModel author, + ProductType type, + this.nearly) + : super( + id, + title, + subtitle, + image, + createDate, + like, + rate, + numRate, + rateText, + status, + favorite, + address, + phone, + email, + website, + hour, + description, + date, + priceRange, + hourDetail, + service, + photo, + feature, + related, + location, + author, + type, + ); + + static List _setHourDetail(hour) { + if (hour != null) { + final Iterable refactorHour = hour; + return refactorHour.map((item) { + return HourModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setService(icon) { + if (icon != null) { + final Iterable refactorService = icon; + return refactorService.map((item) { + return IconModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setPhoto(photo) { + if (photo != null) { + final Iterable refactorPhoto = photo; + return refactorPhoto.map((item) { + return ImageModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setFeature(feature) { + if (feature != null) { + final Iterable refactorFeature = feature; + return refactorFeature.map((item) { + return ProductModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setNearly(nearly) { + if (nearly != null) { + final Iterable refactorNearly = nearly; + return refactorNearly.map((item) { + return ProductModel.fromJson(item); + }).toList(); + } + return null; + } + + static List _setRelated(related) { + if (related != null) { + final Iterable refactorRelated = related; + return refactorRelated.map((item) { + return ProductModel.fromJson(item); + }).toList(); + } + return null; + } + + static LocationModel _setLocation(Map location) { + if (location != null) { + return LocationModel.fromJson(location); + } + return null; + } + + static UserModel _setAuthor(Map author) { + if (author != null) { + return UserModel.fromJson(author); + } + return null; + } + + static ProductType _setType(String type) { + switch (type) { + case 'hotel': + return ProductType.hotel; + case 'shop': + return ProductType.shop; + case 'drink': + return ProductType.drink; + case 'event': + return ProductType.event; + case 'estate': + return ProductType.estate; + case 'job': + return ProductType.job; + case 'restaurant': + return ProductType.restaurant; + case 'automotive': + return ProductType.automotive; + default: + return ProductType.place; + } + } + + factory HotelProductModel.fromJson(Map json) { + return HotelProductModel( + json['id'] as int ?? 0, + json['title'] as String ?? 'Unknown', + json['subtitle'] as String ?? 'Unknown', + json['image'] as String ?? 'Unknown', + json['created_date'] as String ?? 'Unknown', + json['like'] as bool ?? false, + json['rate'] as num ?? 0, + json['num_rate'] as num ?? 0, + json['rate_text'] as String ?? 'Unknown', + json['status'] as String ?? 'Unknown', + json['favorite'] as bool ?? false, + json['address'] as String ?? 'Unknown', + json['phone'] as String ?? 'Unknown', + json['email'] as String ?? 'Unknown', + json['website'] as String ?? 'Unknown', + json['hour'] as String ?? 'Unknown', + json['description'] as String ?? 'Unknown', + json['date'] as String ?? 'Unknown', + json['price_range'] as String ?? 'Unknown', + _setHourDetail(json['hour_detail']), + _setService(json['service']), + _setPhoto(json['photo']), + _setFeature(json['feature']), + _setRelated(json['related']), + _setLocation(json['location']), + _setAuthor(json['author']), + _setType(json['type']), + _setNearly(json['nearly']), + ); + } +} diff --git a/lib/models/model_rate.dart b/lib/models/model_rate.dart new file mode 100644 index 0000000..3b918e6 --- /dev/null +++ b/lib/models/model_rate.dart @@ -0,0 +1,34 @@ +class RateModel { + final double one; + final double two; + final double three; + final double four; + final double five; + final int range; + final double avg; + final int total; + + RateModel( + this.one, + this.two, + this.three, + this.four, + this.five, + this.range, + this.avg, + this.total, + ); + + factory RateModel.fromJson(Map json) { + return RateModel( + json['one'] as double ?? 0.0, + json['two'] as double ?? 0.0, + json['three'] as double ?? 0.0, + json['four'] as double ?? 0.0, + json['five'] as double ?? 0.0, + json['range'] as int ?? 5, + json['avg'] as double ?? 0.0, + json['total'] as int ?? 5, + ); + } +} diff --git a/lib/models/model_result_api.dart b/lib/models/model_result_api.dart new file mode 100644 index 0000000..8702103 --- /dev/null +++ b/lib/models/model_result_api.dart @@ -0,0 +1,22 @@ +class ResultApiModel { + final bool success; + final String message; + final Map data; + final int code; + + ResultApiModel( + this.success, + this.message, + this.data, + this.code, + ); + + factory ResultApiModel.fromJson(Map json) { + return ResultApiModel( + json['success'] as bool ?? false, + json['message'] as String ?? 'Unknown', + json['data'] as Map ?? {}, + json['code'] as int ?? 0, + ); + } +} diff --git a/lib/models/model_sort.dart b/lib/models/model_sort.dart new file mode 100644 index 0000000..3f926d1 --- /dev/null +++ b/lib/models/model_sort.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class SortModel { + final String code; + final String name; + final IconData icon; + + SortModel( + this.code, + this.name, + this.icon, + ); + + factory SortModel.fromJson(Map json) { + return SortModel( + json['code'] as String ?? "Unknown", + json['name'] as String ?? "Unknown", + json['icon'] as IconData ?? Icons.help, + ); + } +} diff --git a/lib/models/model_tab.dart b/lib/models/model_tab.dart new file mode 100644 index 0000000..c819a13 --- /dev/null +++ b/lib/models/model_tab.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; + +class TabModel { + final int id; + final String key; + final GlobalKey keyContentItem; + final GlobalKey keyTabItem; + final String title; + final List list; + + TabModel( + this.id, + this.key, + this.keyContentItem, + this.keyTabItem, + this.title, + this.list, + ); + + static List _setList(list) { + if (list != null) { + final Iterable refactorList = list; + return refactorList.map((item) { + return ProductModel.fromJson(item); + }).toList(); + } + return null; + } + + factory TabModel.fromJson(Map json) { + return TabModel( + json['id'] as int ?? 0, + json['key'] as String ?? 'Unknown', + GlobalKey(), + GlobalKey(), + json['title'] as String ?? 'Unknown', + _setList(json['list']), + ); + } +} diff --git a/lib/models/model_tag.dart b/lib/models/model_tag.dart new file mode 100644 index 0000000..3e81a29 --- /dev/null +++ b/lib/models/model_tag.dart @@ -0,0 +1,16 @@ +class TagModel { + final int id; + final String title; + + TagModel( + this.id, + this.title, + ); + + factory TagModel.fromJson(Map json) { + return TagModel( + json['id'] as int ?? 0, + json['title'] as String ?? 'Unknoun', + ); + } +} diff --git a/lib/models/model_theme.dart b/lib/models/model_theme.dart new file mode 100644 index 0000000..e544a38 --- /dev/null +++ b/lib/models/model_theme.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +class ThemeModel { + final String name; + final Color color; + final String lightTheme; + final String darkTheme; + + ThemeModel( + this.name, + this.color, + this.lightTheme, + this.darkTheme, + ); + + factory ThemeModel.fromJson(Map json) { + return ThemeModel( + json['name'] as String ?? "Unknown", + json['color'] as Color ?? Colors.black, + json['light'] as String ?? "Unknown", + json['dark'] as String ?? "Unknown", + ); + } +} diff --git a/lib/models/model_user.dart b/lib/models/model_user.dart new file mode 100644 index 0000000..191da62 --- /dev/null +++ b/lib/models/model_user.dart @@ -0,0 +1,55 @@ +class UserModel { + final int id; + final String name; + final String nickname; + final String image; + final String link; + final String level; + final String description; + final String tag; + final double rate; + final String token; + + UserModel( + this.id, + this.name, + this.nickname, + this.image, + this.link, + this.level, + this.description, + this.tag, + this.rate, + this.token, + ); + + factory UserModel.fromJson(Map json) { + return UserModel( + json['id'] as int ?? 0, + json['full_name'] as String ?? 'Unknown', + json['nickname'] as String ?? 'Unknown', + json['photo'] as String ?? 'Unknown', + json['url'] as String ?? 'Unknown', + json['level'] as String ?? 'Unknown', + json['description'] as String ?? 'Unknown', + json['tag'] as String ?? 'Unknown', + json['rate'] as double ?? 0.0, + json['token'] as String ?? 'Unknown', + ); + } + + Map toJson() { + return { + 'id': id, + 'full_name': name, + 'nickname': nickname, + 'photo': image, + 'url': link, + 'level': level, + 'description': description, + 'tag': tag, + 'rate': rate, + 'token': token, + }; + } +} diff --git a/lib/models/screen_models/aboutus_page_model.dart b/lib/models/screen_models/aboutus_page_model.dart new file mode 100644 index 0000000..58bc73d --- /dev/null +++ b/lib/models/screen_models/aboutus_page_model.dart @@ -0,0 +1,30 @@ +import 'package:listar_flutter/models/model.dart'; + +class AboutUsPageModel { + final String banner; + final String whoWeAre; + final List whatWeDo; + final List team; + + AboutUsPageModel( + this.banner, + this.whoWeAre, + this.whatWeDo, + this.team, + ); + + factory AboutUsPageModel.fromJson(Map json) { + final Iterable refactorTeam = json['team'] ?? []; + + final listTeam = refactorTeam.map((item) { + return UserModel.fromJson(item); + }).toList(); + + return AboutUsPageModel( + json['banner'] as String ?? 'Unknown', + json['who_we_are'] as String ?? 'Unknown', + json['what_we_do'].cast() ?? [], + listTeam, + ); + } +} diff --git a/lib/models/screen_models/category_page_model.dart b/lib/models/screen_models/category_page_model.dart new file mode 100644 index 0000000..cac3605 --- /dev/null +++ b/lib/models/screen_models/category_page_model.dart @@ -0,0 +1,21 @@ +import 'package:listar_flutter/models/model.dart'; + +class CategoryPageModel { + final List category; + + CategoryPageModel( + this.category, + ); + + factory CategoryPageModel.fromJson(Map json) { + final Iterable convertCategory = json['category'] ?? []; + + final listCategory = convertCategory.map((item) { + return CategoryModel.fromJson(item); + }).toList(); + + return CategoryPageModel( + listCategory, + ); + } +} diff --git a/lib/models/screen_models/chat_page_model.dart b/lib/models/screen_models/chat_page_model.dart new file mode 100644 index 0000000..8e6ced7 --- /dev/null +++ b/lib/models/screen_models/chat_page_model.dart @@ -0,0 +1,36 @@ +import 'package:listar_flutter/models/model.dart'; + +class ChatPageModel { + final String roomName; + final int online; + final List member; + final List message; + + ChatPageModel( + this.roomName, + this.online, + this.member, + this.message, + ); + + factory ChatPageModel.fromJson(Map json) { + final Iterable convertMessage = json['message'] ?? []; + + final listMessage = convertMessage.map((item) { + return MessageModel.fromJson(item); + }).toList(); + + final Iterable convertUser = json['member'] ?? []; + + final listUser = convertUser.map((item) { + return UserModel.fromJson(item); + }).toList(); + + return ChatPageModel( + json['room_name'] as String ?? '', + json['online'] as int ?? 0, + listUser, + listMessage, + ); + } +} diff --git a/lib/models/screen_models/filter_page_model.dart b/lib/models/screen_models/filter_page_model.dart new file mode 100644 index 0000000..96b07ba --- /dev/null +++ b/lib/models/screen_models/filter_page_model.dart @@ -0,0 +1,16 @@ +class FilterPageModel { + final List category; + final List service; + + FilterPageModel( + this.category, + this.service, + ); + + factory FilterPageModel.fromJson(Map json) { + return FilterPageModel( + json['category'], + json['service'], + ); + } +} diff --git a/lib/models/screen_models/home_page_model.dart b/lib/models/screen_models/home_page_model.dart new file mode 100644 index 0000000..1ea0eac --- /dev/null +++ b/lib/models/screen_models/home_page_model.dart @@ -0,0 +1,45 @@ +import 'package:listar_flutter/models/model.dart'; + +class HomePageModel { + final List banner; + final List category; + final List popular; + final List list; + + HomePageModel( + this.banner, + this.category, + this.popular, + this.list, + ); + + factory HomePageModel.fromJson(Map json) { + final Iterable refactorBanner = json['banner'] ?? []; + final Iterable refactorCategory = json['category'] ?? []; + final Iterable refactorPopular = json['popular'] ?? []; + final Iterable refactorList = json['list'] ?? []; + + final listBanner = refactorBanner.map((item) { + return ImageModel.fromJson(item); + }).toList(); + + final listCategory = refactorCategory.map((item) { + return CategoryModel.fromJson(item); + }).toList(); + + final listPopular = refactorPopular.map((item) { + return ProductModel.fromJson(item); + }).toList(); + + final listProduct = refactorList.map((item) { + return ProductModel.fromJson(item); + }).toList(); + + return HomePageModel( + listBanner, + listCategory, + listPopular, + listProduct, + ); + } +} diff --git a/lib/models/screen_models/message_detail_page_model.dart b/lib/models/screen_models/message_detail_page_model.dart new file mode 100644 index 0000000..636adc4 --- /dev/null +++ b/lib/models/screen_models/message_detail_page_model.dart @@ -0,0 +1,21 @@ +import 'package:listar_flutter/models/model.dart'; + +class MessageDetailPageModel { + final List message; + + MessageDetailPageModel( + this.message, + ); + + factory MessageDetailPageModel.fromJson(Map json) { + final Iterable convertMessage = json['message'] ?? []; + + final listMessage = convertMessage.map((item) { + return MessageModel.fromJson(item); + }).toList(); + + return MessageDetailPageModel( + listMessage, + ); + } +} diff --git a/lib/models/screen_models/message_page_model.dart b/lib/models/screen_models/message_page_model.dart new file mode 100644 index 0000000..a5cecc2 --- /dev/null +++ b/lib/models/screen_models/message_page_model.dart @@ -0,0 +1,21 @@ +import 'package:listar_flutter/models/model.dart'; + +class MessagePageModel { + final List message; + + MessagePageModel( + this.message, + ); + + factory MessagePageModel.fromJson(Map json) { + final Iterable convertMessage = json['message'] ?? []; + + final listMessage = convertMessage.map((item) { + return MessageModel.fromJson(item); + }).toList(); + + return MessagePageModel( + listMessage, + ); + } +} diff --git a/lib/models/screen_models/notification_page_model.dart b/lib/models/screen_models/notification_page_model.dart new file mode 100644 index 0000000..7106149 --- /dev/null +++ b/lib/models/screen_models/notification_page_model.dart @@ -0,0 +1,21 @@ +import 'package:listar_flutter/models/model.dart'; + +class NotificationPageModel { + final List notification; + + NotificationPageModel( + this.notification, + ); + + factory NotificationPageModel.fromJson(Map json) { + final Iterable convertNotification = json['notification'] ?? []; + + final listCategory = convertNotification.map((item) { + return NotificationModel.fromJson(item); + }).toList(); + + return NotificationPageModel( + listCategory, + ); + } +} diff --git a/lib/models/screen_models/product_detail_page_model.dart b/lib/models/screen_models/product_detail_page_model.dart new file mode 100644 index 0000000..93c29f1 --- /dev/null +++ b/lib/models/screen_models/product_detail_page_model.dart @@ -0,0 +1,11 @@ +import 'package:listar_flutter/models/model.dart'; + +class ProductDetailPageModel { + final ProductModel product; + + ProductDetailPageModel(this.product); + + factory ProductDetailPageModel.fromJson(Map json) { + return ProductDetailPageModel(ProductModel.fromJson(json)); + } +} diff --git a/lib/models/screen_models/product_detail_tab_page_model.dart b/lib/models/screen_models/product_detail_tab_page_model.dart new file mode 100644 index 0000000..c9eaee4 --- /dev/null +++ b/lib/models/screen_models/product_detail_tab_page_model.dart @@ -0,0 +1,28 @@ +import 'package:listar_flutter/models/model.dart'; + +class ProductDetailTabPageModel { + final ProductModel product; + final List tab; + + ProductDetailTabPageModel( + this.product, + this.tab, + ); + + static List _setTab(tab) { + if (tab != null) { + final Iterable refactorTab = tab ?? []; + return refactorTab.map((item) { + return TabModel.fromJson(item); + }).toList(); + } + return null; + } + + factory ProductDetailTabPageModel.fromJson(Map json) { + return ProductDetailTabPageModel( + ProductModel.fromJson(json), + _setTab(json['tab']), + ); + } +} diff --git a/lib/models/screen_models/product_list_page_model.dart b/lib/models/screen_models/product_list_page_model.dart new file mode 100644 index 0000000..872767c --- /dev/null +++ b/lib/models/screen_models/product_list_page_model.dart @@ -0,0 +1,19 @@ +import 'package:listar_flutter/models/model.dart'; + +class ProductListPageModel { + final List list; + + ProductListPageModel( + this.list, + ); + + factory ProductListPageModel.fromJson(Map json) { + final Iterable refactorList = json['list'] ?? []; + + final list = refactorList.map((item) { + return ProductModel.fromJson(item); + }).toList(); + + return ProductListPageModel(list); + } +} diff --git a/lib/models/screen_models/profile_page_model.dart b/lib/models/screen_models/profile_page_model.dart new file mode 100644 index 0000000..88bcd44 --- /dev/null +++ b/lib/models/screen_models/profile_page_model.dart @@ -0,0 +1,18 @@ +import 'package:listar_flutter/models/model.dart'; + +class ProfilePageModel { + final UserModel user; + final List> value; + + ProfilePageModel( + this.user, + this.value, + ); + + factory ProfilePageModel.fromJson(Map json) { + return ProfilePageModel( + new UserModel.fromJson(json['user']), + json['value'].cast>() ?? [], + ); + } +} diff --git a/lib/models/screen_models/review_page_model.dart b/lib/models/screen_models/review_page_model.dart new file mode 100644 index 0000000..b1fd042 --- /dev/null +++ b/lib/models/screen_models/review_page_model.dart @@ -0,0 +1,26 @@ +import 'package:listar_flutter/models/model.dart'; + +class ReviewPageModel { + final UserModel author; + final RateModel rate; + final List comment; + + ReviewPageModel( + this.author, + this.rate, + this.comment, + ); + + factory ReviewPageModel.fromJson(Map json) { + final Iterable refactorComment = json['comment'] ?? []; + final comment = refactorComment.map((item) { + return CommentModel.fromJson(item); + }).toList(); + + return ReviewPageModel( + UserModel.fromJson(json['author']), + RateModel.fromJson(json['rate']), + comment, + ); + } +} diff --git a/lib/models/screen_models/screen_models.dart b/lib/models/screen_models/screen_models.dart new file mode 100644 index 0000000..b059f37 --- /dev/null +++ b/lib/models/screen_models/screen_models.dart @@ -0,0 +1,16 @@ +export 'aboutus_page_model.dart'; +export 'category_page_model.dart'; +export 'chat_page_model.dart'; +export 'filter_page_model.dart'; +export 'home_page_model.dart'; +export 'message_detail_page_model.dart'; +export 'message_page_model.dart'; +export 'notification_page_model.dart'; +export 'product_detail_page_model.dart'; +export 'product_detail_page_model.dart'; +export 'product_detail_tab_page_model.dart'; +export 'product_list_page_model.dart'; +export 'profile_page_model.dart'; +export 'review_page_model.dart'; +export 'search_history_page_model.dart'; +export 'wish_list_page_model.dart'; diff --git a/lib/models/screen_models/search_history_page_model.dart b/lib/models/screen_models/search_history_page_model.dart new file mode 100644 index 0000000..bccfd39 --- /dev/null +++ b/lib/models/screen_models/search_history_page_model.dart @@ -0,0 +1,45 @@ +import 'package:listar_flutter/models/model.dart'; + +class SearchHistoryPageModel { + final List tag; + final List discover; + final List popular; + final List history; + + SearchHistoryPageModel( + this.tag, + this.discover, + this.popular, + this.history, + ); + + factory SearchHistoryPageModel.fromJson(Map json) { + final Iterable refactorTag = json['tag'] ?? []; + final Iterable refactorDiscover = json['discover'] ?? []; + final Iterable refactorPopular = json['popular'] ?? []; + final Iterable refactorHistory = json['history'] ?? []; + + final listTag = refactorTag.map((item) { + return TagModel.fromJson(item); + }).toList(); + + final listDiscover = refactorDiscover.map((item) { + return TagModel.fromJson(item); + }).toList(); + + final listPopular = refactorPopular.map((item) { + return ProductModel.fromJson(item); + }).toList(); + + final listHistory = refactorHistory.map((item) { + return ProductModel.fromJson(item); + }).toList(); + + return SearchHistoryPageModel( + listTag, + listDiscover, + listPopular, + listHistory, + ); + } +} diff --git a/lib/models/screen_models/wish_list_page_model.dart b/lib/models/screen_models/wish_list_page_model.dart new file mode 100644 index 0000000..8af6f3e --- /dev/null +++ b/lib/models/screen_models/wish_list_page_model.dart @@ -0,0 +1,19 @@ +import 'package:listar_flutter/models/model.dart'; + +class WishListPageModel { + final List list; + + WishListPageModel( + this.list, + ); + + factory WishListPageModel.fromJson(Map json) { + final Iterable refactorList = json['list'] ?? []; + + final list = refactorList.map((item) { + return ProductModel.fromJson(item); + }).toList(); + + return WishListPageModel(list); + } +} diff --git a/lib/screens/choose_location/choose_location.dart b/lib/screens/choose_location/choose_location.dart new file mode 100644 index 0000000..9d3c65f --- /dev/null +++ b/lib/screens/choose_location/choose_location.dart @@ -0,0 +1,183 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/api/api.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/other.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:listar_flutter/widgets/widget.dart'; + +class ChooseLocation extends StatefulWidget { + final List location; + + ChooseLocation({Key key, this.location}) : super(key: key); + + @override + _ChooseLocationState createState() { + return _ChooseLocationState(); + } +} + +class _ChooseLocationState extends State { + final _textLanguageController = TextEditingController(); + bool _loading = false; + + List _location; + List _locationBackup; + List _locationSelected; + + @override + void initState() { + _loadData(); + super.initState(); + } + + ///Fetch API + Future _loadData() async { + final ResultApiModel result = await Api.getLocationList(); + if (result.success) { + final Iterable data = result.data['location'] ?? []; + setState(() { + _location = data.map((item) { + return LocationModel.fromJson(item); + }).toList(); + _locationBackup = _location; + _locationSelected = widget.location; + }); + } + } + + ///On filter location + void _onFilter(String text) { + if (text.isEmpty) { + setState(() { + _location = _locationBackup; + }); + return; + } + setState(() { + _location = _location.where(((item) { + return item.name.toUpperCase().contains(text.toUpperCase()); + })).toList(); + }); + } + + ///On Select Location + void _onSelect(LocationModel item) { + if (_locationSelected.contains(item)) { + _locationSelected.remove(item); + } else { + _locationSelected = []; + _locationSelected.add(item); + } + setState(() { + _locationSelected = _locationSelected; + }); + } + + ///Build List location + Widget _buildContent() { + if (_location == null) { + return Center( + child: SizedBox( + width: 26, + height: 26, + child: CircularProgressIndicator( + strokeWidth: 1.5, + ), + ), + ); + } + + return ListView.builder( + padding: EdgeInsets.only(left: 20, right: 20), + itemBuilder: (context, index) { + final item = _location[index]; + final trailing = _locationSelected.contains(item) + ? Icon( + Icons.check, + color: Theme.of(context).primaryColor, + ) + : null; + return AppListTitle( + title: item.name, + textStyle: _locationSelected.contains(item) + ? Theme.of(context) + .textTheme + .subtitle1 + .copyWith(color: Theme.of(context).primaryColor) + : null, + trailing: trailing, + onPressed: () { + _onSelect(item); + }, + ); + }, + itemCount: _location.length, + ); + } + + ///On change language + Future _onChange() async { + UtilOther.hiddenKeyboard(context); + setState(() { + _loading = true; + }); + await Future.delayed(Duration(seconds: 1)); + Navigator.pop(context, _locationSelected); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + Translate.of(context).translate('location'), + ), + ), + body: SafeArea( + child: Column( + children: [ + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 15, + bottom: 15, + ), + child: AppTextInput( + hintText: Translate.of(context).translate('search'), + icon: Icon(Icons.clear), + controller: _textLanguageController, + onChanged: _onFilter, + onSubmitted: _onFilter, + onTapIcon: () async { + await Future.delayed(Duration(milliseconds: 100)); + _textLanguageController.clear(); + }, + ), + ), + Expanded( + child: _buildContent(), + ), + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 15, + bottom: 15, + ), + child: AppButton( + onPressed: () { + _onChange(); + }, + text: Translate.of(context).translate('apply'), + loading: _loading, + disableTouchWhenLoading: true, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/font_setting/font_setting.dart b/lib/screens/font_setting/font_setting.dart new file mode 100644 index 0000000..f50162f --- /dev/null +++ b/lib/screens/font_setting/font_setting.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:listar_flutter/blocs/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:listar_flutter/widgets/widget.dart'; + +class FontSetting extends StatefulWidget { + FontSetting({Key key}) : super(key: key); + + @override + _FontSettingState createState() { + return _FontSettingState(); + } +} + +class _FontSettingState extends State { + ThemeBloc _themeBloc; + String _currentFont = AppTheme.currentFont; + + @override + void initState() { + _themeBloc = BlocProvider.of(context); + super.initState(); + } + + ///On change Font + void _onChange() async { + _themeBloc.add(ChangeTheme(font: _currentFont)); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + Translate.of(context).translate('font'), + ), + ), + body: SafeArea( + child: Column( + children: [ + Expanded( + child: ListView.builder( + padding: EdgeInsets.only(left: 20, right: 20, top: 10), + itemBuilder: (context, index) { + final item = AppTheme.fontSupport[index]; + final trailing = item == _currentFont + ? Icon( + Icons.check, + color: Theme.of(context).primaryColor, + ) + : null; + return AppListTitle( + title: item, + trailing: trailing, + onPressed: () { + setState(() { + _currentFont = item; + }); + }, + textStyle: Theme.of(context) + .textTheme + .subtitle1 + .copyWith(fontFamily: item), + ); + }, + itemCount: AppTheme.fontSupport.length, + ), + ), + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 15, + bottom: 15, + ), + child: BlocBuilder( + builder: (context, theme) { + return AppButton( + onPressed: _onChange, + text: Translate.of(context).translate('apply'), + loading: theme is ThemeUpdating, + disableTouchWhenLoading: true, + ); + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart new file mode 100644 index 0000000..4e637f1 --- /dev/null +++ b/lib/screens/home/home.dart @@ -0,0 +1,271 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/api/api.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/models/screen_models/screen_models.dart'; +import 'package:listar_flutter/screens/home/home_category_item.dart'; +import 'package:listar_flutter/screens/home/home_sliver_app_bar.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class Home extends StatefulWidget { + Home({Key key}) : super(key: key); + + @override + _HomeState createState() { + return _HomeState(); + } +} + +class _HomeState extends State { + HomePageModel _homePage; + List _locationSelected = []; + + @override + void initState() { + _loadData(); + super.initState(); + } + + void updateLocation(String currentLocation) async { + UtilPreferences.setString(Preferences.location, currentLocation); + } + + // Fetch API + Future _loadData() async { + final ResultApiModel result = await Api.getHome(); + if (result.success) { + setState(() { + _homePage = HomePageModel.fromJson(result.data); + }); + } + } + + // On select category + void _onTapService(CategoryModel item) { + switch (item.title) { + case 'Storm Tracking': + Navigator.pushNamed(context, Routes.stormTracking, + arguments: item.title); + break; + case 'Personal Safety': + Navigator.pushNamed(context, Routes.personalSafety, + arguments: item.title); + break; + case 'Personal Risk': + Navigator.pushNamed(context, Routes.personalRisk, + arguments: item.title); + break; + case 'Property Safety': + Navigator.pushNamed(context, Routes.propertySafety, + arguments: item.title); + break; + case 'Property Risk': + Navigator.pushNamed(context, Routes.propertyRisk, + arguments: item.title); + break; + case 'Supplies': + Navigator.pushNamed(context, Routes.supplies, arguments: item.title); + break; + case 'Evacuation': + Navigator.pushNamed(context, Routes.evacuation, arguments: item.title); + break; + case 'Stay in Touch': + Navigator.pushNamed(context, Routes.stayInTouch, arguments: item.title); + break; + default: + break; + } + } + + // Build category UI + Widget _buildCategory() { + if (_homePage?.category == null) { + return Wrap( + runSpacing: 10, + alignment: WrapAlignment.center, + children: List.generate(8, (index) => index).map( + (item) { + return HomeCategoryItem(); + }, + ).toList(), + ); + } + + List listBuild = _homePage.category; + + return Wrap( + runSpacing: 10, + alignment: WrapAlignment.center, + children: listBuild.map( + (item) { + return HomeCategoryItem( + item: item, + onPressed: (item) { + _onTapService(item); + }, + ); + }, + ).toList(), + ); + } + + Future _onNavigateLocation() async { + final result = await Navigator.pushNamed( + context, + Routes.chooseLocation, + arguments: _locationSelected, + ); + if (result != null) { + setState(() { + _locationSelected = result; + }); + updateLocation(_locationSelected[0].name); + } + } + + String _buildLocationText() { + return UtilPreferences.getString(Preferences.location); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: CustomScrollView( + slivers: [ + SliverPersistentHeader( + delegate: AppBarHomeSliver( + expandedHeight: MediaQuery.of(context).size.height * 0.30, + banners: _homePage?.banner ?? [], + ), + pinned: true, + ), + SliverList( + delegate: SliverChildListDelegate([ + SafeArea( + top: false, + bottom: false, + child: Column( + children: [ + Padding( + padding: EdgeInsets.only( + top: 15, + right: 20, + left: 20, + ), + child: InkWell( + onTap: _onNavigateLocation, + child: Container( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + Translate.of(context) + .translate('location'), + style: Theme.of(context) + .textTheme + .headline6 + .copyWith( + fontWeight: FontWeight.w600, + ), + ), + Padding( + padding: EdgeInsets.only(top: 5), + child: Text( + _buildLocationText(), + style: Theme.of(context) + .textTheme + .caption + .copyWith( + color: Theme.of(context) + .primaryColor, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ), + RotatedBox( + quarterTurns: UtilLanguage.isRTL() ? 2 : 0, + child: Icon( + Icons.keyboard_arrow_right, + textDirection: TextDirection.ltr, + ), + ) + ], + ), + ), + ), + ), + Container( + padding: EdgeInsets.only( + top: 15, + bottom: 0, + left: 35, + right: 35, + ), + child: _buildCategory(), + ), + Container( + padding: EdgeInsets.only( + top: 15, + left: 20, + right: 20, + ), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Dashboard', + style: Theme.of(context) + .textTheme + .headline6 + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 3)), + Text( + 'Urgent Care and Red Cross Facilities Map', + style: Theme.of(context).textTheme.bodyText1, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + width: + MediaQuery.of(context).size.width * 0.89, + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: GestureDetector( + onTap: () { + launch( + 'https://connecticut.maps.arcgis.com/apps/opsdashboard/index.html#/728b88c606af45dcb3f891ffa20ee7cf'); + }, + child: Image.asset( + 'assets/images/dashboard.png', + fit: BoxFit.cover, + ), + ))) + ], + ), + ], + ), + ), + ], + ), + ) + ]), + ) + ], + ), + ); + } +} diff --git a/lib/screens/home/home_category_item.dart b/lib/screens/home/home_category_item.dart new file mode 100644 index 0000000..07f0905 --- /dev/null +++ b/lib/screens/home/home_category_item.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:shimmer/shimmer.dart'; + +class HomeCategoryItem extends StatelessWidget { + final CategoryModel item; + final ValueChanged onPressed; + + HomeCategoryItem({ + Key key, + this.item, + this.onPressed, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if (item == null) { + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Container( + width: MediaQuery.of(context).size.width * 0.26, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 36, + height: 36, + alignment: Alignment.center, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(top: 3), + child: Text( + Translate.of(context).translate('loading'), + style: Theme.of(context) + .textTheme + .caption + .copyWith(fontWeight: FontWeight.bold), + ), + ), + ], + ), + ), + ); + } + + return Container( + width: MediaQuery.of(context).size.width * 0.26, + child: GestureDetector( + onTap: () => onPressed(item), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 36, + height: 36, + alignment: Alignment.center, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: item.color, + ), + child: Icon( + item.icon, + size: 18, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(top: 3, left: 2, right: 2), + child: Text( + item.title, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .caption + .copyWith(fontWeight: FontWeight.w500), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/home/home_category_list.dart b/lib/screens/home/home_category_list.dart new file mode 100644 index 0000000..2e201d4 --- /dev/null +++ b/lib/screens/home/home_category_list.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/screens/home/home_category_item.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class HomeCategoryList extends StatelessWidget { + final List category; + final Function(CategoryModel) onPress; + final VoidCallback onOpenList; + + HomeCategoryList({ + Key key, + this.category, + this.onPress, + this.onOpenList, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return SafeArea( + bottom: false, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + topRight: Radius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.only(left: 16, right: 16), + child: IntrinsicHeight( + child: Column( + children: [ + Container( + margin: EdgeInsets.all(8), + width: 40, + height: 3, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: Theme.of(context).dividerColor, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + Translate.of(context).translate('more_options'), + style: Theme.of(context) + .textTheme + .subtitle1 + .copyWith(fontWeight: FontWeight.w600), + ), + GestureDetector( + onTap: onOpenList, + child: Padding( + padding: EdgeInsets.only(top: 4, bottom: 4), + ), + ), + ], + ), + Padding( + padding: EdgeInsets.only(top: 16, bottom: 24), + child: Wrap( + runSpacing: 16, + alignment: WrapAlignment.center, + children: category.map( + (item) { + return HomeCategoryItem( + item: item, + onPressed: onPress, + ); + }, + ).toList(), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/home/home_sliver_app_bar.dart b/lib/screens/home/home_sliver_app_bar.dart new file mode 100644 index 0000000..2100b1f --- /dev/null +++ b/lib/screens/home/home_sliver_app_bar.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/screens/home/home_swiper.dart'; + +class AppBarHomeSliver extends SliverPersistentHeaderDelegate { + final double expandedHeight; + final List banners; + + AppBarHomeSliver({this.expandedHeight, this.banners}); + + @override + Widget build(context, shrinkOffset, overlapsContent) { + return Stack( + alignment: Alignment.bottomCenter, + children: [ + Padding( + padding: EdgeInsets.only(bottom: 15), + child: HomeSwipe( + images: banners, + height: expandedHeight, + ), + ), + ], + ); + } + + @override + double get maxExtent => expandedHeight; + + @override + double get minExtent => 120; + + @override + bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true; +} diff --git a/lib/screens/home/home_swiper.dart b/lib/screens/home/home_swiper.dart new file mode 100644 index 0000000..2dbf757 --- /dev/null +++ b/lib/screens/home/home_swiper.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_swiper/flutter_swiper.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:shimmer/shimmer.dart'; + +class HomeSwipe extends StatelessWidget { + HomeSwipe({ + Key key, + @required this.images, + this.height, + }) : super(key: key); + final double height; + final List images; + + @override + Widget build(BuildContext context) { + if (images.length > 0) { + return Swiper( + itemBuilder: (BuildContext context, int index) { + return Image.asset( + images[index].image, + fit: BoxFit.cover, + ); + }, + autoplayDelay: 3000, + autoplayDisableOnInteraction: false, + autoplay: true, + itemCount: images.length, + pagination: SwiperPagination( + alignment: Alignment(0.0, 1), + builder: SwiperPagination.dots, + ), + ); + } + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Container( + color: Colors.white, + ), + ); + } +} diff --git a/lib/screens/language_setting/language_setting.dart b/lib/screens/language_setting/language_setting.dart new file mode 100644 index 0000000..1ab72fd --- /dev/null +++ b/lib/screens/language_setting/language_setting.dart @@ -0,0 +1,152 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:listar_flutter/blocs/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/language.dart'; +import 'package:listar_flutter/utils/other.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:listar_flutter/widgets/widget.dart'; + +class LanguageSetting extends StatefulWidget { + LanguageSetting({Key key}) : super(key: key); + + @override + _LanguageSettingState createState() { + return _LanguageSettingState(); + } +} + +class _LanguageSettingState extends State { + LanguageBloc _languageBloc; + final _textLanguageController = TextEditingController(); + bool _loading = false; + + List _listLanguage = AppLanguage.supportLanguage; + Locale _languageSelected = AppLanguage.defaultLanguage; + + @override + void initState() { + _languageBloc = BlocProvider.of(context); + super.initState(); + } + + ///On filter language + void _onFilter(String text) { + if (text.isEmpty) { + setState(() { + _listLanguage = AppLanguage.supportLanguage; + }); + return; + } + setState(() { + _listLanguage = _listLanguage.where(((item) { + return UtilLanguage.getGlobalLanguageName(item.languageCode) + .toUpperCase() + .contains(text.toUpperCase()); + })).toList(); + }); + } + + ///On change language + Future _changeLanguage() async { + UtilOther.hiddenKeyboard(context); + setState(() { + _loading = true; + }); + _languageBloc.add( + ChangeLanguage(_languageSelected), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text(Translate.of(context).translate('change_language')), + ), + body: SafeArea( + child: Column( + children: [ + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 15, + bottom: 15, + ), + child: AppTextInput( + hintText: Translate.of(context).translate('search'), + icon: Icon(Icons.clear), + controller: _textLanguageController, + onChanged: _onFilter, + onSubmitted: _onFilter, + onTapIcon: () async { + await Future.delayed(Duration(milliseconds: 100)); + _textLanguageController.clear(); + }, + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.only(left: 20, right: 20), + itemBuilder: (context, index) { + final item = _listLanguage[index]; + final trailing = item == _languageSelected + ? Icon( + Icons.check, + color: Theme.of(context).primaryColor, + ) + : null; + return AppListTitle( + title: UtilLanguage.getGlobalLanguageName( + item.languageCode, + ), + textStyle: item == _languageSelected + ? Theme.of(context) + .textTheme + .subtitle1 + .copyWith(color: Theme.of(context).primaryColor) + : null, + trailing: trailing, + onPressed: () { + setState(() { + _languageSelected = item; + }); + }, + ); + }, + itemCount: _listLanguage.length, + ), + ), + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 15, + bottom: 15, + ), + child: BlocListener( + listener: (context, state) { + if (state is LanguageUpdated) { + setState(() { + _loading = false; + }); + } + }, + child: AppButton( + onPressed: () { + _changeLanguage(); + }, + text: Translate.of(context).translate('confirm'), + loading: _loading, + disableTouchWhenLoading: true, + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/loading/loading.dart b/lib/screens/loading/loading.dart new file mode 100644 index 0000000..47cc3fb --- /dev/null +++ b/lib/screens/loading/loading.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:listar_flutter/blocs/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; + +class SplashScreen extends StatefulWidget { + SplashScreen({Key key}) : super(key: key); + + @override + _SplashScreenState createState() { + return _SplashScreenState(); + } +} + +class _SplashScreenState extends State { + ApplicationBloc _applicationBloc; + + @override + void initState() { + _applicationBloc = BlocProvider.of(context); + _applicationBloc.add(SetupApplication()); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Stack( + alignment: Alignment.center, + children: [ + Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset(Images.Logo, width: 120, height: 120), + ], + ), + ), + Padding( + padding: EdgeInsets.only(top: 300), + child: SizedBox( + width: 26, + height: 26, + child: CircularProgressIndicator(strokeWidth: 2), + ), + ) + ], + ), + ); + } +} diff --git a/lib/screens/profile/profile.dart b/lib/screens/profile/profile.dart new file mode 100644 index 0000000..9e5357e --- /dev/null +++ b/lib/screens/profile/profile.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:listar_flutter/widgets/widget.dart'; + +class Profile extends StatefulWidget { + Profile({Key key}) : super(key: key); + + @override + _ProfileState createState() { + return _ProfileState(); + } +} + +class _ProfileState extends State { + @override + void initState() { + super.initState(); + } + + ///On navigation + void _onNavigate(String route) { + Navigator.pushNamed(context, route); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + Translate.of(context).translate('pref'), + ), + ), + body: SafeArea( + child: ListView( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 15, + ), + children: [ + // AppListTitle( + // title: Translate.of(context).translate('language'), + // onPressed: () { + // _onNavigate(Routes.changeLanguage); + // }, + // trailing: Row( + // children: [ + // Text( + // UtilLanguage.getGlobalLanguageName( + // AppLanguage.defaultLanguage.languageCode, + // ), + // style: Theme.of(context).textTheme.bodyText1, + // ), + // RotatedBox( + // quarterTurns: UtilLanguage.isRTL() ? 2 : 0, + // child: Icon( + // Icons.keyboard_arrow_right, + // textDirection: TextDirection.ltr, + // ), + // ), + // ], + // ), + // ), + AppListTitle( + title: Translate.of(context).translate('theme'), + onPressed: () { + _onNavigate(Routes.themeSetting); + }, + trailing: Container( + margin: EdgeInsets.only(right: 10), + width: 16, + height: 16, + color: Theme.of(context).primaryColor, + ), + ), + AppListTitle( + title: Translate.of(context).translate('terms_of_use'), + onPressed: () { + Navigator.pushNamed(context, Routes.termsOfUse, + arguments: Translate.of(context).translate('terms_of_use')); + }, + trailing: Row( + children: [ + RotatedBox( + quarterTurns: UtilLanguage.isRTL() ? 2 : 0, + child: Icon( + Icons.keyboard_arrow_right, + textDirection: TextDirection.ltr, + ), + ), + ], + ), + ), + AppListTitle( + title: Translate.of(context).translate('version'), + onPressed: () {}, + trailing: Row( + children: [ + Text( + Application.version, + style: Theme.of(context).textTheme.bodyText1, + ), + RotatedBox( + quarterTurns: UtilLanguage.isRTL() ? 2 : 0, + child: Icon( + Icons.arrow_drop_up, + textDirection: TextDirection.ltr, + ), + ), + ], + ), + border: false, + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/evacuation.dart b/lib/screens/safer_main_menu/evacuation.dart new file mode 100644 index 0000000..3fe2a51 --- /dev/null +++ b/lib/screens/safer_main_menu/evacuation.dart @@ -0,0 +1,304 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class Evacuation extends StatefulWidget { + final String title; + + Evacuation({Key key, this.title}) : super(key: key); + + @override + _EvacuationState createState() { + return _EvacuationState(); + } +} + +class _EvacuationState extends State { + String location = UtilPreferences.getString(Preferences.location); + + Map emergencyService = { + "Bridgeport": "https://www.bridgeportct.gov/emergencymgmt", + "Milford": "https://www.ci.milford.ct.us/emergency-management-services", + "New Haven": + "https://www.newhavenct.gov/gov/depts/emergency_info/default.htm", + "New London": "http://newlondonct.org/content/8251/13617/default.aspx", + "Norwalk": "https://www.norwalkct.org/324/Emergency-Management", + }; + + Map evacuationRoutes = { + "Bridgeport": + "https://www.redcross.org/get-help/disaster-relief-and-recovery-services/find-an-open-shelter.html", + "Milford": + "https://www.redcross.org/get-help/disaster-relief-and-recovery-services/find-an-open-shelter.html", + "New Haven": + "https://www.redcross.org/get-help/disaster-relief-and-recovery-services/find-an-open-shelter.html", + "New London": + "https://www.redcross.org/get-help/disaster-relief-and-recovery-services/find-an-open-shelter.html", + "Norwalk": "https://www.norwalkct.org/FAQ.aspx?QID=226", + }; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Alerted for Evacuation', + children: [ + TextSpan( + text: '\n\n- Before Leaving:', + style: TextStyle(fontSize: 15)), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: '\n - Load emergency supplies in a car', + recognizer: TapGestureRecognizer() + ..onTap = () { + Navigator.pushNamed(context, Routes.supplies, + arguments: Translate.of(context) + .translate('Supplies')); + }, + ), + TextSpan( + text: + '\n - Secure pets/livestock with food/water for 5 days\n - Disconnect all electrical appliances\n - Shut off electricity, gas, water\n - Secure people in car\n - Secure pets in carrier/crate in car, if pet shelter open', + style: TextStyle(fontSize: 15)), + TextSpan( + text: '\n\n- While en route', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n - Follow the evacuation routes given\n - Expect heavy traffic\n - Monitor route change\n - Avoid creeks/flooded roads\n - If stranded, call emergency assistance or search alternative routes (see below)', + style: TextStyle(fontSize: 15)), + ], + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Evacuation Routes/Shelters', + children: [ + TextSpan( + text: '\n\n- Local emergency service: ', + style: TextStyle(fontSize: 15)), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: 'City of $location', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch(emergencyService[location]); + }, + ), + TextSpan( + text: '\n- Evacuation routes/shelter location: ', + style: TextStyle(fontSize: 15)), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: 'City of $location', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch(evacuationRoutes[location]); + }, + ), + TextSpan( + text: '\n- Alternative evacuation shelter locator:', + style: TextStyle(fontSize: 15)), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: '\n - American Red Cross', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('http://www.redcross.org/find-help/shelter'); + }, + ), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: '\n - American Red Cross, CT Chapter', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('http://www.redcross.org/ct/'); + }, + ), + ], + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Evacuation Transport', + children: [ + TextSpan( + text: + '\n\n- Prepare household to evacuate in car\n- Prepare to evacuate to shelter or others\' home\n- Arrange for transport, if lacking car access\n- Arrange for transport, if unable to drive', + style: TextStyle(fontSize: 15)), + ], + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Evacuation Items in Car', + children: [ + TextSpan( + text: + '\n\nWaterproof items below, as needed\n- Full-tank of gasoline in car(s)\n- Fully-charged cell phone(s)\n- A first aid kit\n- Sleeping bags, blankets\n- Emergency food, water, medicine\n- Flashlights and flares\n- Booster cables and maps\n- Rubber boots, sturdy shoes, waterproof gloves', + style: TextStyle(fontSize: 15)), + ], + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Not Yet Alerted for Evacuation', + children: [ + TextSpan( + text: '\n\n- Monitor changing conditions', + style: TextStyle(fontSize: 15)), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: '\n- Prepare for Emergency Needs', + recognizer: TapGestureRecognizer() + ..onTap = () { + Navigator.pushNamed(context, Routes.supplies, + arguments: Translate.of(context) + .translate('Supplies')); + }, + ), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: + '\n- Prepare for disruption of power, utility service, communication, transportation', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.ready.gov/power-outages'); + }, + ), + TextSpan( + style: TextStyle( + fontSize: 15, color: Colors.blue.withOpacity(1)), + text: '\n- Secure your property safely', + recognizer: TapGestureRecognizer() + ..onTap = () { + Navigator.pushNamed(context, Routes.propertySafety, + arguments: Translate.of(context) + .translate('Property Safety')); + }, + ), + TextSpan( + text: + '\n- Be evacuation-ready in car or to other\'s home', + style: TextStyle(fontSize: 15)), + ], + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/personal_risk.dart b/lib/screens/safer_main_menu/personal_risk.dart new file mode 100644 index 0000000..e433616 --- /dev/null +++ b/lib/screens/safer_main_menu/personal_risk.dart @@ -0,0 +1,576 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinbox/material.dart'; + +class PersonalRisk extends StatefulWidget { + final String title; + + PersonalRisk({Key key, this.title}) : super(key: key); + + @override + _PersonalRiskState createState() { + return _PersonalRiskState(); + } +} + +class _PersonalRiskState extends State { + List _specialNeeds = []; + List _priorFlooding = []; + List _priorDamages = []; + List _priorDangers = []; + List _priorOutage = []; + List _safePlace = []; + List _doYouHave = []; + + Map _riskScore = { + "specialNeeds": 0, + "priorFlooding": 0, + "priorDamages": 0, + "priorDangers": 0, + "priorOutage": 0, + "safePlace": 0, + "doYouHave": 0, + }; + + final Map> _headingData = { + "specialNeeds": [ + "Medication", + "Walking", + "Bathing", + "Wheelchair", + "Breathing", + "Feeding", + "Cooking", + "Cleaning", + "Young Children", + "Pets", + ], + "priorFlooding": [ + "Front/Back Yard", + "Ground Floor", + "Basement", + "Street", + "Neighborhood", + ], + "priorDamages": [ + "Roof", + "Gutters", + "Window(s)", + "Door(s)", + "Garage(s)", + "House Foundation", + "Out Buildings", + ], + "priorDangers": [ + "Fallen Trees near Houses", + "Carbon Monoxide Leak", + "Propane Tank Leak", + "Sewage Overflow", + "Mudslide Nearby", + "Sinkhole Nearby", + "Electrical Pole Fire", + "Fallen Electrical Wires", + ], + "priorOutage": [ + "Water Outage", + "Sanitation System Outage", + "Electrical Power Outage", + "Air Conditioning Outage", + "Heating System Outage", + ], + "safePlace": [ + "Windowless Hallway", + "Windowless Closet", + "Bathtub in Windowless Room", + "Underground Shelter", + "Neighbor's House", + "Friend's House", + "Relative's House", + ], + "doYouHave": [ + "Functional Car", + "Functional Smartphone", + "Functional Fixed-line Phone", + "Operable Radio with Batteries", + "Electrical Generator", + "Evacuation Plan", + "Disaster Kit", + ] + }; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, fontSize: 20, fontFamily: 'Raleway'), + text: + 'Your Risk Score: ${_riskScore.values.reduce((sum, element) => sum + element)}', + ))), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Special Needs Care', + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + children: _headingData["specialNeeds"].map((item) { + final bool selected = _specialNeeds.contains(item); + return SizedBox( + height: 32, + child: FilterChip( + selected: selected, + label: Text(item), + onSelected: (value) { + selected + ? _specialNeeds.remove(item) + : _specialNeeds.add(item); + setState(() { + _specialNeeds = _specialNeeds; + _riskScore["specialNeeds"] = _specialNeeds.length; + }); + }, + ), + ); + }).toList(), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Prior Flooding', + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + children: _headingData["priorFlooding"].map((item) { + final bool selected = _priorFlooding.contains(item); + return SizedBox( + height: 32, + child: FilterChip( + selected: selected, + label: Text(item), + onSelected: (value) { + selected + ? _priorFlooding.remove(item) + : _priorFlooding.add(item); + setState(() { + _priorFlooding = _priorFlooding; + _riskScore["priorFlooding"] = + _priorFlooding.length; + }); + }, + ), + ); + }).toList(), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Prior Damages', + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + children: _headingData["priorDamages"].map((item) { + final bool selected = _priorDamages.contains(item); + return SizedBox( + height: 32, + child: FilterChip( + selected: selected, + label: Text(item), + onSelected: (value) { + selected + ? _priorDamages.remove(item) + : _priorDamages.add(item); + setState(() { + _priorDamages = _priorDamages; + _riskScore["priorDamages"] = _priorDamages.length; + }); + }, + ), + ); + }).toList(), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Prior Dangers', + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + children: _headingData["priorDangers"].map((item) { + final bool selected = _priorDangers.contains(item); + return SizedBox( + height: 32, + child: FilterChip( + selected: selected, + label: Text(item), + onSelected: (value) { + selected + ? _priorDangers.remove(item) + : _priorDangers.add(item); + setState(() { + _priorDangers = _priorDangers; + _riskScore["priorDangers"] = _priorDangers.length; + }); + }, + ), + ); + }).toList(), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Prior Outage', + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + children: _headingData["priorOutage"].map((item) { + final bool selected = _priorOutage.contains(item); + return SizedBox( + height: 32, + child: FilterChip( + selected: selected, + label: Text(item), + onSelected: (value) { + selected + ? _priorOutage.remove(item) + : _priorOutage.add(item); + setState(() { + _priorOutage = _priorOutage; + _riskScore["priorOutage"] = _priorOutage.length; + }); + }, + ), + ); + }).toList(), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Safe Place to Hide', + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + children: _headingData["safePlace"].map((item) { + final bool selected = _safePlace.contains(item); + return SizedBox( + height: 32, + child: FilterChip( + selected: selected, + label: Text(item), + onSelected: (value) { + selected + ? _safePlace.remove(item) + : _safePlace.add(item); + setState(() { + _safePlace = _safePlace; + _riskScore["safePlace"] = _safePlace.length; + }); + }, + ), + ); + }).toList(), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Do you have a(n)?', + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 15, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + children: _headingData["doYouHave"].map((item) { + final bool selected = _doYouHave.contains(item); + return SizedBox( + height: 32, + child: FilterChip( + selected: selected, + label: Text(item), + onSelected: (value) { + selected + ? _doYouHave.remove(item) + : _doYouHave.add(item); + setState(() { + _doYouHave = _doYouHave; + _riskScore["doYouHave"] = _doYouHave.length; + }); + }, + ), + ); + }).toList(), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, fontSize: 20, fontFamily: 'Raleway'), + text: + 'Your Risk Score: ${_riskScore.values.reduce((sum, element) => sum + element)}', + ))), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/personal_safety.dart b/lib/screens/safer_main_menu/personal_safety.dart new file mode 100644 index 0000000..f1a34d5 --- /dev/null +++ b/lib/screens/safer_main_menu/personal_safety.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +class PersonalSafety extends StatefulWidget { + final String title; + + PersonalSafety({Key key, this.title}) : super(key: key); + + @override + _PersonalSafetyState createState() { + return _PersonalSafetyState(); + } +} + +class _PersonalSafetyState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'Personal Safety in a Storm', + children: [ + TextSpan( + text: '\n\n- Stay home/indoors', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\n- Stay away from:\n - Electrical equipment\n - Windows/skylights/doors', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\n- Stay in lower home level:\n - Glassless space\n - Hallway/closet/bathroom', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\n- Shut off electricty breaker\n - Hear thundering\n - See lightening\n - If flooding is likely', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\n- Don\'t use:\n - Phones\n - Bath/shower', + style: TextStyle(fontSize: 15)), + TextSpan( + text: '\n\n- During power loss:', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n - Shut off all appliances:\n - AC, water heater, etc.\n - Computer, toaster, etc.', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n - No refrigerator use:\n - Turn to coldest setting\n - Keep doors shut', + style: TextStyle(fontSize: 15)), + TextSpan( + text: '\n\n- Don\'t go outside', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n - Eye of the storm passed:\n - New wind will strike\n - Lightening can strike\n - Flying debris can strike', + style: TextStyle(fontSize: 15)), + ], + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/property_risk.dart b/lib/screens/safer_main_menu/property_risk.dart new file mode 100644 index 0000000..ece87af --- /dev/null +++ b/lib/screens/safer_main_menu/property_risk.dart @@ -0,0 +1,498 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinbox/flutter_spinbox.dart'; + +class PropertyRisk extends StatefulWidget { + final String title; + + PropertyRisk({Key key, this.title}) : super(key: key); + + @override + _PropertyRiskState createState() { + return _PropertyRiskState(); + } +} + +class _PropertyRiskState extends State { + Map _riskScore = { + "buildingStructure": 0, + "roofAge": 0, + "elevation": 0, + "flooding": 0, + "drainage": 0, + "waterDamage": 0, + "window": 0, + "sewage": 0, + "waterSupply": 0, + "fuelSupply": 0, + "itemSecurity": 0, + "treeFalling": 0, + }; + + String _dropDownValue; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/property-risk.png')), + title: Text('Property Risk in a Storm'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Score the items below:', + children: [ + TextSpan( + text: '\n\nScoring Range: 0 - 60', + ), + TextSpan( + text: + '\n0 = no risk \t\t\t\t\t 1 = minimal risk \n2 = low risk \t\t\t 3 = medium risk\n4 = high risk \t\t\t 5 = very high risk', + ), + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/house.png')), + title: Container( + child: DropdownButton( + hint: _dropDownValue == null + ? Text('Dropdown') + : Text( + _dropDownValue, + style: TextStyle(color: Colors.blue), + ), + isExpanded: true, + iconSize: 30.0, + items: ['One', 'Two'].map( + (val) { + return DropdownMenuItem( + value: val, + child: Text(val), + ); + }, + ).toList(), + onChanged: (val) { + setState( + () { + _dropDownValue = val; + }, + ); + }, + )), + subtitle: Container( + child: TextFormField( + decoration: InputDecoration( + labelText: 'Building Age', suffixText: 'years'), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, fontSize: 20, fontFamily: 'Raleway'), + text: + 'Your Risk Score: ${_riskScore.values.reduce((sum, element) => sum + element)}', + ))), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Building Structure', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["buildingStructure"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _riskScore["buildingStructure"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Age of the Roof', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["roofAge"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _riskScore["roofAge"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Property Elevation Level', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["elevation"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _riskScore["elevation"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Potential Flooding via Nearby River/Lake', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["flooding"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _riskScore["flooding"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Drainage System Functions', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["drainage"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _riskScore["drainage"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Potential Water Damage on Property', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["waterDamage"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _riskScore["waterDamage"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Window Protection from Storm', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["window"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _riskScore["window"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Sewage System', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["sewage"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _riskScore["sewage"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Water Supply', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["waterSupply"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _riskScore["waterSupply"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Heating/Cooking Fuel Supply', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["fuelSupply"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _riskScore["fuelSupply"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Boat/Outdoor Item Security', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["itemSecurity"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _riskScore["itemSecurity"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only( + left: 25, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontFamily: 'Raleway'), + text: 'Tree Falling on House', + )), + ), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _riskScore["treeFalling"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _riskScore["treeFalling"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, fontSize: 20, fontFamily: 'Raleway'), + text: + 'Your Risk Score: ${_riskScore.values.reduce((sum, element) => sum + element)}', + ))), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/property_safety.dart b/lib/screens/safer_main_menu/property_safety.dart new file mode 100644 index 0000000..f179520 --- /dev/null +++ b/lib/screens/safer_main_menu/property_safety.dart @@ -0,0 +1,279 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class PropertySafety extends StatefulWidget { + final String title; + + PropertySafety({Key key, this.title}) : super(key: key); + + @override + _PropertySafetyState createState() { + return _PropertySafetyState(); + } +} + +class _PropertySafetyState extends State { + String location = UtilPreferences.getString(Preferences.location); + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text('Property Safety'), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/map.png')), + title: const Text('Map Your Geographic Terrain'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Google Maps', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.google.com/maps/'); + }, + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/flood-zone.png')), + title: const Text('Flood Zone'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Flood Maps', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://hazards-fema.maps.arcgis.com/apps/webappviewer/index.html?id=8b0adb51996444d4879338b5529aa9cd'); + }, + children: [ + TextSpan( + text: '\nFEMA Flood Map Address Search', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.fema.gov/flood-maps'); + }), + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/structure.png')), + title: const Text('Structural Integrity'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Home Structure Safety', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.nachi.org/structural-design-basics-residential-construction.htm'); + }, + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/drainage.png')), + title: const Text('Drainage System'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Rainwater Drainage System', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.youtube.com/watch?v=Zgz33tfSu8M'); + }, + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/home-flooding.png')), + title: const Text('Home Flooding'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Home Flooding Mitigation', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.youtube.com/watch?v=Zgz33tfSu8M'); + }, + children: [ + TextSpan( + text: '\nFlood Prevention Tips', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.youtube.com/watch?v=g_BkmkqgUMg'); + }), + TextSpan( + text: '\nWhat to do during a flood?', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.youtube.com/watch?v=g_BkmkqgUMg'); + }), + TextSpan( + text: '\nHow to survive a flood evacuation?', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.youtube.com/watch?v=fz2_oeeA52c'); + }), + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/boat.png')), + title: const Text('Boat/Outdoor Items'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: + 'Prepare to secure your boat and store your outdoor items.', + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/beach.png')), + title: const Text('Beach Safety'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Bridgeport Flood/Storm Surge Map', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.bridgeportct.gov/filestorage/341650/341652/346107/342903/SLOSH-bridgeport_(2).pdf'); + }, + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/stay_in_touch.dart b/lib/screens/safer_main_menu/stay_in_touch.dart new file mode 100644 index 0000000..64d36d5 --- /dev/null +++ b/lib/screens/safer_main_menu/stay_in_touch.dart @@ -0,0 +1,209 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class StayInTouch extends StatefulWidget { + final String title; + + StayInTouch({Key key, this.title}) : super(key: key); + + @override + _StayInTouchState createState() { + return _StayInTouchState(); + } +} + +class _StayInTouchState extends State { + String location = UtilPreferences.getString(Preferences.location); + Map townEmergencyLink = { + "Bridgeport": + "https://www.bridgeportct.gov/content/341307/341419/368105.aspx", + "Milford": "https://www.ci.milford.ct.us/emergency-management-services", + "New Haven": + "https://www.newhavenct.gov/cityservices/emergency_services/default.htm", + "New London": + "http://www.ci.new-london.ct.us/content/8251/13617/default.aspx", + "Norwalk": "https://www.norwalkct.org/324/Emergency-Management", + }; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/social_media.png')), + title: const Text('Social Media'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Facebook', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.facebook.com'); + }, + children: [ + TextSpan( + text: '\nTwitter', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.twitter.com'); + }, + ) + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/police.png')), + title: const Text('Police, Fire, and Medical Emergency:'), + subtitle: Text( + 'Call 911', + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/emergency.png')), + title: const Text('Emergency Needs'), + subtitle: Text( + 'Call 211', + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/emergency-service.png')), + title: const Text('Emergency Service Center'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'City of $location', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch(townEmergencyLink[location]); + }, + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/resources.png')), + title: const Text('Resources'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Get in Contact with FEMA', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.fema.gov/about/contact'); + }, + children: [ + TextSpan( + text: '\nRed Cross Relief', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.redcross.org/get-help/disaster-relief-and-recovery-services.html'); + }, + ) + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/storm_tracking.dart b/lib/screens/safer_main_menu/storm_tracking.dart new file mode 100644 index 0000000..00fa63c --- /dev/null +++ b/lib/screens/safer_main_menu/storm_tracking.dart @@ -0,0 +1,232 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class StormTracking extends StatefulWidget { + final String title; + + StormTracking({Key key, this.title}) : super(key: key); + + @override + _StormTrackingState createState() { + return _StormTrackingState(); + } +} + +class _StormTrackingState extends State { + String location = UtilPreferences.getString(Preferences.location); + Map townAlertNotification = { + "Bridgeport": "https://veoci.com/veoci/p/form/y9qpadaf4mq9#tab=entryForm", + "Milford": "https://www.ci.milford.ct.us/sign-up-for-e-alerts", + "New Haven": + "https://www.newhavenct.gov/gov/depts/emergency_info/alerts.htm", + "New London": "", + "Norwalk": "", + }; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/ct-alert.png')), + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontSize: 16, + fontFamily: 'Raleway'), + text: 'Register for CT Alert Notification System', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://portal.ct.gov/CTAlert/Common-Elements/Common-Elements/Sign-up-for-CT-Alerts'); + }, + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/ct-map.png')), + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontSize: 16, + fontFamily: 'Raleway'), + text: 'Register for $location Alert Notification', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch(townAlertNotification[location]); + }, + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/nhc.png')), + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontSize: 16, + fontFamily: 'Raleway'), + text: 'National Hurricane Center', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.nhc.noaa.gov/'); + })), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/storm.png')), + title: const Text('Severe Weather and Storm Tracker'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: '- Weather.com', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://weather.com/'); + }, + children: [ + TextSpan( + text: '\n\nNational Weather Service:', + style: TextStyle( + color: Colors.black.withOpacity(0.6)), + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.facebook.com/'); + }), + TextSpan( + text: '\n - Weather.gov', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.weather.gov/'); + }), + TextSpan( + text: '\n - Weather Forecast Office', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.weather.gov/okx/'); + }), + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/tv.png')), + title: const Text('Weather Coverage on Local TV Stations'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: '- WTNH (ABC)', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.wtnh.com/weather-alerts/'); + }, + children: [ + TextSpan( + text: '\n- WFSP (CBS)', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch('https://www.wfsb.com/weather/maps/'); + }), + TextSpan( + text: '\n- WVIT (NBC)', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://www.nbcconnecticut.com/weather/severe-weather-alerts/'); + }), + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/safer_main_menu/supplies.dart b/lib/screens/safer_main_menu/supplies.dart new file mode 100644 index 0000000..3f10daf --- /dev/null +++ b/lib/screens/safer_main_menu/supplies.dart @@ -0,0 +1,553 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinbox/flutter_spinbox.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class Supplies extends StatefulWidget { + final String title; + + Supplies({Key key, this.title}) : super(key: key); + + @override + _SuppliesState createState() { + return _SuppliesState(); + } +} + +class _SuppliesState extends State { + Map _readinessScore = { + "necessities": 0, + "food": 0, + "water": 0, + "safety": 0, + "medical": 0, + "care": 0, + "tools": 0, + "communication": 0, + "documents": 0, + "power": 0, + }; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/green-check.png')), + title: const Text('Readiness for Emergency'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Score the items below:', + children: [ + TextSpan( + text: '\n\nScoring Range: 0 - 50', + ), + TextSpan( + text: + '\n0 = no risk \t\t\t\t\t 1 = minimal risk \n2 = low risk \t\t\t 3 = medium risk\n4 = high risk \t\t\t 5 = very high risk', + ), + ], + ), + )), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, fontSize: 18, fontFamily: 'Raleway'), + text: + 'Your Readiness Score: ${_readinessScore.values.reduce((sum, element) => sum + element)}', + ))), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/burger.png')), + title: const Text('Access to Emergency Necessities'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.blue.withOpacity(1), + fontFamily: 'Raleway'), + text: 'Register Here', + recognizer: TapGestureRecognizer() + ..onTap = () { + launch( + 'https://biznet.ct.gov/cp-openclosewebservice/index.html'); + }), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["necessities"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["necessities"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/food.png')), + title: const Text('Food 3-5 Day Supply'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- Ready-to-eat Food', + children: [ + TextSpan( + text: '\n- Baby Food, if needed', + ), + TextSpan( + text: '\n- Special Diet Food, if needed', + ), + TextSpan( + text: '\n- Pet Food, if needed', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["food"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _readinessScore["food"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/water.png')), + title: const Text('Drinking Water: 3-5 Day Supply'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- Bottled Water', + children: [ + TextSpan( + text: '\n- 5 Gallons each Person', + ), + TextSpan( + text: '\n- 5 Gallons each Pet, if needed', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["water"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["water"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/safety.png')), + title: const Text('Personal Safety'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- First Aid Kit/Manual', + children: [ + TextSpan( + text: + '\n- Insect Repellent (with DEET or Picaridin)', + ), + TextSpan( + text: + '\n- Long-sleeved/Legged Clothing Against Mosquito Bites', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["safety"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["safety"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/medical.png')), + title: const Text('Medical Supply'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- Over-the-counter Medicine', + children: [ + TextSpan( + text: '\n- Prescription Medicines', + ), + TextSpan( + text: '\n- Medical Devices, if needed', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["medical"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["medical"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/care.png')), + title: const Text('Personal Care'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: + '\n- Personal Hygiene (Soap, Shampoo, Toothpaste, Sanitary Napkins, etc.)', + children: [ + TextSpan( + text: '\n- Sleeping Bags or Blankets', + ), + TextSpan( + text: + '\n- Disposable Cleaning Supplies (Baby Wipes, Dry Shampoos, etc.)', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["care"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => + setState(() => _readinessScore["care"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/tools.png')), + title: const Text('Handy Tools'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- Manual Can Opener', + children: [ + TextSpan( + text: '\n- Flashlights', + ), + TextSpan( + text: '\n- Batteries', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["tools"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["tools"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/phone.png')), + title: const Text('Communication Devices'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- Fully-charged Cellular Phone', + children: [ + TextSpan( + text: + '\n- Battery-powered Radio and Extra Batteries', + ), + TextSpan( + text: '\n- Special Diet Food, if needed', + ), + TextSpan( + text: '\n- Pet Food, if needed', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["communication"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["communication"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: + AssetImage('assets/images/documents.png')), + title: const Text('Important Documents'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- Waterproofed Insurance/ID Cards', + children: [ + TextSpan( + text: '\n- Waterproofed Medical Records, if needed', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["documents"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["documents"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + leading: CircleAvatar( + backgroundImage: AssetImage('assets/images/power.png')), + title: const Text('Power Supply'), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black.withOpacity(1), + fontFamily: 'Raleway'), + text: '\n- Power Generator', + children: [ + TextSpan( + text: '\n- Gasoline in Cans', + ), + ], + ), + )), + Padding( + child: SpinBox( + min: 0, + max: 5, + value: _readinessScore["power"].toDouble(), + decoration: InputDecoration(border: InputBorder.none), + validator: (text) => text.isEmpty ? 'Invalid' : null, + onChanged: (value) => setState( + () => _readinessScore["power"] = value.toInt()), + ), + padding: EdgeInsets.only(left: 10), + ), + ], + ), + ), + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, fontSize: 18, fontFamily: 'Raleway'), + text: + 'Your Readiness Score: ${_readinessScore.values.reduce((sum, element) => sum + element)}', + ))), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/screen.dart b/lib/screens/screen.dart new file mode 100644 index 0000000..4ef9971 --- /dev/null +++ b/lib/screens/screen.dart @@ -0,0 +1,16 @@ +export 'font_setting/font_setting.dart'; +export 'home/home.dart'; +export 'language_setting/language_setting.dart'; +export 'loading/loading.dart'; +export 'profile/profile.dart'; +export 'theme_setting/theme_setting.dart'; +export 'terms_of_use/terms_of_use.dart'; + +export 'safer_main_menu/storm_tracking.dart'; +export 'safer_main_menu/personal_safety.dart'; +export 'safer_main_menu/personal_risk.dart'; +export 'safer_main_menu/property_safety.dart'; +export 'safer_main_menu/property_risk.dart'; +export 'safer_main_menu/supplies.dart'; +export 'safer_main_menu/evacuation.dart'; +export 'safer_main_menu/stay_in_touch.dart'; diff --git a/lib/screens/terms_of_use/terms_of_use.dart b/lib/screens/terms_of_use/terms_of_use.dart new file mode 100644 index 0000000..2ae4f25 --- /dev/null +++ b/lib/screens/terms_of_use/terms_of_use.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; + +class TermsOfUse extends StatefulWidget { + final String title; + + TermsOfUse({Key key, this.title}) : super(key: key); + + @override + _TermsOfUseState createState() { + return _TermsOfUseState(); + } +} + +class _TermsOfUseState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + widget.title, + ), + ), + body: ListView( + children: [ + Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + ), + ListTile( + title: RichText( + text: TextSpan( + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontFamily: 'Raleway'), + text: 'SAFER App Terms of Use', + children: [ + TextSpan( + text: + '\n\nBy downloading the SAFER App, the user agrees to the following terms:', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\nThe SAFER App system provider makes no representations or warranties of any kind express or implied, as to the operation of this site or the information, content, or materials included on or otherwise made available to you through this App. The information, content, and materials made available to you through this App are provided by on an "as is" and "as available" basis. By downloading this app, you expressly agree that your use of this app is at your own risk. The SAFER App system provider disclaims all warranties, express or implied, including, but not limited to, implied warranties of merchantability and fitness for a particular purpose to the full extent permissible, by applicable Federal law. The SAFER App system provider does not warrant that the information, content, or materials included on or otherwise made available to you through this App are free of viruses or other harmful elements. The SAFER App system provider will not be liable for any damages of any kind resulting from the use of any information, content, or materials, included on or otherwise made available to you through this App, including, but not limited to direct, indirect, incidental, punitive, and consequential damages.', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\nThe SAFER App system is free of charge to its users; however normal carrier data fees may apply. Please consult your mobile phone carrier for any possible charges related to the use of this App. The SAFER App system does not rent, sell or share personal identification information about you with other people or any other entities.', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\nThe SAFER App system does not endorse any other entities, whether they are for-profit, non-profit or government entities. None of the information, content and materials included on or otherwise made available to you through this App implies that the SAFER App system endorses any entities. The SAFER App system does not provide any emergency assistance. If you are in need of emergency assistance, please contact 9-1-1.', + style: TextStyle(fontSize: 15)), + TextSpan( + text: + '\n\nIn order to maximize the utilities of the SAFER App system, the system may collect user location, property or emergency planning information. For example, user location information is collected to be linked to a city’s emergency management resources such as evacuation routes or evacuation shelters; user property information is collected to aid self-assessment of property risk; user storm preparedness information is collected to provide a self-referenced storm mitigation evaluation tool. In other instances, the SAFER App system may serve as a portal for users to provide personal identification information to another website. For instance, the SAFER App system may directly link users to a state or city’s storm alert system or flood zone maps. Other examples of when the SAFER App system collects personal identification information could be when users complete a survey or participate in an online forum or community, or customize the Services. Turning location services off will disable certain services in the application, including severe weather alerts.', + style: TextStyle(fontSize: 15)), + ], + )), + ), + Padding( + padding: const EdgeInsets.all(8), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/theme_setting/theme_setting.dart b/lib/screens/theme_setting/theme_setting.dart new file mode 100644 index 0000000..bccb2b7 --- /dev/null +++ b/lib/screens/theme_setting/theme_setting.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:listar_flutter/blocs/bloc.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:listar_flutter/widgets/widget.dart'; + +class ThemeSetting extends StatefulWidget { + ThemeSetting({Key key}) : super(key: key); + + @override + _ThemeSettingState createState() { + return _ThemeSettingState(); + } +} + +class _ThemeSettingState extends State { + ThemeBloc _themeBloc; + ThemeModel _currentTheme = AppTheme.currentTheme; + + @override + void initState() { + _themeBloc = BlocProvider.of(context); + super.initState(); + } + + ///On Change Theme + void _onChange() { + _themeBloc.add(ChangeTheme(theme: _currentTheme)); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + Translate.of(context).translate('theme'), + ), + ), + body: SafeArea( + child: Column( + children: [ + Expanded( + child: ListView.builder( + padding: EdgeInsets.only(left: 20, right: 20, top: 10), + itemBuilder: (context, index) { + final item = AppTheme.themeSupport[index]; + final selected = item.name == _currentTheme.name; + return InkWell( + onTap: () { + setState(() { + _currentTheme = item; + }); + }, + child: Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1, + color: Theme.of(context).dividerColor, + ), + ), + ), + child: Padding( + padding: EdgeInsets.only(top: 20, bottom: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 24, + height: 24, + color: item.color, + ), + Padding( + padding: EdgeInsets.only(left: 10), + ), + Text( + Translate.of(context).translate(item.name), + style: Theme.of(context).textTheme.subtitle2, + ) + ], + ), + selected + ? Icon( + Icons.check, + color: Theme.of(context).primaryColor, + ) + : Container() + ], + ), + ), + ), + ); + }, + itemCount: AppTheme.themeSupport.length, + ), + ), + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 15, + bottom: 15, + ), + child: BlocBuilder( + builder: (context, theme) { + return AppButton( + onPressed: _onChange, + text: Translate.of(context).translate('apply'), + loading: theme is ThemeUpdating, + disableTouchWhenLoading: true, + ); + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/utils/asset.dart b/lib/utils/asset.dart new file mode 100644 index 0000000..9160772 --- /dev/null +++ b/lib/utils/asset.dart @@ -0,0 +1,19 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart' show rootBundle; + +class UtilAsset { + static Future> loadJson(String path) async { + String content = await rootBundle.loadString(path); + return jsonDecode(content); + } + + ///Singleton factory + static final UtilAsset _instance = UtilAsset._internal(); + + factory UtilAsset() { + return _instance; + } + + UtilAsset._internal(); +} diff --git a/lib/utils/color.dart b/lib/utils/color.dart new file mode 100644 index 0000000..bb52bce --- /dev/null +++ b/lib/utils/color.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +class UtilColor { + static Color getColorFromHex(String hexColor) { + hexColor = hexColor.toUpperCase().replaceAll("#", ""); + if (hexColor.length == 6) { + hexColor = "FF" + hexColor; + } + if (int.tryParse(hexColor, radix: 16) != null) { + return Color(int.tryParse(hexColor, radix: 16)); + } + return Colors.black; + } + + ///Singleton factory + static final UtilColor _instance = UtilColor._internal(); + + factory UtilColor() { + return _instance; + } + + UtilColor._internal(); +} diff --git a/lib/utils/icon.dart b/lib/utils/icon.dart new file mode 100644 index 0000000..0ba8985 --- /dev/null +++ b/lib/utils/icon.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; + +class UtilIcon { + static IconData getIconData(String name) { + switch (name) { + case 'fas fa-shopping-bag': + case 'shopping_basket': + return Icons.shopping_basket; + case 'fas fa-coffee': + case 'local_drink': + return Icons.local_drink; + case 'fas fa-star': + case 'event_available': + return Icons.event_available; + case 'fas fa-handshake': + case 'all_inclusive': + return Icons.all_inclusive; + case 'fas fa-briefcase': + case 'card_travel': + return Icons.card_travel; + case 'fas fa-utensil': + case 'restaurant': + return Icons.restaurant; + case 'fas fa-car': + case 'directions_car': + return Icons.directions_car; + case 'more_horiz': + return Icons.more_horiz; + case 'wifi': + return Icons.wifi; + case 'whatshot': + return Icons.whatshot; + case 'directions_bus': + return Icons.directions_bus; + case 'shopping_cart': + return Icons.shopping_cart; + case 'pets': + return Icons.pets; + case 'access_time': + return Icons.access_time; + case 'sort': + return Icons.sort; + case "swap_vert": + return Icons.swap_vert; + case 'hotel': + return Icons.hotel; + case 'location_on': + return Icons.location_on; + case 'directions_car': + return Icons.directions_car; + case 'flight': + return Icons.flight; + case 'directions_boat': + return Icons.directions_boat; + case 'event': + return Icons.event; + case 'description': + return Icons.description; + + default: + return Icons.help; + } + } + + ///Singleton factory + static final UtilIcon _instance = UtilIcon._internal(); + + factory UtilIcon() { + return _instance; + } + + UtilIcon._internal(); +} diff --git a/lib/utils/language.dart b/lib/utils/language.dart new file mode 100644 index 0000000..aeade5d --- /dev/null +++ b/lib/utils/language.dart @@ -0,0 +1,62 @@ +import 'package:listar_flutter/configs/config.dart'; + +class UtilLanguage { + ///Get Language Global Language Name + static String getGlobalLanguageName(String code) { + switch (code) { + case 'en': + return 'English'; + case 'vi': + return 'Vietnamese'; + case 'ar': + return 'Arabic'; + case 'da': + return 'Danish'; + case 'de': + return 'German'; + case 'el': + return 'Greek'; + case 'fr': + return 'French'; + case 'he': + return 'Hebrew'; + case 'id': + return 'Indonesian'; + case 'ja': + return 'Japanese'; + case 'ko': + return 'Korean'; + case 'lo': + return 'Lao'; + case 'nl': + return 'Dutch'; + case 'zh': + return 'Chinese'; + case 'fa': + return 'Iran'; + case 'km': + return 'Cambodian'; + default: + return 'Unknown'; + } + } + + static bool isRTL() { + switch (AppLanguage.defaultLanguage.languageCode) { + case "ar": + case "he": + return true; + default: + return false; + } + } + + ///Singleton factory + static final UtilLanguage _instance = UtilLanguage._internal(); + + factory UtilLanguage() { + return _instance; + } + + UtilLanguage._internal(); +} diff --git a/lib/utils/logger.dart b/lib/utils/logger.dart new file mode 100644 index 0000000..802e482 --- /dev/null +++ b/lib/utils/logger.dart @@ -0,0 +1,22 @@ +import 'dart:developer' as developer; + +import 'package:listar_flutter/configs/application.dart'; + +class UtilLogger { + static const String TAG = "LISTAR"; + + static log([String tag = TAG, dynamic msg]) { + if (Application.debug) { + developer.log('$msg', name: tag); + } + } + + ///Singleton factory + static final UtilLogger _instance = UtilLogger._internal(); + + factory UtilLogger() { + return _instance; + } + + UtilLogger._internal(); +} diff --git a/lib/utils/other.dart b/lib/utils/other.dart new file mode 100644 index 0000000..f22cefe --- /dev/null +++ b/lib/utils/other.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +class UtilOther { + static fieldFocusChange( + BuildContext context, + FocusNode current, + FocusNode next, + ) { + current.unfocus(); + FocusScope.of(context).requestFocus(next); + } + + static hiddenKeyboard(BuildContext context) { + FocusScope.of(context).requestFocus(new FocusNode()); + } + + ///Singleton factory + static final UtilOther _instance = UtilOther._internal(); + + factory UtilOther() { + return _instance; + } + + UtilOther._internal(); +} diff --git a/lib/utils/preferences.dart b/lib/utils/preferences.dart new file mode 100644 index 0000000..d6d482e --- /dev/null +++ b/lib/utils/preferences.dart @@ -0,0 +1,76 @@ +import 'package:listar_flutter/configs/config.dart'; + +class UtilPreferences { + static Future clear() { + return Application.preferences.clear(); + } + + static bool containsKey(String key) { + return Application.preferences.containsKey(key); + } + + static dynamic get(String key) { + return Application.preferences.get(key); + } + + static bool getBool(String key) { + return Application.preferences.getBool(key); + } + + static double getDouble(String key) { + return Application.preferences.getDouble(key); + } + + static int getInt(String key) { + return Application.preferences.getInt(key); + } + + static Set getKeys() { + return Application.preferences.getKeys(); + } + + static String getString(String key) { + return Application.preferences.getString(key); + } + + static List getStringList(String key) { + return Application.preferences.getStringList(key); + } + + static Future reload() { + return Application.preferences.reload(); + } + + static Future remove(String key) { + return Application.preferences.remove(key); + } + + static Future setBool(String key, bool value) { + return Application.preferences.setBool(key, value); + } + + static Future setDouble(String key, double value) { + return Application.preferences.setDouble(key, value); + } + + static Future setInt(String key, int value) { + return Application.preferences.setInt(key, value); + } + + static Future setString(String key, String value) { + return Application.preferences.setString(key, value); + } + + static Future setStringList(String key, List value) { + return Application.preferences.setStringList(key, value); + } + + ///Singleton factory + static final UtilPreferences _instance = UtilPreferences._internal(); + + factory UtilPreferences() { + return _instance; + } + + UtilPreferences._internal(); +} diff --git a/lib/utils/theme.dart b/lib/utils/theme.dart new file mode 100644 index 0000000..b881320 --- /dev/null +++ b/lib/utils/theme.dart @@ -0,0 +1,23 @@ +import 'package:listar_flutter/configs/config.dart'; + +class UtilTheme { + static String exportLangTheme(DarkOption option) { + switch (option) { + case DarkOption.dynamic: + return "dynamic_theme"; + case DarkOption.alwaysOff: + return "always_off"; + default: + return "always_on"; + } + } + + ///Singleton factory + static final UtilTheme _instance = UtilTheme._internal(); + + factory UtilTheme() { + return _instance; + } + + UtilTheme._internal(); +} diff --git a/lib/utils/translate.dart b/lib/utils/translate.dart new file mode 100644 index 0000000..6c5effa --- /dev/null +++ b/lib/utils/translate.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/app_locale_delegate.dart'; +import 'package:listar_flutter/utils/utils.dart'; + +class Translate { + final Locale locale; + + Translate(this.locale); + + static Translate of(BuildContext context) { + return Localizations.of(context, Translate); + } + + static const LocalizationsDelegate delegate = AppLocaleDelegate(); + + Map _localizedStrings; + + Future load() async { + final jsonMap = await UtilAsset.loadJson( + "assets/locale/${locale.languageCode}.json", + ); + + _localizedStrings = jsonMap.map((key, value) { + return MapEntry(key, value.toString()); + }); + + return true; + } + + String translate(String key) { + return _localizedStrings[key] ?? key; + } +} diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart new file mode 100644 index 0000000..7867d96 --- /dev/null +++ b/lib/utils/utils.dart @@ -0,0 +1,10 @@ +export 'asset.dart'; +export 'color.dart'; +export 'icon.dart'; +export 'language.dart'; +export 'logger.dart'; +export 'other.dart'; +export 'preferences.dart'; +export 'theme.dart'; +export 'translate.dart'; +export 'validate.dart'; diff --git a/lib/utils/validate.dart b/lib/utils/validate.dart new file mode 100644 index 0000000..9f032ba --- /dev/null +++ b/lib/utils/validate.dart @@ -0,0 +1,65 @@ +enum Type { + normal, + email, + password, + phone, +} + +class UtilValidator { + static const String error_empty = "value_not_empty"; + static const String error_range = "value_not_valid_range"; + static const String error_email = "value_not_valid_email"; + static const String error_phone = "value_not_valid_phone"; + static const String error_password = "value_not_valid_password"; + static const String error_id = "value_not_valid_id"; + + static validate({ + String data, + Type type = Type.normal, + int min, + int max, + bool allowEmpty = false, + }) { + switch (type) { + case Type.email: + + ///Empty + if (!allowEmpty && data.isEmpty) { + return error_empty; + } + + ///Length + if (min != null || + max != null && (data.length < min || data.length > max)) { + return '$error_range ($min-$max)'; + } + + ///More pattern + final Pattern _emailPattern = + r"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$"; + if (!RegExp(_emailPattern).hasMatch(data)) { + return error_email; + } + return null; + + default: + if (!allowEmpty && data.isEmpty) { + return error_empty; + } + if (min != null || + max != null && (data.length < min || data.length > max)) { + return '$error_range ($min-$max)'; + } + return null; + } + } + + ///Singleton factory + static final UtilValidator _instance = UtilValidator._internal(); + + factory UtilValidator() { + return _instance; + } + + UtilValidator._internal(); +} diff --git a/lib/widgets/app_button.dart b/lib/widgets/app_button.dart new file mode 100644 index 0000000..f57af00 --- /dev/null +++ b/lib/widgets/app_button.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +class AppButton extends StatelessWidget { + final VoidCallback onPressed; + final String text; + final bool loading; + final bool disableTouchWhenLoading; + final ShapeBorder shape; + + AppButton({ + Key key, + this.onPressed, + this.text, + this.loading = false, + this.disableTouchWhenLoading = false, + this.shape, + }) : super(key: key); + + Widget _buildLoading() { + if (!loading) { + return Container(); + } + return Container( + margin: EdgeInsets.only(left: 10, right: 10), + width: 14, + height: 14, + child: CircularProgressIndicator(strokeWidth: 2), + ); + } + + @override + Widget build(BuildContext context) { + return RaisedButton( + shape: shape, + onPressed: disableTouchWhenLoading && loading ? null : onPressed, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + text, + style: Theme.of(context) + .textTheme + .button + .copyWith(color: Colors.white, fontWeight: FontWeight.w600), + ), + _buildLoading() + ], + ), + ); + } +} diff --git a/lib/widgets/app_category_item.dart b/lib/widgets/app_category_item.dart new file mode 100644 index 0000000..257785b --- /dev/null +++ b/lib/widgets/app_category_item.dart @@ -0,0 +1,181 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:shimmer/shimmer.dart'; + +enum CategoryType { full, icon } + +class AppCategory extends StatelessWidget { + AppCategory({ + Key key, + this.type = CategoryType.full, + this.item, + this.onPressed, + }) : super(key: key); + + final CategoryType type; + final CategoryModel item; + final ValueChanged onPressed; + + @override + Widget build(BuildContext context) { + switch (type) { + case CategoryType.full: + if (item == null) { + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Container( + height: 120, + alignment: Alignment.topLeft, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + ), + ); + } + + return GestureDetector( + onTap: () => onPressed(item), + child: Container( + height: 120, + alignment: Alignment.topLeft, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(item.image), + fit: BoxFit.cover, + ), + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 32, + height: 32, + alignment: Alignment.center, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: item.color, + ), + child: Icon( + item.icon, + color: Colors.white, + size: 18, + ), + ), + Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.title, + style: Theme.of(context) + .textTheme + .subtitle1 + .copyWith( + color: Colors.white, + fontWeight: FontWeight.w600), + ), + Text( + '${item.count} location', + style: Theme.of(context) + .textTheme + .bodyText1 + .copyWith(color: Colors.white), + ), + ], + ), + ) + ], + ) + ], + ), + )); + + case CategoryType.icon: + if (item == null) { + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Container( + height: 120, + alignment: Alignment.topLeft, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + ), + ); + } + return InkWell( + onTap: () => onPressed(item), + child: Container( + padding: EdgeInsets.only(bottom: 15), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Theme.of(context).dividerColor, + ), + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 60, + height: 60, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: item.color, + ), + child: Icon( + item.icon, + color: Colors.white, + size: 32, + ), + ), + Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.title, + style: Theme.of(context) + .textTheme + .subtitle1 + .copyWith(fontWeight: FontWeight.w600), + ), + Text( + '${item.count} location', + style: Theme.of(context).textTheme.bodyText1, + ), + ], + ), + ) + ], + ), + )); + default: + return Container(); + } + } +} diff --git a/lib/widgets/app_circle_avatar.dart b/lib/widgets/app_circle_avatar.dart new file mode 100644 index 0000000..750efbd --- /dev/null +++ b/lib/widgets/app_circle_avatar.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class AppCircleAvatar extends StatelessWidget { + final String imgUrl; + final double size; + + const AppCircleAvatar({ + Key key, + @required this.imgUrl, + this.size = 40.0, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white, + width: 2, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.3), + offset: Offset(0, 2), + blurRadius: 5, + ) + ], + image: DecorationImage( + image: AssetImage(imgUrl), + fit: BoxFit.cover, + ), + ), + ); + } +} diff --git a/lib/widgets/app_comment_item.dart b/lib/widgets/app_comment_item.dart new file mode 100644 index 0000000..15ec83e --- /dev/null +++ b/lib/widgets/app_comment_item.dart @@ -0,0 +1,214 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/widgets/app_star_rating.dart'; +import 'package:shimmer/shimmer.dart'; + +class AppCommentItem extends StatelessWidget { + final CommentModel item; + + AppCommentItem({Key key, this.item}) : super(key: key); + + @override + Widget build(BuildContext context) { + if (item == null) { + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: 10, + width: 150, + color: Colors.white, + ), + Container( + height: 10, + width: 50, + color: Colors.white, + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 5), + ), + Container( + height: 10, + width: 50, + color: Colors.white, + ) + ], + ), + ), + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 5, bottom: 10), + child: Container( + height: 10, + width: 100, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(top: 3), + child: Container( + height: 10, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(top: 3), + child: Container( + height: 10, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(top: 3), + child: Container( + height: 10, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(top: 3), + child: Container( + height: 10, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(top: 3), + child: Container( + height: 10, + color: Colors.white, + ), + ) + ], + ), + ), + ); + } + + return Container( + padding: EdgeInsets.all( + 10, + ), + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: AssetImage(item.user.image), + fit: BoxFit.cover, + ), + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + item.user.name, + maxLines: 1, + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + ), + Text( + item.createDate, + style: Theme.of(context).textTheme.caption, + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 3), + ), + StarRating( + rating: item.rate, + size: 14, + color: AppTheme.yellowColor, + borderColor: AppTheme.yellowColor, + ) + ], + ), + ), + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 5, bottom: 10), + child: Text( + item.title, + maxLines: 1, + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + ), + Text( + item.comment, + maxLines: 5, + style: Theme.of(context).textTheme.bodyText1, + ) + ], + ), + ); + } +} diff --git a/lib/widgets/app_group_circle_avatar.dart b/lib/widgets/app_group_circle_avatar.dart new file mode 100644 index 0000000..456958f --- /dev/null +++ b/lib/widgets/app_group_circle_avatar.dart @@ -0,0 +1,262 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; + +class AppGroupCircleAvatar extends StatelessWidget { + final List member; + final double size; + + const AppGroupCircleAvatar({ + Key key, + @required this.member, + this.size = 40, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + switch (member.length) { + case 1: + return Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white, + width: 2, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.3), + offset: Offset(0, 2), + blurRadius: 5, + ) + ], + image: DecorationImage( + image: AssetImage(member[0].image), + fit: BoxFit.cover, + ), + ), + ); + case 2: + return Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white, + width: 2, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.3), + offset: Offset(0, 2), + blurRadius: 5, + ) + ], + ), + child: ClipOval( + child: Column( + children: [ + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[0].image), + fit: BoxFit.cover, + ), + ), + ), + ), + Container( + height: 0.5, + color: Colors.white, + ), + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[1].image), + fit: BoxFit.cover, + ), + ), + ), + ) + ], + ), + ), + ); + case 3: + return Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white, + width: 2, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.3), + offset: Offset(0, 2), + blurRadius: 5, + ) + ], + ), + child: ClipOval( + child: Column( + children: [ + Flexible( + flex: 1, + child: Row( + children: [ + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[0].image), + fit: BoxFit.cover, + ), + ), + ), + ), + Container( + width: 0.5, + color: Colors.white, + ), + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[1].image), + fit: BoxFit.cover, + ), + ), + ), + ) + ], + )), + Container( + height: 0.5, + color: Colors.white, + ), + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[2].image), + fit: BoxFit.cover, + ), + ), + ), + ) + ], + ), + ), + ); + default: + return Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white, + width: 2, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.3), + offset: Offset(0, 2), + blurRadius: 5, + ) + ], + ), + child: ClipOval( + child: Column( + children: [ + Flexible( + flex: 1, + child: Row( + children: [ + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[0].image), + fit: BoxFit.cover, + ), + ), + ), + ), + Container( + width: 0.5, + color: Colors.white, + ), + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[1].image), + fit: BoxFit.cover, + ), + ), + ), + ) + ], + ), + ), + Container( + height: 0.5, + color: Colors.white, + ), + Flexible( + flex: 1, + child: Row( + children: [ + Flexible( + flex: 1, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(member[2].image), + fit: BoxFit.cover, + ), + ), + ), + ), + Container( + width: 0.5, + color: Colors.white, + ), + Flexible( + flex: 1, + child: Container( + alignment: Alignment.center, + padding: EdgeInsets.only(bottom: 2, right: 2), + child: Text( + '+${member.length - 3}', + style: Theme.of(context).textTheme.caption.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white), + ), + ), + ) + ], + ), + ) + ], + ), + ), + ); + } + } +} diff --git a/lib/widgets/app_list_title.dart b/lib/widgets/app_list_title.dart new file mode 100644 index 0000000..1817fc7 --- /dev/null +++ b/lib/widgets/app_list_title.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +class AppListTitle extends StatelessWidget { + final String title; + final Widget trailing; + final VoidCallback onPressed; + final bool border; + final TextStyle textStyle; + + AppListTitle({ + Key key, + this.title, + this.trailing, + this.onPressed, + this.border = true, + this.textStyle, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onPressed, + child: Container( + decoration: BoxDecoration( + border: border + ? Border( + bottom: BorderSide( + width: 1, + color: Theme.of(context).dividerColor, + ), + ) + : null, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.only(top: 20, bottom: 20), + child: Text( + title, + style: textStyle ?? Theme.of(context).textTheme.subtitle1, + ), + ), + trailing ?? Container() + ], + ), + ), + ); + } +} diff --git a/lib/widgets/app_loading.dart b/lib/widgets/app_loading.dart new file mode 100644 index 0000000..10c8117 --- /dev/null +++ b/lib/widgets/app_loading.dart @@ -0,0 +1,217 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +class AppLoading extends StatefulWidget { + final Color color1; + final Color color2; + final Color color3; + + AppLoading({ + this.color1 = Colors.deepOrangeAccent, + this.color2 = Colors.yellow, + this.color3 = Colors.lightGreen, + }); + + @override + _AppLoadingState createState() => _AppLoadingState(); +} + +class _AppLoadingState extends State with TickerProviderStateMixin { + Animation animation1; + Animation animation2; + Animation animation3; + AnimationController controller1; + AnimationController controller2; + AnimationController controller3; + + @override + void initState() { + super.initState(); + + controller1 = AnimationController( + duration: Duration(seconds: 2), + vsync: this, + ); + + controller2 = AnimationController( + duration: Duration(seconds: 2), + vsync: this, + ); + + controller3 = AnimationController( + duration: Duration(seconds: 2), + vsync: this, + ); + + animation1 = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: controller1, + curve: Interval( + 0.0, + 1.0, + curve: Curves.linear, + ), + ), + ); + + animation2 = Tween(begin: -1.0, end: 0.0).animate( + CurvedAnimation( + parent: controller2, + curve: Interval( + 0.0, + 1.0, + curve: Curves.easeIn, + ), + ), + ); + + animation3 = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: controller3, + curve: Interval( + 0.0, + 1.0, + curve: Curves.decelerate, + ), + ), + ); + + controller1.repeat(); + controller2.repeat(); + controller3.repeat(); + } + + @override + Widget build(BuildContext context) { + return Container( + child: Stack( + children: [ + new RotationTransition( + turns: animation1, + child: CustomPaint( + painter: Arc1Painter(widget.color1), + child: Container( + width: 50.0, + height: 50.0, + ), + ), + ), + new RotationTransition( + turns: animation2, + child: CustomPaint( + painter: Arc2Painter(widget.color2), + child: Container( + width: 50.0, + height: 50.0, + ), + ), + ), + new RotationTransition( + turns: animation3, + child: CustomPaint( + painter: Arc3Painter(widget.color3), + child: Container( + width: 50.0, + height: 50.0, + ), + ), + ) + ], + ), + ); + } + + @override + void dispose() { + controller1.dispose(); + controller2.dispose(); + controller3.dispose(); + super.dispose(); + } +} + +class Arc1Painter extends CustomPainter { + final Color color; + + Arc1Painter(this.color); + + @override + void paint(Canvas canvas, Size size) { + Paint p1 = new Paint() + ..color = color + ..strokeWidth = 2.0 + ..strokeCap = StrokeCap.round + ..style = PaintingStyle.stroke; + + Rect rect1 = new Rect.fromLTWH(0.0, 0.0, size.width, size.height); + + canvas.drawArc(rect1, 0.0, 0.5 * pi, false, p1); + canvas.drawArc(rect1, 0.6 * pi, 0.8 * pi, false, p1); + canvas.drawArc(rect1, 1.5 * pi, 0.4 * pi, false, p1); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} + +class Arc2Painter extends CustomPainter { + final Color color; + + Arc2Painter(this.color); + + @override + void paint(Canvas canvas, Size size) { + Paint p2 = new Paint() + ..color = color + ..strokeWidth = 2.0 + ..strokeCap = StrokeCap.round + ..style = PaintingStyle.stroke; + + Rect rect2 = new Rect.fromLTWH( + 0.0 + (0.2 * size.width) / 2, + 0.0 + (0.2 * size.height) / 2, + size.width - 0.2 * size.width, + size.height - 0.2 * size.height); + + canvas.drawArc(rect2, 0.0, 0.5 * pi, false, p2); + canvas.drawArc(rect2, 0.8 * pi, 0.6 * pi, false, p2); + canvas.drawArc(rect2, 1.6 * pi, 0.2 * pi, false, p2); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} + +class Arc3Painter extends CustomPainter { + final Color color; + + Arc3Painter(this.color); + + @override + void paint(Canvas canvas, Size size) { + Paint p3 = new Paint() + ..color = color + ..strokeWidth = 1.5 + ..strokeCap = StrokeCap.round + ..style = PaintingStyle.stroke; + + Rect rect3 = new Rect.fromLTWH( + 0.0 + (0.4 * size.width) / 2, + 0.0 + (0.4 * size.height) / 2, + size.width - 0.4 * size.width, + size.height - 0.4 * size.height); + + canvas.drawArc(rect3, 0.0, 0.9 * pi, false, p3); + canvas.drawArc(rect3, 1.1 * pi, 0.8 * pi, false, p3); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} diff --git a/lib/widgets/app_message_item.dart b/lib/widgets/app_message_item.dart new file mode 100644 index 0000000..f690613 --- /dev/null +++ b/lib/widgets/app_message_item.dart @@ -0,0 +1,145 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/widgets/widget.dart'; +import 'package:shimmer/shimmer.dart'; + +class AppMessageItem extends StatelessWidget { + final MessageModel item; + final VoidCallback onPressed; + final bool border; + + AppMessageItem({ + Key key, + this.item, + this.onPressed, + this.border = true, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if (item == null) { + return Shimmer.fromColors( + child: Container( + padding: EdgeInsets.only(top: 8, bottom: 8, left: 20, right: 20), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 48, + height: 48, + color: Colors.white, + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: 10, + width: 150, + color: Colors.white, + ), + Container( + height: 10, + width: 50, + color: Colors.white, + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 5), + ), + Container( + height: 10, + color: Colors.white, + ) + ], + ), + ), + ) + ], + ), + ), + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + ); + } + + return InkWell( + onTap: onPressed, + child: Container( + padding: EdgeInsets.only(top: 8, bottom: 8, left: 20, right: 20), + decoration: BoxDecoration( + border: border + ? Border( + bottom: BorderSide( + width: 1, + color: Theme.of(context).dividerColor, + ), + ) + : null, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppGroupCircleAvatar( + size: 48, + member: item.member, + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 8, right: 8), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + item.roomName, + maxLines: 1, + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + ), + Text( + DateFormat( + 'EEE MMM d yyyy', + AppLanguage.defaultLanguage.languageCode, + ).format(item.date), + style: Theme.of(context).textTheme.caption, + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 3), + ), + Text( + item.message, + maxLines: 1, + style: Theme.of(context) + .textTheme + .caption + .copyWith(fontWeight: FontWeight.w500), + ) + ], + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/widgets/app_model_bottom_sheet.dart b/lib/widgets/app_model_bottom_sheet.dart new file mode 100644 index 0000000..6b37327 --- /dev/null +++ b/lib/widgets/app_model_bottom_sheet.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:listar_flutter/widgets/widget.dart'; + +class AppModelBottomSheet extends StatefulWidget { + final SortModel selected; + final List option; + final ValueChanged onChange; + + AppModelBottomSheet({ + Key key, + this.selected, + this.option, + this.onChange, + }) : super(key: key); + + @override + _AppModelBottomSheetState createState() { + return _AppModelBottomSheetState(); + } +} + +class _AppModelBottomSheetState extends State { + SortModel _currentSort; + + @override + void initState() { + _currentSort = widget.selected; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return SafeArea( + bottom: false, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), + topRight: Radius.circular(10), + ), + ), + child: Padding( + padding: EdgeInsets.only(left: 20, right: 20), + child: SingleChildScrollView( + child: IntrinsicHeight( + child: Column( + children: [ + Container( + margin: EdgeInsets.all(10), + width: 40, + height: 3, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + color: Theme.of(context).dividerColor, + ), + ), + Column( + children: widget.option.map((item) { + return AppListTitle( + title: Translate.of(context).translate(item.name), + textStyle: item.code == _currentSort.code + ? Theme.of(context) + .textTheme + .subtitle1 + .copyWith(color: Theme.of(context).primaryColor) + : null, + trailing: item.code == _currentSort.code + ? Icon( + Icons.check, + color: Theme.of(context).primaryColor, + ) + : Container(), + onPressed: () { + setState(() { + _currentSort = item; + }); + }, + ); + }).toList(), + ), + Padding( + padding: EdgeInsets.only(top: 20, bottom: 20), + child: AppButton( + onPressed: () { + widget.onChange(_currentSort); + Navigator.pop(context); + }, + text: Translate.of(context).translate('apply'), + ), + ) + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/app_notification_item.dart b/lib/widgets/app_notification_item.dart new file mode 100644 index 0000000..197b241 --- /dev/null +++ b/lib/widgets/app_notification_item.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:shimmer/shimmer.dart'; + +class AppNotificationItem extends StatelessWidget { + final NotificationModel item; + final VoidCallback onPressed; + final bool border; + + AppNotificationItem({ + Key key, + this.item, + this.onPressed, + this.border = true, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if (item == null) { + return Shimmer.fromColors( + child: Container( + padding: EdgeInsets.only(top: 8, bottom: 8, right: 20, left: 20), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 8, right: 8), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: 10, + width: 150, + color: Colors.white, + ), + Container( + height: 10, + width: 50, + color: Colors.white, + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 5), + ), + Container( + height: 10, + color: Colors.white, + ) + ], + ), + ), + ) + ], + ), + ), + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + ); + } + return InkWell( + onTap: onPressed, + child: Container( + padding: EdgeInsets.only(top: 8, bottom: 8, left: 20, right: 20), + decoration: BoxDecoration( + border: border + ? Border( + bottom: BorderSide( + width: 1, + color: Theme.of(context).dividerColor, + ), + ) + : null, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: item.category.color, + ), + child: Icon( + item.category.icon, + color: Colors.white, + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 8, right: 8), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + item.title, + maxLines: 1, + style: Theme.of(context).textTheme.subtitle2, + overflow: TextOverflow.ellipsis, + ), + ), + Text( + DateFormat( + 'hh:mm, MMM dd yyyy', + AppLanguage.defaultLanguage.languageCode, + ).format(item.date), + style: Theme.of(context).textTheme.caption, + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 3), + ), + Text( + item.subtitle, + maxLines: 1, + style: Theme.of(context) + .textTheme + .caption + .copyWith(fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis, + ) + ], + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/widgets/app_product_item.dart b/lib/widgets/app_product_item.dart new file mode 100644 index 0000000..ded14e5 --- /dev/null +++ b/lib/widgets/app_product_item.dart @@ -0,0 +1,877 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/configs/config.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/widgets/widget.dart'; +import 'package:shimmer/shimmer.dart'; + +enum ProductViewType { small, gird, list, block, cardLarge, cardSmall } + +class AppProductItem extends StatelessWidget { + AppProductItem({ + Key key, + this.item, + this.onPressed, + this.type, + }) : super(key: key); + + final ProductModel item; + final ProductViewType type; + final Function(ProductModel) onPressed; + + @override + Widget build(BuildContext context) { + switch (type) { + + ///Mode View Small + case ProductViewType.small: + if (item == null) { + return Shimmer.fromColors( + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Container( + width: 80, + height: 80, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + top: 5, + bottom: 5, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 10, + width: 180, + color: Colors.white, + ), + Padding( + padding: EdgeInsets.only(top: 5), + ), + Container( + height: 10, + width: 150, + color: Colors.white, + ), + Padding( + padding: EdgeInsets.only(top: 10), + ), + Container( + height: 10, + width: 100, + color: Colors.white, + ), + ], + ), + ), + ], + ), + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + ); + } + + return FlatButton( + onPressed: () { + onPressed(item); + }, + padding: EdgeInsets.all(0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + item.image, + width: 80, + height: 80, + fit: BoxFit.cover, + ), + ), + Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + top: 5, + bottom: 5, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + item.title, + maxLines: 1, + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 5)), + Text( + item.subtitle, + style: Theme.of(context) + .textTheme + .caption + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 10)), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppTag( + "${item.rate}", + type: TagType.rateSmall, + ), + Padding(padding: EdgeInsets.only(left: 5)), + StarRating( + rating: item.rate, + size: 14, + color: AppTheme.yellowColor, + borderColor: AppTheme.yellowColor, + ) + ], + ) + ], + ), + ) + ], + ), + ); + + ///Mode View Gird + case ProductViewType.gird: + if (item == null) { + return Shimmer.fromColors( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 120, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: Colors.white, + ), + ), + Padding(padding: EdgeInsets.only(top: 5)), + Container( + height: 10, + width: 80, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 5)), + Container( + height: 10, + width: 100, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + height: 20, + width: 100, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + height: 10, + width: 80, + color: Colors.white, + ), + ], + ), + ), + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + ); + } + + return FlatButton( + onPressed: () { + onPressed(item); + }, + padding: EdgeInsets.all(0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 120, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + image: DecorationImage( + image: AssetImage(item.image), + fit: BoxFit.cover, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + item.status != null + ? Padding( + padding: EdgeInsets.all(5), + child: AppTag( + item.status, + type: TagType.status, + ), + ) + : Container() + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsets.all(5), + child: Icon( + item.favorite + ? Icons.favorite + : Icons.favorite_border, + color: Colors.white, + ), + ) + ], + ) + ], + ), + ), + Padding(padding: EdgeInsets.only(top: 3)), + Text( + item.subtitle, + style: Theme.of(context) + .textTheme + .caption + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 5)), + Text( + item.title, + maxLines: 1, + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 10)), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppTag( + "${item.rate}", + type: TagType.rateSmall, + ), + Padding(padding: EdgeInsets.only(left: 5)), + StarRating( + rating: item.rate, + size: 14, + color: AppTheme.yellowColor, + borderColor: AppTheme.yellowColor, + ) + ], + ), + Padding(padding: EdgeInsets.only(top: 10)), + Text( + item.address, + maxLines: 1, + style: Theme.of(context).textTheme.caption, + ), + ], + ), + ), + ); + + ///Mode View List + case ProductViewType.list: + if (item == null) { + return Shimmer.fromColors( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 120, + height: 140, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + bottomLeft: Radius.circular(8), + ), + color: Colors.white, + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.only( + top: 5, + bottom: 5, + left: 10, + right: 10, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 10, + width: 80, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + height: 10, + width: 100, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + height: 20, + width: 80, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + height: 10, + width: 100, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + height: 10, + width: 80, + color: Colors.white, + ), + Padding( + padding: EdgeInsets.only(top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + width: 18, + height: 18, + color: Colors.white, + ) + ], + ), + ) + ], + ), + ), + ) + ], + ), + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + ); + } + + return FlatButton( + onPressed: () { + onPressed(item); + }, + padding: EdgeInsets.all(0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 120, + height: 140, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(item.image), + fit: BoxFit.cover, + ), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + bottomLeft: Radius.circular(8), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + item.status != null + ? Padding( + padding: EdgeInsets.all(5), + child: AppTag( + item.status, + type: TagType.status, + ), + ) + : Container() + ], + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.only( + top: 5, + bottom: 5, + left: 10, + right: 10, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.subtitle, + style: Theme.of(context).textTheme.caption.copyWith( + fontWeight: FontWeight.w600, + ), + ), + Padding(padding: EdgeInsets.only(top: 5)), + Text( + item.title, + maxLines: 1, + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 5)), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppTag( + "${item.rate}", + type: TagType.rateSmall, + ), + Padding(padding: EdgeInsets.only(left: 5)), + StarRating( + rating: item.rate, + size: 14, + color: AppTheme.yellowColor, + borderColor: AppTheme.yellowColor, + ) + ], + ), + Padding(padding: EdgeInsets.only(top: 5)), + Row( + children: [ + Icon( + Icons.location_on, + size: 12, + color: Theme.of(context).primaryColor, + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 3, right: 3), + child: Text(item.address, + maxLines: 1, + style: Theme.of(context).textTheme.caption), + ), + ) + ], + ), + Padding(padding: EdgeInsets.only(top: 5)), + Row( + children: [ + Icon( + Icons.phone, + size: 12, + color: Theme.of(context).primaryColor, + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 3, right: 3), + child: Text(item.phone, + maxLines: 1, + style: Theme.of(context).textTheme.caption), + ), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Icon( + item.favorite + ? Icons.favorite + : Icons.favorite_border, + color: Theme.of(context).primaryColor, + ) + ], + ) + ], + ), + ), + ) + ], + ), + ); + + ///Mode View Block + case ProductViewType.block: + if (item == null) { + return Shimmer.fromColors( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 200, + color: Colors.white, + ), + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 10, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 10, + width: 150, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 5)), + Container( + height: 10, + width: 200, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 10)), + Container( + height: 10, + width: 150, + color: Colors.white, + ), + Padding(padding: EdgeInsets.only(top: 5)), + Container( + height: 10, + width: 150, + color: Colors.white, + ), + ], + ), + ) + ], + ), + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + ); + } + + return FlatButton( + onPressed: () { + onPressed(item); + }, + padding: EdgeInsets.all(0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 200, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(item.image), + fit: BoxFit.cover, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(5), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + item.status != null + ? AppTag( + item.status, + type: TagType.status, + ) + : Container(), + Icon( + item.favorite + ? Icons.favorite + : Icons.favorite_border, + color: Colors.white, + ) + ], + ), + ), + Padding( + padding: EdgeInsets.all(5), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + AppTag( + "${item.rate}", + type: TagType.rateSmall, + ), + Padding( + padding: EdgeInsets.only(left: 5), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(left: 3), + child: Text( + item.rateText, + style: Theme.of(context) + .textTheme + .caption + .copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ), + StarRating( + rating: item.rate, + size: 14, + color: AppTheme.yellowColor, + borderColor: AppTheme.yellowColor, + ) + ], + ), + ) + ], + ), + Padding( + padding: EdgeInsets.only(top: 3), + child: Text( + "${item.numRate} reviews", + style: Theme.of(context) + .textTheme + .caption + .copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ) + ], + ) + ], + ), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.only( + left: 20, + right: 20, + top: 10, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.subtitle, + style: Theme.of(context) + .textTheme + .caption + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 5)), + Text( + item.title, + maxLines: 1, + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + Padding(padding: EdgeInsets.only(top: 10)), + Row( + children: [ + Icon( + Icons.location_on, + size: 12, + color: Theme.of(context).primaryColor, + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 3, right: 3), + child: Text( + item.address, + maxLines: 1, + style: Theme.of(context).textTheme.caption, + ), + ), + ) + ], + ), + Padding(padding: EdgeInsets.only(top: 5)), + Row( + children: [ + Icon( + Icons.phone, + size: 12, + color: Theme.of(context).primaryColor, + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 3, right: 3), + child: Text( + item.phone, + maxLines: 1, + style: Theme.of(context).textTheme.caption, + ), + ), + ) + ], + ), + ], + ), + ) + ], + ), + ); + + ///Case View Card large + case ProductViewType.cardLarge: + if (item == null) { + return SizedBox( + width: 135, + height: 160, + child: Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ); + } + + return SizedBox( + width: 135, + height: 160, + child: GestureDetector( + onTap: () { + onPressed(item); + }, + child: Card( + elevation: 2, + margin: EdgeInsets.all(0), + clipBehavior: Clip.antiAliasWithSaveLayer, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(item.image), + fit: BoxFit.cover, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(10), + child: Text( + item.title, + style: Theme.of(context).textTheme.subtitle2.copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ) + ], + ), + ), + ), + ), + ); + + ///Case View Card small + case ProductViewType.cardSmall: + if (item == null) { + return SizedBox( + width: 100, + height: 100, + child: Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ); + } + + return SizedBox( + width: 100, + height: 100, + child: GestureDetector( + onTap: () { + onPressed(item); + }, + child: Card( + elevation: 2, + margin: EdgeInsets.all(0), + clipBehavior: Clip.antiAliasWithSaveLayer, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(item.image), + fit: BoxFit.cover, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(10), + child: Text( + item.title, + style: Theme.of(context).textTheme.subtitle2.copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ) + ], + ), + ), + ), + ), + ); + + default: + return Container(width: 160.0); + } + } +} diff --git a/lib/widgets/app_profile_performance.dart b/lib/widgets/app_profile_performance.dart new file mode 100644 index 0000000..9f95991 --- /dev/null +++ b/lib/widgets/app_profile_performance.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:shimmer/shimmer.dart'; + +class AppProfilePerformance extends StatelessWidget { + final List> data; + final Function(Map) onPressed; + + AppProfilePerformance({ + Key key, + this.data, + this.onPressed, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if (data == null) { + return Padding( + padding: EdgeInsets.only(top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [1, 2, 3].map((item) { + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Column( + children: [ + Container( + width: 50, + height: 10, + color: Colors.white, + ), + Padding( + padding: EdgeInsets.only(top: 5), + ), + Container( + width: 50, + height: 10, + color: Colors.white, + ), + ], + ), + ); + }).toList(), + ), + ); + } + + return Padding( + padding: EdgeInsets.only(top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: data.map((item) { + return InkWell( + onTap: () { + onPressed(item); + }, + child: Column( + children: [ + Text( + item['value'], + style: Theme.of(context).textTheme.subtitle2, + ), + Text( + Translate.of(context).translate( + item['title'], + ), + style: Theme.of(context).textTheme.caption, + ) + ], + ), + ); + }).toList(), + ), + ); + } +} diff --git a/lib/widgets/app_rating.dart b/lib/widgets/app_rating.dart new file mode 100644 index 0000000..0c4e94e --- /dev/null +++ b/lib/widgets/app_rating.dart @@ -0,0 +1,467 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:listar_flutter/utils/utils.dart'; +import 'package:shimmer/shimmer.dart'; + +class AppRating extends StatelessWidget { + final RateModel rate; + + AppRating({ + Key key, + this.rate, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if (rate == null) { + return Shimmer.fromColors( + child: Row( + children: [ + Padding( + padding: EdgeInsets.only(right: 10), + child: Column( + children: [ + Text( + "0.0", + style: Theme.of(context) + .textTheme + .headline2 + .copyWith(color: Theme.of(context).primaryColor), + ), + Text( + "${Translate.of(context).translate('out_of')} 0", + style: Theme.of(context) + .textTheme + .subtitle1 + .copyWith(fontWeight: FontWeight.w600), + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2, 3, 4, 5].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2, 3, 4].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2, 3].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "Loading", + style: Theme.of(context).textTheme.subtitle2, + ), + ], + ) + ], + ), + ) + ], + ), + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + ); + } + + return Row( + children: [ + Padding( + padding: EdgeInsets.only(right: 10), + child: Column( + children: [ + Text( + "${rate.avg}", + style: Theme.of(context) + .textTheme + .headline2 + .copyWith(color: Theme.of(context).primaryColor), + ), + Text( + "${Translate.of(context).translate('out_of')} ${rate.range}", + style: Theme.of(context) + .textTheme + .subtitle1 + .copyWith(fontWeight: FontWeight.w600), + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2, 3, 4, 5].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + child: FractionallySizedBox( + widthFactor: rate.five, + child: Container( + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2, 3, 4].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + child: FractionallySizedBox( + widthFactor: rate.four, + child: Container( + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2, 3].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + child: FractionallySizedBox( + widthFactor: rate.three, + child: Container( + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1, 2].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + child: FractionallySizedBox( + widthFactor: rate.two, + child: Container( + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Container( + width: 60, + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [1].map((item) { + return Icon( + Icons.star, + size: 12, + ); + }).toList(), + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 10), + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + child: FractionallySizedBox( + widthFactor: rate.one, + child: Container( + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + ), + ), + ), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "${rate.total} ${Translate.of(context).translate('rating')}", + style: Theme.of(context) + .textTheme + .subtitle2 + .copyWith(fontWeight: FontWeight.w600), + ), + ], + ) + ], + ), + ) + ], + ); + } +} diff --git a/lib/widgets/app_star_rating.dart b/lib/widgets/app_star_rating.dart new file mode 100644 index 0000000..fd9c626 --- /dev/null +++ b/lib/widgets/app_star_rating.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; + +typedef void RatingChangeCallback(double rating); + +class StarRating extends StatelessWidget { + final int starCount; + final double rating; + final RatingChangeCallback onRatingChanged; + final Color color; + final Color borderColor; + final double size; + final bool allowHalfRating; + final IconData filledIconData; + final IconData halfFilledIconData; + final IconData defaultIconData; + final double spacing; + + StarRating({ + this.starCount = 5, + this.spacing = 0.0, + this.rating = 0.0, + this.defaultIconData, + this.onRatingChanged, + this.color, + this.borderColor, + this.size = 24, + this.filledIconData, + this.halfFilledIconData, + this.allowHalfRating = true, + }) { + assert(this.rating != null); + } + + Widget buildStar(BuildContext context, int index) { + Icon icon; + if (index >= rating) { + icon = new Icon( + defaultIconData != null ? defaultIconData : Icons.star_border, + color: borderColor ?? Theme.of(context).primaryColor, + size: size, + ); + } else if (index > rating - (allowHalfRating ? 1.0 : 0.5) && + index < rating) { + icon = new Icon( + halfFilledIconData != null ? halfFilledIconData : Icons.star_half, + color: color ?? Theme.of(context).primaryColor, + size: size, + ); + } else { + icon = new Icon( + filledIconData != null ? filledIconData : Icons.star, + color: color ?? Theme.of(context).primaryColor, + size: size, + ); + } + + return new GestureDetector( + onTap: () { + if (this.onRatingChanged != null) onRatingChanged(index + 1.0); + }, + onHorizontalDragUpdate: (dragDetails) { + RenderBox box = context.findRenderObject(); + var _pos = box.globalToLocal(dragDetails.globalPosition); + var i = _pos.dx / size; + var newRating = allowHalfRating ? i.round().toDouble() : i; + if (newRating > starCount) { + newRating = starCount.toDouble(); + } + if (newRating < 0) { + newRating = 0.0; + } + if (this.onRatingChanged != null) onRatingChanged(newRating); + }, + child: icon, + ); + } + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: Wrap( + alignment: WrapAlignment.start, + spacing: spacing, + children: new List.generate( + starCount, + (index) => buildStar(context, index), + ), + ), + ); + } +} diff --git a/lib/widgets/app_tag.dart b/lib/widgets/app_tag.dart new file mode 100644 index 0000000..b028dab --- /dev/null +++ b/lib/widgets/app_tag.dart @@ -0,0 +1,193 @@ +import 'package:flutter/material.dart'; + +enum TagType { + primary, + primaryIcon, + outLine, + secondaryIcon, + small, + status, + light, + gray, + chip, + rate, + rateSmall +} + +class AppTag extends StatelessWidget { + AppTag( + this.data, { + Key key, + this.type, + this.icon, + this.onPressed, + }) : super(key: key); + + final String data; + final TagType type; + final Widget icon; + final VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + switch (type) { + case TagType.primary: + return RaisedButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + onPressed: onPressed, + child: Text( + data, + style: Theme.of(context).textTheme.caption.copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ); + + case TagType.primaryIcon: + return RaisedButton.icon( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + onPressed: onPressed, + icon: icon, + label: Text( + data, + style: Theme.of(context).textTheme.caption.copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ); + + case TagType.outLine: + return OutlineButton( + onPressed: onPressed, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + child: Text( + data, + style: Theme.of(context).textTheme.caption.copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ); + + case TagType.gray: + return InkWell( + onTap: onPressed, + child: Container( + color: Theme.of(context).hoverColor, + padding: EdgeInsets.all(5), + child: Text( + data, + style: Theme.of(context).textTheme.caption.copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ), + ); + + case TagType.rateSmall: + return InkWell( + onTap: onPressed, + child: Container( + padding: EdgeInsets.only( + left: 5, + right: 5, + bottom: 3, + top: 3, + ), + decoration: BoxDecoration( + color: Theme.of(context).primaryColorLight, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(3), + bottomLeft: Radius.circular(3), + bottomRight: Radius.circular(3), + ), + ), + child: Text( + data, + style: Theme.of(context).textTheme.caption.copyWith( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ), + ); + + case TagType.status: + return InkWell( + onTap: onPressed, + child: Container( + padding: EdgeInsets.only( + left: 5, + right: 5, + top: 3, + bottom: 3, + ), + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.all(Radius.circular(3)), + ), + child: Text( + data, + style: Theme.of(context) + .textTheme + .caption + .copyWith(color: Colors.white), + ), + ), + ); + + case TagType.chip: + return InkWell( + onTap: onPressed, + child: Container( + padding: EdgeInsets.only( + top: 3, + bottom: 3, + left: 6, + right: 6, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + color: Theme.of(context).dividerColor, + ), + child: Container( + child: Row( + children: [ + icon != null + ? Padding( + padding: EdgeInsets.only(right: 3), + child: icon, + ) + : Container(), + Text( + data, + style: Theme.of(context) + .textTheme + .caption + .copyWith(color: Theme.of(context).accentColor), + ) + ], + ), + ), + ), + ); + + default: + return InkWell( + onTap: onPressed, + child: Container(), + ); + } + } +} diff --git a/lib/widgets/app_text_input.dart b/lib/widgets/app_text_input.dart new file mode 100644 index 0000000..8a9bbb7 --- /dev/null +++ b/lib/widgets/app_text_input.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; + +class AppTextInput extends StatelessWidget { + final String hintText; + final TextEditingController controller; + final FocusNode focusNode; + final VoidCallback onTapIcon; + final GestureTapCallback onTap; + final ValueChanged onChanged; + final ValueChanged onSubmitted; + final Icon icon; + final bool obscureText; + final TextInputType keyboardType; + final TextInputAction textInputAction; + final String errorText; + final int maxLines; + + AppTextInput({ + Key key, + this.hintText, + this.controller, + this.focusNode, + this.onTapIcon, + this.onTap, + this.onChanged, + this.onSubmitted, + this.icon, + this.obscureText = false, + this.keyboardType, + this.textInputAction, + this.errorText, + this.maxLines = 1, + }) : super(key: key); + + Widget _buildErrorLabel(BuildContext context) { + if (errorText == null) { + return Container(); + } + + return Container( + padding: EdgeInsets.only(left: 16, right: 16), + child: Text( + errorText, + style: Theme.of(context) + .textTheme + .caption + .copyWith(color: Theme.of(context).errorColor), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.circular(10), + ), + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + TextField( + onTap: onTap, + textAlignVertical: TextAlignVertical.center, + onSubmitted: onSubmitted, + controller: controller, + focusNode: focusNode, + onChanged: onChanged, + obscureText: obscureText, + keyboardType: keyboardType, + textInputAction: textInputAction, + maxLines: maxLines, + decoration: InputDecoration( + hintText: hintText, + suffixIcon: icon != null + ? IconButton( + icon: icon, + onPressed: onTapIcon, + ) + : null, + border: InputBorder.none, + ), + ), + _buildErrorLabel(context) + ], + ), + ); + } +} diff --git a/lib/widgets/app_user_info.dart b/lib/widgets/app_user_info.dart new file mode 100644 index 0000000..dd90536 --- /dev/null +++ b/lib/widgets/app_user_info.dart @@ -0,0 +1,230 @@ +import 'package:flutter/material.dart'; +import 'package:listar_flutter/models/model.dart'; +import 'package:shimmer/shimmer.dart'; + +enum AppUserType { basic, information } + +class AppUserInfo extends StatelessWidget { + final UserModel user; + final VoidCallback onPressed; + final AppUserType type; + + AppUserInfo({ + Key key, + this.user, + this.onPressed, + this.type = AppUserType.basic, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if (user == null) { + switch (type) { + case AppUserType.information: + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Row( + children: [ + Stack( + alignment: Alignment.bottomRight, + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + ), + Container( + width: 14, + height: 14, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + ) + ], + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 10, + width: 100, + color: Colors.white, + ), + Padding( + padding: EdgeInsets.only(top: 3, bottom: 3), + child: Container( + height: 10, + width: 100, + color: Colors.white, + ), + ), + Container( + height: 10, + width: 150, + color: Colors.white, + ), + ], + ), + ), + ), + ], + ), + ); + default: + return Shimmer.fromColors( + baseColor: Theme.of(context).hoverColor, + highlightColor: Theme.of(context).highlightColor, + enabled: true, + child: Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + ), + Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 10, + width: 100, + color: Colors.white, + ), + Padding( + padding: EdgeInsets.only(top: 3), + ), + Container( + height: 10, + width: 150, + color: Colors.white, + ), + ], + ), + ) + ], + ), + ); + } + } + + switch (type) { + case AppUserType.information: + return InkWell( + onTap: onPressed, + child: Row( + children: [ + Stack( + alignment: Alignment.bottomRight, + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: AssetImage(user.image), + fit: BoxFit.cover, + ), + ), + ), + Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).primaryColor, + ), + child: Text( + "${user.rate}", + style: TextStyle( + color: Colors.white, + fontSize: 8, + ), + ), + ) + ], + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(user.name, + maxLines: 1, + style: Theme.of(context).textTheme.subtitle2), + Padding( + padding: EdgeInsets.only(top: 3, bottom: 3), + child: Text( + user.description, + maxLines: 1, + style: Theme.of(context).textTheme.caption, + ), + ), + Text( + user.tag, + maxLines: 1, + style: Theme.of(context).textTheme.caption, + ), + ], + ), + ), + ), + ], + ), + ); + default: + return Container( + child: Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: AssetImage( + user.image, + ), + fit: BoxFit.cover, + ), + ), + ), + Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + user.name, + style: Theme.of(context) + .textTheme + .subtitle1 + .copyWith(fontWeight: FontWeight.w600), + ), + Text( + user.description, + style: Theme.of(context).textTheme.caption, + ) + ], + ), + ) + ], + ), + ); + } + } +} diff --git a/lib/widgets/widget.dart b/lib/widgets/widget.dart new file mode 100644 index 0000000..2271b78 --- /dev/null +++ b/lib/widgets/widget.dart @@ -0,0 +1,16 @@ +export 'app_button.dart'; +export 'app_category_item.dart'; +export 'app_circle_avatar.dart'; +export 'app_comment_item.dart'; +export 'app_group_circle_avatar.dart'; +export 'app_list_title.dart'; +export 'app_loading.dart'; +export 'app_model_bottom_sheet.dart'; +export 'app_notification_item.dart'; +export 'app_product_item.dart'; +export 'app_profile_performance.dart'; +export 'app_rating.dart'; +export 'app_star_rating.dart'; +export 'app_tag.dart'; +export 'app_text_input.dart'; +export 'app_user_info.dart'; diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..7718f41 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,472 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.6.1" + bloc: + dependency: "direct main" + description: + name: bloc + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + dio: + dependency: "direct main" + description: + name: dio + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.10" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_page_indicator: + dependency: transitive + description: + name: flutter_page_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.3" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.11" + flutter_slidable: + dependency: "direct main" + description: + name: flutter_slidable + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.7" + flutter_spinbox: + dependency: "direct main" + description: + name: flutter_spinbox + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" + flutter_swiper: + dependency: "direct main" + description: + name: flutter_swiper + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: transitive + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.2" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.4" + image_picker: + dependency: "direct main" + description: + name: image_picker + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.7+22" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" + intro_views_flutter: + dependency: "direct main" + description: + name: intro_views_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "2.9.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+2" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.5" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.0" + photo_view: + dependency: "direct main" + description: + name: photo_view + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.2" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.1" + provider: + dependency: transitive + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.3" + pull_to_refresh: + dependency: "direct main" + description: + name: pull_to_refresh + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.4" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.12+4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2+4" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+11" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2+7" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2+3" + shimmer: + dependency: "direct main" + description: + name: shimmer + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + transformer_page_view: + dependency: transitive + description: + name: transformer_page_view + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.6" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.dartlang.org" + source: hosted + version: "5.7.10" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+4" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+9" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.9" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5+3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+3" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" +sdks: + dart: ">=2.12.0 <3.0.0" + flutter: ">=1.22.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..c403a5d --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,83 @@ +name: listar_flutter +description: wem2017.github.io +version: 1.0.6+12 +environment: + sdk: ">=2.1.0 <3.0.0" +dependencies: + flutter: + sdk: flutter + flutter_localizations: + sdk: flutter + cupertino_icons: ^0.1.3 + shared_preferences: ^0.5.7+2 + intl: ^0.17.0-nullsafety.2 + bloc: ^4.0.0 + flutter_bloc: ^4.0.0 + dio: ^3.0.9 + flutter_swiper: ^1.1.6 + shimmer: ^1.1.1 + pull_to_refresh: ^1.5.8 + flutter_slidable: ^0.5.4 + image_picker: ^0.6.6+1 + photo_view: ^0.9.2 + intro_views_flutter: ^2.8.1 + url_launcher: ^5.4.0 + flutter_spinbox: 0.2.0 + +dev_dependencies: + flutter_test: + sdk: flutter +flutter: + assets: + - assets/data/ + - assets/images/ + - assets/locale/ + fonts: + - family: Raleway + fonts: + - asset: assets/fonts/Raleway-Black.ttf + - asset: assets/fonts/Raleway-BlackItalic.ttf + - asset: assets/fonts/Raleway-Bold.ttf + - asset: assets/fonts/Raleway-BoldItalic.ttf + - asset: assets/fonts/Raleway-ExtraBold.ttf + - asset: assets/fonts/Raleway-ExtraBoldItalic.ttf + - asset: assets/fonts/Raleway-ExtraLight.ttf + - asset: assets/fonts/Raleway-ExtraLightItalic.ttf + - asset: assets/fonts/Raleway-Italic.ttf + - asset: assets/fonts/Raleway-Light.ttf + - asset: assets/fonts/Raleway-LightItalic.ttf + - asset: assets/fonts/Raleway-Medium.ttf + - asset: assets/fonts/Raleway-MediumItalic.ttf + - asset: assets/fonts/Raleway-Regular.ttf + - asset: assets/fonts/Raleway-SemiBold.ttf + - asset: assets/fonts/Raleway-SemiBoldItalic.ttf + - asset: assets/fonts/Raleway-Thin.ttf + - asset: assets/fonts/Raleway-ThinItalic.ttf + - family: Roboto + fonts: + - asset: assets/fonts/Roboto-Black.ttf + - asset: assets/fonts/Roboto-BlackItalic.ttf + - asset: assets/fonts/Roboto-Bold.ttf + - asset: assets/fonts/Roboto-BoldItalic.ttf + - asset: assets/fonts/Roboto-Italic.ttf + - asset: assets/fonts/Roboto-Light.ttf + - asset: assets/fonts/Roboto-LightItalic.ttf + - asset: assets/fonts/Roboto-Medium.ttf + - asset: assets/fonts/Roboto-MediumItalic.ttf + - asset: assets/fonts/Roboto-Regular.ttf + - asset: assets/fonts/Roboto-Thin.ttf + - asset: assets/fonts/Roboto-ThinItalic.ttf + - family: Merriweather + fonts: + - asset: assets/fonts/Merriweather-Black.ttf + - asset: assets/fonts/Merriweather-BlackItalic.ttf + - asset: assets/fonts/Merriweather-Bold.ttf + - asset: assets/fonts/Merriweather-BoldItalic.ttf + - asset: assets/fonts/Merriweather-Italic.ttf + - asset: assets/fonts/Merriweather-Light.ttf + - asset: assets/fonts/Merriweather-LightItalic.ttf + - asset: assets/fonts/Merriweather-Regular.ttf + uses-material-design: true + +dependency_overrides: + intl: 0.17.0