Compare commits

..

No commits in common. "6.x" and "master" have entirely different histories.
6.x ... master

172 changed files with 3532 additions and 4381 deletions

3
.idea/.gitignore generated vendored
View File

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/vcs.xml generated
View File

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

View File

@ -1,25 +1,21 @@
# *<! ------ App ------!>*
APP_NAME="Raster"
APP_NAME="MyApp"
APP_ENV="local"
APP_DEBUG="true"
APP_URL="https://rasterdoo.com"
APP_URL="https://mywoocommercestore.com"
ASSET_PATH_PUBLIC="public/assets/"
ASSET_PATH_IMAGES="public/assets/images"
TIMEZONE="UTC"
LIGHT_THEME_ID="default_light_theme"
DARK_THEME_ID="default_dark_theme"
# *<! ------ Language ------!>*
DEFAULT_LOCALE="en"
DEFAULT_LOCALE=null
# supports: "en" (English), "es" (Spanish), "fr" (French), "hi" (Hindi), "it" (Italian), "pt" (Portuguese) or "zh" (Simplified Chinese)
# *<! ------ WooSignal Config ------!>*
APP_KEY="app_50818d11780aaba6b545076dea5b90"
APP_KEY="your app key"
# App key from WooSignal link: https://woosignal.com/dashboard
# *<! ------ STRIPE (OPTIONAL) ------!>*
@ -50,9 +46,3 @@ RAZORPAY_API_KEY=""
PRODUCT_PLACEHOLDER_IMAGE="https://woosignal.com/images/woocommerce-placeholder.png"
# Sets the default placeholder image for products with no image
AUTH_USER_KEY="AUTH_USER"
FCM_ENABLED=null
ENCRYPT_KEY=null
ENCRYPT_SECRET=null

View File

@ -1,109 +1,3 @@
## [6.10.1] - 2023-08-28
* Refactor project for Nylo 5.x.
* Fix AndroidManifest splash screen
* Pubspec.yaml dependency updates
## [6.10.0] - 2023-08-21
* Small refactor to project
* Pubspec.yaml dependency updates
## [6.9.0] - 2023-07-13
* Pull firebase config via woosignal api
* New encrypt key and secret added to .env
* fix fetchRelated to return "publish" products
* Pubspec.yaml dependency updates
## [6.8.2] - 2023-07-04
* Update gradle + kotlin versions.
* Pubspec.yaml dependency updates.
## [6.8.1] - 2023-07-03
* Fix auth bug.
* Pubspec.yaml dependency updates.
## [6.8.0] - 2023-07-03
* UI fixes.
* Fix price on coupon page error alerts.
* Fix issue where IOS builds were not using the correct build version.
* Small refactor to the project.
* Pubspec.yaml dependency updates.
## [6.7.0] - 2023-06-20
* Refactor project for Nylo 5.x.
* New Firebase provider for FCM.
* Pubspec.yaml dependency updates.
## [6.6.2] - 2023-06-14
* Page bug fixes
* Pubspec.yaml dependency updates.
## [6.6.1] - 2023-05-28
* Refactor widgets + bug fixes
* Refactor extensions.dart
* Pubspec.yaml dependency updates.
## [6.6.0] - 2023-05-18
* Nylo v5.0.0 migration
* Refactor project
* Flutter v3.10.0 compatibility
## [6.5.1] - 2023-03-04
* New translation added.
## [6.5.0] - 2023-03-04
* When making payments via Stripe, it will now save the card for later.
* Small UI changes to the checkout confirmation page.
* New translation added.
* Pubspec.yaml dependency updates.
## [6.4.1] - 2023-02-23
* Upgrade to Nylo v4.1.3
* Small refactor to TextStyle
* Fix the ThemeColor.get helper method to support ColorStyles.
* Pubspec.yaml dependency updates
## [6.4.0] - 2023-01-06
* Upgrade to Nylo v4.0.0
* Update copyright
* Refactor wp_json_api metadata
* Pubspec.yaml dependency updates
## [6.3.1] - 2022-11-04
* Fix email address bug in customer_address_input.dart
## [6.3.0] - 2022-11-03
* Ability to add Menu Links to the drawer widget through the WooSignal dashboard
* Fix wording when a shipping zone cannot be found to "Shipping is not supported for your location, sorry"
* Update account shipping widget to be uniform with the checkout shipping widget
* When logged in, the `CheckoutDetailsPage` will now populate shipping info from the users account
* Small refactor to resources/pages
* Pubspec.yaml dependency updates
## [6.2.0] - 2022-09-23
* Migration to use Nylo v3.4.0
* Pubspec.yaml dependency updates
* Increase the minimum targetSdkVersion to 31
* Merge #51, #50, #47, #40, #39 and #38 by @jeanmatthieud
* UI changes to the search page for a nicer experience
* More translations added throughout the app
## [6.1.0] - 2022-07-09
* Add RazorPay

View File

@ -1,6 +1,6 @@
BSD 2-Clause License
Copyright (c) 2023, WooSignal Ltd
Copyright (c) 2022, WooSignal Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -4,7 +4,8 @@
# WooCommerce App: Label StoreMax
### Label StoreMax
### Label StoreMax - v6.1.0
[Official WooSignal WooCommerce App](https://woosignal.com)

View File

@ -30,7 +30,7 @@ android {
exclude 'META-INF/DEPENDENCIES'
}
compileSdkVersion 33
compileSdkVersion 31
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@ -44,7 +44,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.woosignal.android"
minSdkVersion 21
targetSdkVersion 33
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true

View File

@ -12,7 +12,7 @@
<application
android:name="${applicationName}"
android:label="Raster Knjizara"
android:label="Label StoreMax"
android:icon="@mipmap/launcher_icon">
<activity
android:name=".MainActivity"
@ -21,8 +21,7 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:exported="true">
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
@ -31,7 +30,15 @@
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,12 +1,12 @@
buildscript {
ext.kotlin_version = '1.7.10'
ext.kotlin_version = '1.6.10'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath 'com.android.tools.build:gradle:7.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip

View File

@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>9.0</string>
</dict>
</plist>

View File

@ -1,49 +0,0 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.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
installer.generated_projects.each do |project|
project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
end
end

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -155,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@ -199,12 +199,10 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@ -215,7 +213,6 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -373,7 +370,6 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.flutter.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -512,7 +508,6 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.flutter.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -545,7 +540,6 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.flutter.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
@ -17,9 +15,13 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>NSCameraUsageDescription</key>
<string>You can take photos of your payment details.</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>MinimumOSVersion</key>
<string>13.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
@ -34,20 +36,14 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
<string>13.0</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string>You can take photos of your payment details.</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
@ -65,5 +61,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict>
</plist>

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "Der Versand wird für Ihr Land leider nicht unterstützt",
"Search": "Suche",
"Debit or Credit Card": "Debit- oder Kreditkarte",
"Cash on delivery": "Barzahlung bei Lieferung",
"Oops, something went wrong": "Ups! Irgendwas lief schief",
"Tax": "MwSt",
"No results": "Keine Ergebnisse",
@ -222,12 +221,8 @@
"Submit": "einreichen",
"Your review has been submitted": "Ihre Bewertung wurde übermittelt",
"Delete Account": "Konto löschen",
"Phone Number": "Telefonnummer",
"Delete your account": "Lösche deinen Account",
"Are you sure?": "Bist du dir sicher?",
"Yes, delete my account": "Ja, lösche mein Konto",
"Account deleted": "Konto gelöscht",
"Shipping is not supported for your location, sorry": "Der Versand wird für Ihren Standort nicht unterstützt, tut mir leid",
"Order Summary": "Bestellübersicht",
"By completing this order, I agree to all": "Mit Abschluss dieser Bestellung stimme ich allem zu"
"Account deleted": "Konto gelöscht"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "Shipping is not supported for your country, sorry",
"Search": "Search",
"Debit or Credit Card": "Debit or Credit Card",
"Cash on delivery": "Cash on delivery",
"Oops, something went wrong": "Oops, something went wrong",
"Tax": "Tax",
"No results": "No results",
@ -222,12 +221,8 @@
"Submit": "Submit",
"Your review has been submitted": "Your review has been submitted",
"Delete Account": "Delete Account",
"Phone Number": "Phone Number",
"Delete your account": "Delete your account",
"Are you sure?": "Are you sure?",
"Yes, delete my account": "Yes, delete my account",
"Account deleted": "Account deleted",
"Shipping is not supported for your location, sorry": "Shipping is not supported for your location, sorry",
"Order Summary": "Order Summary",
"By completing this order, I agree to all": "By completing this order, I agree to all"
"Account deleted": "Account deleted"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "El envío no es compatible con su país, lo siento",
"Search": "Buscar",
"Debit or Credit Card": "Tarjeta de débito o crédito",
"Cash on delivery": "Contra reembolso",
"Oops, something went wrong": "Huy! Algo salió mal",
"Tax": "Impuesto",
"No results": "No hay resultados",
@ -222,12 +221,8 @@
"Submit": "Entregar",
"Your review has been submitted": "Tu reseña ha sido enviada",
"Delete Account": "Borrar cuenta",
"Phone Number": "Número de teléfono",
"Delete your account": "eliminar su cuenta",
"Are you sure?": "¿Está seguro?",
"Yes, delete my account": "Sí, eliminar mi cuenta",
"Account deleted": "Cuenta borrada",
"Shipping is not supported for your location, sorry": "El envío no es compatible para su ubicación, lo siento",
"Order Summary": "Resumen del pedido",
"By completing this order, I agree to all": "Al completar este pedido, acepto todos"
"Account deleted": "Cuenta borrada"
}

View File

@ -1,19 +1,19 @@
{
"Categories": "Catégories",
"Categories": "Les catégories",
"Shop": "Boutique",
"Newest": "Le plus récent",
"Browse categories": "Parcourir les catégories",
"Cart": "Panier",
"You need items in your cart to checkout": "Ajoutez d'abord des articles à votre panier !",
"Cart": "Chariot",
"You need items in your cart to checkout": "Vous avez besoin d'articles dans votre panier pour passer à la caisse",
"Updated": "Mise à jour",
"Item removed": "Élément supprimé",
"Success": "C'est fait !",
"Cart cleared": "Panier vidé",
"Success": "Succès",
"Cart cleared": "Panier effacé",
"Shopping Cart": "Panier",
"Clear Cart": "Vider le panier",
"Empty Basket": "Panier vide",
"PROCEED TO CHECKOUT": "PASSER AU PAIEMENT",
"Browse": "Parcourir",
"PROCEED TO CHECKOUT": "PASSER À LA CAISSE",
"Browse": "Feuilleter",
"Search results for": "Résultats de recherche pour",
"Select a": "Sélectionner un",
"Added to cart": "Ajouté au panier",
@ -22,53 +22,53 @@
"Choose your options": "Choisissez vos options",
"Out of stock": "En rupture de stock",
"In Stock": "En stock",
"Add to cart": "Ajouter au panier",
"Oops": "Oups",
"Add to cart": "Ajouter au chariot",
"Oops": "Oops",
"Please select valid options first": "Veuillez d'abord sélectionner les options valides",
"Sorry": "Désolé",
"This item is not in stock": "Cet article n'est pas en stock",
"Description": "Description",
"This item is not in stock": "Cet article n'est pas en réserve",
"Description": "La description",
"Full description": "Description complète",
"ADD TO CART": "AJOUTER AU PANIER",
"ADD TO CART": "AJOUTER AU CHARIOT",
"This item is out of stock": "L'article n'est plus en stock",
"Add your shipping details first": "Ajoutez d'abord vos informations d'expédition",
"Checkout": "Commander",
"Add your shipping details first": "Ajoutez d'abord vos détails d'expédition",
"Checkout": "Check-out",
"Billing/shipping details": "Détails de facturation / expédition",
"Add billing & shipping details": "Ajouter les détails de facturation et d'expédition",
"Payment method": "Mode de paiement",
"Pay with": "Payer avec",
"Select a payment method": "Choisissez une méthode de paiement",
"Shipping selected": "Livraison sélectionnée",
"Select shipping": "Sélectionnez le mode de livraison",
"Select shipping": "Sélectionnez Livraison",
"Select a shipping option": "Sélectionnez une option d'expédition",
"Shipping fee": "Frais d'expédition",
"Subtotal": "Total",
"Total": "Total",
"CHECKOUT": "COMMANDER",
"One moment": "Veuillez patienter",
"CHECKOUT": "CHECK-OUT",
"One moment": "Un moment",
"Please select add your billing/shipping address to proceed": "Veuillez sélectionner ajouter votre adresse de facturation / expédition pour continuer",
"Your billing/shipping details are incomplete": "Vos coordonnées de facturation / expédition sont incomplètes",
"Please select a shipping method to proceed": "Veuillez sélectionner une méthode d'expédition pour continuer",
"Please select a payment method to proceed": "Veuillez sélectionner un mode de paiement pour continuer",
"Something went wrong, please contact our store": "Quelque chose s'est mal passé, veuillez contacter notre équipe",
"Something went wrong, please contact our store": "Quelque chose s'est mal passé, veuillez contacter notre magasin",
"Error": "Erreur",
"Order Status": "Statut de la commande",
"Thank You!": "Merci !",
"Thank You!": "Merci!",
"Your transaction details": "Vos détails de transaction",
"Order Ref": "Réf commande",
"Items": "Articles",
"Back to Home": "Retourner à l'accueil",
"Orders": "Commandes",
"Back to Home": "De retour à la maison",
"Orders": "Ordres",
"Billing & Shipping Details": "Détails de facturation et d'expédition",
"First Name": "Prénom",
"Last Name": "Nom de famille",
"Address Line": "Adresse",
"Address Line": "Ligne d'adresse",
"City": "Ville",
"Postal code": "Code postal",
"Email address": "Adresse électronique",
"Selected": "Sélectionné",
"Selected": "Choisi",
"Select country": "Choisissez le pays",
"Remember my details": "Retenir mes coordonnées",
"Remember my details": "Rappelez-vous mes coordonnées",
"USE SHIPPING ADDRESS": "UTILISER L'ADRESSE D'EXPÉDITION",
"About": "À propos de",
"Privacy policy": "Politique de confidentialité",
@ -76,13 +76,12 @@
"Version": "Version",
"Payment Method": "Mode de paiement",
"CANCEL": "ANNULER",
"Shipping Methods": "Méthodes de livraison",
"Shipping Methods": "méthodes de livraison",
"Shipping is not supported for your country, sorry": "La livraison n'est pas prise en charge pour votre pays, désolé",
"Search": "Chercher",
"Debit or Credit Card": "Carte de débit ou de crédit",
"Cash on delivery": "Paiement à la livraison",
"Oops, something went wrong": "Oups, quelque chose s'est mal passé",
"Tax": "TVA",
"Tax": "Impôt",
"No results": "Aucun résultat",
"There is an item out of stock": "Il y a un article en rupture de stock",
"Maximum stock reached": "Stock maximum atteint",
@ -99,35 +98,35 @@
"Create an account": "Créer un compte",
"Login": "S'identifier",
"Password": "Mot de passe",
"Oops!": "Oups !",
"Oops!": "Oops!",
"Invalid login credentials": "Authentification invalide",
"That email address is not valid": "Cette adresse e-mail n'est pas valide",
"Password must be a min 6 characters": "Le mot de passe doit contenir au moins 6 caractères",
"Please check your details": "Veuillez vérifier vos informations",
"Please check your details": "S'il vous plaît vérifier vos informations",
"Invalid": "Invalide",
"Actions": "Actions",
"View Terms and Conditions or Privacy policy": "Afficher les conditions générales ou la politique de confidentialité",
"Terms and Conditions": "Mentions légales",
"Terms and Conditions": "Termes et conditions",
"Privacy Policy": "Politique de confidentialité",
"terms and conditions": "mentions légales",
"terms and conditions": "Termes et conditions",
"and": "et",
"By tapping \"Register\" you agree to ": "En appuyant sur \"S'inscrire\", vous acceptez de ",
"privacy policy": "politique de confidentialité",
"Sign up": "S'inscrire",
"Email": "Email",
"Update details": "Informations personnelles",
"Settings": "Paramètres",
"Update details": "Mettre à jour les détails",
"Settings": "Réglages",
"Account": "Compte",
"Logout": "Se déconnecter",
"No orders found": "Aucune commande trouvée",
"items": "articles",
"Update Details": "Mettre à jour les informations",
"Invalid details": "Informations invalides",
"Update Details": "Détails de mise à jour",
"Invalid details": "Détails invalides",
"Please check your email and password": "Veuillez vérifier votre e-mail et votre mot de passe",
"Something went wrong, please try again.": "Une erreur s'est produite. Veuillez réessayer.",
"Done": "Terminé",
"Billing Details": "Facturation",
"Shipping Details": "Expédition",
"Billing Details": "Détails de la facturation",
"Shipping Details": "Les détails d'expédition",
"Shipping Address": "Adresse de livraison",
"State": "Etat",
"Country": "Pays",
@ -144,14 +143,14 @@
"Sort results": "Trier les résultats",
"you're now logged in": "Vous êtes maintenant connecté",
"Hello": "Bonjour",
"Welcome back": "Content de vous revoir",
"Welcome back": "Nous saluons le retour",
"Quantity": "Quantité",
"Select a state": "Sélectionner un état",
"Select state": "Sélectionnez l'état",
"Ship to a different address?": "Expédier à une adresse différente?",
"USE DETAILS": "METTRE À JOUR",
"USE DETAILS": "DÉTAILS D'UTILISATION",
"Not supported, try a card payment": "Non pris en charge, essayez un paiement par carte",
"Invalid shipping address, please check your shipping details": "Adresse de livraison non valide, veuillez vérifier vos infos de livraison",
"Invalid shipping address, please check your shipping details": "Adresse de livraison non valide, veuillez vérifier vos détails de livraison",
"Was": "Était",
"off": "de",
"Maximum quantity reached": "Quantité maximale atteinte",
@ -169,14 +168,14 @@
"A user already exists": "Un utilisateur existe déjà",
"That email is taken, try another": "Cet e-mail est pris, essayez un autre",
"The email field is empty": "Le champ e-mail est vide",
"No more orders": "Pas plus de commandes",
"No more orders": "Plus de commandes",
"Account updated": "Compte mis à jour",
"Spend a minimum of": "Dépensez un minimum de",
"for": "pour",
"Buy Product": "Acheter un produit",
"Retry": "Recommencez",
"Retry later": "Réessayer plus tard",
"Light Mode": "Mode clair",
"Light Mode": "Mode lumière",
"Dark Mode": "Mode sombre",
"PayPal Checkout": "Paiement PayPal",
"Processing Payment": "Traitement du paiement",
@ -184,26 +183,26 @@
"If you are not automatically redirected to PayPal within 5 seconds": "Si vous n'etes pas automatiquement redirige vers PayPal dans les 5 secondes",
"Payment Cancelled": "Paiement annulé",
"The payment has been cancelled": "Le paiement a été annulé",
"Must have": "Produits à voir",
"Must have": "Doit avoir",
"Our selection of new items": "Notre sélection de nouveautés",
"Register": "S'inscrire",
"No payment methods are available": "Aucun mode de paiement n'est disponible",
"Please enter a valid billing email": "Veuillez saisir une adresse e-mail de facturation valide",
"Please enter a valid shipping email": "Veuillez saisir un e-mail de livraison valide",
"Free postage": "Frais de port offerts",
"Free postage": "Sans frais de port",
"PROCESSING": "EN TRAITEMENT",
"Social": "Social",
"Please enter coupon to redeem": "Veuillez entrer le code promo pour l'utiliser",
"Coupon": "Code promo",
"Please enter coupon to redeem": "Veuillez entrer le coupon pour l'utiliser",
"Coupon": "Coupon",
"Apply": "Appliquer",
"Apply Coupon": "Appliquer code promo",
"Added to checkout": "Ajouté au panier",
"Redeem Coupon": "Échanger le code promo",
"Apply Coupon": "Appliquer Coupon",
"Added to checkout": "Ajouté à la caisse",
"Redeem Coupon": "Échanger le coupon",
"Add coupon code": "Ajouter un code promo",
"Coupon not found": "Code promo introuvable",
"Sorry, this coupon can not be used with your cart": "Désolé, ce code promo ne peut pas être utilisé avec votre panier",
"You cannot redeem this coupon": "Vous ne pouvez pas utiliser ce code promo",
"This coupon has expired": "Ce code promo a expiré",
"Coupon not found": "Coupon introuvable",
"Sorry, this coupon can not be used with your cart": "Désolé, ce coupon ne peut pas être utilisé avec votre panier",
"You cannot redeem this coupon": "Vous ne pouvez pas utiliser ce coupon",
"This coupon has expired": "Ce coupon a expiré",
"Usage limit has been reached": "La limite d'utilisation a été atteinte",
"View All": "Voir tout",
"Wishlist": "Liste de souhaits",
@ -214,20 +213,16 @@
"Spend less than maximumAmount to redeem": "Dépensez moins de {{maximumAmount}} de racheter",
"Related products": "Produits connexes",
"Reviews": "Commentaires",
"There are no reviews yet.": "Il n'y a pas encore de commentaire.",
"There are no reviews yet.": "Il n'y a pas encore de critiques.",
"More": "Suite",
"You may also like": "Vous pourriez aussi aimer",
"You may also like": "Tu pourrais aussi aimer",
"Leave a review": "Laisser un commentaire",
"How would you rate": "Comment évalueriez-vous",
"Submit": "Envoyer",
"Submit": "Soumettre",
"Your review has been submitted": "Votre avis a été soumis",
"Delete Account": "Supprimer le compte",
"Phone Number": "Numéro de téléphone",
"Delete your account": "Supprimer votre compte",
"Are you sure?": "Êtes-vous sûr?",
"Yes, delete my account": "Oui, supprimer mon compte",
"Account deleted": "Compte supprimé",
"Shipping is not supported for your location, sorry": "L'expédition n'est pas prise en charge pour votre emplacement, désolé",
"Order Summary": "Récapitulatif de la commande",
"By completing this order, I agree to all": "En remplissant cette commande, j'accepte toutes"
"Account deleted": "Compte supprimé"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "shiping aapake desh ke lie samarthit nahin hai, kshama karen",
"Search": "khoj",
"Debit or Credit Card": "debit ya kredit kaard",
"Cash on delivery": "dilavaree par nakadee\n",
"Oops, something went wrong": "oh! kuchh galat ho gaya hai",
"Tax": "kar",
"No results": "koee parinaam nahin",
@ -222,12 +221,8 @@
"Submit": "prastut karana",
"Your review has been submitted": "aapakee sameeksha jama ho chukee hai",
"Delete Account": "khaata hata do",
"Phone Number": "fon nambar",
"Delete your account": "apane khaate ko nasht karo",
"Are you sure?": "kya aapako yakeen hai?",
"Yes, delete my account": "haan, mera akaunt dileet kar do",
"Account deleted": "khaata hataaya gaya",
"Shipping is not supported for your location, sorry": "aapake sthaan ke lie shiping samarthit nahin hai, kshama karen",
"Order Summary": "aadesh saaraansh",
"By completing this order, I agree to all": "is aadesh ko poora karake, main sabhee ke lie sahamat hoon"
"Account deleted": "khaata hataaya gaya"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "La spedizione non è supportata per il tuo Paese, mi dispiace",
"Search": "Ricerca",
"Debit or Credit Card": "Bancomat o carta di credito",
"Cash on delivery": "Pagamento alla consegna",
"Oops, something went wrong": "Oops! Qualcosa è andato storto",
"Tax": "Imposta",
"No results": "Nessun risultato",
@ -222,12 +221,8 @@
"Submit": "Invia",
"Your review has been submitted": "La tua recensione è stata inviata",
"Delete Account": "Eliminare l'account",
"Phone Number": "Numero di telefono",
"Delete your account": "cancella il tuo account",
"Are you sure?": "Sei sicuro?",
"Yes, delete my account": "Sì, elimina il mio account",
"Account deleted": "Account cancellato",
"Shipping is not supported for your location, sorry": "La spedizione non è supportata per la tua posizione, mi dispiace",
"Order Summary": "Riepilogo dell'ordine",
"By completing this order, I agree to all": "Completando questo ordine, accetto tutto"
"Account deleted": "Account cancellato"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "Verzending wordt niet ondersteund voor uw land, sorry",
"Search": "Zoekopdracht",
"Debit or Credit Card": "Debet- of creditcard",
"Cash on delivery": "Onder rembours",
"Oops, something went wrong": "Oeps! Er is iets misgegaan",
"Tax": "Belasting",
"No results": "Geen resultaten",
@ -222,12 +221,8 @@
"Submit": "Indienen",
"Your review has been submitted": "Uw beoordeling is verzonden",
"Delete Account": "Account verwijderen",
"Phone Number": "Telefoonnummer",
"Delete your account": "Verwijder je account",
"Are you sure?": "Weet je het zeker?",
"Yes, delete my account": "Ja, verwijder mijn account",
"Account deleted": "Account verwijderd",
"Shipping is not supported for your location, sorry": "Verzending wordt niet ondersteund voor uw locatie, sorry",
"Order Summary": "Overzicht van de bestelling",
"By completing this order, I agree to all": "Door deze bestelling te voltooien, ga ik akkoord met alles"
"Account deleted": "Account verwijderd"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "O envio não é suportado pelo seu país, desculpe",
"Search": "Procurar",
"Debit or Credit Card": "Cartão de Débito ou Crédito",
"Cash on delivery": "Dinheiro na entrega",
"Oops, something went wrong": "Ops, algo deu errado",
"Tax": "Imposto",
"No results": "Sem resultados",
@ -222,12 +221,8 @@
"Submit": "Enviar",
"Your review has been submitted": "Sua avaliação foi enviada",
"Delete Account": "Deletar conta",
"Phone Number": "Número de telefone",
"Delete your account": "Deletar sua conta",
"Are you sure?": "Tem certeza?",
"Yes, delete my account": "Sim, excluir minha conta",
"Account deleted": "Conta excluída",
"Shipping is not supported for your location, sorry": "O envio não é suportado para a sua localização, desculpe",
"Order Summary": "Resumo do pedido",
"By completing this order, I agree to all": "Ao concluir este pedido, concordo com todos"
"Account deleted": "Conta excluída"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "Ülkeniz için gönderim desteklenmiyor, üzgünüm",
"Search": "Aramak",
"Debit or Credit Card": "Banka veya Kredi Kartı",
"Cash on delivery": "Kapıda ödeme",
"Oops, something went wrong": "Hoop! Birşeyler yanlış gitti",
"Tax": "Vergi",
"No results": "Sonuç yok",
@ -222,12 +221,8 @@
"Submit": "Göndermek",
"Your review has been submitted": "İncelemeniz gönderildi",
"Delete Account": "Hesabı sil",
"Phone Number": "Telefon numarası",
"Delete your account": "Hesabını sil",
"Are you sure?": "Emin misin?",
"Yes, delete my account": "Evet, hesabımı sil",
"Account deleted": "Hesap silindi",
"Shipping is not supported for your location, sorry": "Bulunduğunuz yer için gönderim desteklenmiyor, üzgünüm",
"Order Summary": "Sipariş özeti",
"By completing this order, I agree to all": "Bu siparişi tamamlayarak, tümünü kabul ediyorum"
"Account deleted": "Hesap silindi"
}

View File

@ -80,7 +80,6 @@
"Shipping is not supported for your country, sorry": "您所在的国家/地区不支持运输,抱歉",
"Search": "搜索",
"Debit or Credit Card": "借记卡或信用卡",
"Cash on delivery": "货到付款",
"Oops, something went wrong": "哎呀!出事了",
"Tax": "税",
"No results": "没结果",
@ -222,12 +221,8 @@
"Submit": "提交",
"Your review has been submitted": "您的评论已提交",
"Delete Account": "删除帐户",
"Phone Number": "电话号码",
"Delete your account": "删除您的帐户",
"Are you sure?": "你确定吗?",
"Yes, delete my account": "是的,删除我的帐户",
"Account deleted": "帐号已删除",
"Shipping is not supported for your location, sorry": "您所在的位置不支持送货,抱歉",
"Order Summary": "订单摘要",
"By completing this order, I agree to all": "通过完成此订单,我同意所有"
"Account deleted": "帐号已删除"
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,7 +10,7 @@
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
import 'package:woosignal/models/response/product_category.dart';
import 'package:woosignal/models/response/product.dart';
import 'package:woosignal/models/response/products.dart';
class ProductCategorySearchLoaderController
extends WooSignalApiLoaderController<Product> {

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -14,7 +14,7 @@ import 'package:flutter_app/app/models/cart_line_item.dart';
import 'package:flutter_app/bootstrap/enums/wishlist_action_enums.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/response/product.dart';
import 'package:woosignal/models/response/products.dart';
import 'package:woosignal/models/response/product_variation.dart'
as ws_product_variation;

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -9,7 +9,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
import 'package:woosignal/models/response/product.dart';
import 'package:woosignal/models/response/products.dart';
class ProductLoaderController extends WooSignalApiLoaderController<Product> {
ProductLoaderController();

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,7 +10,7 @@
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
import 'package:woosignal/models/response/product_review.dart';
import 'package:woosignal/models/response/product.dart';
import 'package:woosignal/models/response/products.dart';
class ProductReviewsLoaderController
extends WooSignalApiLoaderController<ProductReview> {

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -9,7 +9,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
import 'package:woosignal/models/response/product.dart';
import 'package:woosignal/models/response/products.dart';
class ProductSearchLoaderController
extends WooSignalApiLoaderController<Product> {

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -15,72 +15,8 @@ class BillingDetails {
CustomerAddress? shippingAddress;
bool? rememberDetails;
BillingDetails();
void initSession() {
billingAddress = CustomerAddress();
shippingAddress = CustomerAddress();
}
Map<String, dynamic> createStripeDetails() => {
'address': {
if (billingAddress?.addressLine != null)
'line1': billingAddress?.addressLine,
if (billingAddress?.city != null) 'city': billingAddress?.city,
if (billingAddress?.postalCode != null)
'postal_code': billingAddress?.postalCode,
if (billingAddress?.customerCountry?.state?.name != null)
'state': billingAddress?.customerCountry?.state?.name,
if (billingAddress?.customerCountry?.countryCode != null)
'country': billingAddress?.customerCountry?.countryCode,
},
'shipping': {
if (shippingAddress?.nameFull() != null)
'name': shippingAddress?.nameFull(),
if (shippingAddress?.city != null) 'city': shippingAddress?.city,
if (shippingAddress?.postalCode != null)
'postal_code': shippingAddress?.postalCode,
if (shippingAddress?.customerCountry?.state?.name != null)
'state': shippingAddress?.customerCountry?.state?.name,
if (shippingAddress?.customerCountry?.countryCode != null)
'country': shippingAddress?.customerCountry?.countryCode,
},
if (billingAddress?.emailAddress != null)
'email': billingAddress?.emailAddress,
if (billingAddress?.nameFull() != null)
'name': billingAddress?.nameFull(),
if (billingAddress?.phoneNumber != null)
'phone': billingAddress?.phoneNumber
};
Map<String, String?> getShippingAddressStripe() => {
"name": shippingAddress?.nameFull(),
"line1": shippingAddress!.addressLine,
"city": shippingAddress!.city,
"postal_code": shippingAddress!.postalCode,
"country": (shippingAddress?.customerCountry?.name ?? "")
};
fromWpMeta(Map<String, String> data) async {
final Map<String, String> shippingDetailsWpMeta = <String, String>{},
billingDetailsWpMeta = <String, String>{};
shippingDetailsWpMeta.addEntries(data.entries
.where((element) => element.key.startsWith("shipping_"))
.map((shippingMeta) => MapEntry(
shippingMeta.key.replaceAll("shipping_", ""), shippingMeta.value)));
billingDetailsWpMeta.addEntries(data.entries
.where((element) => element.key.startsWith("billing_"))
.map((billingMeta) => MapEntry(
billingMeta.key.replaceAll("billing_", ""), billingMeta.value)));
CustomerAddress billingCustomerAddress = CustomerAddress();
await billingCustomerAddress.fromWpMetaData(billingDetailsWpMeta);
CustomerAddress shippingCustomerAddress = CustomerAddress();
await shippingCustomerAddress.fromWpMetaData(shippingDetailsWpMeta);
billingAddress = billingCustomerAddress;
shippingAddress = shippingCustomerAddress;
}
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -11,7 +11,7 @@
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/response/product_variation.dart';
import 'package:woosignal/models/response/product.dart' as ws_product;
import 'package:woosignal/models/response/products.dart' as ws_product;
class CartLineItem {
String? name;

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -9,9 +9,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter_app/app/models/customer_country.dart';
import 'package:flutter_app/app/models/default_shipping.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:wp_json_api/models/wp_meta_meta.dart';
class CustomerAddress {
String? firstName;
@ -117,61 +114,4 @@ class CustomerAddress {
}
return data;
}
fromWpMetaData(Map<String, dynamic> data) async {
if (data.containsKey('first_name')) {
firstName = data['first_name'];
}
if (data.containsKey('last_name')) {
lastName = data['last_name'];
}
if (data.containsKey('address_1')) {
addressLine = data['address_1'];
}
if (data.containsKey('city')) {
city = data['city'];
}
if (data.containsKey('postcode')) {
postalCode = data['postcode'];
}
if (data.containsKey('email')) {
emailAddress = data['email'];
}
if (data.containsKey('phone')) {
phoneNumber = data['phone'];
}
if (data.containsKey('country')) {
DefaultShipping? defaultShipping =
await findCountryMetaForShipping(data['country']);
if (defaultShipping == null) {
return;
}
customerCountry = CustomerCountry.fromWpMeta(data, defaultShipping);
}
}
List<WpMetaData> toUserMetaDataItem(String type) {
return [
WpMetaData(key: "${type}_first_name", value: firstName),
WpMetaData(key: "${type}_last_name", value: lastName),
WpMetaData(key: "${type}_address_1", value: addressLine),
WpMetaData(key: "${type}_city", value: city),
WpMetaData(key: "${type}_postcode", value: postalCode),
WpMetaData(key: "${type}_phone", value: phoneNumber),
if (type != "shipping")
WpMetaData(key: "${type}_email", value: emailAddress),
WpMetaData(key: "${type}_country", value: customerCountry?.countryCode),
WpMetaData(
key: "${type}_state",
value: customerCountry?.state?.code
?.replaceAll("${customerCountry?.countryCode}:", "")),
];
}
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -9,7 +9,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter_app/app/models/default_shipping.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
class CustomerCountry {
String? countryCode;
@ -27,14 +26,6 @@ class CustomerCountry {
}
}
CustomerCountry.fromWpMeta(
Map<String, dynamic> json, DefaultShipping defaultShipping) {
countryCode = json['country'];
name = defaultShipping.country;
state = findDefaultShippingStateByCode(
defaultShipping, "${json['country']}:${json['state']}");
}
CustomerCountry.fromJson(Map<String, dynamic>? json) {
if (json == null) {
return;

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,16 +10,18 @@
import 'package:nylo_framework/nylo_framework.dart';
class User extends Model {
class User extends Storable {
String? userId;
String? token;
User();
User.fromUserAuthResponse({this.userId, this.token});
toJson() => {"token": token, "user_id": userId};
@override
toStorage() => {"token": token, "user_id": userId};
User.fromJson(dynamic data) {
@override
fromStorage(dynamic data) {
token = data['token'];
userId = data['user_id'];
}

View File

@ -8,7 +8,7 @@ import 'package:nylo_framework/nylo_framework.dart';
| ApiService
| -------------------------------------------------------------------------
| Define your API endpoints
| Learn more https://nylo.dev/docs/5.x/networking
| Learn more https://nylo.dev/docs/3.x/networking
|--------------------------------------------------------------------------
*/

View File

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_app/app/networking/dio/interceptors/logging_interceptor.dart';
import 'package:flutter_app/config/decoders.dart';
import 'package:nylo_framework/networking/ny_base_networking.dart';
import 'package:nylo_framework/nylo_framework.dart';
class BaseApiService extends NyBaseApiService {
BaseApiService(BuildContext? context) : super(context);
@ -13,7 +12,5 @@ class BaseApiService extends NyBaseApiService {
/// Default interceptors
@override
final interceptors = {
if (getEnv('APP_DEBUG') == true) LoggingInterceptor: LoggingInterceptor()
};
final interceptors = {LoggingInterceptor: LoggingInterceptor()};
}

View File

@ -16,7 +16,7 @@ class BearerAuthInterceptor extends Interceptor {
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
void onError(DioError err, ErrorInterceptorHandler handler) {
handler.next(err);
}
}

View File

@ -4,23 +4,29 @@ import 'package:nylo_framework/nylo_framework.dart';
class LoggingInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
print('REQUEST[${options.method}] => PATH: ${options.path}');
if (getEnv('APP_DEBUG') == true) {
print('REQUEST[${options.method}] => PATH: ${options.path}');
}
return super.onRequest(options, handler);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
print(
'RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');
print('DATA: ${response.requestOptions.path}');
log(response.data.toString());
if (getEnv('APP_DEBUG') == true) {
print(
'RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');
print('DATA: ${response.requestOptions.path}');
log(response.data.toString());
}
handler.next(response);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
print(
'ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
void onError(DioError err, ErrorInterceptorHandler handler) {
if (getEnv('APP_DEBUG') == true) {
print(
'ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
}
handler.next(err);
}
}

View File

@ -1,13 +1,7 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/config/decoders.dart';
import 'package:flutter_app/config/design.dart';
import 'package:flutter_app/config/theme.dart';
import 'package:flutter_app/config/validation_rules.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:flutter_app/config/localization.dart';
import 'package:woosignal/models/response/woosignal_app.dart';
@ -15,17 +9,35 @@ import 'package:woosignal/woosignal.dart';
import 'package:wp_json_api/wp_json_api.dart';
class AppProvider implements NyProvider {
@override
boot(Nylo nylo) async {
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
await WooSignal.instance
.init(appKey: getEnv('APP_KEY'), debugMode: getEnv('APP_DEBUG'),
encryptKey: getEnv('ENCRYPT_KEY', defaultValue: null),
encryptSecret: getEnv('ENCRYPT_SECRET', defaultValue: null)
);
.init(appKey: getEnv('APP_KEY'), debugMode: getEnv('APP_DEBUG'));
// Notifications
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
///
/// FirebaseMessaging messaging = FirebaseMessaging.instance;
///
/// NotificationSettings settings = await messaging.requestPermission(
/// alert: true,
/// announcement: false,
/// badge: true,
/// carPlay: false,
/// criticalAlert: false,
/// provisional: false,
/// sound: true,
/// );
///
/// if (settings.authorizationStatus == AuthorizationStatus.authorized) {
/// String token = await messaging.getToken();
/// WooSignal.instance.setFcmToken(token);
/// }
AppHelper.instance.appConfig = WooSignalApp();
AppHelper.instance.appConfig!.themeFont = "Poppins";
@ -49,27 +61,17 @@ class AppProvider implements NyProvider {
};
// WooSignal Setup
WooSignalApp? wooSignalApp = await (appWooSignal((api) => api.getApp(encrypted: shouldEncrypt())));
WooSignalApp? wooSignalApp = await (appWooSignal((api) => api.getApp()));
Locale locale = Locale('en');
if (wooSignalApp != null) {
AppHelper.instance.appConfig = wooSignalApp;
if (wooSignalApp.wpLoginEnabled == 1) {
if (wooSignalApp.wpLoginBaseUrl == null) {
AppHelper.instance.appConfig?.wpLoginEnabled = 0;
log('Set your stores domain on WooSignal. Go to Features > WP Login and add your domain to "Store Base Url"');
}
if (wooSignalApp.wpLoginWpApiPath == null) {
AppHelper.instance.appConfig?.wpLoginEnabled = 0;
log('Set your stores Wp JSON path on WooSignal. Go to Features > WP Login and add your Wp JSON path to "WP API Path"');
}
WPJsonAPI.instance.initWith(
baseUrl: wooSignalApp.wpLoginBaseUrl ?? "",
baseUrl: wooSignalApp.wpLoginBaseUrl!,
shouldDebug: getEnv('APP_DEBUG'),
wpJsonPath: wooSignalApp.wpLoginWpApiPath ?? "",
wpJsonPath: wooSignalApp.wpLoginWpApiPath!,
);
}
@ -89,19 +91,6 @@ class AppProvider implements NyProvider {
assetsDirectory: assetsDirectory,
valuesAsMap: valuesAsMap);
nylo.appThemes = appThemes;
nylo.appLoader = loader;
nylo.appLogo = logo;
nylo.addModelDecoders(modelDecoders);
nylo.addValidationRules(validationRules);
nylo.toastNotification = getToastNotificationWidget;
return nylo;
}
@override
afterBoot(Nylo nylo) async {
}
}

View File

@ -3,7 +3,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -14,7 +14,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_app/bootstrap/data/order_wc.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation_page.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';

View File

@ -8,9 +8,4 @@ class EventProvider implements NyProvider {
return nylo;
}
@override
afterBoot(Nylo nylo) async {
}
}

View File

@ -3,7 +3,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -14,7 +14,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_app/bootstrap/data/order_wc.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation_page.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';
@ -29,16 +29,8 @@ import 'package:woosignal/models/response/tax_rate.dart';
//
// });
// TO USE A PAYMENT GATEWAY, FIRST OPEN /config/payment_gateways.dart.
// THEN ADD A NEW PAYMENT LIKE IN THE BELOW EXAMPLE
//
// addPayment(
// id: 6,
// name: "My Payment",
// description: trans("Debit or Credit Card"),
// assetImage: "payment_logo.png", E.g. /public/assets/images/payment_logo.png
// pay: examplePay,
// ),
// REMEMBER TO ADD THIS METHOD E.G. "examplePay" TO THE APP_PAYMENT_METHODS
// AS THE PAY METHOD
examplePay(context,
{required CheckoutConfirmationPageState state, TaxRate? taxRate}) async {

View File

@ -1,49 +0,0 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/firebase_options.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/woosignal.dart';
class FirebaseProvider implements NyProvider {
@override
boot(Nylo nylo) async {
return null;
}
@override
afterBoot(Nylo nylo) async {
bool? firebaseFcmIsEnabled = AppHelper.instance.appConfig?.firebaseFcmIsEnabled;
if (firebaseFcmIsEnabled == null) {
firebaseFcmIsEnabled = getEnv('FCM_ENABLED', defaultValue: false);
}
if (firebaseFcmIsEnabled != true) return;
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseMessaging messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (settings.authorizationStatus != AuthorizationStatus.authorized) {
return;
}
String? token = await messaging.getToken();
if (token != null) {
WooSignal.instance.setFcmToken(token);
}
}
}

View File

@ -3,7 +3,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -15,7 +15,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_app/app/models/cart_line_item.dart';
import 'package:flutter_app/bootstrap/data/order_wc.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation_page.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation.dart';
import 'package:flutter_app/resources/widgets/checkout_paypal.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/payload/order_wc.dart';

View File

@ -3,7 +3,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -15,7 +15,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_app/app/models/cart.dart';
import 'package:flutter_app/bootstrap/data/order_wc.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation_page.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart';
import 'package:woosignal/models/response/tax_rate.dart';
@ -24,36 +24,36 @@ import 'package:woosignal/models/response/order.dart';
razorPay(context,
{required CheckoutConfirmationPageState state, TaxRate? taxRate}) async {
Razorpay razorpay = Razorpay();
Razorpay razorpay = Razorpay();
razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS,
(PaymentSuccessResponse response) async {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS,
(PaymentSuccessResponse response) async {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
Order? order = await appWooSignal((api) => api.createOrder(orderWC));
Order? order = await appWooSignal((api) => api.createOrder(orderWC));
if (order != null) {
showToastNotification(
context,
title: "Error".tr(),
description: trans("Something went wrong, please contact our store"),
);
state.reloadState(showLoader: false);
return;
}
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
});
if (order != null) {
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showToastNotification(
context,
title: "Error".tr(),
description: trans("Something went wrong, please contact our store"),
);
state.reloadState(showLoader: false);
}
});
razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, (PaymentFailureResponse response) {
showToastNotification(context,
title: trans("Error"),
description: response.message ?? "",
style: ToastNotificationStyleType.WARNING);
state.reloadState(showLoader: false);
});
razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, (PaymentFailureResponse response) {
showToastNotification(context,
title: trans("Error"),
description: response.message ?? "",
style: ToastNotificationStyleType.WARNING);
state.reloadState(showLoader: false);
});
razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet);
razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet);
// CHECKOUT HELPER
await checkout(taxRate, (total, billingDetails, cart) async {
@ -74,7 +74,7 @@ razorPay(context,
state.reloadState(showLoader: true);
razorpay.open(options);
razorpay.open(options);
});
}

View File

@ -1,20 +1,10 @@
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/routes/router.dart';
import 'package:nylo_framework/nylo_framework.dart';
class RouteProvider implements NyProvider {
@override
boot(Nylo nylo) async {
nylo.addRouter(appRouter());
return nylo;
}
@override
afterBoot(Nylo nylo) async {
String initialRoute = AppHelper.instance.appConfig!.appStatus != null
? '/home'
: '/no-connection';
nylo.setInitialRoute(initialRoute);
}
}

View File

@ -3,7 +3,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -15,7 +15,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/bootstrap/data/order_wc.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation_page.dart';
import 'package:flutter_app/resources/pages/checkout_confirmation.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/payload/order_wc.dart';
@ -47,17 +47,24 @@ stripePay(context,
}
try {
Map<String, dynamic>? rsp = {};
dynamic rsp = {};
// // CHECKOUT HELPER
await checkout(taxRate, (total, billingDetails, cart) async {
Map<String, dynamic> address = {
"name": billingDetails!.billingAddress?.nameFull(),
"line1": billingDetails.shippingAddress!.addressLine,
"city": billingDetails.shippingAddress!.city,
"postal_code": billingDetails.shippingAddress!.postalCode,
"country": (billingDetails.shippingAddress?.customerCountry?.name ?? "")
};
String cartShortDesc = await cart.cartShortDesc();
rsp = await appWooSignal((api) => api.stripePaymentIntentV2(
rsp = await appWooSignal((api) => api.stripePaymentIntent(
amount: total,
email: billingDetails?.billingAddress?.emailAddress,
email: billingDetails.billingAddress?.emailAddress,
desc: cartShortDesc,
shipping: billingDetails?.getShippingAddressStripe(),
customerDetails: billingDetails?.createStripeDetails(),
shipping: address,
));
});
@ -72,37 +79,22 @@ stripePay(context,
}
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
style: Theme.of(state.context).brightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
merchantDisplayName:
envVal('APP_NAME', defaultValue: wooSignalApp?.appName),
customerId: rsp!['customer'],
paymentIntentClientSecret: rsp!['client_secret'],
customerEphemeralKeySecret: rsp!['ephemeral_key'],
setupIntentClientSecret: rsp!['setup_intent_secret']),
);
paymentSheetParameters: SetupPaymentSheetParameters(
applePay: false,
googlePay: false,
style: Theme.of(state.context).brightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
testEnv: liveMode,
merchantCountryCode: envVal('STRIPE_COUNTRY_CODE',
defaultValue: wooSignalApp!.stripeCountryCode),
merchantDisplayName:
envVal('APP_NAME', defaultValue: wooSignalApp.appName),
paymentIntentClientSecret: rsp['client_secret'],
));
await Stripe.instance.presentPaymentSheet();
PaymentIntent paymentIntent =
await Stripe.instance.retrievePaymentIntent(rsp!['client_secret']);
if (paymentIntent.status == PaymentIntentsStatus.Unknown) {
showToastNotification(
context,
title: trans("Oops!"),
description: trans("Something went wrong, please try again."),
icon: Icons.payment,
style: ToastNotificationStyleType.WARNING,
);
}
if (paymentIntent.status != PaymentIntentsStatus.Succeeded) {
return;
}
state.reloadState(showLoader: true);
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
@ -118,7 +110,7 @@ stripePay(context,
return;
}
routeTo('/checkout-status', navigationType: NavigationType.pushAndForgetAll, data: order);
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} on StripeException catch (e) {
if (getEnv('APP_DEBUG', defaultValue: true)) {
NyLogger.error(e.error.message!);

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_app/config/theme.dart';
import 'package:nylo_framework/nylo_framework.dart';
// ignore: must_be_immutable
@ -59,12 +60,14 @@ class AppBuild extends StatelessWidget {
@override
Widget build(BuildContext context) {
Nylo nylo = Backpack.instance.read('nylo');
List<AppTheme> appThemes =
nylo.appThemes.map((appTheme) => appTheme.toAppTheme()).toList();
return LocalizedApp(
child: ThemeProvider(
themes: appThemes,
themes: appThemes
.map((appTheme) => appTheme.toAppTheme(
defaultTheme: appTheme.theme!.brightness == Brightness.light
? lightTheme
: darkTheme))
.toList(),
child: ThemeConsumer(
child: Builder(
builder: (themeContext) => ValueListenableBuilder(
@ -90,12 +93,7 @@ class AppBuild extends StatelessWidget {
title: title ?? "",
initialRoute: initialRoute,
onGenerateRoute: onGenerateRoute,
darkTheme: darkTheme ??
appThemes
.firstWhere(
(theme) => theme.id == getEnv('DARK_THEME_ID'),
orElse: () => appThemes.first)
.data,
darkTheme: darkTheme ?? ThemeConfig.dark().theme,
theme: themeData ?? ThemeProvider.themeOf(context).data,
localeResolutionCallback:
(Locale? locale, Iterable<Locale> supportedLocales) {

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
import 'package:flutter_app/resources/themes/styles/base_styles.dart';
import 'package:nylo_framework/nylo_framework.dart';
class BaseThemeConfig {
final String? id;
final String? description;
final ThemeData? theme;
final BaseColorStyles? colors;
final dynamic meta;
BaseThemeConfig(
{this.id,
this.description,
this.theme,
this.colors,
this.meta = const {}});
AppTheme toAppTheme({ThemeData? defaultTheme}) => AppTheme(
id: id!,
data: defaultTheme ?? theme!,
description: description!,
);
}

View File

@ -1,8 +1,12 @@
// import 'package:firebase_core/firebase_core.dart';
// import 'package:firebase_messaging/firebase_messaging.dart';
// import 'package:flutter_app/firebase_options.dart';
/// boot application
import 'package:flutter_app/config/providers.dart';
import 'package:nylo_framework/nylo_framework.dart';
class Boot {
static Future<Nylo> nylo() async => await bootApplication(providers);
static Future<void> finished(Nylo nylo) async => await bootFinished(nylo, providers);
static Future<void> finished(Nylo nylo) async => await bootFinished(nylo);
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -15,7 +15,6 @@ import 'package:flutter_app/app/models/cart.dart';
import 'package:flutter_app/app/models/cart_line_item.dart';
import 'package:flutter_app/app/models/checkout_session.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/bootstrap/shared_pref/sp_auth.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/tax_rate.dart';
@ -52,7 +51,7 @@ Future<OrderWC> buildOrderWC({TaxRate? taxRate, bool markPaid = true}) async {
tmpLineItem.variationId = cartItem.variationId;
}
tmpLineItem.subtotal = (parseWcPrice(cartItem.subtotal) * parseWcPrice(cartItem.quantity.toString())).toString();
tmpLineItem.subtotal = cartItem.subtotal;
lineItems.add(tmpLineItem);
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,49 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/themes/styles/color_styles.dart';
import 'package:nylo_framework/nylo_framework.dart';
extension NyText on Text {
/// Sets the color from your [ColorStyles] or [Color].
Text setColor(
BuildContext context, Color Function(ColorStyles color) newColor,
{String? themeId}) {
return copyWith(
style: TextStyle(
color: newColor(ThemeColor.get(context, themeId: themeId))));
}
}
/// Check if the [Product] is new.
extension DateTimeExtension on DateTime? {
bool? isAfterOrEqualTo(DateTime dateTime) {
final date = this;
if (date != null) {
final isAtSameMomentAs = dateTime.isAtSameMomentAs(date);
return isAtSameMomentAs | date.isAfter(dateTime);
}
return null;
}
bool? isBeforeOrEqualTo(DateTime dateTime) {
final date = this;
if (date != null) {
final isAtSameMomentAs = dateTime.isAtSameMomentAs(date);
return isAtSameMomentAs | date.isBefore(dateTime);
}
return null;
}
bool? isBetween(
DateTime fromDateTime,
DateTime toDateTime,
) {
final date = this;
if (date != null) {
final isAfter = date.isAfterOrEqualTo(fromDateTime) ?? false;
final isBefore = date.isBeforeOrEqualTo(toDateTime) ?? false;
return isAfter && isBefore;
}
return null;
}
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -20,12 +20,13 @@ import 'package:flutter_app/app/models/payment_type.dart';
import 'package:flutter_app/app/models/user.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/bootstrap/enums/symbol_position_enums.dart';
import 'package:flutter_app/bootstrap/extensions.dart';
import 'package:flutter_app/bootstrap/shared_pref/shared_key.dart';
import 'package:flutter_app/config/currency.dart';
import 'package:flutter_app/config/decoders.dart';
import 'package:flutter_app/config/events.dart';
import 'package:flutter_app/config/payment_gateways.dart';
import 'package:flutter_app/config/theme.dart';
import 'package:flutter_app/resources/themes/styles/base_styles.dart';
import 'package:flutter_app/resources/widgets/no_results_for_products_widget.dart';
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
@ -38,42 +39,23 @@ import 'package:money_formatter/money_formatter.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
import 'package:status_alert/status_alert.dart';
import 'package:woosignal/models/response/product.dart';
import 'package:woosignal/models/response/products.dart';
import 'package:woosignal/models/response/tax_rate.dart';
import 'package:woosignal/woosignal.dart';
import 'package:wp_json_api/models/responses/wp_user_info_response.dart';
import '../resources/themes/styles/color_styles.dart';
import 'package:flutter/services.dart' show rootBundle;
Future<User?> getUser() async =>
(await (NyStorage.read<User>(SharedKey.authUser)));
(await (NyStorage.read<User>(SharedKey.authUser, model: User())));
Future appWooSignal(Function(WooSignal api) api) async {
Future appWooSignal(Function(WooSignal) api) async {
return await api(WooSignal.instance);
}
/// helper to find correct color from the [context].
class ThemeColor {
static ColorStyles get(BuildContext context, {String? themeId}) {
Nylo nylo = Backpack.instance.read('nylo');
List<BaseThemeConfig<ColorStyles>> appThemes =
nylo.appThemes as List<BaseThemeConfig<ColorStyles>>;
if (themeId == null) {
BaseThemeConfig<ColorStyles> themeFound = appThemes.firstWhere(
(theme) =>
theme.id ==
getEnv(Theme.of(context).brightness == Brightness.light
? 'LIGHT_THEME_ID'
: 'DARK_THEME_ID'),
orElse: () => appThemes.first);
return themeFound.colors;
}
BaseThemeConfig<ColorStyles> baseThemeConfig = appThemes.firstWhere(
(theme) => theme.id == themeId,
orElse: () => appThemes.first);
return baseThemeConfig.colors;
static BaseColorStyles? get(BuildContext context) {
return ((Theme.of(context).brightness == Brightness.light)
? ThemeConfig.light().colors
: ThemeConfig.dark().colors);
}
}
@ -85,7 +67,7 @@ extension ColorsHelper on TextStyle {
}
}
Future<List<PaymentType?>> getPaymentTypes() async {
List<PaymentType?> getPaymentTypes() {
List<PaymentType?> paymentTypes = [];
for (var appPaymentGateway in appPaymentGateways) {
if (paymentTypes.firstWhere(
@ -122,13 +104,13 @@ dynamic envVal(String envVal, {dynamic defaultValue}) =>
PaymentType addPayment(
{required int id,
required String name,
required String description,
required String desc,
required String assetImage,
required Function pay}) =>
PaymentType(
id: id,
name: name,
desc: description,
desc: desc,
assetImage: assetImage,
pay: pay,
);
@ -157,7 +139,6 @@ String moneyFormatter(double amount) {
amount: amount,
settings: MoneyFormatterSettings(
symbol: AppHelper.instance.appConfig!.currencyMeta!.symbolNative,
symbolAndNumberSeparator: ""
),
);
if (appCurrencySymbolPosition == SymbolPositionType.left) {
@ -488,7 +469,7 @@ Widget refreshableScroll(context,
return StaggeredGridTile.fit(
crossAxisCellCount: 1,
child: Container(
height: 350,
height: 200,
child: ProductItemContainer(
product: product,
onTap: onTap,
@ -506,9 +487,9 @@ class UserAuth {
String redirect = "/home";
}
Future<List<DefaultShipping>> getDefaultShipping() async {
String data =
await rootBundle.loadString('public/assets/json/default_shipping.json');
Future<List<DefaultShipping>> getDefaultShipping(BuildContext context) async {
String data = await DefaultAssetBundle.of(context)
.loadString("public/assets/json/default_shipping.json");
dynamic dataJson = json.decode(data);
List<DefaultShipping> shipping = [];
@ -526,47 +507,6 @@ Future<List<DefaultShipping>> getDefaultShipping() async {
return shipping;
}
Future<DefaultShipping?> findCountryMetaForShipping(String countryCode) async {
List<DefaultShipping> defaultShipping = await getDefaultShipping();
List<DefaultShipping> shippingByCountryCode =
defaultShipping.where((element) => element.code == countryCode).toList();
if (shippingByCountryCode.isNotEmpty) {
return shippingByCountryCode.first;
}
return null;
}
DefaultShippingState? findDefaultShippingStateByCode(
DefaultShipping defaultShipping, String code) {
List<DefaultShippingState> defaultShippingStates =
defaultShipping.states.where((state) => state.code == code).toList();
if (defaultShippingStates.isEmpty) {
return null;
}
DefaultShippingState defaultShippingState = defaultShippingStates.first;
return DefaultShippingState(
code: defaultShippingState.code, name: defaultShippingState.name);
}
bool hasKeyInMeta(WPUserInfoResponse wpUserInfoResponse, String key) {
return (wpUserInfoResponse.data!.metaData ?? [])
.where((meta) => meta.key == key)
.toList()
.isNotEmpty;
}
String fetchValueInMeta(WPUserInfoResponse wpUserInfoResponse, String key) {
String value = "";
List<dynamic>? metaDataValue = (wpUserInfoResponse.data!.metaData ?? [])
.where((meta) => meta.key == key)
.first
.value;
if (metaDataValue != null && metaDataValue.isNotEmpty) {
return metaDataValue.first ?? "";
}
return value;
}
String truncateString(String data, int length) {
return (data.length >= length) ? '${data.substring(0, length)}...' : data;
}
@ -609,46 +549,6 @@ removeWishlistProduct({required Product? product}) async {
await NyStorage.store(SharedKey.wishlistProducts, json);
}
Future<BillingDetails> billingDetailsFromWpUserInfoResponse(
wpUserInfoResponse) async {
List<String> metaDataAddress = [
'billing_first_name',
'billing_last_name',
'billing_company',
'billing_address_1',
'billing_address_2',
'billing_city',
'billing_postcode',
'billing_country',
'billing_state',
'billing_phone',
'billing_email',
'shipping_first_name',
'shipping_last_name',
'shipping_company',
'shipping_address_1',
'shipping_address_2',
'shipping_city',
'shipping_postcode',
'shipping_country',
'shipping_state',
'shipping_phone',
];
Map<String, String> metaData = {};
for (var dataKey in metaDataAddress) {
if (hasKeyInMeta(wpUserInfoResponse, dataKey)) {
String value = fetchValueInMeta(wpUserInfoResponse, dataKey);
metaData.addAll({dataKey: value});
}
}
BillingDetails billingDetails = BillingDetails();
await billingDetails.fromWpMeta(metaData);
return billingDetails;
}
/// API helper
api<T>(dynamic Function(T) request, {BuildContext? context}) async =>
await nyApi<T>(
@ -656,27 +556,3 @@ api<T>(dynamic Function(T) request, {BuildContext? context}) async =>
/// Event helper
event<T>({Map? data}) async => nyEvent<T>(params: data, events: events);
/// Check if the [Product] is new.
bool isProductNew(Product? product) {
if (product?.dateCreatedGMT == null) false;
try {
DateTime dateTime = DateTime.parse(product!.dateCreatedGMT!);
return dateTime.isBetween(DateTime.now().subtract(Duration(days: 2)), DateTime.now()) ?? false;
} on Exception catch (e) {
NyLogger.error(e.toString());
}
return false;
}
bool shouldEncrypt() {
String? encryptKey = getEnv('ENCRYPT_KEY', defaultValue: "");
if (encryptKey == null || encryptKey == "") {
return false;
}
String? encryptSecret = getEnv('ENCRYPT_KEY', defaultValue: "");
if (encryptSecret == null || encryptSecret == "") {
return false;
}
return true;
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -1,19 +1,16 @@
import 'package:flutter_app/app/models/user.dart';
import 'package:flutter_app/app/networking/api_service.dart';
import 'package:flutter_app/app/networking/dio/base_api_service.dart';
/*
|--------------------------------------------------------------------------
| Model Decoders
| -------------------------------------------------------------------------
| Model decoders are used in 'app/networking/' for morphing json payloads
| into Models. Learn more https://nylo.dev/docs/5.x/decoders#model-decoders
| into Models. Learn more https://nylo.dev/docs/3.x/decoders#model-decoders
|--------------------------------------------------------------------------
*/
final Map<Type, dynamic> modelDecoders = {
// ...
User: (data) => User.fromJson(data)
};
/*
@ -22,11 +19,11 @@ final Map<Type, dynamic> modelDecoders = {
| -------------------------------------------------------------------------
| API decoders are used when you need to access an API service using the
| 'api' helper. E.g. api<MyApiService>((request) => request.fetchData());
| Learn more https://nylo.dev/docs/5.x/decoders#api-decoders
| Learn more https://nylo.dev/docs/3.x/decoders#api-decoders
|--------------------------------------------------------------------------
*/
final Map<Type, BaseApiService> apiDecoders = {
final Map<Type, dynamic> apiDecoders = {
ApiService: ApiService(),
// ...

View File

@ -1,32 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_app/config/toast_notification.dart';
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
import 'package:flutter_app/resources/widgets/toast_notification_widget.dart';
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
import 'package:nylo_framework/nylo_framework.dart';
/*
|--------------------------------------------------------------------------
| Design
| Contains widgets used in the Nylo framework.
|
| Learn more: https://nylo.dev/docs/5.x/themes
|--------------------------------------------------------------------------
*/
Widget logo = StoreLogo();
// resources/widgets/woosignal_ui.dart
Widget loader = AppLoaderWidget();
// resources/widgets/app_loader_widget.dart
Widget getToastNotificationWidget({
required ToastNotificationStyleType style,
Function(ToastNotificationStyleMetaHelper helper)? toastNotificationStyleMeta, Function? onDismiss}) {
if (toastNotificationStyleMeta == null) return SizedBox.shrink();
ToastMeta toastMeta = toastNotificationStyleMeta(NyToastNotificationStyleMetaHelper(style));
return ToastNotification(toastMeta, onDismiss: onDismiss);
// resources/widgets/toast_notification.dart
}

View File

@ -8,12 +8,11 @@ import 'package:nylo_framework/nylo_framework.dart';
| Add your "app/events" here.
| Events can be fired using: event<MyEvent>();
|
| Learn more: https://nylo.dev/docs/5.x/events
| Learn more: https://nylo.dev/docs/3.x/events
|--------------------------------------------------------------------------
*/
final Map<Type, NyEvent> events = {
LoginEvent: LoginEvent(),
LogoutEvent: LogoutEvent(),
AuthUserEvent: AuthUserEvent(),
};

View File

@ -1,10 +1,9 @@
import 'package:flutter_app/app/models/payment_type.dart';
import 'package:flutter_app/app/providers/payments/cash_on_delivery.dart';
import 'package:flutter_app/app/providers/payments/paypal_pay.dart';
import 'package:flutter_app/app/providers/payments/razorpay_pay.dart';
import 'package:flutter_app/app/providers/payments/stripe_pay.dart';
import 'package:flutter_app/app/providers/cash_on_delivery.dart';
import 'package:flutter_app/app/providers/paypal_pay.dart';
import 'package:flutter_app/app/providers/razorpay_pay.dart';
import 'package:flutter_app/app/providers/stripe_pay.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:nylo_framework/nylo_framework.dart';
/*
|--------------------------------------------------------------------------
@ -15,7 +14,7 @@ import 'package:nylo_framework/nylo_framework.dart';
|--------------------------------------------------------------------------
*/
const appPaymentGateways = ["CashOnDelivery"];
const appPaymentGateways = [];
// Available: "Stripe", "CashOnDelivery", "PayPal", "RazorPay"
// e.g. app_payment_gateways = ["Stripe", "CashOnDelivery"]; will only use Stripe and Cash on Delivery.
@ -23,7 +22,7 @@ List<PaymentType> paymentTypeList = [
addPayment(
id: 1,
name: "Stripe",
description: trans("Debit or Credit Card"),
desc: "Debit or Credit Card",
assetImage: "dark_powered_by_stripe.png",
pay: stripePay,
),
@ -31,7 +30,7 @@ List<PaymentType> paymentTypeList = [
addPayment(
id: 2,
name: "CashOnDelivery",
description: trans("Cash on delivery"),
desc: "Cash on delivery",
assetImage: "cash_on_delivery.jpeg",
pay: cashOnDeliveryPay,
),
@ -39,7 +38,7 @@ List<PaymentType> paymentTypeList = [
addPayment(
id: 4,
name: "PayPal",
description: trans("Debit or Credit Card"),
desc: "Debit or Credit Card",
assetImage: "paypal_logo.png",
pay: payPalPay,
),
@ -47,7 +46,7 @@ List<PaymentType> paymentTypeList = [
addPayment(
id: 5,
name: "RazorPay",
description: trans("Debit or Credit Card"),
desc: "Debit or Credit Card",
assetImage: "razorpay.png",
pay: razorPay,
),
@ -57,7 +56,7 @@ List<PaymentType> paymentTypeList = [
// addPayment(
// id: 6,
// name: "MyNewPaymentMethod",
// description: "Debit or Credit Card",
// desc: "Debit or Credit Card",
// assetImage: "add icon image to public/assets/images/myimage.png",
// pay: "myCustomPaymentFunction",
// ),

View File

@ -1,8 +1,6 @@
import '/app/providers/firebase_provider.dart';
import 'package:flutter_app/app/providers/app_provider.dart';
import 'package:flutter_app/app/providers/event_provider.dart';
import 'package:flutter_app/app/providers/route_provider.dart';
import 'package:nylo_framework/nylo_framework.dart';
/*
|--------------------------------------------------------------------------
@ -10,15 +8,12 @@ import 'package:nylo_framework/nylo_framework.dart';
| Add your "app/providers" here.
| Providers are booted when your application start.
|
| Learn more: https://nylo.dev/docs/5.x/providers
| Learn more: https://nylo.dev/docs/3.x/providers
|--------------------------------------------------------------------------
*/
final Map<Type, NyProvider> providers = {
final providers = {
AppProvider: AppProvider(),
RouteProvider: RouteProvider(),
EventProvider: EventProvider(),
FirebaseProvider: FirebaseProvider(),
};

View File

@ -1,19 +0,0 @@
/*
|--------------------------------------------------------------------------
| Storage Keys
| Add your storage keys here and then use them later to retrieve data.
| E.g. static String userCoins = "USER_COINS";
| String coins = NyStorage.read( StorageKey.userCoins );
|
| Learn more: https://nylo.dev/docs/5.x/storage#storage-keys
|--------------------------------------------------------------------------
*/
import 'package:nylo_framework/nylo_framework.dart';
class StorageKey {
static String userToken = "USER_TOKEN";
static String authUser = getEnv('AUTH_USER_KEY', defaultValue: 'AUTH_USER');
/// Add your storage keys here...
}

View File

@ -1,9 +1,9 @@
import 'package:flutter_app/bootstrap/base_theme_config.dart';
import 'package:flutter_app/resources/themes/dark_theme.dart';
import 'package:flutter_app/resources/themes/light_theme.dart';
import 'package:flutter_app/resources/themes/styles/color_styles.dart';
import 'package:flutter_app/resources/themes/styles/base_styles.dart';
import 'package:flutter_app/resources/themes/styles/dark_theme_colors.dart';
import 'package:flutter_app/resources/themes/styles/light_theme_colors.dart';
import 'package:nylo_framework/nylo_framework.dart';
/*
|--------------------------------------------------------------------------
@ -12,7 +12,7 @@ import 'package:nylo_framework/nylo_framework.dart';
*/
// App Themes
final List<BaseThemeConfig<ColorStyles>> appThemes = [
final appThemes = [
ThemeConfig.light(),
ThemeConfig.dark(),
];
@ -24,10 +24,10 @@ final List<BaseThemeConfig<ColorStyles>> appThemes = [
*/
// Light Colors
ColorStyles lightColors = LightThemeColors();
BaseColorStyles lightColors = LightThemeColors();
// Dark Colors
ColorStyles darkColors = DarkThemeColors();
BaseColorStyles darkColors = DarkThemeColors();
/*
|--------------------------------------------------------------------------
@ -38,7 +38,7 @@ ColorStyles darkColors = DarkThemeColors();
// Preset Themes
class ThemeConfig {
// LIGHT
static BaseThemeConfig<ColorStyles> light() => BaseThemeConfig<ColorStyles>(
static BaseThemeConfig light() => BaseThemeConfig(
id: "default_light_theme",
description: "Light theme",
theme: lightTheme(lightColors),
@ -46,7 +46,7 @@ class ThemeConfig {
);
// DARK
static BaseThemeConfig<ColorStyles> dark() => BaseThemeConfig<ColorStyles>(
static BaseThemeConfig dark() => BaseThemeConfig(
id: "default_dark_theme",
description: "Dark theme",
theme: darkTheme(darkColors),
@ -60,10 +60,10 @@ class ThemeConfig {
// First add the colors which was created into the above section like the following:
// Bright Colors
/// ColorStyles brightColors = BrightThemeColors();
/// BaseColorStyles brightColors = BrightThemeColors();
// Next, uncomment the below:
/// static BaseThemeConfig<ColorStyles> bright() => BaseThemeConfig<ColorStyles>(
/// static BaseThemeConfig bright() => BaseThemeConfig(
/// id: "default_bright_theme",
/// description: "Bright theme",
/// theme: brightTheme(brightColors),

View File

@ -1,34 +0,0 @@
import 'package:nylo_framework/nylo_framework.dart';
/// ToastNotificationStyleMetaHelper is used to return
/// the correct value for the [ToastNotificationStyleType] toast style.
class NyToastNotificationStyleMetaHelper extends ToastNotificationStyleMetaHelper {
NyToastNotificationStyleMetaHelper(ToastNotificationStyleType? style) : super(style);
onSuccess() {
return ToastMeta.success();
}
onWarning() {
return ToastMeta.warning();
}
onInfo() {
return ToastMeta.info();
}
onDanger() {
return ToastMeta.danger();
}
// Example customizing a notification
// onSuccess() {
// return ToastMeta.success(
// title: "Hello",
// description: "World",
// action: () {},
// backgroundColor: Colors.Yellow
// );
// }
}

View File

@ -1,36 +0,0 @@
/*
|--------------------------------------------------------------------------
| Validation Rules
| -------------------------------------------------------------------------
| Add custom validation rules for your project in this file.
| Learn more https://nylo.dev/docs/5.x/validation#custom-validation-rules
|--------------------------------------------------------------------------
*/
final Map<String, dynamic> validationRules = {
/// Example
// "simple_password": (attribute) => SimplePassword(attribute)
};
/// Example validation class
// class SimplePassword extends ValidationRule {
// SimplePassword(String attribute)
// : super(
// attribute: attribute,
// signature: "simple_password", // Use this signature for the validator
// description: "The $attribute field must be between 4 and 8 digits long and include at least one numeric digit", // Toast description when an error occurs
// textFieldMessage: "Must be between 4 and 8 digits long with one numeric digit"); // TextField description when an error occurs
//
// @override
// handle(Map<String, dynamic> info) {
// super.handle(info);
//
// /// info['rule'] = Validation rule i.e "min".
// /// info['data'] = Data the user has passed into the validation.
// /// info['message'] = Overriding message to be displayed for validation (optional).
//
// RegExp regExp = RegExp(r'^(?=.*\d).{4,8}$');
// return regExp.hasMatch(info['data']);
// }
// }

View File

@ -1,66 +0,0 @@
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
import 'package:flutter_app/bootstrap/app_helper.dart';
/// Default [FirebaseOptions] for use with your Firebase apps.
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for web - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
if (AppHelper.instance.appConfig?.firebaseOptionsAndroid == null) {
throw UnsupportedError(
'Add a valid Firebase json config on https://woosignal.com for your WooCommerce store',
);
}
return FirebaseOptions(
apiKey: AppHelper.instance.appConfig!.firebaseOptionsAndroid!['apiKey'],
appId: AppHelper.instance.appConfig!.firebaseOptionsAndroid!['appId'],
messagingSenderId: AppHelper.instance.appConfig!.firebaseOptionsAndroid!['messagingSenderId'],
projectId: AppHelper.instance.appConfig!.firebaseOptionsAndroid!['projectId'],
storageBucket: AppHelper.instance.appConfig!.firebaseOptionsAndroid!['storageBucket'],
);
case TargetPlatform.iOS:
if (AppHelper.instance.appConfig?.firebaseOptionsIos == null) {
throw UnsupportedError(
'Add a valid Firebase plist config on https://woosignal.com for your WooCommerce store',
);
}
return FirebaseOptions(
apiKey: AppHelper.instance.appConfig!.firebaseOptionsIos!['apiKey'],
appId: AppHelper.instance.appConfig!.firebaseOptionsIos!['appId'],
messagingSenderId: AppHelper.instance.appConfig!.firebaseOptionsIos!['messagingSenderId'],
projectId: AppHelper.instance.appConfig!.firebaseOptionsIos!['projectId'],
storageBucket: AppHelper.instance.appConfig!.firebaseOptionsIos!['storageBucket'],
iosClientId: AppHelper.instance.appConfig!.firebaseOptionsIos!['iosClientId'],
iosBundleId: AppHelper.instance.appConfig!.firebaseOptionsIos!['iosBundleId'],
);
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_app/bootstrap/app.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/bootstrap/boot.dart';
import 'package:nylo_framework/nylo_framework.dart';
@ -7,11 +8,15 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized();
Nylo nylo = await Nylo.init(setup: Boot.nylo, setupFinished: Boot.finished);
String initialRoute = AppHelper.instance.appConfig!.appStatus != null
? '/home'
: '/no-connection';
runApp(
AppBuild(
navigatorKey: NyNavigator.instance.router.navigatorKey,
onGenerateRoute: nylo.router!.generator(),
initialRoute: nylo.getInitialRoute(),
initialRoute: initialRoute,
debugShowCheckedModeBanner: false,
),
);

View File

@ -0,0 +1,234 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/bootstrap/shared_pref/sp_auth.dart';
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
import 'package:flutter_app/resources/widgets/buttons.dart';
import 'package:flutter_app/resources/widgets/safearea_widget.dart';
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:wp_json_api/models/responses/wc_customer_info_response.dart';
import 'package:wp_json_api/models/responses/wc_customer_updated_response.dart';
import 'package:wp_json_api/wp_json_api.dart';
class AccountBillingDetailsPage extends StatefulWidget {
AccountBillingDetailsPage();
@override
_AccountBillingDetailsPageState createState() =>
_AccountBillingDetailsPageState();
}
class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
_AccountBillingDetailsPageState();
// BILLING TEXT CONTROLLERS
final TextEditingController _txtShippingFirstName = TextEditingController(),
_txtShippingLastName = TextEditingController(),
_txtShippingAddressLine = TextEditingController(),
_txtShippingCity = TextEditingController(),
_txtShippingState = TextEditingController(),
_txtShippingPostalCode = TextEditingController(),
_txtShippingCountry = TextEditingController();
bool _isLoading = true, _isUpdating = false;
@override
void initState() {
super.initState();
_fetchUserDetails();
}
_fetchUserDetails() async {
WCCustomerInfoResponse wcCustomerInfoResponse =
await WPJsonAPI.instance.api((request) async {
return request.wcCustomerInfo((await readAuthToken())!);
});
Billing billing = wcCustomerInfoResponse.data!.billing!;
_txtShippingFirstName.text = billing.firstName!;
_txtShippingLastName.text = billing.lastName!;
_txtShippingAddressLine.text = billing.address1!;
_txtShippingCity.text = billing.city!;
_txtShippingState.text = billing.state!;
_txtShippingPostalCode.text = billing.postcode!;
_txtShippingCountry.text = billing.country!;
setState(() {
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(trans("Billing Details")),
centerTitle: true,
),
body: SafeAreaWidget(
child: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
child: _isLoading
? AppLoaderWidget()
: LayoutBuilder(
builder: (context, constraints) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
child: Container(
margin: EdgeInsets.only(top: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Row(
children: <Widget>[
Flexible(
child: TextEditingRow(
heading: trans("First Name"),
controller: _txtShippingFirstName,
shouldAutoFocus: true,
),
),
Flexible(
child: TextEditingRow(
heading: trans("Last Name"),
controller: _txtShippingLastName,
),
),
],
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
),
TextEditingRow(
heading: trans("Address Line"),
controller: _txtShippingAddressLine,
),
Row(children: <Widget>[
Flexible(
child: TextEditingRow(
heading: trans("City"),
controller: _txtShippingCity,
),
),
Flexible(
child: TextEditingRow(
heading: trans("State"),
keyboardType: TextInputType.emailAddress,
controller: _txtShippingState),
),
]),
Row(
children: <Widget>[
Flexible(
child: TextEditingRow(
heading: trans("Postal code"),
controller: _txtShippingPostalCode,
),
),
Flexible(
child: TextEditingRow(
heading: trans("Country"),
keyboardType: TextInputType.emailAddress,
controller: _txtShippingCountry,
),
),
],
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
)
],
),
decoration: BoxDecoration(
color: ThemeColor.get(context)!.surfaceBackground,
borderRadius: BorderRadius.circular(10),
boxShadow: (Theme.of(context).brightness ==
Brightness.light)
? wsBoxShadow()
: null,
),
padding: EdgeInsets.all(8),
),
height:
(constraints.maxHeight - constraints.minHeight) *
0.6,
),
Column(
children: <Widget>[
PrimaryButton(
title: trans("UPDATE DETAILS"),
isLoading: _isUpdating,
action: _updateBillingDetails,
),
],
),
],
),
),
),
),
);
}
_updateBillingDetails() async {
String firstName = _txtShippingFirstName.text;
String lastName = _txtShippingLastName.text;
String addressLine = _txtShippingAddressLine.text;
String city = _txtShippingCity.text;
String state = _txtShippingState.text;
String postalCode = _txtShippingPostalCode.text;
String country = _txtShippingCountry.text;
String? userToken = await readAuthToken();
setState(() {
_isUpdating = true;
});
WCCustomerUpdatedResponse? wcCustomerUpdatedResponse;
try {
wcCustomerUpdatedResponse = await WPJsonAPI.instance.api((request) =>
request.wcUpdateCustomerInfo(userToken,
billingFirstName: firstName,
billingLastName: lastName,
billingAddress1: addressLine,
billingCity: city,
billingState: state,
billingPostcode: postalCode,
billingCountry: country));
} on Exception catch (_) {
showToastNotification(context,
title: trans("Oops!"),
description: trans("Something went wrong"),
style: ToastNotificationStyleType.DANGER);
} finally {
setState(() {
_isUpdating = false;
});
}
if (wcCustomerUpdatedResponse != null &&
wcCustomerUpdatedResponse.status == 200) {
showToastNotification(context,
title: trans("Success"),
description: trans("Account updated"),
style: ToastNotificationStyleType.SUCCESS);
Navigator.pop(context);
}
}
}

View File

@ -1,13 +1,3 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart';
import 'package:flutter_app/bootstrap/shared_pref/sp_auth.dart';
import 'package:flutter_app/resources/widgets/buttons.dart';
@ -24,8 +14,11 @@ class AccountDeletePage extends StatefulWidget {
}
class _AccountDeletePageState extends NyState<AccountDeletePage> {
@override
init() async {}
init() async {
}
@override
void dispose() {
@ -40,40 +33,33 @@ class _AccountDeletePageState extends NyState<AccountDeletePage> {
),
body: SafeAreaWidget(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.no_accounts_rounded, size: 50),
Text(
trans("Delete your account"),
style: textTheme.displaySmall,
),
Padding(
padding: const EdgeInsets.only(top: 18),
child: Text(trans("Are you sure?")),
),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
PrimaryButton(
title: trans("Yes, delete my account"),
isLoading: isLocked('delete_account'),
action: _deleteAccount,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.no_accounts_rounded, size: 50),
Text(trans("Delete your account"), style: textTheme.headline3,),
Padding(
padding: const EdgeInsets.only(top: 18),
child: Text(trans("Are you sure?")),
),
],),
),
LinkButton(title: trans("Back"), action: pop)
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
PrimaryButton(title: trans("Yes, delete my account"), isLoading: isLocked('delete_account'), action: _deleteAccount),
LinkButton(title: trans("Back"), action: pop)
],
)
],
)
],
)),
),
);
}
@ -84,7 +70,9 @@ class _AccountDeletePageState extends NyState<AccountDeletePage> {
WPUserDeleteResponse? wpUserDeleteResponse;
try {
wpUserDeleteResponse = await WPJsonAPI.instance
.api((request) => request.wpUserDelete(userToken));
.api((request) => request.wpUserDelete(
userToken
));
} on Exception catch (e) {
NyLogger.error(e.toString());
showToastNotification(
@ -96,8 +84,7 @@ class _AccountDeletePageState extends NyState<AccountDeletePage> {
}
if (wpUserDeleteResponse != null) {
showToast(
title: trans("Success"), description: trans("Account deleted"));
showToast(title: trans("Success"), description: trans("Account deleted"));
await authLogout(context);
}
});

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -154,15 +154,30 @@ class _AccountDetailPageState extends State<AccountDetailPage>
),
Expanded(
child: Padding(
child: Text(
[userFirstName, userLastName]
.where((t) => (t != null || t != ""))
.toList()
.join(" "),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
[userFirstName, userLastName]
.where(
(t) => (t != null || t != ""))
.toList()
.join(" "),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
],
)
],
),
padding: EdgeInsets.only(left: 16),
),
@ -197,7 +212,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
(Theme.of(context).brightness == Brightness.light)
? wsBoxShadow()
: null,
color: ThemeColor.get(context).backgroundContainer,
color: ThemeColor.get(context)!.backgroundContainer,
),
),
Expanded(child: activeBody),

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -32,9 +32,15 @@ class AccountLandingPage extends StatefulWidget {
}
class _AccountLandingPageState extends NyState<AccountLandingPage> {
final TextEditingController _tfEmailController = TextEditingController(),
_tfPasswordController = TextEditingController();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -59,10 +65,7 @@ class _AccountLandingPageState extends NyState<AccountLandingPage> {
child: Text(
trans("Login"),
textAlign: TextAlign.left,
style: Theme.of(context)
.textTheme
.headlineMedium!
.copyWith(
style: Theme.of(context).textTheme.headline4!.copyWith(
fontSize: 24,
fontWeight: FontWeight.w700,
),
@ -76,7 +79,7 @@ class _AccountLandingPageState extends NyState<AccountLandingPage> {
(Theme.of(context).brightness == Brightness.light)
? wsBoxShadow()
: null,
color: ThemeColor.get(context).backgroundContainer,
color: ThemeColor.get(context)!.backgroundContainer,
),
padding: EdgeInsets.symmetric(vertical: 18, horizontal: 8),
margin: EdgeInsets.symmetric(horizontal: 16),
@ -118,7 +121,7 @@ class _AccountLandingPageState extends NyState<AccountLandingPage> {
Padding(
child: Text(
trans("Create an account"),
style: Theme.of(context).textTheme.bodyLarge,
style: Theme.of(context).textTheme.bodyText1,
),
padding: EdgeInsets.only(left: 8),
)
@ -223,18 +226,19 @@ class _AccountLandingPageState extends NyState<AccountLandingPage> {
if (wpUserLoginResponse.status != 200) {
return;
}
String? token = wpUserLoginResponse.data!.userToken;
String userId = wpUserLoginResponse.data!.userId.toString();
User user = User.fromUserAuthResponse(token: token, userId: userId);
await user.save(SharedKey.authUser);
String? token = wpUserLoginResponse.data!.userToken;
String userId = wpUserLoginResponse.data!.userId.toString();
User user = User.fromUserAuthResponse(token: token, userId: userId);
await user.save(SharedKey.authUser);
showToastNotification(context,
title: trans("Hello"),
description: trans("Welcome back"),
style: ToastNotificationStyleType.SUCCESS,
icon: Icons.account_circle);
navigatorPush(context,
routeName: UserAuth.instance.redirect, forgetLast: 1);
showToastNotification(context,
title: trans("Hello"),
description: trans("Welcome back"),
style: ToastNotificationStyleType.SUCCESS,
icon: Icons.account_circle);
navigatorPush(context,
routeName: UserAuth.instance.redirect, forgetLast: 1);
});
}
}

View File

@ -0,0 +1,214 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart';
import 'package:flutter_app/app/controllers/account_order_detail_controller.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
import 'package:flutter_app/resources/widgets/safearea_widget.dart';
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/response/order.dart';
class AccountOrderDetailPage extends NyStatefulWidget {
final AccountOrderDetailController controller =
AccountOrderDetailController();
AccountOrderDetailPage({Key? key}) : super(key: key);
@override
_AccountOrderDetailPageState createState() => _AccountOrderDetailPageState();
}
class _AccountOrderDetailPageState extends NyState<AccountOrderDetailPage> {
int? _orderId;
Order? _order;
bool _isLoading = true;
@override
init() async {
_orderId = widget.controller.data();
await _fetchOrder();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Container(
child: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.pop(context),
),
margin: EdgeInsets.only(left: 0),
),
title: Text("${trans("Order").capitalize()} #${_orderId.toString()}"),
centerTitle: true,
),
resizeToAvoidBottomInset: false,
body: SafeAreaWidget(
child: _isLoading
? AppLoaderWidget()
: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 8),
child: Text(
"${trans("Date Ordered").capitalize()}: " +
dateFormatted(
date: _order!.dateCreated!,
formatType: formatForDateTime(FormatType.date),
),
),
),
Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Text("${trans("Ships to").capitalize()}:"),
),
Flexible(
child: Text(
[
[
_order!.shipping!.firstName,
_order!.shipping!.lastName
].where((t) => t != null).toList().join(" "),
_order!.shipping!.address1,
_order!.shipping!.address2,
_order!.shipping!.city,
_order!.shipping!.state,
_order!.shipping!.postcode,
_order!.shipping!.country,
]
.where((t) => (t != "" && t != null))
.toList()
.join("\n"),
textAlign: TextAlign.right,
),
),
],
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
boxShadow:
(Theme.of(context).brightness == Brightness.light)
? wsBoxShadow()
: null,
color: (Theme.of(context).brightness == Brightness.light)
? Colors.white
: Color(0xFF2C2C2C),
),
),
Expanded(
child: ListView.builder(
itemBuilder: (cxt, i) {
LineItems lineItem = _order!.lineItems![i];
return Card(
child: ListTile(
contentPadding: EdgeInsets.only(
top: 5, bottom: 5, left: 8, right: 6),
title: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color(0xFFFCFCFC), width: 1),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Text(
lineItem.name!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Text(
formatStringCurrency(total: lineItem.price)
.capitalize(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
formatStringCurrency(
total: lineItem.total,
),
style: Theme.of(context)
.textTheme
.bodyText2!
.copyWith(
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.left,
),
Text(
"x${lineItem.quantity.toString()}",
style: Theme.of(context)
.textTheme
.bodyText1,
textAlign: TextAlign.left,
),
],
),
],
),
),
),
);
},
itemCount: _order!.lineItems!.length,
),
),
],
),
),
);
}
@override
void dispose() {
super.dispose();
}
_fetchOrder() async {
_order = await (appWooSignal((api) {
return api.retrieveOrder(_orderId!);
}));
if (_order != null) {
setState(() {
_isLoading = false;
});
}
}
}

View File

@ -1,221 +0,0 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/app/controllers/account_order_detail_controller.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/widgets/safearea_widget.dart';
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'package:woosignal/models/response/order.dart';
class AccountOrderDetailPage extends NyStatefulWidget {
final AccountOrderDetailController controller =
AccountOrderDetailController();
AccountOrderDetailPage({Key? key}) : super(key: key);
@override
_AccountOrderDetailPageState createState() => _AccountOrderDetailPageState();
}
class _AccountOrderDetailPageState extends NyState<AccountOrderDetailPage> {
int? _orderId;
Order? _order;
@override
init() async {
super.init();
}
@override
boot() async {
_orderId = widget.controller.data();
await _fetchOrder();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Container(
child: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.pop(context),
),
margin: EdgeInsets.only(left: 0),
),
title: afterNotNull(_orderId, child: () => Text("${trans("Order").capitalize()} #${_orderId.toString()}"), loading: CupertinoActivityIndicator()),
centerTitle: true,
),
resizeToAvoidBottomInset: false,
body: SafeAreaWidget(
child: afterLoad(child: () => Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 8),
child: Text(
"${trans("Date Ordered").capitalize()}: ${dateFormatted(
date: _order?.dateCreated ?? "",
formatType: formatForDateTime(FormatType.date),
)}",
),
),
Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Text("${trans("Ships to").capitalize()}:"),
),
Flexible(
child: Text(
[
[
_order!.shipping!.firstName,
_order!.shipping!.lastName
].where((t) => t != null).toList().join(" "),
_order!.shipping!.address1,
_order!.shipping!.address2,
_order!.shipping!.city,
_order!.shipping!.state,
_order!.shipping!.postcode,
_order!.shipping!.country,
]
.where((t) => (t != "" && t != null))
.toList()
.join("\n"),
textAlign: TextAlign.right,
),
),
],
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
boxShadow:
(Theme.of(context).brightness == Brightness.light)
? wsBoxShadow()
: null,
color: (Theme.of(context).brightness == Brightness.light)
? Colors.white
: Color(0xFF2C2C2C),
),
),
Expanded(
child: ListView.builder(
itemBuilder: (cxt, i) {
LineItems lineItem = _order!.lineItems![i];
return Card(
child: ListTile(
contentPadding: EdgeInsets.only(
top: 5, bottom: 5, left: 8, right: 6),
title: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color(0xFFFCFCFC), width: 1),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Text(
lineItem.name!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
Container(
width: 70,
alignment: Alignment.topRight,
child: Text(
formatStringCurrency(total: lineItem.total)
.capitalize(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold
),
),
),
],
),
),
subtitle: Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.grey[100]!)
)
),
padding: const EdgeInsets.only(top: 10),
margin: EdgeInsets.only(top: 4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
formatStringCurrency(
total: lineItem.price,
),
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.left,
),
Text(
"x ${lineItem.quantity.toString()}",
style: Theme.of(context)
.textTheme
.bodyLarge,
textAlign: TextAlign.left,
),
],
),
],
),
),
),
);
},
itemCount: _order?.lineItems?.length ?? 0,
),
),
],
)),
),
);
}
@override
void dispose() {
super.dispose();
}
_fetchOrder() async {
_order = await (appWooSignal((api) => api.retrieveOrder(_orderId!)));
}
}

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -108,7 +108,7 @@ class _AccountProfileUpdatePageState extends State<AccountProfileUpdatePage> {
padding: EdgeInsets.only(top: 10),
),
PrimaryButton(
title: trans("Update Details"),
title: trans("Update details"),
isLoading: isLoading,
action: _updateDetails,
)

View File

@ -1,7 +1,7 @@
// Label StoreMax
//
// Created by Anthony Gordon.
// 2023, WooSignal Ltd. All rights reserved.
// 2022, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -48,6 +48,11 @@ class _AccountRegistrationPageState extends NyState<AccountRegistrationPage> {
final WooSignalApp? _wooSignalApp = AppHelper.instance.appConfig;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -109,8 +114,9 @@ class _AccountRegistrationPageState extends NyState<AccountRegistrationPage> {
child: InkWell(
child: RichText(
text: TextSpan(
text:
'${trans("By tapping \"Register\" you agree to ")} ${AppHelper.instance.appConfig!.appName!}\'s ',
text: trans("By tapping \"Register\" you agree to ") +
AppHelper.instance.appConfig!.appName! +
'\'s ',
children: <TextSpan>[
TextSpan(
text: trans("terms and conditions"),
@ -171,21 +177,12 @@ class _AccountRegistrationPageState extends NyState<AccountRegistrationPage> {
WPUserRegisterResponse? wpUserRegisterResponse;
try {
wpUserRegisterResponse = await WPJsonAPI.instance.api(
(request) => request.wpRegister(
(request) => request.wpRegister(
email: email.toLowerCase(),
password: password,
username: username,
),
);
if (wpUserRegisterResponse?.data?.userToken != null) {
await WPJsonAPI.instance.api((request) => request.wpUserAddRole(
wpUserRegisterResponse!.data!.userToken,
role: "customer"));
await WPJsonAPI.instance.api((request) => request.wpUserRemoveRole(
wpUserRegisterResponse!.data!.userToken,
role: "subscriber"));
}
} on UsernameTakenException catch (e) {
showToastNotification(context,
title: trans("Oops!"),
@ -195,7 +192,7 @@ class _AccountRegistrationPageState extends NyState<AccountRegistrationPage> {
showToastNotification(context,
title: trans("Invalid details"),
description:
trans("Something went wrong, please contact our store"),
trans("Something went wrong, please contact our store"),
style: ToastNotificationStyleType.DANGER);
} on ExistingUserLoginException catch (_) {
showToastNotification(context,
@ -233,21 +230,21 @@ class _AccountRegistrationPageState extends NyState<AccountRegistrationPage> {
}
// Save user to shared preferences
String? token = wpUserRegisterResponse.data!.userToken;
String userId = wpUserRegisterResponse.data!.userId.toString();
User user = User.fromUserAuthResponse(token: token, userId: userId);
await user.save(SharedKey.authUser);
String? token = wpUserRegisterResponse.data!.userToken;
String userId = wpUserRegisterResponse.data!.userId.toString();
User user = User.fromUserAuthResponse(token: token, userId: userId);
await user.save(SharedKey.authUser);
await WPJsonAPI.instance.api((request) => request.wpUpdateUserInfo(token,
firstName: firstName, lastName: lastName));
await WPJsonAPI.instance.api((request) => request
.wpUpdateUserInfo(token, firstName: firstName, lastName: lastName));
showToastNotification(context,
title: "${trans("Hello")} $firstName",
description: trans("you're now logged in"),
style: ToastNotificationStyleType.SUCCESS,
icon: Icons.account_circle);
navigatorPush(context,
routeName: UserAuth.instance.redirect, forgetLast: 2);
showToastNotification(context,
title: "${trans("Hello")} $firstName",
description: trans("you're now logged in"),
style: ToastNotificationStyleType.SUCCESS,
icon: Icons.account_circle);
navigatorPush(context,
routeName: UserAuth.instance.redirect, forgetLast: 2);
});
}

Some files were not shown because too many files have changed in this diff Show More