v5.6.0 - update
This commit is contained in:
parent
d7a38cb95e
commit
5c4addcc66
@ -15,7 +15,7 @@ DEFAULT_LOCALE=null
|
||||
|
||||
# *<! ------ WooSignal Config ------!>*
|
||||
|
||||
APP_KEY="your app key"
|
||||
APP_KEY="app_affb6434339b34443a297c2e40a3edab7102137e6d67de9abfe612b749bd"
|
||||
# App key from WooSignal link: https://woosignal.com/dashboard/apps
|
||||
|
||||
# *<! ------ STRIPE (OPTIONAL) ------!>*
|
||||
|
||||
@ -1,3 +1,15 @@
|
||||
## [5.6.0] - 2022-01-03
|
||||
|
||||
* Fix bug with banner in Mello theme
|
||||
* Support new languages - Dutch (nl) and Turkish (tr)
|
||||
* Refactor as per dart analysis
|
||||
* Ability to add coupons
|
||||
* Wishlist
|
||||
* New theme "Compo"
|
||||
* Analysis options added
|
||||
* Code cleanup
|
||||
* Pubspec.yaml dependency updates
|
||||
|
||||
## [5.5.2] - 2021-12-18
|
||||
|
||||
* Fix continuous loading on categories screen
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2021, WooSignal Ltd
|
||||
Copyright (c) 2022, WooSignal Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
# WooCommerce App: Label StoreMax
|
||||
|
||||
### Label StoreMax - v5.5.2
|
||||
### Label StoreMax - v5.6.0
|
||||
|
||||
|
||||
[Official WooSignal WooCommerce App](https://woosignal.com)
|
||||
|
||||
30
LabelStoreMax/analysis_options.yaml
Normal file
30
LabelStoreMax/analysis_options.yaml
Normal file
@ -0,0 +1,30 @@
|
||||
# This file configures the static analysis results for your project (errors,
|
||||
# warnings, and lints).
|
||||
#
|
||||
# This enables the 'recommended' set of lints from `package:lints`.
|
||||
# This set helps identify many issues that may lead to problems when running
|
||||
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||
# style and format.
|
||||
#
|
||||
# If you want a smaller set of lints you can change this to specify
|
||||
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||
# (the recommended set includes the core lints).
|
||||
# The core lints are also what is used by pub.dev for scoring packages.
|
||||
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
# Uncomment the following section to specify additional rules.
|
||||
|
||||
# linter:
|
||||
# rules:
|
||||
# - camel_case_types
|
||||
|
||||
# analyzer:
|
||||
# exclude:
|
||||
# - path/to/excluded/files/**
|
||||
|
||||
# For more information about the core and recommended set of lints, see
|
||||
# https://dart.dev/go/core-lints
|
||||
|
||||
# For additional information about configuring this file, see
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "Bitte geben Sie eine gültige Versand-E-Mail ein",
|
||||
"Free postage": "Portofrei",
|
||||
"PROCESSING": "WIRD BEARBEITET",
|
||||
"Social": "Sozial"
|
||||
"Social": "Sozial",
|
||||
"Please enter coupon to redeem": "Bitte Coupon zum Einlösen eingeben",
|
||||
"Coupon": "Coupon",
|
||||
"Apply": "Sich bewerben",
|
||||
"Apply Coupon": "Gutschein anwenden",
|
||||
"Added to checkout": "Zur Kasse hinzugefügt",
|
||||
"Redeem Coupon": "Gutschein einlösen",
|
||||
"Add coupon code": "Gutscheincode hinzufügen",
|
||||
"Coupon not found": "Gutschein nicht gefunden",
|
||||
"Sorry, this coupon can not be used with your cart": "Dieser Gutschein kann leider nicht mit Ihrem Warenkorb verwendet werden",
|
||||
"You cannot redeem this coupon": "Sie können diesen Gutschein nicht einlösen",
|
||||
"This coupon has expired": "Dieser Gutschein ist abgelaufen",
|
||||
"Usage limit has been reached": "Nutzungslimit wurde erreicht",
|
||||
"View All": "Alle ansehen",
|
||||
"Wishlist": "Wunschzettel",
|
||||
"No items found": "Keine Elemente gefunden",
|
||||
"This product has been removed from your wishlist": "Dieses Produkt wurde von Ihrer Wunschliste entfernt",
|
||||
"This product has been added to your wishlist": "Dieses Produkt wurde Ihrer Wunschliste hinzugefügt",
|
||||
"Spend a minimum of minimumAmount to redeem": "Verbringen Sie mindestens {{minimumAmount}} einlösen",
|
||||
"Spend less than maximumAmount to redeem": "Geben Sie weniger aus als {{maximumAmount}} einlösen"
|
||||
}
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "Please enter a valid shipping email",
|
||||
"Free postage": "Free postage",
|
||||
"PROCESSING": "PROCESSING",
|
||||
"Social": "Social"
|
||||
"Social": "Social",
|
||||
"Please enter coupon to redeem": "Please enter coupon to redeem",
|
||||
"Coupon": "Coupon",
|
||||
"Apply": "Apply",
|
||||
"Apply Coupon": "Apply Coupon",
|
||||
"Spend a minimum of minimumAmount to redeem": "Spend a minimum of {{minimumAmount}} to redeem",
|
||||
"Spend less than maximumAmount to redeem": "Spend less than {{maximumAmount}} to redeem",
|
||||
"Added to checkout": "Added to checkout",
|
||||
"Redeem Coupon": "Redeem Coupon",
|
||||
"Add coupon code": "Add coupon code",
|
||||
"Coupon not found": "Coupon not found",
|
||||
"Sorry, this coupon can not be used with your cart": "Sorry, this coupon can not be used with your cart",
|
||||
"You cannot redeem this coupon": "You cannot redeem this coupon",
|
||||
"This coupon has expired": "This coupon has expired",
|
||||
"Usage limit has been reached": "Usage limit has been reached",
|
||||
"View All": "View All",
|
||||
"Wishlist": "Wishlist",
|
||||
"No items found": "No items found",
|
||||
"This product has been removed from your wishlist": "This product has been removed from your wishlist",
|
||||
"This product has been added to your wishlist": "This product has been added to your wishlist"
|
||||
}
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "Ingrese un correo electrónico de envío válido",
|
||||
"Free postage": "Gastos de envío gratis",
|
||||
"PROCESSING": "PROCESANDO",
|
||||
"Social": "Social"
|
||||
"Social": "Social",
|
||||
"Please enter coupon to redeem": "Ingrese el cupón para canjear",
|
||||
"Coupon": "Cupón",
|
||||
"Apply": "Solicitar",
|
||||
"Apply Coupon": "Aplicar cupón",
|
||||
"Added to checkout": "Agregado al pago",
|
||||
"Redeem Coupon": "Canjear cupón",
|
||||
"Add coupon code": "Agregar código de cupón",
|
||||
"Coupon not found": "Cupón no encontrado",
|
||||
"Sorry, this coupon can not be used with your cart": "Lo sentimos, este cupón no se puede utilizar con su carrito",
|
||||
"You cannot redeem this coupon": "No puedes canjear este cupón",
|
||||
"This coupon has expired": "Este cupón ha caducado",
|
||||
"Usage limit has been reached": "Se alcanzó el límite de uso",
|
||||
"View All": "Ver todo",
|
||||
"Wishlist": "Lista de deseos",
|
||||
"No items found": "No se encontraron artículos",
|
||||
"This product has been removed from your wishlist": "Este producto ha sido eliminado de tu lista de deseos.",
|
||||
"This product has been added to your wishlist": "Este producto ha sido añadido a su lista de deseos",
|
||||
"Spend a minimum of minimumAmount to redeem": "Gasta un mínimo de {{minimumAmount}} para redimir",
|
||||
"Spend less than maximumAmount to redeem": "Gasta menos de {{maximumAmount}} para redimir"
|
||||
}
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "Veuillez saisir un e-mail de livraison valide",
|
||||
"Free postage": "Sans frais de port",
|
||||
"PROCESSING": "EN TRAITEMENT",
|
||||
"Social": "Social"
|
||||
"Social": "Social",
|
||||
"Please enter coupon to redeem": "Veuillez entrer le coupon pour l'utiliser",
|
||||
"Coupon": "Coupon",
|
||||
"Apply": "Appliquer",
|
||||
"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": "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",
|
||||
"No items found": "Aucun élément trouvé",
|
||||
"This product has been removed from your wishlist": "Ce produit a été supprimé de votre liste de souhaits",
|
||||
"This product has been added to your wishlist": "Ce produit a été ajouté à votre liste de souhaits",
|
||||
"Spend a minimum of minimumAmount to redeem": "Dépensez un minimum de {{minimumAmount}} de racheter",
|
||||
"Spend less than maximumAmount to redeem": "Dépensez moins de {{maximumAmount}} de racheter"
|
||||
}
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "krpaya ek maany shiping eemel darj karen",
|
||||
"Free postage": "mupht daak",
|
||||
"PROCESSING": "prasanskaran",
|
||||
"Social": "saamaajik"
|
||||
"Social": "saamaajik",
|
||||
"Please enter coupon to redeem": "rideem karane ke lie krpaya koopan darj karen",
|
||||
"Coupon": "koopan",
|
||||
"Apply": "laagoo karana",
|
||||
"Apply Coupon": "koopan laagoo karen",
|
||||
"Added to checkout": "chekaut mein joda gaya",
|
||||
"Redeem Coupon": "koopan rideem karaen",
|
||||
"Add coupon code": "koopan kod joden",
|
||||
"Coupon not found": "koopan nahin mila",
|
||||
"Sorry, this coupon can not be used with your cart": "kshama karen, is koopan ka upayog aapake kaart ke saath nahin kiya ja sakata",
|
||||
"You cannot redeem this coupon": "aap is koopan ko rideem nahin kar sakate",
|
||||
"This coupon has expired": "yah koopan samaapt ho gaya hai",
|
||||
"Usage limit has been reached": "upayog kee seema pooree ho chukee hai",
|
||||
"View All": "sabhee ko dekhen",
|
||||
"Wishlist": "ichchha-soochee",
|
||||
"No items found": "kuchh nahin mila",
|
||||
"This product has been removed from your wishlist": "yah utpaad aapakee ichchha soochee se hata diya gaya hai",
|
||||
"This product has been added to your wishlist": "is utpaad ko aapakee vish - list mein jod diya gaya hai",
|
||||
"Spend a minimum of minimumAmount to redeem": "kam se kam kharch karen {{minimumAmount}} ke evaj mein lena",
|
||||
"Spend less than maximumAmount to redeem": "se kam kharch karen {{maximumAmount}} ke evaj mein lena"
|
||||
}
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "Si prega di inserire un'e-mail di spedizione valida",
|
||||
"Free postage": "Spedizione gratuita",
|
||||
"PROCESSING": "IN LAVORAZIONE",
|
||||
"Social": "Sociale"
|
||||
"Social": "Sociale",
|
||||
"Please enter coupon to redeem": "Inserisci il coupon per riscattare",
|
||||
"Coupon": "Buono",
|
||||
"Apply": "Applicare",
|
||||
"Apply Coupon": "Applicare il coupon",
|
||||
"Added to checkout": "Aggiunto al checkout",
|
||||
"Redeem Coupon": "Utilizza il coupon",
|
||||
"Add coupon code": "Aggiungi il codice coupon",
|
||||
"Coupon not found": "Coupon non trovato",
|
||||
"Sorry, this coupon can not be used with your cart": "Spiacenti, questo coupon non può essere utilizzato con il carrello",
|
||||
"You cannot redeem this coupon": "Non puoi riscattare questo coupon",
|
||||
"This coupon has expired": "Questo coupon è scaduto",
|
||||
"Usage limit has been reached": "È stato raggiunto il limite di utilizzo",
|
||||
"View All": "Mostra tutto",
|
||||
"Wishlist": "Lista dei desideri",
|
||||
"No items found": "Nessun articolo trovato",
|
||||
"This product has been removed from your wishlist": "Questo prodotto è stato rimosso dalla tua lista dei desideri",
|
||||
"This product has been added to your wishlist": "Questo prodotto è stato aggiunto alla tua lista dei desideri",
|
||||
"Spend a minimum of minimumAmount to redeem": "Spendi un minimo di {{minimumAmount}} riscattare",
|
||||
"Spend less than maximumAmount to redeem": "Spendi meno di {{maximumAmount}} riscattare"
|
||||
}
|
||||
214
LabelStoreMax/lang/nl.json
Normal file
214
LabelStoreMax/lang/nl.json
Normal file
@ -0,0 +1,214 @@
|
||||
{
|
||||
"Categories": "Categorieën",
|
||||
"Shop": "Winkel",
|
||||
"Newest": "Nieuwste",
|
||||
"Browse categories": "Bladeren door rubrieken",
|
||||
"Cart": "winkelwagentje",
|
||||
"You need items in your cart to checkout": "Je hebt artikelen in je winkelwagen nodig om af te rekenen",
|
||||
"Updated": "Bijgewerkt",
|
||||
"Item removed": "Artikel verwijderd",
|
||||
"Success": "succes",
|
||||
"Cart cleared": "winkelwagen leeggemaakt",
|
||||
"Shopping Cart": "Winkelwagen",
|
||||
"Clear Cart": "Winkelwagen leegmaken",
|
||||
"Empty Basket": "Lege mand",
|
||||
"PROCEED TO CHECKOUT": "GA NAAR DE KASSA",
|
||||
"Browse": "Bladeren",
|
||||
"Search results for": "zoekresultaten voor",
|
||||
"Select a": "Selecteer een",
|
||||
"Added to cart": "Toegevoegd aan winkelwagen",
|
||||
"Options": "Opties",
|
||||
"Price": "prijs",
|
||||
"Choose your options": "Kies je opties",
|
||||
"Out of stock": "Uitverkocht",
|
||||
"In Stock": "op voorraad",
|
||||
"Add to cart": "Voeg toe aan winkelmandje",
|
||||
"Oops": "oeps",
|
||||
"Please select valid options first": "Selecteer eerst geldige opties",
|
||||
"Sorry": "Sorry",
|
||||
"This item is not in stock": "Dit artikel is niet op voorraad",
|
||||
"Description": "Beschrijving",
|
||||
"Full description": "Volledige beschrijving",
|
||||
"ADD TO CART": "VOEG TOE AAN WINKELMANDJE",
|
||||
"This item is out of stock": "Dit product is niet meer op voorraad",
|
||||
"Add your shipping details first": "Voeg eerst uw verzendgegevens toe",
|
||||
"Checkout": "uitchecken",
|
||||
"Billing/shipping details": "Factuur-/verzendgegevens",
|
||||
"Add billing & shipping details": "Facturerings- en verzendgegevens toevoegen",
|
||||
"Payment method": "Betalingsmiddel",
|
||||
"Pay with": "betaal met",
|
||||
"Select a payment method": "Kies een betalingsmethode",
|
||||
"Shipping selected": "Verzending geselecteerd",
|
||||
"Select shipping": "Selecteer verzending",
|
||||
"Select a shipping option": "Selecteer een verzendoptie",
|
||||
"Shipping fee": "Verzendkosten",
|
||||
"Subtotal": "subtotaal",
|
||||
"Total": "Totaal",
|
||||
"CHECKOUT": "UITCHECKEN",
|
||||
"One moment": "een moment",
|
||||
"Please select add your billing/shipping address to proceed": "Selecteer uw factuur-/verzendadres toevoegen om door te gaan",
|
||||
"Your billing/shipping details are incomplete": "Uw factuur-/verzendgegevens zijn onvolledig",
|
||||
"Please select a shipping method to proceed": "Selecteer een verzendmethode om verder te gaan",
|
||||
"Please select a payment method to proceed": "Selecteer een betaalmethode om door te gaan",
|
||||
"Something went wrong, please contact our store": "Er is iets misgegaan, neem contact op met onze winkel!",
|
||||
"Error": "Fout",
|
||||
"Order Status": "Bestelstatus",
|
||||
"Thank You!": "Dank u!",
|
||||
"Your transaction details": "Uw transactiegegevens",
|
||||
"Order Ref": "Bestelreferentie",
|
||||
"Items": "Artikelen",
|
||||
"Back to Home": "Terug naar huis",
|
||||
"Orders": "bestellingen",
|
||||
"Billing & Shipping Details": "Facturerings- en verzendgegevens",
|
||||
"First Name": "Voornaam",
|
||||
"Last Name": "Achternaam",
|
||||
"Address Line": "Adresregel",
|
||||
"City": "Stad",
|
||||
"Postal code": "Postcode",
|
||||
"Email address": "E-mailadres",
|
||||
"Selected": "Geselecteerd",
|
||||
"Select country": "Selecteer land",
|
||||
"Remember my details": "Onthoud mijn gegevens",
|
||||
"USE SHIPPING ADDRESS": "VERZENDADRES GEBRUIKEN",
|
||||
"About": "Over",
|
||||
"Privacy policy": "Privacybeleid",
|
||||
"Terms and conditions": "Voorwaarden",
|
||||
"Version": "versie",
|
||||
"Payment Method": "Betalingsmiddel",
|
||||
"CANCEL": "ANNULEREN",
|
||||
"Shipping Methods": "Verzendmethoden:",
|
||||
"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",
|
||||
"Oops, something went wrong": "Oeps! Er is iets misgegaan",
|
||||
"Tax": "Belasting",
|
||||
"No results": "Geen resultaten",
|
||||
"There is an item out of stock": "Er is een artikel niet op voorraad",
|
||||
"Maximum stock reached": "Maximale voorraad bereikt",
|
||||
"Select a country": "Selecteer een land",
|
||||
"Menu": "Menu",
|
||||
"About Us": "Over ons",
|
||||
"Something went wrong": "Er is iets fout gegaan",
|
||||
"Product variation does not exist": "Productvariatie bestaat niet",
|
||||
"This variation is unavailable": "Deze variant is niet beschikbaar",
|
||||
"Sorry, something went wrong": "Sorry, er ging iets mis",
|
||||
"Back": "Rug",
|
||||
"Profile": "Profiel",
|
||||
"Forgot Password": "Wachtwoord vergeten",
|
||||
"Create an account": "Account aanmaken",
|
||||
"Login": "Log in",
|
||||
"Password": "Wachtwoord",
|
||||
"Oops!": "Oeps!",
|
||||
"Invalid login credentials": "Ongeldige inloggegevens",
|
||||
"That email address is not valid": "Dat e-mailadres is niet geldig",
|
||||
"Password must be a min 6 characters": "Wachtwoord moet minimaal 6 tekens lang zijn",
|
||||
"Please check your details": "Kijk alsjeblieft je gegevens na",
|
||||
"Invalid": "Invalide",
|
||||
"Actions": "Acties",
|
||||
"View Terms and Conditions or Privacy policy": "Bekijk de algemene voorwaarden of het privacybeleid",
|
||||
"Terms and Conditions": "Voorwaarden",
|
||||
"Privacy Policy": "Privacybeleid",
|
||||
"terms and conditions": "voorwaarden",
|
||||
"and": "en",
|
||||
"By tapping \"Register\" you agree to ": "Door op \"Registreren\" te tikken, gaat u akkoord met:",
|
||||
"privacy policy": "privacybeleid",
|
||||
"Sign up": "Inschrijven",
|
||||
"Email": "E-mail",
|
||||
"Update details": "Gegevens bijwerken",
|
||||
"Settings": "Instellingen",
|
||||
"Account": "Rekening",
|
||||
"Logout": "Uitloggen",
|
||||
"No orders found": "Geen bestellingen gevonden",
|
||||
"items": "artikelen",
|
||||
"Update Details": "Gegevens bijwerken",
|
||||
"Invalid details": "Ongeldige gegevens",
|
||||
"Please check your email and password": "Controleer uw e-mail en wachtwoord",
|
||||
"Something went wrong, please try again.": "Er is iets mis gegaan, probeer het alstublieft nogmaals.",
|
||||
"Done": "Gedaan",
|
||||
"Billing Details": "Factureringsgegevens",
|
||||
"Shipping Details": "Verzendgegevens",
|
||||
"Shipping Address": "Verzendingsadres",
|
||||
"State": "Staat",
|
||||
"Country": "Land",
|
||||
"UPDATE DETAILS": "DETAILS BIJWERKEN",
|
||||
"No more products": "Geen producten meer",
|
||||
"release to load more": "laat los om meer te laden",
|
||||
"Load Failed! Click retry!": "Laden mislukt! Klik opnieuw!",
|
||||
"pull up load": "trek de lading omhoog",
|
||||
"Sort: Low to high": "Sorteren: laag naar hoog",
|
||||
"Sort: High to low": "Sorteren: hoog naar laag",
|
||||
"Sort: Name A-Z": "Sorteren: Naam A-Z",
|
||||
"Sort: Name Z-A": "Sorteren: Naam Z-A",
|
||||
"Cancel": "Annuleren",
|
||||
"Sort results": "Sorteer resultaten",
|
||||
"you're now logged in": "Je bent nu ingelogd",
|
||||
"Hello": "Hallo",
|
||||
"Welcome back": "Welkom terug",
|
||||
"Quantity": "Hoeveelheid",
|
||||
"Select a state": "Selecteer een staat",
|
||||
"Select state": "Selecteer staat",
|
||||
"Ship to a different address?": "Verzend naar een ander adres?",
|
||||
"USE DETAILS": "GEBRUIK DETAILS",
|
||||
"Not supported, try a card payment": "Niet ondersteund, probeer een kaartbetaling",
|
||||
"Invalid shipping address, please check your shipping details": "Ongeldig verzendadres, controleer uw verzendgegevens",
|
||||
"Was": "Was",
|
||||
"off": "uit",
|
||||
"Maximum quantity reached": "Maximale hoeveelheid bereikt",
|
||||
"Sorry, only": "Sorry, alleen",
|
||||
"left": "links",
|
||||
"Billing address is incomplete": "Factuuradres is onvolledig",
|
||||
"Order": "Volgorde",
|
||||
"Date Ordered": "Datum besteld",
|
||||
"Ships to": "wordt verzonden naar",
|
||||
"That email does not match our records": "Dat e-mailadres komt niet overeen met onze gegevens",
|
||||
"That username does not match our records": "Die gebruikersnaam komt niet overeen met onze gegevens",
|
||||
"That password does not match our records": "Dat wachtwoord komt niet overeen met onze gegevens",
|
||||
"The email and password field cannot be empty": "Het veld voor e-mail en wachtwoord mag niet leeg zijn",
|
||||
"Username taken, try another.": "Die gebruikersnaam is in gebruik, probeer een andere.",
|
||||
"A user already exists": "Er bestaat al een gebruiker",
|
||||
"That email is taken, try another": "Die e-mail is in gebruik, probeer een andere",
|
||||
"The email field is empty": "Het e-mailveld is leeg",
|
||||
"No more orders": "Geen bestellingen meer",
|
||||
"Account updated": "Account bijgewerkt",
|
||||
"Spend a minimum of": "Besteed minimaal €",
|
||||
"for": "voor",
|
||||
"Buy Product": "Koop product",
|
||||
"Retry": "Opnieuw proberen",
|
||||
"Retry later": "Probeer het later opnieuw",
|
||||
"Light Mode": "Lichtmodus",
|
||||
"Dark Mode": "Donkere modus",
|
||||
"PayPal Checkout": "PayPal Afrekenen",
|
||||
"Processing Payment": "Betaling verwerken",
|
||||
"Please wait, your order is being processed and you will be redirected to the PayPal website.": "Een ogenblik geduld, uw bestelling wordt verwerkt en u wordt doorgestuurd naar de PayPal-website.",
|
||||
"If you are not automatically redirected to PayPal within 5 seconds": "Als u niet binnen 5 seconden automatisch wordt doorgestuurd naar PayPal",
|
||||
"Payment Cancelled": "Betaling geannuleerd",
|
||||
"The payment has been cancelled": "De betaling is geannuleerd",
|
||||
"Must have": "Hebbeding",
|
||||
"Our selection of new items": "Onze selectie van nieuwe items",
|
||||
"Register": "Register",
|
||||
"No payment methods are available": "Er zijn geen betaalmethoden beschikbaar",
|
||||
"Please enter a valid billing email": "Voer een geldig e-mailadres voor facturering in",
|
||||
"Please enter a valid shipping email": "Voer een geldig verzend-e-mailadres in",
|
||||
"Free postage": "Gratis verzending",
|
||||
"PROCESSING": "VERWERKEN",
|
||||
"Social": "sociaal",
|
||||
"Please enter coupon to redeem": "Voer de coupon in om deze in te wisselen",
|
||||
"Coupon": "Coupon",
|
||||
"Apply": "Van toepassing zijn",
|
||||
"Apply Coupon": "gebruik coupon",
|
||||
"Added to checkout": "Toegevoegd aan afrekenen",
|
||||
"Redeem Coupon": "coupon inwisselen",
|
||||
"Add coupon code": "Voeg couponcode toe",
|
||||
"Coupon not found": "Coupon niet gevonden",
|
||||
"Sorry, this coupon can not be used with your cart": "Sorry, deze coupon kan niet worden gebruikt met uw winkelwagentje",
|
||||
"You cannot redeem this coupon": "U kunt deze coupon niet inwisselen",
|
||||
"This coupon has expired": "Deze coupon is verlopen",
|
||||
"Usage limit has been reached": "Gebruikslimiet is bereikt",
|
||||
"View All": "Bekijk alles",
|
||||
"Wishlist": "verlanglijst",
|
||||
"No items found": "Geen items gevonden",
|
||||
"This product has been removed from your wishlist": "Dit product is van je verlanglijst verwijderd",
|
||||
"This product has been added to your wishlist": "Dit product is toegevoegd aan je verlanglijst",
|
||||
"Spend a minimum of minimumAmount to redeem": "Besteed minimaal € {{minimumAmount}} verlossen",
|
||||
"Spend less than maximumAmount to redeem": "Minder uitgeven dan {{maximumAmount}} verlossen"
|
||||
}
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "Por favor, insira um e-mail de envio válido",
|
||||
"Free postage": "Postagem grátis",
|
||||
"PROCESSING": "EM PROCESSAMENTO",
|
||||
"Social": "Social"
|
||||
"Social": "Social",
|
||||
"Please enter coupon to redeem": "Por favor, insira o cupom para resgatar",
|
||||
"Coupon": "Cupom",
|
||||
"Apply": "Aplicar",
|
||||
"Apply Coupon": "Aplicar cupom",
|
||||
"Added to checkout": "Adicionado ao checkout",
|
||||
"Redeem Coupon": "Resgatar cupom",
|
||||
"Add coupon code": "Adicionar código de cupom",
|
||||
"Coupon not found": "Cupom não encontrado",
|
||||
"Sorry, this coupon can not be used with your cart": "Desculpe, este cupom não pode ser usado com seu carrinho",
|
||||
"You cannot redeem this coupon": "Você não pode resgatar este cupom",
|
||||
"This coupon has expired": "Este cupom expirou",
|
||||
"Usage limit has been reached": "O limite de uso foi atingido",
|
||||
"View All": "Ver tudo",
|
||||
"Wishlist": "Lista de Desejos",
|
||||
"No items found": "Nenhum item encontrado",
|
||||
"This product has been removed from your wishlist": "Este produto foi removido da sua lista de desejos",
|
||||
"This product has been added to your wishlist": "Este produto foi adicionado à sua lista de desejos",
|
||||
"Spend a minimum of minimumAmount to redeem": "Gaste um mínimo de {{minimumAmount}} redimir",
|
||||
"Spend less than maximumAmount to redeem": "Gaste menos que {{maximumAmount}} redimir"
|
||||
}
|
||||
214
LabelStoreMax/lang/tr.json
Normal file
214
LabelStoreMax/lang/tr.json
Normal file
@ -0,0 +1,214 @@
|
||||
{
|
||||
"Categories": "Kategoriler",
|
||||
"Shop": "Mağaza",
|
||||
"Newest": "en yeni",
|
||||
"Browse categories": "Kategorilere Gözat",
|
||||
"Cart": "Araba",
|
||||
"You need items in your cart to checkout": "Ödeme yapmak için sepetinizdeki öğelere ihtiyacınız var",
|
||||
"Updated": "Güncellenmiş",
|
||||
"Item removed": "Öğe kaldırıldı",
|
||||
"Success": "Başarı",
|
||||
"Cart cleared": "Sepet temizlendi",
|
||||
"Shopping Cart": "Alışveriş Sepeti",
|
||||
"Clear Cart": "Sepeti Temizle",
|
||||
"Empty Basket": "Boş sepet",
|
||||
"PROCEED TO CHECKOUT": "ÇIKIŞA DOĞRU DEVAM ET",
|
||||
"Browse": "Araştır",
|
||||
"Search results for": "için arama sonuçları",
|
||||
"Select a": "Bir seçin",
|
||||
"Added to cart": "Sepete eklendi",
|
||||
"Options": "Seçenekler",
|
||||
"Price": "Fiyat",
|
||||
"Choose your options": "Seçeneklerinizi seçin",
|
||||
"Out of stock": "Stoklar tükendi",
|
||||
"In Stock": "Stokta var",
|
||||
"Add to cart": "Sepete ekle",
|
||||
"Oops": "ayy",
|
||||
"Please select valid options first": "Lütfen önce geçerli seçenekleri seçin",
|
||||
"Sorry": "Üzgünüm",
|
||||
"This item is not in stock": "Bu ürün stokta yok",
|
||||
"Description": "Açıklama",
|
||||
"Full description": "Tam tanım",
|
||||
"ADD TO CART": "SEPETE EKLE",
|
||||
"This item is out of stock": "Bu ürün stokta yok",
|
||||
"Add your shipping details first": "Önce gönderim bilgilerinizi ekleyin",
|
||||
"Checkout": "Ödeme",
|
||||
"Billing/shipping details": "Fatura/gönderim ayrıntıları",
|
||||
"Add billing & shipping details": "Fatura ve gönderim ayrıntılarını ekleyin",
|
||||
"Payment method": "Ödeme şekli",
|
||||
"Pay with": "İle ödemek",
|
||||
"Select a payment method": "Bir ödeme şekli seçin",
|
||||
"Shipping selected": "Sevkiyat seçildi",
|
||||
"Select shipping": "Gönderim seç",
|
||||
"Select a shipping option": "Bir nakliye seçeneği seçin",
|
||||
"Shipping fee": "Nakliye ücreti",
|
||||
"Subtotal": "ara toplam",
|
||||
"Total": "Toplam",
|
||||
"CHECKOUT": "ÖDEME",
|
||||
"One moment": "Bir dakika",
|
||||
"Please select add your billing/shipping address to proceed": "Devam etmek için lütfen fatura/gönderim adresinizi ekleyin'i seçin",
|
||||
"Your billing/shipping details are incomplete": "Faturalandırma/gönderim bilgileriniz eksik",
|
||||
"Please select a shipping method to proceed": "Lütfen devam etmek için bir gönderim yöntemi seçin",
|
||||
"Please select a payment method to proceed": "Lütfen devam etmek için bir ödeme yöntemi seçin",
|
||||
"Something went wrong, please contact our store": "Bir şeyler ters gitti, lütfen mağazamızla iletişime geçin",
|
||||
"Error": "Hata",
|
||||
"Order Status": "Sipariş durumu",
|
||||
"Thank You!": "Teşekkürler!",
|
||||
"Your transaction details": "İşlem ayrıntılarınız",
|
||||
"Order Ref": "Sipariş Referansı",
|
||||
"Items": "Öğeler",
|
||||
"Back to Home": "Eve geri dön",
|
||||
"Orders": "Emirler",
|
||||
"Billing & Shipping Details": "Faturalandırma ve Gönderim Ayrıntıları",
|
||||
"First Name": "İlk adı",
|
||||
"Last Name": "Soyadı",
|
||||
"Address Line": "Adres satırı",
|
||||
"City": "Şehir",
|
||||
"Postal code": "Posta kodu",
|
||||
"Email address": "E",
|
||||
"Selected": "Seçildi",
|
||||
"Select country": "Ülke seçin",
|
||||
"Remember my details": "Ayrıntılarımı hatırla",
|
||||
"USE SHIPPING ADDRESS": "NAKLİYE ADRESİNİ KULLAN",
|
||||
"About": "Hakkında",
|
||||
"Privacy policy": "Gizlilik Politikası",
|
||||
"Terms and conditions": "Şartlar ve koşullar",
|
||||
"Version": "sürüm",
|
||||
"Payment Method": "Ödeme şekli",
|
||||
"CANCEL": "İPTAL ET",
|
||||
"Shipping Methods": "Nakliye Yöntemleri",
|
||||
"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ı",
|
||||
"Oops, something went wrong": "Hoop! Birşeyler yanlış gitti",
|
||||
"Tax": "Vergi",
|
||||
"No results": "Sonuç yok",
|
||||
"There is an item out of stock": "Stokta olmayan bir ürün var",
|
||||
"Maximum stock reached": "Maksimum stoka ulaşıldı",
|
||||
"Select a country": "Bir ülke seçin",
|
||||
"Menu": "Menü",
|
||||
"About Us": "Hakkımızda",
|
||||
"Something went wrong": "Bir şeyler yanlış gitti",
|
||||
"Product variation does not exist": "Ürün varyasyonu mevcut değil",
|
||||
"This variation is unavailable": "Bu varyasyon kullanılamıyor",
|
||||
"Sorry, something went wrong": "Üzgünüm, bir şeyler ters gitti",
|
||||
"Back": "Geri",
|
||||
"Profile": "Profil",
|
||||
"Forgot Password": "Parolanızı mı unuttunuz",
|
||||
"Create an account": "Bir hesap oluşturun",
|
||||
"Login": "Giriş yapmak",
|
||||
"Password": "Parola",
|
||||
"Oops!": "Hata!",
|
||||
"Invalid login credentials": "Geçersiz giriş bilgileri",
|
||||
"That email address is not valid": "Bu e-posta adresi geçerli değil",
|
||||
"Password must be a min 6 characters": "Şifre en az 6 karakter olmalıdır",
|
||||
"Please check your details": "Lütfen bilgilerinizi kontrol edin",
|
||||
"Invalid": "Geçersiz",
|
||||
"Actions": "Hareketler",
|
||||
"View Terms and Conditions or Privacy policy": "Hüküm ve Koşulları veya Gizlilik Politikasını Görüntüle",
|
||||
"Terms and Conditions": "Şartlar ve koşullar",
|
||||
"Privacy Policy": "Gizlilik Politikası",
|
||||
"terms and conditions": "Şartlar ve koşullar",
|
||||
"and": "ve",
|
||||
"By tapping \"Register\" you agree to ": "\"Kaydol\"a dokunarak şunları kabul etmiş olursunuz:",
|
||||
"privacy policy": "Gizlilik Politikası",
|
||||
"Sign up": "Üye olmak",
|
||||
"Email": "E-posta",
|
||||
"Update details": "Ayrıntıları güncelle",
|
||||
"Settings": "Ayarlar",
|
||||
"Account": "Hesap",
|
||||
"Logout": "Çıkış Yap",
|
||||
"No orders found": "sipariş bulunamadı",
|
||||
"items": "öğeler",
|
||||
"Update Details": "Ayrıntıları Güncelle",
|
||||
"Invalid details": "Geçersiz ayrıntılar",
|
||||
"Please check your email and password": "Lütfen e-posta adresinizi ve şifrenizi kontrol edin",
|
||||
"Something went wrong, please try again.": "Bir şeyler ters gitti lütfen tekrar deneyin.",
|
||||
"Done": "Tamamlandı",
|
||||
"Billing Details": "Fatura Detayları",
|
||||
"Shipping Details": "Nakliye ayrıntıları",
|
||||
"Shipping Address": "Teslimat Adresi",
|
||||
"State": "Belirtmek, bildirmek",
|
||||
"Country": "Ülke",
|
||||
"UPDATE DETAILS": "GÜNCELLEME DETAYLARI",
|
||||
"No more products": "Daha fazla ürün yok",
|
||||
"release to load more": "daha fazla yüklemek için bırakın",
|
||||
"Load Failed! Click retry!": "Yükleme başarısız! Yeniden dene'yi tıklayın!",
|
||||
"pull up load": "yükü yukarı çekmek",
|
||||
"Sort: Low to high": "Sıralama: Düşükten yükseğe",
|
||||
"Sort: High to low": "Sıralama: Yüksekten düşüğe",
|
||||
"Sort: Name A-Z": "Sırala: İsim A-Z",
|
||||
"Sort: Name Z-A": "Sıralama: İsim Z-A",
|
||||
"Cancel": "İptal etmek",
|
||||
"Sort results": "Sonuçları sırala",
|
||||
"you're now logged in": "şimdi giriş yaptınız",
|
||||
"Hello": "Merhaba",
|
||||
"Welcome back": "Tekrar hoşgeldiniz",
|
||||
"Quantity": "Miktar",
|
||||
"Select a state": "Bir eyalet seçin",
|
||||
"Select state": "Eyalet seç",
|
||||
"Ship to a different address?": "Farklı bir adrese mi gönderiyorsunuz?",
|
||||
"USE DETAILS": "KULLANIM DETAYLARI",
|
||||
"Not supported, try a card payment": "Desteklenmiyor, kartla ödeme yapmayı deneyin",
|
||||
"Invalid shipping address, please check your shipping details": "Geçersiz gönderim adresi, lütfen gönderim ayrıntılarınızı kontrol edin",
|
||||
"Was": "Oldu",
|
||||
"off": "kapalı",
|
||||
"Maximum quantity reached": "Maksimum miktara ulaşıldı",
|
||||
"Sorry, only": "Üzgünüm, sadece",
|
||||
"left": "ayrıldı",
|
||||
"Billing address is incomplete": "Fatura adresi eksik",
|
||||
"Order": "Emir",
|
||||
"Date Ordered": "Sipariş Tarihi",
|
||||
"Ships to": "Şuraya gönderilir:",
|
||||
"That email does not match our records": "Bu e-posta kayıtlarımızla eşleşmiyor",
|
||||
"That username does not match our records": "Bu kullanıcı adı kayıtlarımızla eşleşmiyor",
|
||||
"That password does not match our records": "Bu şifre kayıtlarımızla eşleşmiyor",
|
||||
"The email and password field cannot be empty": "E-posta ve şifre alanı boş olamaz",
|
||||
"Username taken, try another.": "Bu kullanıcı adı alınmış, başka bir tane deneyin.",
|
||||
"A user already exists": "Bir kullanıcı zaten var",
|
||||
"That email is taken, try another": "Bu e-posta alındı, başka bir tane deneyin",
|
||||
"The email field is empty": "E-posta alanı boş",
|
||||
"No more orders": "Başka sipariş yok",
|
||||
"Account updated": "Hesap güncellendi",
|
||||
"Spend a minimum of": "Minimum harcamak",
|
||||
"for": "için",
|
||||
"Buy Product": "Ürün Satın Al",
|
||||
"Retry": "yeniden dene",
|
||||
"Retry later": "daha sonra tekrar dene",
|
||||
"Light Mode": "Işık Modu",
|
||||
"Dark Mode": "Karanlık Mod",
|
||||
"PayPal Checkout": "PayPal Ödemesi",
|
||||
"Processing Payment": "Ödeme İşlemi",
|
||||
"Please wait, your order is being processed and you will be redirected to the PayPal website.": "Lütfen bekleyin, siparişiniz işleniyor ve PayPal web sitesine yönlendirileceksiniz.",
|
||||
"If you are not automatically redirected to PayPal within 5 seconds": "5 saniye içinde otomatik olarak PayPal'a yönlendirilmezseniz",
|
||||
"Payment Cancelled": "Ödeme İptal Edildi",
|
||||
"The payment has been cancelled": "ödeme iptal edildi",
|
||||
"Must have": "sahip olmalı",
|
||||
"Our selection of new items": "Yeni ürün seçimimiz",
|
||||
"Register": "Kayıt olmak",
|
||||
"No payment methods are available": "Ödeme yöntemi yok",
|
||||
"Please enter a valid billing email": "Lütfen geçerli bir fatura e-postası girin",
|
||||
"Please enter a valid shipping email": "Lütfen geçerli bir gönderim e-postası girin",
|
||||
"Free postage": "Bedava posta",
|
||||
"PROCESSING": "İŞLEME",
|
||||
"Social": "Sosyal",
|
||||
"Please enter coupon to redeem": "Lütfen kullanmak için kupon girin",
|
||||
"Coupon": "Kupon",
|
||||
"Apply": "Uygulamak",
|
||||
"Apply Coupon": "kuponu onayla",
|
||||
"Added to checkout": "ödemeye eklendi",
|
||||
"Redeem Coupon": "Kuponu Kullan",
|
||||
"Add coupon code": "Kupon kodu ekle",
|
||||
"Coupon not found": "Kupon bulunamadı",
|
||||
"Sorry, this coupon can not be used with your cart": "Üzgünüz, bu kupon sepetinizle kullanılamaz",
|
||||
"You cannot redeem this coupon": "Bu kuponu kullanamazsınız",
|
||||
"This coupon has expired": "Bu kuponun süresi doldu",
|
||||
"Usage limit has been reached": "Kullanım sınırına ulaşıldı",
|
||||
"View All": "Hepsini gör",
|
||||
"Wishlist": "istek listesi",
|
||||
"No items found": "hiç bir öğe bulunamadı",
|
||||
"This product has been removed from your wishlist": "Bu ürün istek listenizden kaldırıldı",
|
||||
"This product has been added to your wishlist": "Bu ürün istek listenize eklendi",
|
||||
"Spend a minimum of minimumAmount to redeem": "Minimum harcamak {{minimumAmount}} rehinden kurtarmak",
|
||||
"Spend less than maximumAmount to redeem": "Şundan daha az harcayın: {{maximumAmount}} rehinden kurtarmak"
|
||||
}
|
||||
@ -191,5 +191,24 @@
|
||||
"Please enter a valid shipping email": "请输入有效的送货电子邮件",
|
||||
"Free postage": "免邮费",
|
||||
"PROCESSING": "加工",
|
||||
"Social": "社会的"
|
||||
"Social": "社会的",
|
||||
"Please enter coupon to redeem": "请输入优惠券进行兑换",
|
||||
"Coupon": "优惠券",
|
||||
"Apply": "申请",
|
||||
"Apply Coupon": "申请优惠券",
|
||||
"Added to checkout": "添加到结帐",
|
||||
"Redeem Coupon": "兑换优惠券",
|
||||
"Add coupon code": "添加优惠券代码",
|
||||
"Coupon not found": "未找到优惠券",
|
||||
"Sorry, this coupon can not be used with your cart": "抱歉,此优惠券不能与您的购物车一起使用",
|
||||
"You cannot redeem this coupon": "您无法兑换此优惠券",
|
||||
"This coupon has expired": "此优惠券已过期",
|
||||
"Usage limit has been reached": "已达到使用限制",
|
||||
"View All": "查看全部",
|
||||
"Wishlist": "愿望清单",
|
||||
"No items found": "未找到任何项目",
|
||||
"This product has been removed from your wishlist": "该产品已从您的愿望清单中删除",
|
||||
"This product has been added to your wishlist": "本产品已经被加入你的心愿单",
|
||||
"Spend a minimum of minimumAmount to redeem": "至少花费 {{minimumAmount}} 赎回",
|
||||
"Spend less than maximumAmount to redeem": "花费少于 {{maximumAmount}} 赎回"
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -1,23 +1,17 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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:nylo_support/controllers/controller.dart';
|
||||
|
||||
/// Base Controller for the Nylo
|
||||
/// See more on controllers here - https://nylo.dev/docs/2.x/controllers
|
||||
class Controller extends BaseController {
|
||||
Controller();
|
||||
|
||||
@override
|
||||
construct(BuildContext context) {
|
||||
super.construct(context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
// 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/cupertino.dart';
|
||||
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
|
||||
import 'package:woosignal/models/response/order.dart';
|
||||
|
||||
class CustomerOrdersLoaderController
|
||||
extends WooSignalApiLoaderController<Order> {
|
||||
CustomerOrdersLoaderController();
|
||||
|
||||
Future<void> loadOrders(
|
||||
{@required bool Function(bool hasProducts) hasResults,
|
||||
@required void Function() didFinish,
|
||||
@required String userId}) async {
|
||||
await load(
|
||||
hasResults: hasResults,
|
||||
didFinish: didFinish,
|
||||
apiQuery: (api) => api.getOrders(
|
||||
customer: int.parse(userId), page: page, perPage: 50));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
// 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/cupertino.dart';
|
||||
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
|
||||
import 'package:woosignal/models/response/product_category.dart';
|
||||
import 'package:woosignal/models/response/products.dart';
|
||||
|
||||
class ProductCategorySearchLoaderController
|
||||
extends WooSignalApiLoaderController<Product> {
|
||||
ProductCategorySearchLoaderController();
|
||||
|
||||
Future<void> loadProducts(
|
||||
{@required bool Function(bool hasProducts) hasResults,
|
||||
@required void Function() didFinish,
|
||||
@required ProductCategory productCategory}) async {
|
||||
await load(
|
||||
hasResults: hasResults,
|
||||
didFinish: didFinish,
|
||||
apiQuery: (api) => api.getProducts(
|
||||
perPage: 50,
|
||||
category: productCategory.id.toString(),
|
||||
page: page,
|
||||
status: "publish",
|
||||
stockStatus: "instock"));
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
// 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/cupertino.dart';
|
||||
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
|
||||
import 'package:woosignal/models/response/products.dart';
|
||||
|
||||
class ProductLoaderController extends WooSignalApiLoaderController<Product> {
|
||||
ProductLoaderController();
|
||||
|
||||
Future<void> loadProducts({
|
||||
@required bool Function(bool hasProducts) hasResults,
|
||||
@required void Function() didFinish,
|
||||
}) async {
|
||||
await load(
|
||||
hasResults: hasResults,
|
||||
didFinish: didFinish,
|
||||
apiQuery: (api) => api.getProducts(
|
||||
perPage: 50,
|
||||
page: page,
|
||||
status: "publish",
|
||||
stockStatus: "instock",
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
// 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/cupertino.dart';
|
||||
import 'package:flutter_app/app/controllers/woosignal_api_loader_controller.dart';
|
||||
import 'package:woosignal/models/response/products.dart';
|
||||
|
||||
class ProductSearchLoaderController
|
||||
extends WooSignalApiLoaderController<Product> {
|
||||
ProductSearchLoaderController();
|
||||
|
||||
Future<void> loadProducts(
|
||||
{@required bool Function(bool hasProducts) hasResults,
|
||||
@required void Function() didFinish,
|
||||
@required String search}) async {
|
||||
await load(
|
||||
hasResults: hasResults,
|
||||
didFinish: didFinish,
|
||||
apiQuery: (api) => api.getProducts(
|
||||
perPage: 100,
|
||||
search: search,
|
||||
page: page,
|
||||
status: "publish",
|
||||
stockStatus: "instock",
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
// 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/cupertino.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:woosignal/woosignal.dart';
|
||||
|
||||
class WooSignalApiLoaderController<T> {
|
||||
List<T> _results = [];
|
||||
int page = 1;
|
||||
bool _waitForNextRequest = false;
|
||||
|
||||
WooSignalApiLoaderController();
|
||||
|
||||
Future<void> load(
|
||||
{@required bool Function(bool hasProducts) hasResults,
|
||||
@required void Function() didFinish,
|
||||
@required Future<List<T>> Function(WooSignal query) apiQuery}) async {
|
||||
if (_waitForNextRequest) {
|
||||
return;
|
||||
}
|
||||
_waitForNextRequest = true;
|
||||
|
||||
List<T> apiResults = await appWooSignal((api) => apiQuery(api));
|
||||
|
||||
if (!hasResults(apiResults.isNotEmpty)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_results.addAll(apiResults);
|
||||
|
||||
page = page + 1;
|
||||
_waitForNextRequest = false;
|
||||
didFinish();
|
||||
}
|
||||
|
||||
List<T> getResults() {
|
||||
return _results;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_results = [];
|
||||
_waitForNextRequest = false;
|
||||
page = 1;
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
19
LabelStoreMax/lib/app/models/bottom_nav_item.dart
Normal file
19
LabelStoreMax/lib/app/models/bottom_nav_item.dart
Normal file
@ -0,0 +1,19 @@
|
||||
// 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';
|
||||
|
||||
class BottomNavItem {
|
||||
int id;
|
||||
BottomNavigationBarItem bottomNavigationBarItem;
|
||||
Widget tabWidget;
|
||||
|
||||
BottomNavItem({this.id, this.bottomNavigationBarItem, this.tabWidget});
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -70,9 +70,15 @@ class Cart {
|
||||
Future<String> getTotal({bool withFormat = false}) async {
|
||||
List<CartLineItem> cartLineItems = await getCart();
|
||||
double total = 0;
|
||||
cartLineItems.forEach((cartItem) {
|
||||
for (var cartItem in cartLineItems) {
|
||||
total += (parseWcPrice(cartItem.total) * cartItem.quantity);
|
||||
});
|
||||
}
|
||||
|
||||
CheckoutSession checkoutSession = CheckoutSession.getInstance;
|
||||
if (checkoutSession.coupon != null) {
|
||||
String discountAmount = await Cart.getInstance.couponDiscountAmount();
|
||||
total = total - double.parse(discountAmount);
|
||||
}
|
||||
|
||||
if (withFormat != null && withFormat == true) {
|
||||
return formatDoubleCurrency(total: total);
|
||||
@ -83,9 +89,9 @@ class Cart {
|
||||
Future<String> getSubtotal({bool withFormat = false}) async {
|
||||
List<CartLineItem> cartLineItems = await getCart();
|
||||
double subtotal = 0;
|
||||
cartLineItems.forEach((cartItem) {
|
||||
for (var cartItem in cartLineItems) {
|
||||
subtotal += (parseWcPrice(cartItem.subtotal) * cartItem.quantity);
|
||||
});
|
||||
}
|
||||
if (withFormat != null && withFormat == true) {
|
||||
return formatDoubleCurrency(total: subtotal);
|
||||
}
|
||||
@ -97,7 +103,7 @@ class Cart {
|
||||
@required int incrementQuantity}) async {
|
||||
List<CartLineItem> cartLineItems = await getCart();
|
||||
List<CartLineItem> tmpCartItem = [];
|
||||
cartLineItems.forEach((cartItem) {
|
||||
for (var cartItem in cartLineItems) {
|
||||
if (cartItem.variationId == cartLineItem.variationId &&
|
||||
cartItem.productId == cartLineItem.productId) {
|
||||
if ((cartItem.quantity + incrementQuantity) > 0) {
|
||||
@ -105,7 +111,7 @@ class Cart {
|
||||
}
|
||||
}
|
||||
tmpCartItem.add(cartItem);
|
||||
});
|
||||
}
|
||||
await saveCartToPref(cartLineItems: tmpCartItem);
|
||||
}
|
||||
|
||||
@ -145,10 +151,14 @@ class Cart {
|
||||
double cartSubtotal = 0;
|
||||
|
||||
if (AppHelper.instance.appConfig.productPricesIncludeTax == 1 &&
|
||||
taxableCartLines.length > 0) {
|
||||
taxableCartLines.isNotEmpty) {
|
||||
cartSubtotal = taxableCartLines
|
||||
.map<double>((m) => parseWcPrice(m.subtotal) * m.quantity)
|
||||
.reduce((a, b) => a + b);
|
||||
if (CheckoutSession.getInstance.coupon != null) {
|
||||
String discountAmount = await Cart.getInstance.couponDiscountAmount();
|
||||
cartSubtotal = cartSubtotal - double.parse(discountAmount);
|
||||
}
|
||||
}
|
||||
|
||||
subtotal = cartSubtotal;
|
||||
@ -189,4 +199,86 @@ class Cart {
|
||||
}
|
||||
return (total).toStringAsFixed(2);
|
||||
}
|
||||
|
||||
Future<String> couponDiscountAmount() async {
|
||||
CheckoutSession checkoutSession = CheckoutSession.getInstance;
|
||||
|
||||
if (checkoutSession.coupon == null) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
List<CartLineItem> cartLineItems = await getCart();
|
||||
List<CartLineItem> eligibleCartLineItems = [];
|
||||
double subtotal = 0;
|
||||
for (var cartItem in cartLineItems) {
|
||||
bool canContinue = true;
|
||||
|
||||
if (checkoutSession.coupon.excludedProductCategories.isNotEmpty) {
|
||||
for (var excludedProductCategory
|
||||
in checkoutSession.coupon.excludedProductCategories) {
|
||||
if (cartItem.categories
|
||||
.map((category) => category.id)
|
||||
.contains(excludedProductCategory)) {
|
||||
canContinue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checkoutSession.coupon.productCategories.isNotEmpty) {
|
||||
for (var productCategories
|
||||
in checkoutSession.coupon.productCategories) {
|
||||
if (cartItem.categories
|
||||
.map((category) => category.id)
|
||||
.contains(productCategories) ==
|
||||
false) {
|
||||
canContinue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canContinue == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkoutSession.coupon.excludeSaleItems == true &&
|
||||
cartItem.onSale == true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkoutSession.coupon.excludedProductIds.isNotEmpty &&
|
||||
checkoutSession.coupon.excludedProductIds
|
||||
.contains(cartItem.productId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkoutSession.coupon.productIds.isNotEmpty &&
|
||||
!checkoutSession.coupon.productIds.contains(cartItem.productId)) {
|
||||
continue;
|
||||
}
|
||||
subtotal += (parseWcPrice(cartItem.subtotal) * cartItem.quantity);
|
||||
eligibleCartLineItems.add(cartItem);
|
||||
}
|
||||
|
||||
String discountType = checkoutSession.coupon.discountType;
|
||||
String amount = checkoutSession.coupon.amount;
|
||||
|
||||
// Percentage
|
||||
if (discountType == 'percent') {
|
||||
return ((subtotal * double.parse(amount)) / 100).toStringAsFixed(2);
|
||||
}
|
||||
|
||||
// Fixed cart
|
||||
if (discountType == 'fixed_cart') {
|
||||
return (double.parse(amount)).toStringAsFixed(2);
|
||||
}
|
||||
|
||||
// Fixed product
|
||||
if (discountType == 'fixed_product') {
|
||||
return (eligibleCartLineItems.length * double.parse(amount))
|
||||
.toStringAsFixed(2);
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -9,6 +9,9 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
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/products.dart' as ws_product;
|
||||
|
||||
class CartLineItem {
|
||||
String name;
|
||||
@ -25,6 +28,8 @@ class CartLineItem {
|
||||
String total;
|
||||
String imageSrc;
|
||||
String variationOptions;
|
||||
List<ws_product.Category> categories;
|
||||
bool onSale;
|
||||
String stockStatus;
|
||||
Object metaData = {};
|
||||
|
||||
@ -39,10 +44,12 @@ class CartLineItem {
|
||||
this.shippingClassId,
|
||||
this.taxStatus,
|
||||
this.taxClass,
|
||||
this.categories,
|
||||
this.shippingIsTaxable,
|
||||
this.variationOptions,
|
||||
this.imageSrc,
|
||||
this.subtotal,
|
||||
this.onSale,
|
||||
this.total,
|
||||
this.metaData});
|
||||
|
||||
@ -50,6 +57,53 @@ class CartLineItem {
|
||||
return (quantity * parseWcPrice(subtotal)).toStringAsFixed(2);
|
||||
}
|
||||
|
||||
CartLineItem.fromProduct({int quantityAmount, ws_product.Product product}) {
|
||||
name = product.name;
|
||||
productId = product.id;
|
||||
quantity = quantityAmount;
|
||||
taxStatus = product.taxStatus;
|
||||
shippingClassId = product.shippingClassId.toString();
|
||||
subtotal = product.price;
|
||||
taxClass = product.taxClass;
|
||||
categories = product.categories;
|
||||
isManagedStock = product.manageStock;
|
||||
stockQuantity = product.stockQuantity;
|
||||
shippingIsTaxable = product.shippingTaxable;
|
||||
imageSrc = product.images.isEmpty
|
||||
? getEnv("PRODUCT_PLACEHOLDER_IMAGE")
|
||||
: product.images.first.src;
|
||||
total = product.price;
|
||||
}
|
||||
|
||||
CartLineItem.fromProductVariation(
|
||||
{int quantityAmount,
|
||||
List<String> options,
|
||||
ws_product.Product product,
|
||||
ProductVariation productVariation}) {
|
||||
String imageSrc = getEnv("PRODUCT_PLACEHOLDER_IMAGE");
|
||||
if (product.images.isNotEmpty) {
|
||||
imageSrc = product.images.first.src;
|
||||
}
|
||||
if (productVariation.image != null) {
|
||||
imageSrc = productVariation.image.src;
|
||||
}
|
||||
name = product.name;
|
||||
productId = product.id;
|
||||
variationId = productVariation.id;
|
||||
quantity = quantityAmount;
|
||||
taxStatus = productVariation.taxStatus;
|
||||
shippingClassId = productVariation.shippingClassId.toString();
|
||||
subtotal = productVariation.price;
|
||||
stockQuantity = productVariation.stockQuantity;
|
||||
isManagedStock = productVariation.manageStock;
|
||||
categories = product.categories;
|
||||
taxClass = productVariation.taxClass;
|
||||
this.imageSrc = imageSrc;
|
||||
shippingIsTaxable = product.shippingTaxable;
|
||||
variationOptions = options.join("; ");
|
||||
total = productVariation.price;
|
||||
}
|
||||
|
||||
CartLineItem.fromJson(Map<String, dynamic> json)
|
||||
: name = json['name'],
|
||||
productId = json['product_id'],
|
||||
@ -68,6 +122,12 @@ class CartLineItem {
|
||||
taxClass = json['tax_class'],
|
||||
stockStatus = json['stock_status'],
|
||||
imageSrc = json['image_src'],
|
||||
categories = json['categories'] == null
|
||||
? null
|
||||
: List.of(json['categories'] as List)
|
||||
.map((e) => ws_product.Category.fromJson(e))
|
||||
.toList(),
|
||||
onSale = json['on_sale'],
|
||||
variationOptions = json['variation_options'],
|
||||
metaData = json['metaData'];
|
||||
|
||||
@ -84,8 +144,12 @@ class CartLineItem {
|
||||
'stock_quantity': stockQuantity,
|
||||
'shipping_is_taxable': shippingIsTaxable,
|
||||
'image_src': imageSrc,
|
||||
'categories': categories != null
|
||||
? categories.map((e) => e.toJson()).toList()
|
||||
: [],
|
||||
'variation_options': variationOptions,
|
||||
'subtotal': subtotal,
|
||||
'on_sale': onSale,
|
||||
'total': total,
|
||||
'meta_data': metaData,
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -17,6 +17,7 @@ import 'package:flutter_app/app/models/shipping_type.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/bootstrap/shared_pref/shared_key.dart';
|
||||
import 'package:nylo_support/helpers/helper.dart';
|
||||
import 'package:woosignal/models/response/coupon.dart';
|
||||
import 'package:woosignal/models/response/tax_rate.dart';
|
||||
|
||||
class CheckoutSession {
|
||||
@ -29,6 +30,7 @@ class CheckoutSession {
|
||||
BillingDetails billingDetails;
|
||||
ShippingType shippingType;
|
||||
PaymentType paymentType;
|
||||
Coupon coupon;
|
||||
|
||||
void initSession() {
|
||||
billingDetails = BillingDetails();
|
||||
@ -39,6 +41,7 @@ class CheckoutSession {
|
||||
billingDetails = null;
|
||||
shippingType = null;
|
||||
paymentType = null;
|
||||
coupon = null;
|
||||
}
|
||||
|
||||
void saveBillingAddress() async {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -39,13 +39,13 @@ class CustomerAddress {
|
||||
}
|
||||
|
||||
bool hasMissingFields() =>
|
||||
(this.firstName.isEmpty ||
|
||||
this.lastName.isEmpty ||
|
||||
this.addressLine.isEmpty ||
|
||||
this.city.isEmpty ||
|
||||
this.postalCode.isEmpty) ||
|
||||
(this.customerCountry.hasState() == true
|
||||
? (this.customerCountry?.state?.name ?? "").isEmpty
|
||||
(firstName.isEmpty ||
|
||||
lastName.isEmpty ||
|
||||
addressLine.isEmpty ||
|
||||
city.isEmpty ||
|
||||
postalCode.isEmpty) ||
|
||||
(customerCountry.hasState() == true
|
||||
? (customerCountry?.state?.name ?? "").isEmpty
|
||||
: false);
|
||||
|
||||
String addressFull() {
|
||||
@ -59,12 +59,11 @@ class CustomerAddress {
|
||||
if (postalCode != null && postalCode != "") {
|
||||
tmpArrAddress.add(postalCode);
|
||||
}
|
||||
if (this.customerCountry != null &&
|
||||
this.customerCountry?.state?.name != null) {
|
||||
tmpArrAddress.add(this.customerCountry?.state?.name);
|
||||
if (customerCountry != null && customerCountry?.state?.name != null) {
|
||||
tmpArrAddress.add(customerCountry?.state?.name);
|
||||
}
|
||||
if (this.customerCountry != null && this.customerCountry?.name != null) {
|
||||
tmpArrAddress.add(this.customerCountry.name);
|
||||
if (customerCountry != null && customerCountry?.name != null) {
|
||||
tmpArrAddress.add(customerCountry.name);
|
||||
}
|
||||
return tmpArrAddress.join(", ");
|
||||
}
|
||||
@ -86,23 +85,23 @@ class CustomerAddress {
|
||||
addressLine = json['address_line'];
|
||||
city = json['city'];
|
||||
postalCode = json['postal_code'];
|
||||
this.customerCountry = CustomerCountry.fromJson(json['customer_country']);
|
||||
customerCountry = CustomerCountry.fromJson(json['customer_country']);
|
||||
emailAddress = json['email_address'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['first_name'] = this.firstName;
|
||||
data['last_name'] = this.lastName;
|
||||
data['address_line'] = this.addressLine;
|
||||
data['city'] = this.city;
|
||||
data['postal_code'] = this.postalCode;
|
||||
data['state'] = this.customerCountry.state;
|
||||
data['country'] = this.customerCountry.name;
|
||||
data['email_address'] = this.emailAddress;
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['first_name'] = firstName;
|
||||
data['last_name'] = lastName;
|
||||
data['address_line'] = addressLine;
|
||||
data['city'] = city;
|
||||
data['postal_code'] = postalCode;
|
||||
data['state'] = customerCountry.state;
|
||||
data['country'] = customerCountry.name;
|
||||
data['email_address'] = emailAddress;
|
||||
data['customer_country'] = null;
|
||||
if (this.customerCountry != null) {
|
||||
data['customer_country'] = this.customerCountry.toJson();
|
||||
if (customerCountry != null) {
|
||||
data['customer_country'] = customerCountry.toJson();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -40,16 +40,15 @@ class CustomerCountry {
|
||||
}
|
||||
}
|
||||
|
||||
bool hasState() =>
|
||||
(this.state != null && this.state.name != null ? true : false);
|
||||
bool hasState() => (state != null && state.name != null ? true : false);
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['country_code'] = this.countryCode;
|
||||
data['name'] = this.name;
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['country_code'] = countryCode;
|
||||
data['name'] = name;
|
||||
data['state'] = null;
|
||||
if (this.state != null) {
|
||||
data['state'] = this.state.toJson();
|
||||
if (state != null) {
|
||||
data['state'] = state.toJson();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -25,14 +25,14 @@ class DefaultShippingState {
|
||||
DefaultShippingState({@required this.code, @required this.name});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['code'] = code;
|
||||
data['name'] = name;
|
||||
return data;
|
||||
}
|
||||
|
||||
DefaultShippingState.fromJson(Map<String, dynamic> json) {
|
||||
this.code = json['code'];
|
||||
this.name = json['name'];
|
||||
code = json['code'];
|
||||
name = json['name'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -32,20 +32,20 @@ class ShippingType {
|
||||
};
|
||||
|
||||
String getTotal({bool withFormatting = false}) {
|
||||
if (this.object != null) {
|
||||
switch (this.methodId) {
|
||||
if (object != null) {
|
||||
switch (methodId) {
|
||||
case "flat_rate":
|
||||
FlatRate flatRate = (this.object as FlatRate);
|
||||
FlatRate flatRate = (object as FlatRate);
|
||||
return (withFormatting == true
|
||||
? formatStringCurrency(total: cost)
|
||||
: flatRate.cost);
|
||||
case "free_shipping":
|
||||
FreeShipping freeShipping = (this.object as FreeShipping);
|
||||
FreeShipping freeShipping = (object as FreeShipping);
|
||||
return (withFormatting == true
|
||||
? formatStringCurrency(total: cost)
|
||||
: freeShipping.cost);
|
||||
case "local_pickup":
|
||||
LocalPickup localPickup = (this.object as LocalPickup);
|
||||
LocalPickup localPickup = (object as LocalPickup);
|
||||
return (withFormatting == true
|
||||
? formatStringCurrency(total: cost)
|
||||
: localPickup.cost);
|
||||
@ -57,16 +57,16 @@ class ShippingType {
|
||||
}
|
||||
|
||||
String getTitle() {
|
||||
if (this.object != null) {
|
||||
switch (this.methodId) {
|
||||
if (object != null) {
|
||||
switch (methodId) {
|
||||
case "flat_rate":
|
||||
FlatRate flatRate = (this.object as FlatRate);
|
||||
FlatRate flatRate = (object as FlatRate);
|
||||
return flatRate.title;
|
||||
case "free_shipping":
|
||||
FreeShipping freeShipping = (this.object as FreeShipping);
|
||||
FreeShipping freeShipping = (object as FreeShipping);
|
||||
return freeShipping.title;
|
||||
case "local_pickup":
|
||||
LocalPickup localPickup = (this.object as LocalPickup);
|
||||
LocalPickup localPickup = (object as LocalPickup);
|
||||
return localPickup.title;
|
||||
default:
|
||||
return "";
|
||||
@ -76,27 +76,27 @@ class ShippingType {
|
||||
}
|
||||
|
||||
Map<String, dynamic> toShippingLineFee() {
|
||||
if (this.object != null) {
|
||||
if (object != null) {
|
||||
Map<String, dynamic> tmpShippingLinesObj = {};
|
||||
|
||||
switch (this.methodId) {
|
||||
switch (methodId) {
|
||||
case "flat_rate":
|
||||
FlatRate flatRate = (this.object as FlatRate);
|
||||
FlatRate flatRate = (object as FlatRate);
|
||||
tmpShippingLinesObj["method_title"] = flatRate.title;
|
||||
tmpShippingLinesObj["method_id"] = flatRate.methodId;
|
||||
tmpShippingLinesObj["total"] = this.cost;
|
||||
tmpShippingLinesObj["total"] = cost;
|
||||
break;
|
||||
case "free_shipping":
|
||||
FreeShipping freeShipping = (this.object as FreeShipping);
|
||||
FreeShipping freeShipping = (object as FreeShipping);
|
||||
tmpShippingLinesObj["method_title"] = freeShipping.title;
|
||||
tmpShippingLinesObj["method_id"] = freeShipping.methodId;
|
||||
tmpShippingLinesObj["total"] = this.cost;
|
||||
tmpShippingLinesObj["total"] = cost;
|
||||
break;
|
||||
case "local_pickup":
|
||||
LocalPickup localPickup = (this.object as LocalPickup);
|
||||
LocalPickup localPickup = (object as LocalPickup);
|
||||
tmpShippingLinesObj["method_title"] = localPickup.title;
|
||||
tmpShippingLinesObj["method_id"] = localPickup.methodId;
|
||||
tmpShippingLinesObj["total"] = this.cost;
|
||||
tmpShippingLinesObj["total"] = cost;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -18,11 +18,11 @@ class User extends Storable {
|
||||
User.fromUserAuthResponse({this.userId, this.token});
|
||||
|
||||
@override
|
||||
toStorage() => {"token": this.token, "user_id": this.userId};
|
||||
toStorage() => {"token": token, "user_id": userId};
|
||||
|
||||
@override
|
||||
fromStorage(dynamic data) {
|
||||
this.token = data['token'];
|
||||
this.userId = data['user_id'];
|
||||
token = data['token'];
|
||||
userId = data['user_id'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -39,38 +39,36 @@ payPalPay(context,
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Payment Cancelled"),
|
||||
description:
|
||||
trans("The payment has been cancelled"),
|
||||
description: trans("The payment has been cancelled"),
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
return;
|
||||
}
|
||||
|
||||
state.reloadState(showLoader: true);
|
||||
if (value.containsKey("status") && value["status"] == "success") {
|
||||
OrderWC orderWC =
|
||||
await buildOrderWC(taxRate: taxRate, markPaid: true);
|
||||
Order order = await appWooSignal((api) => api.createOrder(orderWC));
|
||||
state.reloadState(showLoader: true);
|
||||
if (value.containsKey("status") && value["status"] == "success") {
|
||||
OrderWC orderWC = await buildOrderWC(taxRate: taxRate, markPaid: true);
|
||||
Order order = await appWooSignal((api) => api.createOrder(orderWC));
|
||||
|
||||
if (order == null) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Error"),
|
||||
description: trans("Something went wrong, please contact our store"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
return;
|
||||
} else {
|
||||
if (order == null) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Payment Cancelled"),
|
||||
description: trans("The payment has been cancelled"),
|
||||
title: trans("Error"),
|
||||
description:
|
||||
trans("Something went wrong, please contact our store"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
return;
|
||||
} else {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Payment Cancelled"),
|
||||
description: trans("The payment has been cancelled"),
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
state.reloadState(showLoader: false);
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -32,13 +32,17 @@ stripePay(context,
|
||||
: getEnv('STRIPE_LIVE_MODE', defaultValue: false);
|
||||
|
||||
// CONFIGURE STRIPE
|
||||
Stripe.stripeAccountId = getEnv('STRIPE_ACCOUNT') == null ? wooSignalApp.stripeAccount : getEnv('STRIPE_ACCOUNT');
|
||||
Stripe.stripeAccountId =
|
||||
getEnv('STRIPE_ACCOUNT') ?? wooSignalApp.stripeAccount;
|
||||
|
||||
Stripe.publishableKey = liveMode ? "pk_live_IyS4Vt86L49jITSfaUShumzi" : "pk_test_0jMmpBntJ6UkizPkfiB8ZJxH"; // Don't change this value
|
||||
Stripe.publishableKey = liveMode
|
||||
? "pk_live_IyS4Vt86L49jITSfaUShumzi"
|
||||
: "pk_test_0jMmpBntJ6UkizPkfiB8ZJxH"; // Don't change this value
|
||||
await Stripe.instance.applySettings();
|
||||
|
||||
if (Stripe.stripeAccountId == '') {
|
||||
NyLogger.error('You need to connect your Stripe account to WooSignal via the dashboard https://woosignal.com/dashboard');
|
||||
NyLogger.error(
|
||||
'You need to connect your Stripe account to WooSignal via the dashboard https://woosignal.com/dashboard');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -51,14 +55,12 @@ stripePay(context,
|
||||
"line1": billingDetails.shippingAddress.addressLine,
|
||||
"city": billingDetails.shippingAddress.city,
|
||||
"postal_code": billingDetails.shippingAddress.postalCode,
|
||||
"country":
|
||||
(billingDetails.shippingAddress?.customerCountry?.name ?? "")
|
||||
"country": (billingDetails.shippingAddress?.customerCountry?.name ?? "")
|
||||
};
|
||||
|
||||
String cartShortDesc = await cart.cartShortDesc();
|
||||
|
||||
rsp = await appWooSignal((api) =>
|
||||
api.stripePaymentIntent(
|
||||
rsp = await appWooSignal((api) => api.stripePaymentIntent(
|
||||
amount: total,
|
||||
email: billingDetails.billingAddress.emailAddress,
|
||||
desc: cartShortDesc,
|
||||
@ -69,21 +71,25 @@ stripePay(context,
|
||||
if (rsp == null) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops!"),
|
||||
description:
|
||||
trans("Something went wrong, please try again."),
|
||||
description: trans("Something went wrong, please try again."),
|
||||
icon: Icons.payment,
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
state.reloadState(showLoader: false);
|
||||
return;
|
||||
}
|
||||
|
||||
await Stripe.instance.initPaymentSheet(paymentSheetParameters: SetupPaymentSheetParameters(
|
||||
await Stripe.instance.initPaymentSheet(
|
||||
paymentSheetParameters: SetupPaymentSheetParameters(
|
||||
applePay: false,
|
||||
googlePay: false,
|
||||
style: Theme.of(state.context).brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark,
|
||||
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),
|
||||
merchantCountryCode: envVal('STRIPE_COUNTRY_CODE',
|
||||
defaultValue: wooSignalApp.stripeCountryCode),
|
||||
merchantDisplayName:
|
||||
envVal('APP_NAME', defaultValue: wooSignalApp.appName),
|
||||
paymentIntentClientSecret: rsp['client_secret'],
|
||||
));
|
||||
|
||||
@ -105,8 +111,7 @@ stripePay(context,
|
||||
}
|
||||
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
|
||||
} on StripeException catch(e) {
|
||||
} on StripeException catch (e) {
|
||||
if (getEnv('APP_DEBUG', defaultValue: true)) {
|
||||
NyLogger.error(e.error.message);
|
||||
}
|
||||
|
||||
@ -62,11 +62,17 @@ class AppBuild extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return LocalizedApp(
|
||||
child: ThemeProvider(
|
||||
themes: appThemes.map((appTheme) => appTheme.toAppTheme(defaultTheme: appTheme.theme.brightness == Brightness.light ? lightTheme : darkTheme)).toList(),
|
||||
themes: appThemes
|
||||
.map((appTheme) => appTheme.toAppTheme(
|
||||
defaultTheme: appTheme.theme.brightness == Brightness.light
|
||||
? lightTheme
|
||||
: darkTheme))
|
||||
.toList(),
|
||||
child: ThemeConsumer(
|
||||
child: Builder(
|
||||
builder: (themeContext) => ValueListenableBuilder(
|
||||
valueListenable: ValueNotifier(locale ?? NyLocalization.instance.locale),
|
||||
valueListenable:
|
||||
ValueNotifier(locale ?? NyLocalization.instance.locale),
|
||||
builder: (context, Locale locale, _) => MaterialApp(
|
||||
navigatorKey: navigatorKey,
|
||||
themeMode: themeMode,
|
||||
@ -86,8 +92,8 @@ class AppBuild extends StatelessWidget {
|
||||
actions: actions,
|
||||
title: title ?? "",
|
||||
initialRoute: initialRoute,
|
||||
onGenerateRoute: this.onGenerateRoute,
|
||||
darkTheme: this.darkTheme == null ? ThemeConfig.dark().theme : this.darkTheme,
|
||||
onGenerateRoute: onGenerateRoute,
|
||||
darkTheme: darkTheme ?? ThemeConfig.dark().theme,
|
||||
theme: themeData ?? ThemeProvider.themeOf(context).data,
|
||||
localeResolutionCallback:
|
||||
(Locale locale, Iterable<Locale> supportedLocales) {
|
||||
@ -95,7 +101,8 @@ class AppBuild extends StatelessWidget {
|
||||
},
|
||||
localizationsDelegates: NyLocalization.instance.delegates,
|
||||
locale: NyLocalization.instance.locale,
|
||||
supportedLocales: supportedLocales ?? NyLocalization.instance.locals(),
|
||||
supportedLocales:
|
||||
supportedLocales ?? NyLocalization.instance.locals(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -9,11 +9,16 @@ class BaseThemeConfig {
|
||||
final BaseColorStyles colors;
|
||||
final dynamic meta;
|
||||
|
||||
BaseThemeConfig({this.id, this.description, this.theme, this.colors, this.meta = const {}});
|
||||
BaseThemeConfig(
|
||||
{this.id,
|
||||
this.description,
|
||||
this.theme,
|
||||
this.colors,
|
||||
this.meta = const {}});
|
||||
|
||||
AppTheme toAppTheme({ThemeData defaultTheme}) => AppTheme(
|
||||
id: this.id,
|
||||
data: defaultTheme == null ? this.theme : defaultTheme,
|
||||
description: this.description,
|
||||
);
|
||||
}
|
||||
id: id,
|
||||
data: defaultTheme ?? theme,
|
||||
description: description,
|
||||
);
|
||||
}
|
||||
|
||||
@ -12,12 +12,12 @@ import 'package:wp_json_api/wp_json_api.dart';
|
||||
|
||||
/// boot application
|
||||
Future<void> boot() async {
|
||||
|
||||
await SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
]);
|
||||
|
||||
await WooSignal.instance.init(appKey: getEnv('APP_KEY'), debugMode: getEnv('APP_DEBUG'));
|
||||
await WooSignal.instance
|
||||
.init(appKey: getEnv('APP_KEY'), debugMode: getEnv('APP_DEBUG'));
|
||||
|
||||
// Notifications
|
||||
/// await Firebase.initializeApp(
|
||||
@ -78,7 +78,8 @@ Future<void> boot() async {
|
||||
);
|
||||
}
|
||||
|
||||
if (getEnv('DEFAULT_LOCALE', defaultValue: null) == null && wooSignalApp.locale != null) {
|
||||
if (getEnv('DEFAULT_LOCALE', defaultValue: null) == null &&
|
||||
wooSignalApp.locale != null) {
|
||||
locale = Locale(wooSignalApp.locale);
|
||||
} else {
|
||||
locale = Locale(envVal('DEFAULT_LOCALE', defaultValue: 'en'));
|
||||
@ -91,6 +92,5 @@ Future<void> boot() async {
|
||||
languageCode: locale.languageCode,
|
||||
languagesList: languagesList,
|
||||
assetsDirectory: assetsDirectory,
|
||||
valuesAsMap: valuesAsMap
|
||||
);
|
||||
}
|
||||
valuesAsMap: valuesAsMap);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -21,10 +21,11 @@ import 'package:woosignal/models/response/tax_rate.dart';
|
||||
import 'package:woosignal/models/response/woosignal_app.dart';
|
||||
|
||||
Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
|
||||
CheckoutSession checkoutSession = CheckoutSession.getInstance;
|
||||
OrderWC orderWC = OrderWC();
|
||||
WooSignalApp wooSignalApp = AppHelper.instance.appConfig;
|
||||
|
||||
String paymentMethodName = CheckoutSession.getInstance.paymentType.name ?? "";
|
||||
String paymentMethodName = checkoutSession.paymentType.name ?? "";
|
||||
|
||||
orderWC.paymentMethod = Platform.isAndroid
|
||||
? "$paymentMethodName - Android App"
|
||||
@ -40,7 +41,7 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
|
||||
|
||||
List<LineItems> lineItems = [];
|
||||
List<CartLineItem> cartItems = await Cart.getInstance.getCart();
|
||||
cartItems.forEach((cartItem) {
|
||||
for (var cartItem in cartItems) {
|
||||
LineItems tmpLineItem = LineItems();
|
||||
tmpLineItem.quantity = cartItem.quantity;
|
||||
tmpLineItem.name = cartItem.name;
|
||||
@ -51,11 +52,11 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
|
||||
|
||||
tmpLineItem.subtotal = cartItem.subtotal;
|
||||
lineItems.add(tmpLineItem);
|
||||
});
|
||||
}
|
||||
|
||||
orderWC.lineItems = lineItems;
|
||||
|
||||
BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails;
|
||||
BillingDetails billingDetails = checkoutSession.billingDetails;
|
||||
|
||||
Billing billing = Billing();
|
||||
billing.firstName = billingDetails.billingAddress.firstName;
|
||||
@ -88,7 +89,7 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
|
||||
orderWC.shippingLines = [];
|
||||
if (wooSignalApp.disableShipping != 1) {
|
||||
Map<String, dynamic> shippingLineFeeObj =
|
||||
CheckoutSession.getInstance.shippingType.toShippingLineFee();
|
||||
checkoutSession.shippingType.toShippingLineFee();
|
||||
if (shippingLineFeeObj != null) {
|
||||
ShippingLines shippingLine = ShippingLines();
|
||||
shippingLine.methodId = shippingLineFeeObj['method_id'];
|
||||
@ -108,5 +109,11 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
|
||||
orderWC.feeLines.add(feeLines);
|
||||
}
|
||||
|
||||
if (checkoutSession.coupon != null) {
|
||||
orderWC.couponLines = [];
|
||||
CouponLines couponLine = CouponLines(code: checkoutSession.coupon.code);
|
||||
orderWC.couponLines.add(couponLine);
|
||||
}
|
||||
|
||||
return orderWC;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -9,8 +9,8 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
enum SortByType {
|
||||
LowToHigh,
|
||||
HighToLow,
|
||||
NameAZ,
|
||||
NameZA,
|
||||
lowToHigh,
|
||||
highToLow,
|
||||
nameAZ,
|
||||
nameZA,
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -44,53 +44,70 @@ import 'package:woosignal/woosignal.dart';
|
||||
Future<User> getUser() async =>
|
||||
(await NyStorage.read<User>(SharedKey.authUser, model: User()));
|
||||
|
||||
appWooSignal(Function(WooSignal) api) async {
|
||||
Future appWooSignal(Function(WooSignal) api) async {
|
||||
return await api(WooSignal.instance);
|
||||
}
|
||||
|
||||
/// helper to find correct color from the [context].
|
||||
class ThemeColor {
|
||||
static BaseColorStyles get(BuildContext context) {
|
||||
return ((Theme.of(context).brightness == Brightness.light) ? ThemeConfig.light().colors : ThemeConfig.dark().colors);
|
||||
return ((Theme.of(context).brightness == Brightness.light)
|
||||
? ThemeConfig.light().colors
|
||||
: ThemeConfig.dark().colors);
|
||||
}
|
||||
}
|
||||
|
||||
/// helper to set colors on TextStyle
|
||||
extension ColorsHelper on TextStyle {
|
||||
TextStyle setColor(BuildContext context, Color Function(BaseColorStyles color) newColor) {
|
||||
return this.copyWith(color: newColor(ThemeColor.get(context)));
|
||||
TextStyle setColor(
|
||||
BuildContext context, Color Function(BaseColorStyles color) newColor) {
|
||||
return copyWith(color: newColor(ThemeColor.get(context)));
|
||||
}
|
||||
}
|
||||
|
||||
List<PaymentType> getPaymentTypes() {
|
||||
List<PaymentType> paymentTypes = [];
|
||||
app_payment_gateways.forEach((element) {
|
||||
if (paymentTypes.firstWhere((paymentType) => paymentType.name != element, orElse: () => null) == null) {
|
||||
paymentTypes.add(paymentTypeList.firstWhere((paymentTypeList) => paymentTypeList.name == element, orElse: () => null));
|
||||
for (var appPaymentGateway in app_payment_gateways) {
|
||||
if (paymentTypes.firstWhere(
|
||||
(paymentType) => paymentType.name != appPaymentGateway,
|
||||
orElse: () => null) ==
|
||||
null) {
|
||||
paymentTypes.add(paymentTypeList.firstWhere(
|
||||
(paymentTypeList) => paymentTypeList.name == appPaymentGateway,
|
||||
orElse: () => null));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!app_payment_gateways.contains('Stripe') && AppHelper.instance.appConfig.stripeEnabled == true) {
|
||||
paymentTypes.add(paymentTypeList.firstWhere((element) => element.name == "Stripe", orElse: () => null));
|
||||
if (!app_payment_gateways.contains('Stripe') &&
|
||||
AppHelper.instance.appConfig.stripeEnabled == true) {
|
||||
paymentTypes.add(paymentTypeList
|
||||
.firstWhere((element) => element.name == "Stripe", orElse: () => null));
|
||||
}
|
||||
if (!app_payment_gateways.contains('PayPal') && AppHelper.instance.appConfig.paypalEnabled == true) {
|
||||
paymentTypes.add(paymentTypeList.firstWhere((element) => element.name == "PayPal", orElse: () => null));
|
||||
if (!app_payment_gateways.contains('PayPal') &&
|
||||
AppHelper.instance.appConfig.paypalEnabled == true) {
|
||||
paymentTypes.add(paymentTypeList
|
||||
.firstWhere((element) => element.name == "PayPal", orElse: () => null));
|
||||
}
|
||||
if (!app_payment_gateways.contains('CashOnDelivery') && AppHelper.instance.appConfig.codEnabled == true) {
|
||||
paymentTypes.add(paymentTypeList.firstWhere((element) => element.name == "CashOnDelivery", orElse: () => null));
|
||||
if (!app_payment_gateways.contains('CashOnDelivery') &&
|
||||
AppHelper.instance.appConfig.codEnabled == true) {
|
||||
paymentTypes.add(paymentTypeList.firstWhere(
|
||||
(element) => element.name == "CashOnDelivery",
|
||||
orElse: () => null));
|
||||
}
|
||||
|
||||
return paymentTypes.where((v) => v != null).toList();
|
||||
}
|
||||
|
||||
dynamic envVal(String envVal, {dynamic defaultValue}) => (getEnv(envVal) == null ? defaultValue : getEnv(envVal));
|
||||
dynamic envVal(String envVal, {dynamic defaultValue}) =>
|
||||
(getEnv(envVal) == null ? defaultValue : getEnv(envVal));
|
||||
|
||||
PaymentType addPayment(
|
||||
{@required int id,
|
||||
@required String name,
|
||||
@required String desc,
|
||||
@required String assetImage,
|
||||
@required Function pay}) => PaymentType(
|
||||
@required Function pay}) =>
|
||||
PaymentType(
|
||||
id: id,
|
||||
name: name,
|
||||
desc: desc,
|
||||
@ -333,7 +350,7 @@ RegExp defaultRegex(
|
||||
String pattern, {
|
||||
bool strict,
|
||||
}) {
|
||||
return new RegExp(
|
||||
return RegExp(
|
||||
pattern,
|
||||
caseSensitive: strict ?? false,
|
||||
multiLine: false,
|
||||
@ -343,17 +360,10 @@ RegExp defaultRegex(
|
||||
bool isEmail(String em) {
|
||||
String p =
|
||||
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
|
||||
RegExp regExp = new RegExp(p);
|
||||
RegExp regExp = RegExp(p);
|
||||
return regExp.hasMatch(em);
|
||||
}
|
||||
|
||||
// 6 LENGTH, 1 DIGIT
|
||||
bool validPassword(String pw) {
|
||||
String p = r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,}$';
|
||||
RegExp regExp = new RegExp(p);
|
||||
return regExp.hasMatch(pw);
|
||||
}
|
||||
|
||||
navigatorPush(BuildContext context,
|
||||
{@required String routeName,
|
||||
Object arguments,
|
||||
@ -391,8 +401,7 @@ showPlatformAlertDialog(BuildContext context,
|
||||
List<PlatformDialogAction> actions,
|
||||
bool showDoneAction = true}) {
|
||||
if (showDoneAction) {
|
||||
actions
|
||||
.add(dialogAction(context, title: trans("Done"), action: () {
|
||||
actions.add(dialogAction(context, title: trans("Done"), action: () {
|
||||
Navigator.of(context).pop();
|
||||
}));
|
||||
}
|
||||
@ -422,22 +431,22 @@ String dateFormatted({@required String date, @required String formatType}) =>
|
||||
formatDateTime(formatType).format(parseDateTime(date));
|
||||
|
||||
enum FormatType {
|
||||
DateTime,
|
||||
Date,
|
||||
Time,
|
||||
dateTime,
|
||||
date,
|
||||
time,
|
||||
}
|
||||
|
||||
String formatForDateTime(FormatType formatType) {
|
||||
switch (formatType) {
|
||||
case FormatType.Date:
|
||||
case FormatType.date:
|
||||
{
|
||||
return "yyyy-MM-dd";
|
||||
}
|
||||
case FormatType.DateTime:
|
||||
case FormatType.dateTime:
|
||||
{
|
||||
return "dd-MM-yyyy hh:mm a";
|
||||
}
|
||||
case FormatType.Time:
|
||||
case FormatType.time:
|
||||
{
|
||||
return "hh:mm a";
|
||||
}
|
||||
@ -450,9 +459,6 @@ String formatForDateTime(FormatType formatType) {
|
||||
|
||||
double parseWcPrice(String price) => (double.tryParse(price ?? "0") ?? 0);
|
||||
|
||||
void appLogOutput(dynamic message) =>
|
||||
(getEnv('APP_DEBUG', defaultValue: true) ? NyLogger.debug(message) : null);
|
||||
|
||||
Widget refreshableScroll(context,
|
||||
{@required refreshController,
|
||||
@required VoidCallback onRefresh,
|
||||
@ -486,7 +492,7 @@ Widget refreshableScroll(context,
|
||||
controller: refreshController,
|
||||
onRefresh: onRefresh,
|
||||
onLoading: onLoading,
|
||||
child: (products.length != null && products.length > 0
|
||||
child: (products.length != null && products.isNotEmpty
|
||||
? StaggeredGridView.countBuilder(
|
||||
crossAxisCount: 2,
|
||||
itemCount: products.length,
|
||||
@ -494,13 +500,12 @@ Widget refreshableScroll(context,
|
||||
return Container(
|
||||
height: 200,
|
||||
child: ProductItemContainer(
|
||||
index: (index),
|
||||
product: products[index],
|
||||
onTap: onTap,
|
||||
),
|
||||
);
|
||||
},
|
||||
staggeredTileBuilder: (int index) => new StaggeredTile.fit(1),
|
||||
staggeredTileBuilder: (int index) => StaggeredTile.fit(1),
|
||||
mainAxisSpacing: 4.0,
|
||||
crossAxisSpacing: 4.0,
|
||||
)
|
||||
@ -538,3 +543,31 @@ Future<List<DefaultShipping>> getDefaultShipping(BuildContext context) async {
|
||||
String truncateString(String data, int length) {
|
||||
return (data.length >= length) ? '${data.substring(0, length)}...' : data;
|
||||
}
|
||||
|
||||
Future<List<dynamic>> getWishlistProducts() async {
|
||||
List<dynamic> favouriteProducts = [];
|
||||
String currentProductsJSON = await NyStorage.read(SharedKey.wishlistProducts);
|
||||
if (currentProductsJSON != null) {
|
||||
favouriteProducts =
|
||||
(jsonDecode(currentProductsJSON) as List<dynamic>).toList();
|
||||
}
|
||||
return favouriteProducts;
|
||||
}
|
||||
|
||||
saveWishlistProduct({@required Product product}) async {
|
||||
List<dynamic> products = await getWishlistProducts();
|
||||
if (products.any((wishListProduct) => wishListProduct['id'] == product.id) ==
|
||||
false) {
|
||||
products.add({"id": product.id});
|
||||
}
|
||||
String json = jsonEncode(products.map((i) => {"id": i['id']}).toList());
|
||||
await NyStorage.store(SharedKey.wishlistProducts, json);
|
||||
}
|
||||
|
||||
removeWishlistProduct({@required Product product}) async {
|
||||
List<dynamic> products = await getWishlistProducts();
|
||||
products.removeWhere((element) => element['id'] == product.id);
|
||||
|
||||
String json = jsonEncode(products.map((i) => {"id": i['id']}).toList());
|
||||
await NyStorage.store(SharedKey.wishlistProducts, json);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -13,4 +13,5 @@ class SharedKey {
|
||||
static const String cart = "CART_SESSION";
|
||||
static const String customerBillingDetails = "CS_BILLING_DETAILS";
|
||||
static const String customerShippingDetails = "CS_SHIPPING_DETAILS";
|
||||
static const String wishlistProducts = "CS_WISHLIST_PRODUCTS";
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@ -16,4 +16,4 @@ import 'package:google_fonts/google_fonts.dart';
|
||||
TextStyle appFont = GoogleFonts.poppins();
|
||||
|
||||
// e.g. custom font in pubspec.yaml - https://flutter.dev/docs/cookbook/design/fonts
|
||||
// final TextStyle appThemeFont = TextStyle(fontFamily: "ZenTokyoZoo");
|
||||
// final TextStyle appThemeFont = TextStyle(fontFamily: "ZenTokyoZoo");
|
||||
|
||||
@ -54,4 +54,4 @@ final String assetsDirectory = 'lang/';
|
||||
| the asset json files.
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
final Map<String, String> valuesAsMap = {};
|
||||
final Map<String, String> valuesAsMap = {};
|
||||
|
||||
@ -13,9 +13,7 @@ import 'package:flutter_app/resources/themes/styles/light_theme_colors.dart';
|
||||
|
||||
// App Themes
|
||||
final appThemes = [
|
||||
|
||||
ThemeConfig.light(),
|
||||
|
||||
ThemeConfig.dark(),
|
||||
];
|
||||
|
||||
@ -39,46 +37,45 @@ BaseColorStyles darkColors = DarkThemeColors();
|
||||
|
||||
// Preset Themes
|
||||
class ThemeConfig {
|
||||
|
||||
// LIGHT
|
||||
static BaseThemeConfig light() => BaseThemeConfig(
|
||||
id: "default_light_theme",
|
||||
description: "Light theme",
|
||||
theme: lightTheme(lightColors),
|
||||
colors: lightColors,
|
||||
);
|
||||
id: "default_light_theme",
|
||||
description: "Light theme",
|
||||
theme: lightTheme(lightColors),
|
||||
colors: lightColors,
|
||||
);
|
||||
|
||||
// DARK
|
||||
static BaseThemeConfig dark() => BaseThemeConfig(
|
||||
id: "default_dark_theme",
|
||||
description: "Dark theme",
|
||||
theme: darkTheme(darkColors),
|
||||
colors: darkColors,
|
||||
);
|
||||
id: "default_dark_theme",
|
||||
description: "Dark theme",
|
||||
theme: darkTheme(darkColors),
|
||||
colors: darkColors,
|
||||
);
|
||||
|
||||
// E.G. CUSTOM THEME
|
||||
/// Run: "flutter pub run nylo_framework:main make:theme bright_theme" // example bright_theme
|
||||
/// Run: "flutter pub run nylo_framework:main make:theme bright_theme" // example bright_theme
|
||||
// Creates a basic theme in /resources/themes/bright_theme.dart
|
||||
// Creates the themes colors in /resources/themes/styles/bright_theme_colors.dart
|
||||
|
||||
// First add the colors which was created into the above section like the following:
|
||||
// Bright Colors
|
||||
/// BaseColorStyles brightColors = BrightThemeColors();
|
||||
/// BaseColorStyles brightColors = BrightThemeColors();
|
||||
|
||||
// Next, uncomment the below:
|
||||
/// static BaseThemeConfig bright() => BaseThemeConfig(
|
||||
/// id: "default_bright_theme",
|
||||
/// description: "Bright theme",
|
||||
/// theme: brightTheme(brightColors),
|
||||
/// colors: brightColors,
|
||||
/// );
|
||||
/// static BaseThemeConfig bright() => BaseThemeConfig(
|
||||
/// id: "default_bright_theme",
|
||||
/// description: "Bright theme",
|
||||
/// theme: brightTheme(brightColors),
|
||||
/// colors: brightColors,
|
||||
/// );
|
||||
|
||||
// To then use this theme, add it to the [appThemes] above like the following:
|
||||
// final appThemes = [
|
||||
/// ThemeConfig.bright(), // new theme
|
||||
/// ThemeConfig.bright(), // new theme
|
||||
//
|
||||
// ThemeConfig.light(),
|
||||
//
|
||||
// ThemeConfig.dark(),
|
||||
// ];
|
||||
}
|
||||
}
|
||||
|
||||
20
LabelStoreMax/lib/generated_plugin_registrant.dart
Normal file
20
LabelStoreMax/lib/generated_plugin_registrant.dart
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// ignore_for_file: directives_ordering
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:flutter_secure_storage_web/flutter_secure_storage_web.dart';
|
||||
import 'package:shared_preferences_web/shared_preferences_web.dart';
|
||||
import 'package:url_launcher_web/url_launcher_web.dart';
|
||||
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
|
||||
// ignore: public_member_api_docs
|
||||
void registerPlugins(Registrar registrar) {
|
||||
FlutterSecureStorageWeb.registerWith(registrar);
|
||||
SharedPreferencesPlugin.registerWith(registrar);
|
||||
UrlLauncherPlugin.registerWith(registrar);
|
||||
registrar.registerMessageHandler();
|
||||
}
|
||||
@ -9,7 +9,9 @@ void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
Nylo nylo = await Nylo.init(router: appRouter(), setup: boot);
|
||||
|
||||
String initialRoute = AppHelper.instance.appConfig.appStatus != null ? '/home' : '/no-connection';
|
||||
String initialRoute = AppHelper.instance.appConfig.appStatus != null
|
||||
? '/home'
|
||||
: '/no-connection';
|
||||
|
||||
runApp(
|
||||
AppBuild(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -32,7 +32,7 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
|
||||
_AccountBillingDetailsPageState();
|
||||
|
||||
// BILLING TEXT CONTROLLERS
|
||||
TextEditingController _txtShippingFirstName = TextEditingController(),
|
||||
final TextEditingController _txtShippingFirstName = TextEditingController(),
|
||||
_txtShippingLastName = TextEditingController(),
|
||||
_txtShippingAddressLine = TextEditingController(),
|
||||
_txtShippingCity = TextEditingController(),
|
||||
@ -71,18 +71,15 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
trans("Billing Details")
|
||||
),
|
||||
title: Text(trans("Billing Details")),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeAreaWidget(
|
||||
child: GestureDetector(
|
||||
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
|
||||
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
|
||||
child: _isLoading
|
||||
? AppLoaderWidget()
|
||||
: LayoutBuilder(
|
||||
@ -160,8 +157,10 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeColor.get(context).surfaceBackground,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
boxShadow: (Theme.of(context).brightness ==
|
||||
Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
),
|
||||
padding: EdgeInsets.all(8),
|
||||
),
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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:bubble_tab_indicator/bubble_tab_indicator.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/controllers/customer_orders_loader_controller.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';
|
||||
@ -33,15 +33,14 @@ class AccountDetailPage extends StatefulWidget {
|
||||
|
||||
class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
RefreshController _refreshController =
|
||||
final RefreshController _refreshController =
|
||||
RefreshController(initialRefresh: false);
|
||||
bool _shouldStopRequests = false,
|
||||
waitForNextRequest = false,
|
||||
_isLoading = true,
|
||||
_isLoadingOrders = true;
|
||||
final CustomerOrdersLoaderController _customerOrdersLoaderController =
|
||||
CustomerOrdersLoaderController();
|
||||
|
||||
int _page = 1, _currentTabIndex = 0;
|
||||
List<Order> _orders = [];
|
||||
bool _shouldStopRequests = false, _isLoading = true, _isLoadingOrders = true;
|
||||
|
||||
int _currentTabIndex = 0;
|
||||
WCCustomerInfoResponse _wcCustomerInfoResponse;
|
||||
Widget _activeBody;
|
||||
|
||||
@ -51,20 +50,18 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_page = 1;
|
||||
_orders = [];
|
||||
_tabs = [
|
||||
new Tab(text: ""),
|
||||
new Tab(text: ""),
|
||||
Tab(text: ""),
|
||||
Tab(text: ""),
|
||||
];
|
||||
_tabController = TabController(vsync: this, length: _tabs.length);
|
||||
_activeBody = AppLoaderWidget();
|
||||
this.init();
|
||||
init();
|
||||
}
|
||||
|
||||
init() async {
|
||||
await _fetchWpUserData();
|
||||
await _fetchOrders();
|
||||
await fetchOrders();
|
||||
}
|
||||
|
||||
_fetchWpUserData() async {
|
||||
@ -98,22 +95,22 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_tabs = [
|
||||
new Tab(text: trans("Orders")),
|
||||
new Tab(text: trans("Settings")),
|
||||
Tab(text: trans("Orders")),
|
||||
Tab(text: trans("Settings")),
|
||||
];
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: widget.showLeadingBackButton ? Container(
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
margin: EdgeInsets.only(left: 0),
|
||||
) : Container(),
|
||||
title: Text(
|
||||
trans("Account")
|
||||
),
|
||||
leading: widget.showLeadingBackButton
|
||||
? Container(
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
margin: EdgeInsets.only(left: 0),
|
||||
)
|
||||
: Container(),
|
||||
title: Text(trans("Account")),
|
||||
centerTitle: true,
|
||||
),
|
||||
resizeToAvoidBottomInset: false,
|
||||
@ -191,7 +188,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
labelColor: Colors.white,
|
||||
unselectedLabelColor: Colors.black87,
|
||||
indicator: new BubbleTabIndicator(
|
||||
indicator: BubbleTabIndicator(
|
||||
indicatorHeight: 25.0,
|
||||
indicatorColor: Colors.black87,
|
||||
tabBarIndicatorSize: TabBarIndicatorSize.tab,
|
||||
@ -204,7 +201,10 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: (Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
color: ThemeColor.get(context).backgroundContainer,
|
||||
),
|
||||
),
|
||||
@ -275,38 +275,34 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
_fetchOrders() async {
|
||||
fetchOrders() async {
|
||||
String userId = await readUserId();
|
||||
|
||||
if (userId == null || _shouldStopRequests == true) {
|
||||
if (userId == null) {
|
||||
setState(() {
|
||||
_isLoadingOrders = false;
|
||||
_activeBody = _widgetOrders();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
List<Order> orders = await appWooSignal((api) =>
|
||||
api.getOrders(customer: int.parse(userId), page: _page, perPage: 50));
|
||||
|
||||
if (orders.length <= 0) {
|
||||
setState(() {
|
||||
_isLoadingOrders = false;
|
||||
_shouldStopRequests = true;
|
||||
_activeBody = _widgetOrders();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_page += 1;
|
||||
_orders.addAll(orders);
|
||||
_isLoadingOrders = false;
|
||||
_activeBody = _widgetOrders();
|
||||
});
|
||||
await _customerOrdersLoaderController.loadOrders(
|
||||
hasResults: (result) {
|
||||
if (result == false) {
|
||||
_isLoadingOrders = false;
|
||||
_shouldStopRequests = true;
|
||||
_activeBody = _widgetOrders();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
didFinish: () => setState(() {
|
||||
_isLoadingOrders = false;
|
||||
_activeBody = _widgetOrders();
|
||||
}),
|
||||
userId: userId);
|
||||
}
|
||||
|
||||
Widget _widgetOrders() {
|
||||
List<Order> orders = _customerOrdersLoaderController.getResults();
|
||||
return _isLoadingOrders
|
||||
? AppLoaderWidget()
|
||||
: SmartRefresher(
|
||||
@ -335,9 +331,10 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
controller: _refreshController,
|
||||
onRefresh: _onRefresh,
|
||||
onLoading: _onLoading,
|
||||
child: (_orders.length > 0
|
||||
child: (orders.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemBuilder: (cxt, i) {
|
||||
Order order = orders[i];
|
||||
return Card(
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.only(
|
||||
@ -356,12 +353,12 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"#${_orders[i].id.toString()}",
|
||||
"#${order.id.toString()}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Text(
|
||||
_orders[i].status.capitalize(),
|
||||
order.status.capitalize(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@ -379,8 +376,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
formatStringCurrency(
|
||||
total: _orders[i].total),
|
||||
formatStringCurrency(total: order.total),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2
|
||||
@ -389,7 +385,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
Text(
|
||||
_orders[i].lineItems.length.toString() +
|
||||
order.lineItems.length.toString() +
|
||||
" " +
|
||||
trans("items"),
|
||||
style: Theme.of(context)
|
||||
@ -403,15 +399,15 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
),
|
||||
Text(
|
||||
dateFormatted(
|
||||
date: _orders[i].dateCreated,
|
||||
date: order.dateCreated,
|
||||
formatType:
|
||||
formatForDateTime(FormatType.Date),
|
||||
formatForDateTime(FormatType.date),
|
||||
) +
|
||||
"\n" +
|
||||
dateFormatted(
|
||||
date: _orders[i].dateCreated,
|
||||
date: order.dateCreated,
|
||||
formatType:
|
||||
formatForDateTime(FormatType.Time),
|
||||
formatForDateTime(FormatType.time),
|
||||
),
|
||||
textAlign: TextAlign.right,
|
||||
style: Theme.of(context)
|
||||
@ -434,7 +430,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: _orders.length,
|
||||
itemCount: orders.length,
|
||||
)
|
||||
: Center(
|
||||
child: Column(
|
||||
@ -456,16 +452,15 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
}
|
||||
|
||||
void _onRefresh() async {
|
||||
_orders = [];
|
||||
_page = 1;
|
||||
_customerOrdersLoaderController.clear();
|
||||
_shouldStopRequests = false;
|
||||
waitForNextRequest = false;
|
||||
await _fetchOrders();
|
||||
|
||||
await fetchOrders();
|
||||
_refreshController.refreshCompleted();
|
||||
}
|
||||
|
||||
void _onLoading() async {
|
||||
await _fetchOrders();
|
||||
await fetchOrders();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
@ -480,6 +475,6 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
_viewProfileDetail(int i) => Navigator.pushNamed(
|
||||
context,
|
||||
"/account-order-detail",
|
||||
arguments: _orders[i].id,
|
||||
arguments: _customerOrdersLoaderController.getResults()[i].id,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -33,7 +33,7 @@ class AccountLandingPage extends StatefulWidget {
|
||||
|
||||
class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
bool _hasTappedLogin = false;
|
||||
TextEditingController _tfEmailController = TextEditingController(),
|
||||
final TextEditingController _tfEmailController = TextEditingController(),
|
||||
_tfPasswordController = TextEditingController();
|
||||
|
||||
@override
|
||||
@ -75,7 +75,10 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: (Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
color: ThemeColor.get(context).backgroundContainer,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(vertical: 18, horizontal: 8),
|
||||
@ -110,8 +113,9 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.account_circle,
|
||||
color:
|
||||
(Theme.of(context).brightness == Brightness.light) ? Colors.black38 : Colors.white70,
|
||||
color: (Theme.of(context).brightness == Brightness.light)
|
||||
? Colors.black38
|
||||
: Colors.white70,
|
||||
),
|
||||
Padding(
|
||||
child: Text(
|
||||
@ -137,16 +141,19 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
"No URL found for \"forgot password\".\nAdd your forgot password URL here https://woosignal.com/dashboard/apps");
|
||||
}
|
||||
}),
|
||||
widget.showBackButton ? Column(
|
||||
children: [
|
||||
Divider(),
|
||||
LinkButton(
|
||||
title: trans("Back"),
|
||||
action: () => Navigator.pop(context),
|
||||
),
|
||||
],
|
||||
) : Padding(padding: EdgeInsets.only(bottom: 20),)
|
||||
|
||||
widget.showBackButton
|
||||
? Column(
|
||||
children: [
|
||||
Divider(),
|
||||
LinkButton(
|
||||
title: trans("Back"),
|
||||
action: () => Navigator.pop(context),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(bottom: 20),
|
||||
)
|
||||
].where((element) => element != null).toList(),
|
||||
),
|
||||
),
|
||||
@ -164,8 +171,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
if (email == "" || password == "") {
|
||||
showToastNotification(context,
|
||||
title: trans("Invalid details"),
|
||||
description:
|
||||
trans("The email and password field cannot be empty"),
|
||||
description: trans("The email and password field cannot be empty"),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
return;
|
||||
}
|
||||
@ -190,25 +196,23 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
} on InvalidNonceException catch (_) {
|
||||
showToastNotification(context,
|
||||
title: trans("Invalid details"),
|
||||
description: trans("Something went wrong, please contact our store"),
|
||||
description:
|
||||
trans("Something went wrong, please contact our store"),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
} on InvalidEmailException catch (_) {
|
||||
showToastNotification(context,
|
||||
title: trans("Invalid details"),
|
||||
description:
|
||||
trans("That email does not match our records"),
|
||||
description: trans("That email does not match our records"),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
} on InvalidUsernameException catch (_) {
|
||||
showToastNotification(context,
|
||||
title: trans("Invalid details"),
|
||||
description:
|
||||
trans("That username does not match our records"),
|
||||
description: trans("That username does not match our records"),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
} on IncorrectPasswordException catch (_) {
|
||||
showToastNotification(context,
|
||||
title: trans("Invalid details"),
|
||||
description:
|
||||
trans("That password does not match our records"),
|
||||
description: trans("That password does not match our records"),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
} on Exception catch (_) {
|
||||
showToastNotification(context,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -43,7 +43,6 @@ class _AccountOrderDetailPageState extends NyState<AccountOrderDetailPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: Container(
|
||||
@ -53,9 +52,7 @@ class _AccountOrderDetailPageState extends NyState<AccountOrderDetailPage> {
|
||||
),
|
||||
margin: EdgeInsets.only(left: 0),
|
||||
),
|
||||
title: Text(
|
||||
"${trans("Order").capitalize()} #${_orderId.toString()}"
|
||||
),
|
||||
title: Text("${trans("Order").capitalize()} #${_orderId.toString()}"),
|
||||
centerTitle: true,
|
||||
),
|
||||
resizeToAvoidBottomInset: false,
|
||||
@ -66,10 +63,13 @@ class _AccountOrderDetailPageState extends NyState<AccountOrderDetailPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text("${trans("Date Ordered").capitalize()}: " +
|
||||
dateFormatted(
|
||||
Text(
|
||||
"${trans("Date Ordered").capitalize()}: " +
|
||||
dateFormatted(
|
||||
date: _order.dateCreated,
|
||||
formatType: formatForDateTime(FormatType.Date))),
|
||||
formatType: formatForDateTime(FormatType.date),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 10, bottom: 10),
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
@ -78,8 +78,7 @@ class _AccountOrderDetailPageState extends NyState<AccountOrderDetailPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Text(
|
||||
"${trans("Ships to").capitalize()}:"),
|
||||
child: Text("${trans("Ships to").capitalize()}:"),
|
||||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
@ -106,7 +105,9 @@ class _AccountOrderDetailPageState extends NyState<AccountOrderDetailPage> {
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
color: (Theme.of(context).brightness == Brightness.light)
|
||||
? Colors.white
|
||||
: Color(0xFF2C2C2C),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -30,7 +30,7 @@ class _AccountProfileUpdatePageState extends State<AccountProfileUpdatePage> {
|
||||
_AccountProfileUpdatePageState();
|
||||
|
||||
bool isLoading = true;
|
||||
TextEditingController _tfFirstName = TextEditingController(),
|
||||
final TextEditingController _tfFirstName = TextEditingController(),
|
||||
_tfLastName = TextEditingController();
|
||||
|
||||
@override
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
@ -42,12 +41,13 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
_AccountRegistrationPageState();
|
||||
|
||||
bool _hasTappedRegister = false;
|
||||
TextEditingController _tfEmailAddressController = TextEditingController(),
|
||||
final TextEditingController _tfEmailAddressController =
|
||||
TextEditingController(),
|
||||
_tfPasswordController = TextEditingController(),
|
||||
_tfFirstNameController = TextEditingController(),
|
||||
_tfLastNameController = TextEditingController();
|
||||
|
||||
WooSignalApp _wooSignalApp = AppHelper.instance.appConfig;
|
||||
final WooSignalApp _wooSignalApp = AppHelper.instance.appConfig;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -56,16 +56,13 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.close),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: Text(
|
||||
trans("Register")
|
||||
),
|
||||
title: Text(trans("Register")),
|
||||
centerTitle: true,
|
||||
),
|
||||
resizeToAvoidBottomInset: false,
|
||||
@ -129,9 +126,10 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
style: TextStyle(
|
||||
color: (Theme.of(context).brightness == Brightness.light)
|
||||
? Colors.black45
|
||||
: Colors.white70),
|
||||
color:
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? Colors.black45
|
||||
: Colors.white70),
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
@ -177,7 +175,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
});
|
||||
|
||||
String username =
|
||||
(email.replaceAll(new RegExp(r'([@.])'), "")) + _randomStr(4);
|
||||
(email.replaceAll(RegExp(r'([@.])'), "")) + _randomStr(4);
|
||||
|
||||
WPUserRegisterResponse wpUserRegisterResponse;
|
||||
try {
|
||||
@ -196,7 +194,8 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
} on InvalidNonceException catch (_) {
|
||||
showToastNotification(context,
|
||||
title: trans("Invalid details"),
|
||||
description: trans("Something went wrong, please contact our store"),
|
||||
description:
|
||||
trans("Something went wrong, please contact our store"),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
} on ExistingUserLoginException catch (_) {
|
||||
showToastNotification(context,
|
||||
@ -257,11 +256,9 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
subtitle: trans("View Terms and Conditions or Privacy policy"),
|
||||
actions: [
|
||||
dialogAction(context,
|
||||
title: trans("Terms and Conditions"),
|
||||
action: _viewTermsConditions),
|
||||
title: trans("Terms and Conditions"), action: _viewTermsConditions),
|
||||
dialogAction(context,
|
||||
title: trans("Privacy Policy"),
|
||||
action: _viewPrivacyPolicy),
|
||||
title: trans("Privacy Policy"), action: _viewPrivacyPolicy),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -33,7 +33,7 @@ class _AccountShippingDetailsPageState
|
||||
_AccountShippingDetailsPageState();
|
||||
|
||||
// BILLING TEXT CONTROLLERS
|
||||
TextEditingController _txtShippingFirstName = TextEditingController(),
|
||||
final TextEditingController _txtShippingFirstName = TextEditingController(),
|
||||
_txtShippingLastName = TextEditingController(),
|
||||
_txtShippingAddressLine = TextEditingController(),
|
||||
_txtShippingCity = TextEditingController(),
|
||||
@ -87,19 +87,16 @@ class _AccountShippingDetailsPageState
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
trans("Shipping Details")
|
||||
),
|
||||
title: Text(trans("Shipping Details")),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeAreaWidget(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
FocusScope.of(context).requestFocus(new FocusNode());
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
},
|
||||
child: _isLoading
|
||||
? AppLoaderWidget()
|
||||
@ -177,8 +174,10 @@ class _AccountShippingDetailsPageState
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeColor.get(context).surfaceBackground,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
boxShadow: (Theme.of(context).brightness ==
|
||||
Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
),
|
||||
padding: EdgeInsets.all(8),
|
||||
),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -9,6 +9,7 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/controllers/product_category_search_loader_controller.dart';
|
||||
import 'package:flutter_app/app/controllers/browse_category_controller.dart';
|
||||
import 'package:flutter_app/bootstrap/enums/sort_enums.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
@ -21,7 +22,7 @@ import 'package:nylo_support/widgets/ny_state.dart';
|
||||
import 'package:nylo_support/widgets/ny_stateful_widget.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:woosignal/models/response/product_category.dart';
|
||||
import 'package:woosignal/models/response/products.dart' as WS;
|
||||
import 'package:woosignal/models/response/products.dart' as ws_product;
|
||||
|
||||
class BrowseCategoryPage extends NyStatefulWidget {
|
||||
final BrowseCategoryController controller = BrowseCategoryController();
|
||||
@ -35,51 +36,20 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
|
||||
ProductCategory productCategory;
|
||||
_BrowseCategoryPageState();
|
||||
|
||||
List<WS.Product> _products = [];
|
||||
RefreshController _refreshController =
|
||||
final RefreshController _refreshController =
|
||||
RefreshController(initialRefresh: false);
|
||||
final ProductCategorySearchLoaderController
|
||||
_productCategorySearchLoaderController =
|
||||
ProductCategorySearchLoaderController();
|
||||
|
||||
int _page = 1;
|
||||
bool _shouldStopRequests = false,
|
||||
waitForNextRequest = false,
|
||||
_isLoading = true;
|
||||
bool _shouldStopRequests = false;
|
||||
bool _isLoading = true;
|
||||
|
||||
@override
|
||||
widgetDidLoad() async {
|
||||
super.widgetDidLoad();
|
||||
this.productCategory = widget.controller.data();
|
||||
await _fetchMoreProducts();
|
||||
}
|
||||
|
||||
_fetchMoreProducts() async {
|
||||
if (waitForNextRequest || _shouldStopRequests) {
|
||||
return;
|
||||
}
|
||||
waitForNextRequest = true;
|
||||
List<WS.Product> products = await appWooSignal(
|
||||
(api) => api.getProducts(
|
||||
perPage: 50,
|
||||
category: productCategory.id.toString(),
|
||||
page: _page,
|
||||
status: "publish",
|
||||
stockStatus: "instock"),
|
||||
);
|
||||
|
||||
if (products.length == 0) {
|
||||
_shouldStopRequests = true;
|
||||
_isLoading = false;
|
||||
setState(() {});
|
||||
return;
|
||||
} else {
|
||||
_products.addAll(products);
|
||||
}
|
||||
|
||||
waitForNextRequest = false;
|
||||
_page = _page + 1;
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
productCategory = widget.controller.data();
|
||||
await fetchProducts();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -95,8 +65,7 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(trans("Browse"),
|
||||
style: Theme.of(context).textTheme.subtitle1),
|
||||
Text(trans("Browse"), style: Theme.of(context).textTheme.subtitle1),
|
||||
Text(parseHtmlString(productCategory.name))
|
||||
],
|
||||
),
|
||||
@ -117,23 +86,22 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
|
||||
refreshController: _refreshController,
|
||||
onRefresh: _onRefresh,
|
||||
onLoading: _onLoading,
|
||||
products: _products,
|
||||
products: _productCategorySearchLoaderController.getResults(),
|
||||
onTap: _showProduct),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onRefresh() async {
|
||||
_products = [];
|
||||
_page = 1;
|
||||
_productCategorySearchLoaderController.clear();
|
||||
_shouldStopRequests = false;
|
||||
waitForNextRequest = false;
|
||||
await _fetchMoreProducts();
|
||||
|
||||
await fetchProducts();
|
||||
_refreshController.refreshCompleted();
|
||||
}
|
||||
|
||||
void _onLoading() async {
|
||||
await _fetchMoreProducts();
|
||||
await fetchProducts();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
@ -146,26 +114,28 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
|
||||
}
|
||||
|
||||
_sortProducts({@required SortByType by}) {
|
||||
List<ws_product.Product> products =
|
||||
_productCategorySearchLoaderController.getResults();
|
||||
switch (by) {
|
||||
case SortByType.LowToHigh:
|
||||
_products.sort(
|
||||
case SortByType.lowToHigh:
|
||||
products.sort(
|
||||
(product1, product2) => (parseWcPrice(product1.price))
|
||||
.compareTo((parseWcPrice(product2.price))),
|
||||
);
|
||||
break;
|
||||
case SortByType.HighToLow:
|
||||
_products.sort(
|
||||
case SortByType.highToLow:
|
||||
products.sort(
|
||||
(product1, product2) => (parseWcPrice(product2.price))
|
||||
.compareTo((parseWcPrice(product1.price))),
|
||||
);
|
||||
break;
|
||||
case SortByType.NameAZ:
|
||||
_products.sort(
|
||||
case SortByType.nameAZ:
|
||||
products.sort(
|
||||
(product1, product2) => product1.name.compareTo(product2.name),
|
||||
);
|
||||
break;
|
||||
case SortByType.NameZA:
|
||||
_products.sort(
|
||||
case SortByType.nameZA:
|
||||
products.sort(
|
||||
(product1, product2) => product2.name.compareTo(product1.name),
|
||||
);
|
||||
break;
|
||||
@ -183,28 +153,28 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
|
||||
children: <Widget>[
|
||||
LinkButton(
|
||||
title: trans("Sort: Low to high"),
|
||||
action: () => _sortProducts(by: SortByType.LowToHigh),
|
||||
action: () => _sortProducts(by: SortByType.lowToHigh),
|
||||
),
|
||||
Divider(
|
||||
height: 0,
|
||||
),
|
||||
LinkButton(
|
||||
title: trans("Sort: High to low"),
|
||||
action: () => _sortProducts(by: SortByType.HighToLow),
|
||||
action: () => _sortProducts(by: SortByType.highToLow),
|
||||
),
|
||||
Divider(
|
||||
height: 0,
|
||||
),
|
||||
LinkButton(
|
||||
title: trans("Sort: Name A-Z"),
|
||||
action: () => _sortProducts(by: SortByType.NameAZ),
|
||||
action: () => _sortProducts(by: SortByType.nameAZ),
|
||||
),
|
||||
Divider(
|
||||
height: 0,
|
||||
),
|
||||
LinkButton(
|
||||
title: trans("Sort: Name Z-A"),
|
||||
action: () => _sortProducts(by: SortByType.NameZA),
|
||||
action: () => _sortProducts(by: SortByType.nameZA),
|
||||
),
|
||||
Divider(
|
||||
height: 0,
|
||||
@ -215,11 +185,28 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
|
||||
);
|
||||
}
|
||||
|
||||
_dismissModal() {
|
||||
Navigator.pop(context);
|
||||
Future fetchProducts() async {
|
||||
await _productCategorySearchLoaderController.loadProducts(
|
||||
hasResults: (result) {
|
||||
if (result == false) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_shouldStopRequests = true;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
didFinish: () => setState(() {
|
||||
_isLoading = false;
|
||||
}),
|
||||
productCategory: productCategory,
|
||||
);
|
||||
}
|
||||
|
||||
_showProduct(WS.Product product) {
|
||||
_dismissModal() => Navigator.pop(context);
|
||||
|
||||
_showProduct(ws_product.Product product) {
|
||||
Navigator.pushNamed(context, "/product-detail", arguments: product);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/controllers/browse_search_controller.dart';
|
||||
import 'package:flutter_app/app/controllers/product_search_loader_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';
|
||||
@ -17,7 +18,7 @@ import 'package:nylo_support/helpers/helper.dart';
|
||||
import 'package:nylo_support/widgets/ny_state.dart';
|
||||
import 'package:nylo_support/widgets/ny_stateful_widget.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:woosignal/models/response/products.dart' as WS;
|
||||
import 'package:woosignal/models/response/products.dart' as ws_product;
|
||||
|
||||
class BrowseSearchPage extends NyStatefulWidget {
|
||||
final BrowseSearchController controller = BrowseSearchController();
|
||||
@ -28,54 +29,19 @@ class BrowseSearchPage extends NyStatefulWidget {
|
||||
}
|
||||
|
||||
class _BrowseSearchState extends NyState<BrowseSearchPage> {
|
||||
RefreshController _refreshController =
|
||||
final RefreshController _refreshController =
|
||||
RefreshController(initialRefresh: false);
|
||||
final ProductSearchLoaderController _productSearchLoaderController =
|
||||
ProductSearchLoaderController();
|
||||
|
||||
List<WS.Product> _products = [];
|
||||
String _search;
|
||||
int _page = 1;
|
||||
bool _shouldStopRequests = false,
|
||||
waitForNextRequest = false,
|
||||
_isLoading = true;
|
||||
bool _shouldStopRequests = false, _isLoading = true;
|
||||
|
||||
@override
|
||||
widgetDidLoad() async {
|
||||
super.widgetDidLoad();
|
||||
_search = widget.controller.data();
|
||||
await _fetchProductsForSearch();
|
||||
}
|
||||
|
||||
_fetchProductsForSearch() async {
|
||||
if (waitForNextRequest || _shouldStopRequests) {
|
||||
return;
|
||||
}
|
||||
waitForNextRequest = true;
|
||||
|
||||
List<WS.Product> products = await appWooSignal(
|
||||
(api) => api.getProducts(
|
||||
perPage: 100,
|
||||
search: _search,
|
||||
page: _page,
|
||||
status: "publish",
|
||||
stockStatus: "instock",
|
||||
),
|
||||
);
|
||||
|
||||
if (products.length == 0) {
|
||||
_shouldStopRequests = true;
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
_products.addAll(products);
|
||||
}
|
||||
waitForNextRequest = false;
|
||||
_page = _page + 1;
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
await fetchProducts();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -103,27 +69,28 @@ class _BrowseSearchState extends NyState<BrowseSearchPage> {
|
||||
? Center(
|
||||
child: AppLoaderWidget(),
|
||||
)
|
||||
: refreshableScroll(context,
|
||||
: refreshableScroll(
|
||||
context,
|
||||
refreshController: _refreshController,
|
||||
onRefresh: _onRefresh,
|
||||
onLoading: _onLoading,
|
||||
products: _products,
|
||||
onTap: _showProduct),
|
||||
products: _productSearchLoaderController.getResults(),
|
||||
onTap: _showProduct,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onRefresh() async {
|
||||
_products = [];
|
||||
_page = 1;
|
||||
_productSearchLoaderController.clear();
|
||||
_shouldStopRequests = false;
|
||||
waitForNextRequest = false;
|
||||
await _fetchProductsForSearch();
|
||||
|
||||
await fetchProducts();
|
||||
_refreshController.refreshCompleted();
|
||||
}
|
||||
|
||||
void _onLoading() async {
|
||||
await _fetchProductsForSearch();
|
||||
await fetchProducts();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
@ -135,7 +102,26 @@ class _BrowseSearchState extends NyState<BrowseSearchPage> {
|
||||
}
|
||||
}
|
||||
|
||||
_showProduct(WS.Product product) {
|
||||
Future fetchProducts() async {
|
||||
await _productSearchLoaderController.loadProducts(
|
||||
hasResults: (result) {
|
||||
if (result == false) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_shouldStopRequests = true;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
didFinish: () => setState(() {
|
||||
_isLoading = false;
|
||||
}),
|
||||
search: _search,
|
||||
);
|
||||
}
|
||||
|
||||
_showProduct(ws_product.Product product) {
|
||||
Navigator.pushNamed(context, "/product-detail", arguments: product);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -40,11 +40,12 @@ class _CartPageState extends State<CartPage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_cartCheck();
|
||||
CheckoutSession.getInstance.coupon = null;
|
||||
}
|
||||
|
||||
_cartCheck() async {
|
||||
List<CartLineItem> cart = await Cart.getInstance.getCart();
|
||||
if (cart.length == 0) {
|
||||
if (cart.isEmpty) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_isCartEmpty = true;
|
||||
@ -56,7 +57,7 @@ class _CartPageState extends State<CartPage> {
|
||||
|
||||
List<dynamic> cartRes =
|
||||
await appWooSignal((api) => api.cartCheck(cartJSON));
|
||||
if (cartRes.length == 0) {
|
||||
if (cartRes.isEmpty) {
|
||||
Cart.getInstance.saveCartToPref(cartLineItems: []);
|
||||
setState(() {
|
||||
_isCartEmpty = true;
|
||||
@ -65,7 +66,7 @@ class _CartPageState extends State<CartPage> {
|
||||
return;
|
||||
}
|
||||
_cartLines = cartRes.map((json) => CartLineItem.fromJson(json)).toList();
|
||||
if (_cartLines.length > 0) {
|
||||
if (_cartLines.isNotEmpty) {
|
||||
Cart.getInstance.saveCartToPref(cartLineItems: _cartLines);
|
||||
}
|
||||
setState(() {
|
||||
@ -80,7 +81,7 @@ class _CartPageState extends State<CartPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cartLineItems.length == 0) {
|
||||
if (cartLineItems.isEmpty) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Cart"),
|
||||
@ -162,7 +163,7 @@ class _CartPageState extends State<CartPage> {
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
icon: Icons.remove_shopping_cart,
|
||||
);
|
||||
if (_cartLines.length == 0) {
|
||||
if (_cartLines.isEmpty) {
|
||||
_isCartEmpty = true;
|
||||
}
|
||||
setState(() {});
|
||||
@ -272,16 +273,17 @@ class _CartPageState extends State<CartPage> {
|
||||
case ConnectionState.waiting:
|
||||
return Text("");
|
||||
default:
|
||||
if (snapshot.hasError)
|
||||
if (snapshot.hasError) {
|
||||
return Text("");
|
||||
else
|
||||
return new Padding(
|
||||
} else {
|
||||
return Padding(
|
||||
child: TextRowWidget(
|
||||
title: trans("Total"),
|
||||
text: (_isLoading ? "" : snapshot.data),
|
||||
),
|
||||
padding: EdgeInsets.only(bottom: 15, top: 15),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -11,12 +11,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/models/cart.dart';
|
||||
import 'package:flutter_app/app/models/checkout_session.dart';
|
||||
import 'package:flutter_app/app/models/customer_address.dart';
|
||||
import 'package:flutter_app/app/models/customer_country.dart';
|
||||
import 'package:flutter_app/app/models/payment_type.dart';
|
||||
import 'package:flutter_app/bootstrap/app_helper.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.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/checkout_coupon_amount_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/checkout_payment_type_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/checkout_select_coupon_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/checkout_shipping_type_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/checkout_store_heading_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/checkout_user_details_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';
|
||||
@ -36,17 +42,18 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
|
||||
bool _showFullLoader = true, _isProcessingPayment = false;
|
||||
|
||||
List<TaxRate> _taxRates = [];
|
||||
final List<TaxRate> _taxRates = [];
|
||||
TaxRate _taxRate;
|
||||
final WooSignalApp _wooSignalApp = AppHelper.instance.appConfig;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
CheckoutSession.getInstance.coupon = null;
|
||||
List<PaymentType> paymentTypes = getPaymentTypes();
|
||||
if (CheckoutSession.getInstance.paymentType == null &&
|
||||
getPaymentTypes().length > 0) {
|
||||
CheckoutSession.getInstance.paymentType = getPaymentTypes().first;
|
||||
paymentTypes.isNotEmpty) {
|
||||
CheckoutSession.getInstance.paymentType = paymentTypes.first;
|
||||
}
|
||||
_getTaxes();
|
||||
}
|
||||
@ -64,7 +71,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
List<TaxRate> tmpTaxRates = await appWooSignal(
|
||||
(api) => api.getTaxRates(page: pageIndex, perPage: 100));
|
||||
|
||||
if (tmpTaxRates != null && tmpTaxRates.length > 0) {
|
||||
if (tmpTaxRates != null && tmpTaxRates.isNotEmpty) {
|
||||
_taxRates.addAll(tmpTaxRates);
|
||||
}
|
||||
if (tmpTaxRates.length >= 100) {
|
||||
@ -74,7 +81,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
}
|
||||
}
|
||||
|
||||
if (_taxRates == null || _taxRates.length == 0) {
|
||||
if (_taxRates == null || _taxRates.isEmpty) {
|
||||
setState(() {
|
||||
_showFullLoader = false;
|
||||
});
|
||||
@ -131,12 +138,10 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
orElse: () => null,
|
||||
);
|
||||
|
||||
if (taxRate == null) {
|
||||
taxRate = _taxRates.firstWhere(
|
||||
(t) => t.country == shippingCountry.countryCode,
|
||||
orElse: () => null,
|
||||
);
|
||||
}
|
||||
taxRate ??= _taxRates.firstWhere(
|
||||
(t) => t.country == shippingCountry.countryCode,
|
||||
orElse: () => null,
|
||||
);
|
||||
}
|
||||
|
||||
if (taxRate != null) {
|
||||
@ -147,225 +152,154 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
});
|
||||
}
|
||||
|
||||
_actionCheckoutDetails() {
|
||||
Navigator.pushNamed(context, "/checkout-details").then((e) {
|
||||
setState(() {
|
||||
_showFullLoader = true;
|
||||
});
|
||||
_getTaxes();
|
||||
});
|
||||
}
|
||||
|
||||
_actionPayWith() {
|
||||
Navigator.pushNamed(context, "/checkout-payment-type")
|
||||
.then((value) => setState(() {}));
|
||||
}
|
||||
|
||||
_actionSelectShipping() {
|
||||
CustomerAddress shippingAddress =
|
||||
CheckoutSession.getInstance.billingDetails.shippingAddress;
|
||||
if (shippingAddress == null || shippingAddress.customerCountry == null) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Add your shipping details first"),
|
||||
icon: Icons.local_shipping);
|
||||
return;
|
||||
}
|
||||
Navigator.pushNamed(context, "/checkout-shipping-type").then((value) {
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
CheckoutSession checkoutSession = CheckoutSession.getInstance;
|
||||
|
||||
if (_showFullLoader == true) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
AppLoaderWidget(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
child: Text(
|
||||
"${trans("One moment")}...",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
trans("Checkout")
|
||||
),
|
||||
title: Text(trans("Checkout")),
|
||||
centerTitle: true,
|
||||
leading: Container(
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: () {
|
||||
CheckoutSession.getInstance.coupon = null;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
margin: EdgeInsets.only(left: 0),
|
||||
),
|
||||
),
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: SafeAreaWidget(
|
||||
child: !_showFullLoader
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeColor.get(context).backgroundContainer,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
),
|
||||
margin: EdgeInsets.only(top: 5, bottom: 5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: (Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow(blurRadius: 10)
|
||||
: null,
|
||||
color: Colors.transparent,
|
||||
),
|
||||
padding: EdgeInsets.all(2),
|
||||
margin: EdgeInsets.only(top: 16),
|
||||
child: ClipRRect(
|
||||
child: StoreLogo(height: 65),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
)),
|
||||
((CheckoutSession.getInstance.billingDetails != null &&
|
||||
CheckoutSession.getInstance.billingDetails
|
||||
.billingAddress !=
|
||||
null)
|
||||
? wsCheckoutRow(context,
|
||||
heading: trans("Billing/shipping details"),
|
||||
leadImage: Icon(Icons.home),
|
||||
leadTitle:
|
||||
(CheckoutSession.getInstance.billingDetails == null ||
|
||||
CheckoutSession.getInstance
|
||||
.billingDetails.billingAddress
|
||||
.hasMissingFields()
|
||||
? trans("Billing address is incomplete")
|
||||
: CheckoutSession.getInstance
|
||||
.billingDetails.billingAddress
|
||||
.addressFull()),
|
||||
action: _actionCheckoutDetails,
|
||||
showBorderBottom: true)
|
||||
: wsCheckoutRow(context,
|
||||
heading:
|
||||
trans("Billing/shipping details"),
|
||||
leadImage: Icon(Icons.home),
|
||||
leadTitle: trans("Add billing & shipping details"),
|
||||
action: _actionCheckoutDetails,
|
||||
showBorderBottom: true)),
|
||||
(CheckoutSession.getInstance.paymentType != null
|
||||
? wsCheckoutRow(context,
|
||||
heading: trans("Payment method"),
|
||||
leadImage: Container(
|
||||
color: Colors.white,
|
||||
child: Image.asset(
|
||||
getImageAsset(CheckoutSession
|
||||
.getInstance.paymentType.assetImage),
|
||||
width: 70,
|
||||
),
|
||||
),
|
||||
leadTitle: CheckoutSession
|
||||
.getInstance.paymentType.desc,
|
||||
action: _actionPayWith,
|
||||
showBorderBottom: true)
|
||||
: wsCheckoutRow(context,
|
||||
heading: trans("Pay with"),
|
||||
leadImage: Icon(Icons.payment),
|
||||
leadTitle: trans("Select a payment method"),
|
||||
action: _actionPayWith,
|
||||
showBorderBottom: true)),
|
||||
_wooSignalApp.disableShipping == 1
|
||||
? null
|
||||
: (CheckoutSession.getInstance.shippingType !=
|
||||
null
|
||||
? wsCheckoutRow(context,
|
||||
heading:
|
||||
trans("Shipping selected"),
|
||||
leadImage: Icon(Icons.local_shipping),
|
||||
leadTitle: CheckoutSession
|
||||
.getInstance.shippingType
|
||||
.getTitle(),
|
||||
action: _actionSelectShipping)
|
||||
: wsCheckoutRow(
|
||||
context,
|
||||
heading:
|
||||
trans("Select shipping"),
|
||||
leadImage: Icon(Icons.local_shipping),
|
||||
leadTitle: trans("Select a shipping option"),
|
||||
action: _actionSelectShipping,
|
||||
)),
|
||||
].where((e) => e != null).toList()),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Divider(
|
||||
color: Colors.black12,
|
||||
thickness: 1,
|
||||
),
|
||||
wsCheckoutSubtotalWidgetFB(
|
||||
title: trans("Subtotal"),
|
||||
),
|
||||
_wooSignalApp.disableShipping == 1
|
||||
? null
|
||||
: widgetCheckoutMeta(context,
|
||||
title: trans("Shipping fee"),
|
||||
amount:
|
||||
CheckoutSession.getInstance.shippingType ==
|
||||
null
|
||||
? trans("Select shipping")
|
||||
: CheckoutSession.getInstance.shippingType
|
||||
.getTotal(withFormatting: true)),
|
||||
(_taxRate != null
|
||||
? wsCheckoutTaxAmountWidgetFB(taxRate: _taxRate)
|
||||
: null),
|
||||
wsCheckoutTotalWidgetFB(
|
||||
title: trans("Total"), taxRate: _taxRate),
|
||||
Divider(
|
||||
color: Colors.black12,
|
||||
thickness: 1,
|
||||
),
|
||||
].where((e) => e != null).toList(),
|
||||
),
|
||||
PrimaryButton(
|
||||
title: _isProcessingPayment
|
||||
? "${trans("PROCESSING")}..."
|
||||
: trans("CHECKOUT"),
|
||||
action: _isProcessingPayment ? null : _handleCheckout,
|
||||
),
|
||||
],
|
||||
)
|
||||
: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
AppLoaderWidget(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
child: Text(
|
||||
"${trans("One moment")}...",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
)
|
||||
],
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeColor.get(context).backgroundContainer,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: (Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
),
|
||||
margin: EdgeInsets.only(top: 5, bottom: 5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
CheckoutStoreHeadingWidget(),
|
||||
CheckoutUserDetailsWidget(
|
||||
context: context,
|
||||
checkoutSession: checkoutSession,
|
||||
resetState: () {
|
||||
setState(() {
|
||||
_showFullLoader = true;
|
||||
});
|
||||
_getTaxes();
|
||||
},
|
||||
),
|
||||
CheckoutPaymentTypeWidget(
|
||||
context: context,
|
||||
checkoutSession: checkoutSession,
|
||||
resetState: () => setState(() {}),
|
||||
),
|
||||
CheckoutShippingTypeWidget(
|
||||
context: context,
|
||||
checkoutSession: checkoutSession,
|
||||
resetState: () => setState(() {}),
|
||||
wooSignalApp: _wooSignalApp,
|
||||
),
|
||||
].where((e) => e != null).toList()),
|
||||
),
|
||||
),
|
||||
if (_wooSignalApp.couponEnabled == true)
|
||||
CheckoutSelectCouponWidget(
|
||||
context: context,
|
||||
checkoutSession: checkoutSession,
|
||||
resetState: () => setState(() {}),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Divider(
|
||||
color: Colors.black12,
|
||||
thickness: 1,
|
||||
),
|
||||
CheckoutSubtotal(
|
||||
title: trans("Subtotal"),
|
||||
),
|
||||
CheckoutCouponAmountWidget(checkoutSession: checkoutSession),
|
||||
_wooSignalApp.disableShipping == 1
|
||||
? null
|
||||
: CheckoutMetaLine(
|
||||
title: trans("Shipping fee"),
|
||||
amount: CheckoutSession.getInstance.shippingType == null
|
||||
? trans("Select shipping")
|
||||
: CheckoutSession.getInstance.shippingType
|
||||
.getTotal(withFormatting: true)),
|
||||
(_taxRate != null ? CheckoutTaxTotal(taxRate: _taxRate) : null),
|
||||
CheckoutTotal(title: trans("Total"), taxRate: _taxRate),
|
||||
Divider(
|
||||
color: Colors.black12,
|
||||
thickness: 1,
|
||||
),
|
||||
].where((e) => e != null).toList(),
|
||||
),
|
||||
PrimaryButton(
|
||||
title: _isProcessingPayment
|
||||
? "${trans("PROCESSING")}..."
|
||||
: trans("CHECKOUT"),
|
||||
action: _isProcessingPayment ? null : _handleCheckout,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_handleCheckout() async {
|
||||
if (CheckoutSession.getInstance.billingDetails.billingAddress == null) {
|
||||
CheckoutSession checkoutSession = CheckoutSession.getInstance;
|
||||
if (checkoutSession.billingDetails.billingAddress == null) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Please select add your billing/shipping address to proceed"),
|
||||
description:
|
||||
trans("Please select add your billing/shipping address to proceed"),
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
icon: Icons.local_shipping,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckoutSession.getInstance.billingDetails.billingAddress
|
||||
.hasMissingFields()) {
|
||||
if (checkoutSession.billingDetails.billingAddress.hasMissingFields()) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
description:
|
||||
trans("Your billing/shipping details are incomplete"),
|
||||
description: trans("Your billing/shipping details are incomplete"),
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
icon: Icons.local_shipping,
|
||||
);
|
||||
@ -373,24 +307,22 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
}
|
||||
|
||||
if (_wooSignalApp.disableShipping == 0 &&
|
||||
CheckoutSession.getInstance.shippingType == null) {
|
||||
checkoutSession.shippingType == null) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
description:
|
||||
trans("Please select a shipping method to proceed"),
|
||||
description: trans("Please select a shipping method to proceed"),
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
icon: Icons.local_shipping,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckoutSession.getInstance.paymentType == null) {
|
||||
if (checkoutSession.paymentType == null) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
description:
|
||||
trans("Please select a payment method to proceed"),
|
||||
description: trans("Please select a payment method to proceed"),
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
icon: Icons.payment,
|
||||
);
|
||||
@ -398,20 +330,20 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
}
|
||||
|
||||
if (_wooSignalApp.disableShipping == 0 &&
|
||||
CheckoutSession.getInstance.shippingType?.minimumValue != null) {
|
||||
checkoutSession.shippingType?.minimumValue != null) {
|
||||
String total = await Cart.getInstance.getTotal();
|
||||
if (total == null) {
|
||||
return;
|
||||
}
|
||||
double doubleTotal = double.parse(total);
|
||||
double doubleMinimumValue =
|
||||
double.parse(CheckoutSession.getInstance.shippingType?.minimumValue);
|
||||
double.parse(checkoutSession.shippingType?.minimumValue);
|
||||
|
||||
if (doubleTotal < doubleMinimumValue) {
|
||||
showToastNotification(context,
|
||||
title: trans("Sorry"),
|
||||
description:
|
||||
"${trans("Spend a minimum of")} ${formatDoubleCurrency(total: doubleMinimumValue)} ${trans("for")} ${CheckoutSession.getInstance.shippingType.getTitle()}",
|
||||
"${trans("Spend a minimum of")} ${formatDoubleCurrency(total: doubleMinimumValue)} ${trans("for")} ${checkoutSession.shippingType.getTitle()}",
|
||||
style: ToastNotificationStyleType.INFO,
|
||||
duration: Duration(seconds: 3));
|
||||
return;
|
||||
@ -423,7 +355,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
if (!appStatus) {
|
||||
showToastNotification(context,
|
||||
title: trans("Sorry"),
|
||||
description: "${trans("Retry later")}",
|
||||
description: trans("Retry later"),
|
||||
style: ToastNotificationStyleType.INFO,
|
||||
duration: Duration(seconds: 3));
|
||||
return;
|
||||
@ -437,13 +369,11 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
_isProcessingPayment = true;
|
||||
});
|
||||
|
||||
await CheckoutSession.getInstance.paymentType
|
||||
await checkoutSession.paymentType
|
||||
.pay(context, state: this, taxRate: _taxRate);
|
||||
|
||||
Future.delayed(Duration(milliseconds: 5000), () {
|
||||
setState(() {
|
||||
_isProcessingPayment = false;
|
||||
});
|
||||
setState(() {
|
||||
_isProcessingPayment = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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/models/billing_details.dart';
|
||||
import 'package:flutter_app/app/models/checkout_session.dart';
|
||||
@ -37,7 +36,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
int activeTabIndex = 0;
|
||||
|
||||
// TEXT CONTROLLERS
|
||||
TextEditingController
|
||||
final TextEditingController
|
||||
// billing
|
||||
_txtBillingFirstName = TextEditingController(),
|
||||
_txtBillingLastName = TextEditingController(),
|
||||
@ -168,7 +167,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
),
|
||||
body: SafeAreaWidget(
|
||||
child: GestureDetector(
|
||||
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
|
||||
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -194,8 +193,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
SwitchAddressTab(
|
||||
title:
|
||||
trans("Billing Details"),
|
||||
title: trans("Billing Details"),
|
||||
currentTabIndex: activeTabIndex,
|
||||
type: "billing",
|
||||
onTapAction: () => setState(() {
|
||||
@ -227,7 +225,9 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
color: ThemeColor.get(context).backgroundContainer,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
),
|
||||
padding: EdgeInsets.only(left: 8, right: 8, top: 8),
|
||||
child: (activeTab ?? tabBillingDetails()),
|
||||
@ -315,7 +315,8 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Invalid shipping address, please check your shipping details"),
|
||||
description: trans(
|
||||
"Invalid shipping address, please check your shipping details"),
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
);
|
||||
return;
|
||||
@ -324,7 +325,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
// Email validation
|
||||
String billingEmail = _txtBillingEmailAddress.text;
|
||||
String shippingEmail = _txtShippingEmailAddress.text;
|
||||
if (billingEmail.length > 0 && !validate.isEmail(billingEmail)) {
|
||||
if (billingEmail.isNotEmpty && !validate.isEmail(billingEmail)) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
@ -334,7 +335,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shippingEmail.length > 0 && !validate.isEmail(shippingEmail)) {
|
||||
if (shippingEmail.isNotEmpty && !validate.isEmail(shippingEmail)) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
@ -380,7 +381,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
city: "",
|
||||
postalCode: "",
|
||||
emailAddress: "",
|
||||
customerCountry: new CustomerCountry());
|
||||
customerCountry: CustomerCountry());
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
@ -393,7 +394,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
@required String postalCode,
|
||||
@required String emailAddress,
|
||||
@required CustomerCountry customerCountry}) {
|
||||
CustomerAddress customerShippingAddress = new CustomerAddress();
|
||||
CustomerAddress customerShippingAddress = CustomerAddress();
|
||||
customerShippingAddress.firstName = firstName;
|
||||
customerShippingAddress.lastName = lastName;
|
||||
customerShippingAddress.addressLine = addressLine;
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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/models/checkout_session.dart';
|
||||
import 'package:flutter_app/app/models/payment_type.dart';
|
||||
@ -35,7 +34,7 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
|
||||
super.initState();
|
||||
|
||||
if (CheckoutSession.getInstance.paymentType == null) {
|
||||
if (getPaymentTypes() != null && getPaymentTypes().length > 0) {
|
||||
if (getPaymentTypes() != null && getPaymentTypes().isNotEmpty) {
|
||||
CheckoutSession.getInstance.paymentType = getPaymentTypes().first;
|
||||
}
|
||||
}
|
||||
@ -44,21 +43,21 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<PaymentType> paymentTypes = getPaymentTypes();
|
||||
if (paymentTypes.length == 0 && getEnv('APP_DEBUG', defaultValue: false) == true) {
|
||||
NyLogger.info('You have no payment methods set. Visit the WooSignal dashboard (https://woosignal.com/dashboard) to set a payment method.');
|
||||
if (paymentTypes.isEmpty &&
|
||||
getEnv('APP_DEBUG', defaultValue: false) == true) {
|
||||
NyLogger.info(
|
||||
'You have no payment methods set. Visit the WooSignal dashboard (https://woosignal.com/dashboard) to set a payment method.');
|
||||
}
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
trans("Payment Method")
|
||||
),
|
||||
title: Text(trans("Payment Method")),
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeAreaWidget(
|
||||
child: GestureDetector(
|
||||
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
|
||||
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -78,53 +77,60 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: paymentTypes.length == 0 ? Container(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Text(trans("No payment methods are available"), style: Theme.of(context).textTheme.bodyText1,),
|
||||
) : ListView.separated(
|
||||
itemCount: paymentTypes.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
PaymentType paymentType =
|
||||
paymentTypes[index];
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
left: 8,
|
||||
right: 8,
|
||||
),
|
||||
leading: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white
|
||||
),
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Image.asset(
|
||||
getImageAsset(paymentType.assetImage),
|
||||
width: 60,
|
||||
fit: BoxFit.contain,
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
),
|
||||
title: Text(paymentType.desc,
|
||||
child: paymentTypes.isEmpty
|
||||
? Container(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Text(
|
||||
trans("No payment methods are available"),
|
||||
style:
|
||||
Theme.of(context).textTheme.subtitle1),
|
||||
selected: true,
|
||||
trailing:
|
||||
(CheckoutSession.getInstance.paymentType ==
|
||||
paymentType
|
||||
? Icon(Icons.check)
|
||||
: null),
|
||||
onTap: () {
|
||||
CheckoutSession.getInstance.paymentType =
|
||||
paymentType;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (cxt, i) => Divider(
|
||||
color: Colors.black12,
|
||||
),
|
||||
),
|
||||
Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
)
|
||||
: ListView.separated(
|
||||
itemCount: paymentTypes.length,
|
||||
itemBuilder:
|
||||
(BuildContext context, int index) {
|
||||
PaymentType paymentType =
|
||||
paymentTypes[index];
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
left: 8,
|
||||
right: 8,
|
||||
),
|
||||
leading: Container(
|
||||
decoration:
|
||||
BoxDecoration(color: Colors.white),
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Image.asset(
|
||||
getImageAsset(paymentType.assetImage),
|
||||
width: 60,
|
||||
fit: BoxFit.contain,
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
),
|
||||
title: Text(paymentType.desc,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.subtitle1),
|
||||
selected: true,
|
||||
trailing: (CheckoutSession
|
||||
.getInstance.paymentType ==
|
||||
paymentType
|
||||
? Icon(Icons.check)
|
||||
: null),
|
||||
onTap: () {
|
||||
CheckoutSession.getInstance
|
||||
.paymentType = paymentType;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (cxt, i) => Divider(
|
||||
color: Colors.black12,
|
||||
),
|
||||
),
|
||||
),
|
||||
LinkButton(
|
||||
title: trans("CANCEL"),
|
||||
@ -136,7 +142,9 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
|
||||
color: ThemeColor.get(context).backgroundContainer,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
),
|
||||
padding: EdgeInsets.all(8),
|
||||
),
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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/models/cart.dart';
|
||||
import 'package:flutter_app/app/models/cart_line_item.dart';
|
||||
@ -36,7 +35,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
_CheckoutShippingTypePageState();
|
||||
|
||||
bool _isShippingSupported = true, _isLoading = true;
|
||||
List<Map<String, dynamic>> _wsShippingOptions = [];
|
||||
final List<Map<String, dynamic>> _wsShippingOptions = [];
|
||||
WSShipping _shipping;
|
||||
|
||||
@override
|
||||
@ -105,7 +104,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
.firstWhere((element) => element.parentId == 0, orElse: () => null);
|
||||
await _handleShippingZones(noZones);
|
||||
}
|
||||
if (_wsShippingOptions.length == 0) {
|
||||
if (_wsShippingOptions.isEmpty) {
|
||||
_isShippingSupported = false;
|
||||
}
|
||||
|
||||
@ -237,15 +236,13 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
trans("Shipping Methods")
|
||||
),
|
||||
title: Text(trans("Shipping Methods")),
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeAreaWidget(
|
||||
child: GestureDetector(
|
||||
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
|
||||
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -253,9 +250,12 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
child: Center(
|
||||
child: Image.asset(getImageAsset('shipping_icon.png'),
|
||||
child: Image.asset(
|
||||
getImageAsset('shipping_icon.png'),
|
||||
height: 100,
|
||||
color: (Theme.of(context).brightness == Brightness.light) ? null : Colors.white,
|
||||
color: (Theme.of(context).brightness == Brightness.light)
|
||||
? null
|
||||
: Colors.white,
|
||||
fit: BoxFit.fitHeight,
|
||||
),
|
||||
),
|
||||
@ -325,8 +325,8 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
"object"]
|
||||
is FreeShipping
|
||||
? TextSpan(
|
||||
text:
|
||||
trans("Free postage"),
|
||||
text: trans(
|
||||
"Free postage"),
|
||||
)
|
||||
: TextSpan(
|
||||
text:
|
||||
@ -376,7 +376,8 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
trans("Shipping is not supported for your country, sorry"),
|
||||
trans(
|
||||
"Shipping is not supported for your country, sorry"),
|
||||
style:
|
||||
Theme.of(context).textTheme.headline6,
|
||||
textAlign: TextAlign.center,
|
||||
@ -391,7 +392,9 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
color: ThemeColor.get(context).backgroundContainer,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow:
|
||||
(Theme.of(context).brightness == Brightness.light) ? wsBoxShadow() : null,
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow()
|
||||
: null,
|
||||
),
|
||||
padding: EdgeInsets.all(8),
|
||||
),
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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/checkout_status_controller.dart';
|
||||
import 'package:flutter_app/app/models/cart.dart';
|
||||
@ -17,7 +16,7 @@ import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/widgets/buttons.dart';
|
||||
import 'package:nylo_support/widgets/ny_state.dart';
|
||||
import 'package:nylo_support/widgets/ny_stateful_widget.dart';
|
||||
import 'package:woosignal/models/response/order.dart' as WS;
|
||||
import 'package:woosignal/models/response/order.dart' as ws_order;
|
||||
import 'package:nylo_support/helpers/helper.dart';
|
||||
|
||||
import '../widgets/woosignal_ui.dart';
|
||||
@ -31,7 +30,7 @@ class CheckoutStatusPage extends NyStatefulWidget {
|
||||
}
|
||||
|
||||
class _CheckoutStatusState extends NyState<CheckoutStatusPage> {
|
||||
WS.Order _order;
|
||||
ws_order.Order _order;
|
||||
|
||||
@override
|
||||
widgetDidLoad() async {
|
||||
@ -43,7 +42,6 @@ class _CheckoutStatusState extends NyState<CheckoutStatusPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0.0,
|
||||
@ -94,7 +92,10 @@ class _CheckoutStatusState extends NyState<CheckoutStatusPage> {
|
||||
border: Border(
|
||||
bottom: BorderSide(color: Colors.black12, width: 1.0),
|
||||
),
|
||||
color: (Theme.of(context).brightness == Brightness.light) ? Colors.white : null),
|
||||
color:
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? Colors.white
|
||||
: null),
|
||||
padding: EdgeInsets.only(bottom: 20),
|
||||
),
|
||||
Container(
|
||||
@ -121,11 +122,11 @@ class _CheckoutStatusState extends NyState<CheckoutStatusPage> {
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
Expanded(
|
||||
child: new ListView.builder(
|
||||
child: ListView.builder(
|
||||
itemCount:
|
||||
_order.lineItems == null ? 0 : _order.lineItems.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
WS.LineItems lineItem = _order.lineItems[index];
|
||||
ws_order.LineItems lineItem = _order.lineItems[index];
|
||||
return Container(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
@ -164,13 +165,16 @@ class _CheckoutStatusState extends NyState<CheckoutStatusPage> {
|
||||
padding: EdgeInsets.all(16),
|
||||
margin: EdgeInsets.all(8),
|
||||
color:
|
||||
(Theme.of(context).brightness == Brightness.light) ? Colors.white : null);
|
||||
(Theme.of(context).brightness == Brightness.light)
|
||||
? Colors.white
|
||||
: null);
|
||||
}),
|
||||
),
|
||||
Align(
|
||||
child: LinkButton(
|
||||
title: trans("Back to Home"),
|
||||
action: () => Navigator.pushNamed(context, "/home"),
|
||||
action: () =>
|
||||
Navigator.pushReplacementNamed(context, "/home"),
|
||||
),
|
||||
alignment: Alignment.bottomCenter,
|
||||
),
|
||||
|
||||
223
LabelStoreMax/lib/resources/pages/coupon_page.dart
Normal file
223
LabelStoreMax/lib/resources/pages/coupon_page.dart
Normal file
@ -0,0 +1,223 @@
|
||||
import 'package:flutter/material.dart';
|
||||
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/helpers.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:nylo_framework/nylo_framework.dart';
|
||||
import 'package:woosignal/models/response/coupon.dart';
|
||||
|
||||
class CouponPage extends StatefulWidget {
|
||||
@override
|
||||
_CouponPageState createState() => _CouponPageState();
|
||||
}
|
||||
|
||||
class _CouponPageState extends State<CouponPage> {
|
||||
List<Coupon> _coupons = [];
|
||||
bool _isLoading = false;
|
||||
|
||||
final couponController = TextEditingController();
|
||||
|
||||
_showAlert({String message, ToastNotificationStyleType style}) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans('Coupon'),
|
||||
description: message,
|
||||
style: style ?? ToastNotificationStyleType.SUCCESS,
|
||||
icon: Icons.call_to_action,
|
||||
);
|
||||
}
|
||||
|
||||
_successAddCoupon(Coupon coupon) {
|
||||
_showAlert(message: trans("Added to checkout"));
|
||||
CheckoutSession.getInstance.coupon = coupon;
|
||||
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
Future<void> findCoupon(String couponCode) async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
_coupons = await appWooSignal(
|
||||
(api) => api.getCoupons(code: couponCode, perPage: 100),
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
CheckoutSession checkoutSession = CheckoutSession.getInstance;
|
||||
return Scaffold(
|
||||
body: SafeAreaWidget(
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Icon(Icons.local_offer_outlined, size: 30),
|
||||
Text(
|
||||
trans('Redeem Coupon'),
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Form(
|
||||
key: _formKey,
|
||||
child: TextFormField(
|
||||
autofocus: true,
|
||||
controller: couponController,
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
return trans('Please enter coupon to redeem');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.black, width: 0.0),
|
||||
),
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.black, width: 0.0),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(8.0),
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: ThemeColor.get(context).primaryAccent)),
|
||||
filled: true,
|
||||
hintStyle: TextStyle(color: Colors.grey[800]),
|
||||
hintText: trans('Add coupon code'),
|
||||
fillColor: Colors.grey[200],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 25,
|
||||
),
|
||||
(_isLoading == true)
|
||||
? AppLoaderWidget()
|
||||
: PrimaryButton(
|
||||
action: () => _applyCoupon(checkoutSession),
|
||||
title: trans('Apply'),
|
||||
),
|
||||
LinkButton(
|
||||
title: trans("Cancel"), action: () => Navigator.pop(context)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_applyCoupon(CheckoutSession checkoutSession) async {
|
||||
await findCoupon(couponController.text);
|
||||
|
||||
if (_formKey.currentState.validate()) {
|
||||
// No coupons found
|
||||
if (_coupons.isEmpty) {
|
||||
_showAlert(
|
||||
message: "${trans('Coupon not found')}.",
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
Coupon coupon = _coupons.first;
|
||||
|
||||
DateTime dateNow = DateTime.now();
|
||||
List<CartLineItem> cart = await Cart.getInstance.getCart();
|
||||
List<int> productIds = cart.map((e) => e.productId).toList();
|
||||
|
||||
// Check excludedProductIds
|
||||
for (var productId in productIds) {
|
||||
if (coupon.excludedProductIds.contains(productId)) {
|
||||
_showAlert(
|
||||
message:
|
||||
"${trans('Sorry, this coupon can not be used with your cart')}.",
|
||||
style: ToastNotificationStyleType.INFO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check email restrictions
|
||||
String emailAddress =
|
||||
checkoutSession.billingDetails.billingAddress.emailAddress;
|
||||
if (coupon.emailRestrictions.contains(emailAddress)) {
|
||||
_showAlert(
|
||||
message: trans('You cannot redeem this coupon'),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for minimum amount
|
||||
double minimumAmount = double.parse(coupon.minimumAmount);
|
||||
String strSubtotal = await Cart.getInstance.getSubtotal();
|
||||
double doubleSubtotal = double.parse(strSubtotal);
|
||||
if (minimumAmount != 0 && doubleSubtotal < minimumAmount) {
|
||||
_showAlert(
|
||||
message: trans("Spend a minimum of minimumAmount to redeem",
|
||||
arguments: {"minimumAmount": minimumAmount.toString()}),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check maximum amount
|
||||
double maximumAmount = double.parse(coupon.maximumAmount);
|
||||
if (maximumAmount != 0 && doubleSubtotal > maximumAmount) {
|
||||
_showAlert(
|
||||
message: trans("Spend less than maximumAmount to redeem",
|
||||
arguments: {"maximumAmount": maximumAmount.toString()}),
|
||||
style: ToastNotificationStyleType.DANGER);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if coupon has expired
|
||||
if (coupon.dateExpires != null &&
|
||||
dateNow.isAfter(
|
||||
DateTime.parse(coupon.dateExpires),
|
||||
)) {
|
||||
_showAlert(
|
||||
message: trans("This coupon has expired"),
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check usage limit
|
||||
if (coupon.usageLimit != null && coupon.usageCount >= coupon.usageLimit) {
|
||||
_showAlert(
|
||||
message: trans("Usage limit has been reached"),
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check usage limit per user
|
||||
int limitPerUser = coupon.usageLimitPerUser;
|
||||
if (limitPerUser != null &&
|
||||
coupon.usedBy
|
||||
.map((e) => e.toLowerCase())
|
||||
.where((usedBy) => usedBy == emailAddress.toLowerCase())
|
||||
.length >=
|
||||
limitPerUser) {
|
||||
_showAlert(
|
||||
message: "${trans('You cannot redeem this coupon')}.",
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
_successAddCoupon(coupon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -26,7 +26,7 @@ class _CustomerCountriesPageState extends State<CustomerCountriesPage> {
|
||||
_CustomerCountriesPageState();
|
||||
|
||||
List<DefaultShipping> _defaultShipping = [], _activeShippingResults = [];
|
||||
TextEditingController _tfSearchCountry = TextEditingController();
|
||||
final TextEditingController _tfSearchCountry = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -45,9 +45,7 @@ class _CustomerCountriesPageState extends State<CustomerCountriesPage> {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
trans("Select a country")
|
||||
),
|
||||
title: Text(trans("Select a country")),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeAreaWidget(
|
||||
@ -57,17 +55,16 @@ class _CustomerCountriesPageState extends State<CustomerCountriesPage> {
|
||||
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16),
|
||||
margin: EdgeInsets.only(bottom: 10, top: 10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 3,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
],
|
||||
color: ThemeColor.get(context).background
|
||||
),
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 3,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
],
|
||||
color: ThemeColor.get(context).background),
|
||||
height: 60,
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/bootstrap/app_helper.dart';
|
||||
import 'package:flutter_app/resources/widgets/compo_theme_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/mello_theme_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/notic_theme_widget.dart';
|
||||
import 'package:woosignal/models/response/woosignal_app.dart';
|
||||
@ -34,6 +35,9 @@ class _HomePageState extends State<HomePage> {
|
||||
if (AppHelper.instance.appConfig.theme == "notic") {
|
||||
theme = NoticThemeWidget(globalKey: _key, wooSignalApp: _wooSignalApp);
|
||||
}
|
||||
if (AppHelper.instance.appConfig.theme == "compo") {
|
||||
theme = CompoThemeWidget(globalKey: _key, wooSignalApp: _wooSignalApp);
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -26,7 +26,7 @@ class HomeSearchPage extends StatefulWidget {
|
||||
class _HomeSearchPageState extends State<HomeSearchPage> {
|
||||
_HomeSearchPageState();
|
||||
|
||||
TextEditingController _txtSearchController = TextEditingController();
|
||||
final TextEditingController _txtSearchController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -37,7 +37,8 @@ class _HomeSearchPageState extends State<HomeSearchPage> {
|
||||
Navigator.pushNamed(context, "/product-search",
|
||||
arguments: _txtSearchController.text)
|
||||
.then((search) {
|
||||
if (AppHelper.instance.appConfig.theme != "notic") {
|
||||
if (["notic", "compo"].contains(AppHelper.instance.appConfig.theme) ==
|
||||
false) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// StoreMob
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -29,7 +29,9 @@ class _NoConnectionPageState extends State<NoConnectionPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
print('WooCommerce site is not connected');
|
||||
if (getEnv('APP_DEBUG') == true) {
|
||||
NyLogger.error('WooCommerce site is not connected');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -67,8 +69,7 @@ class _NoConnectionPageState extends State<NoConnectionPage> {
|
||||
|
||||
if (wooSignalApp == null) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Retry later"));
|
||||
title: trans("Oops"), description: trans("Retry later"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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/product_detail_controller.dart';
|
||||
import 'package:flutter_app/app/models/cart.dart';
|
||||
import 'package:flutter_app/app/models/cart_line_item.dart';
|
||||
import 'package:flutter_app/bootstrap/app_helper.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/buttons.dart';
|
||||
@ -20,11 +20,14 @@ import 'package:flutter_app/resources/widgets/cached_image_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/cart_icon_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:woosignal/models/response/product_variation.dart' as WS;
|
||||
import 'package:woosignal/models/response/products.dart' as WSProduct;
|
||||
import 'package:woosignal/models/response/product_variation.dart'
|
||||
as ws_product_variation;
|
||||
import 'package:woosignal/models/response/products.dart' as ws_product;
|
||||
import 'package:flutter_swiper/flutter_swiper.dart';
|
||||
import 'package:woosignal/models/response/woosignal_app.dart';
|
||||
|
||||
class ProductDetailPage extends NyStatefulWidget {
|
||||
@override
|
||||
final ProductDetailController controller = ProductDetailController();
|
||||
ProductDetailPage({Key key}) : super(key: key);
|
||||
|
||||
@ -34,10 +37,12 @@ class ProductDetailPage extends NyStatefulWidget {
|
||||
|
||||
class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
bool _isLoading = false;
|
||||
WSProduct.Product _product;
|
||||
ws_product.Product _product;
|
||||
bool isInFavourites = false;
|
||||
int _quantityIndicator = 1;
|
||||
List<WS.ProductVariation> _productVariations = [];
|
||||
Map<int, dynamic> _tmpAttributeObj = {};
|
||||
List<ws_product_variation.ProductVariation> _productVariations = [];
|
||||
final Map<int, dynamic> _tmpAttributeObj = {};
|
||||
final WooSignalApp _wooSignalApp = AppHelper.instance.appConfig;
|
||||
|
||||
@override
|
||||
widgetDidLoad() async {
|
||||
@ -50,16 +55,16 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
}
|
||||
|
||||
_fetchProductVariations() async {
|
||||
List<WS.ProductVariation> tmpVariations = [];
|
||||
List<ws_product_variation.ProductVariation> tmpVariations = [];
|
||||
int currentPage = 1;
|
||||
|
||||
bool isFetching = true;
|
||||
while (isFetching) {
|
||||
List<WS.ProductVariation> tmp = await appWooSignal(
|
||||
List<ws_product_variation.ProductVariation> tmp = await appWooSignal(
|
||||
(api) => api.getProductVariations(_product.id,
|
||||
perPage: 100, page: currentPage),
|
||||
);
|
||||
if (tmp != null && tmp.length > 0) {
|
||||
if (tmp != null && tmp.isNotEmpty) {
|
||||
tmpVariations.addAll(tmp);
|
||||
}
|
||||
|
||||
@ -75,25 +80,25 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
});
|
||||
}
|
||||
|
||||
WS.ProductVariation findProductVariation() {
|
||||
WS.ProductVariation tmpProductVariation;
|
||||
ws_product_variation.ProductVariation findProductVariation() {
|
||||
ws_product_variation.ProductVariation tmpProductVariation;
|
||||
|
||||
Map<String, dynamic> tmpSelectedObj = {};
|
||||
(_tmpAttributeObj.values).forEach((attributeObj) {
|
||||
for (var attributeObj in _tmpAttributeObj.values) {
|
||||
tmpSelectedObj[attributeObj["name"]] = attributeObj["value"];
|
||||
});
|
||||
}
|
||||
|
||||
_productVariations.forEach((productVariation) {
|
||||
for (var productVariation in _productVariations) {
|
||||
Map<String, dynamic> tmpVariations = {};
|
||||
|
||||
productVariation.attributes.forEach((attr) {
|
||||
for (var attr in productVariation.attributes) {
|
||||
tmpVariations[attr.name] = attr.option;
|
||||
});
|
||||
}
|
||||
|
||||
if (tmpVariations.toString() == tmpSelectedObj.toString()) {
|
||||
tmpProductVariation = productVariation;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return tmpProductVariation;
|
||||
}
|
||||
@ -101,8 +106,7 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
_modalBottomSheetOptionsForAttribute(int attributeIndex) {
|
||||
wsModalBottom(
|
||||
context,
|
||||
title:
|
||||
"${trans("Select a")} ${_product.attributes[attributeIndex].name}",
|
||||
title: "${trans("Select a")} ${_product.attributes[attributeIndex].name}",
|
||||
bodyWidget: ListView.separated(
|
||||
itemCount: _product.attributes[attributeIndex].options.length,
|
||||
separatorBuilder: (BuildContext context, int index) => Divider(),
|
||||
@ -144,7 +148,8 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
}
|
||||
|
||||
_modalBottomSheetAttributes() {
|
||||
WS.ProductVariation productVariation = findProductVariation();
|
||||
ws_product_variation.ProductVariation productVariation =
|
||||
findProductVariation();
|
||||
wsModalBottom(
|
||||
context,
|
||||
title: trans("Options"),
|
||||
@ -203,8 +208,7 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
_tmpAttributeObj.values.length) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops"),
|
||||
description:
|
||||
trans("Please select valid options first"),
|
||||
description: trans("Please select valid options first"),
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
return;
|
||||
}
|
||||
@ -212,8 +216,7 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
if (productVariation == null) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops"),
|
||||
description:
|
||||
trans("Product variation does not exist"),
|
||||
description: trans("Product variation does not exist"),
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
return;
|
||||
}
|
||||
@ -221,8 +224,7 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
if (productVariation.stockStatus != "instock") {
|
||||
showToastNotification(context,
|
||||
title: trans("Sorry"),
|
||||
description:
|
||||
trans("This item is not in stock"),
|
||||
description: trans("This item is not in stock"),
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
return;
|
||||
}
|
||||
@ -232,27 +234,11 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
options.add("${v["name"]}: ${v["value"]}");
|
||||
});
|
||||
|
||||
CartLineItem cartLineItem = CartLineItem(
|
||||
name: _product.name,
|
||||
productId: _product.id,
|
||||
variationId: productVariation.id,
|
||||
quantity: _quantityIndicator,
|
||||
taxStatus: productVariation.taxStatus,
|
||||
shippingClassId:
|
||||
productVariation.shippingClassId.toString(),
|
||||
subtotal: productVariation.price,
|
||||
stockQuantity: productVariation.stockQuantity,
|
||||
isManagedStock: productVariation.manageStock,
|
||||
taxClass: productVariation.taxClass,
|
||||
imageSrc: (productVariation.image != null
|
||||
? productVariation.image.src
|
||||
: _product.images.length == 0
|
||||
? getEnv("PRODUCT_PLACEHOLDER_IMAGE")
|
||||
: _product.images.first.src),
|
||||
shippingIsTaxable: _product.shippingTaxable,
|
||||
variationOptions: options.join(", "),
|
||||
total: productVariation.price,
|
||||
);
|
||||
CartLineItem cartLineItem = CartLineItem.fromProductVariation(
|
||||
quantityAmount: _quantityIndicator,
|
||||
options: options,
|
||||
product: _product,
|
||||
productVariation: productVariation);
|
||||
|
||||
_itemAddToCart(cartLineItem: cartLineItem);
|
||||
Navigator.of(context).pop();
|
||||
@ -281,9 +267,18 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
actions: <Widget>[
|
||||
if (_wooSignalApp.wishlistEnabled)
|
||||
IconButton(
|
||||
onPressed: _toggleWishList,
|
||||
icon: isInFavourites
|
||||
? Icon(Icons.favorite, color: Colors.red)
|
||||
: Icon(Icons.favorite_border, color: Colors.black54),
|
||||
),
|
||||
CartIconWidget(),
|
||||
],
|
||||
title: StoreLogo(height: 55, showBgWhite: (Theme.of(context).brightness == Brightness.dark)),
|
||||
title: StoreLogo(
|
||||
height: 55,
|
||||
showBgWhite: (Theme.of(context).brightness == Brightness.dark)),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeArea(
|
||||
@ -302,9 +297,11 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
child: Swiper(
|
||||
itemBuilder: (BuildContext context, int index) =>
|
||||
CachedImageWidget(
|
||||
image: _product.images.length != 0 ? _product.images[index].src : getEnv("PRODUCT_PLACEHOLDER_IMAGE"),
|
||||
image: _product.images.isNotEmpty
|
||||
? _product.images[index].src
|
||||
: getEnv("PRODUCT_PLACEHOLDER_IMAGE"),
|
||||
),
|
||||
itemCount: _product.images.length == 0
|
||||
itemCount: _product.images.isEmpty
|
||||
? 1
|
||||
: _product.images.length,
|
||||
viewportFraction: 0.85,
|
||||
@ -375,7 +372,6 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeColor.get(context).background,
|
||||
// boxShadow: wsBoxShadow(),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
padding:
|
||||
@ -548,22 +544,8 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
return;
|
||||
}
|
||||
_itemAddToCart(
|
||||
cartLineItem: CartLineItem(
|
||||
name: _product.name,
|
||||
productId: _product.id,
|
||||
quantity: _quantityIndicator,
|
||||
taxStatus: _product.taxStatus,
|
||||
shippingClassId: _product.shippingClassId.toString(),
|
||||
subtotal: _product.price,
|
||||
taxClass: _product.taxClass,
|
||||
isManagedStock: _product.manageStock,
|
||||
stockQuantity: _product.stockQuantity,
|
||||
shippingIsTaxable: _product.shippingTaxable,
|
||||
imageSrc: _product.images.length == 0
|
||||
? getEnv("PRODUCT_PLACEHOLDER_IMAGE")
|
||||
: _product.images.first.src,
|
||||
total: _product.price,
|
||||
));
|
||||
cartLineItem: CartLineItem.fromProduct(
|
||||
quantityAmount: _quantityIndicator, product: _product));
|
||||
}
|
||||
|
||||
_addQuantityTapped() {
|
||||
@ -591,4 +573,23 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_toggleWishList() async {
|
||||
String subtitleMsg;
|
||||
if (isInFavourites) {
|
||||
await removeWishlistProduct(product: _product);
|
||||
subtitleMsg = trans("This product has been removed from your wishlist");
|
||||
} else {
|
||||
await saveWishlistProduct(product: _product);
|
||||
subtitleMsg = trans("This product has been added to your wishlist");
|
||||
}
|
||||
showStatusAlert(context,
|
||||
title: trans("Success"),
|
||||
subtitle: subtitleMsg,
|
||||
icon: Icons.favorite,
|
||||
duration: 1);
|
||||
|
||||
isInFavourites = !isInFavourites;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -33,8 +33,8 @@ class _ProductImageViewerPageState extends NyState<ProductImageViewerPage> {
|
||||
@override
|
||||
void initState() {
|
||||
Map<String, dynamic> imageData = widget.controller.data();
|
||||
this._initialIndex = imageData['index'];
|
||||
this._arrImageSrc = imageData['images'];
|
||||
_initialIndex = imageData['index'];
|
||||
_arrImageSrc = imageData['images'];
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@ -49,11 +49,11 @@ class _ProductImageViewerPageState extends NyState<ProductImageViewerPage> {
|
||||
index: _initialIndex,
|
||||
itemBuilder: (BuildContext context, int index) =>
|
||||
CachedImageWidget(
|
||||
image: (_arrImageSrc.length == 0
|
||||
image: (_arrImageSrc.isEmpty
|
||||
? getEnv("PRODUCT_PLACEHOLDER_IMAGE")
|
||||
: _arrImageSrc[index]),
|
||||
),
|
||||
itemCount: _arrImageSrc.length == 0 ? 1 : _arrImageSrc.length,
|
||||
itemCount: _arrImageSrc.isEmpty ? 1 : _arrImageSrc.length,
|
||||
viewportFraction: 0.9,
|
||||
scale: 0.95,
|
||||
),
|
||||
|
||||
150
LabelStoreMax/lib/resources/pages/wishlist_page_widget.dart
Normal file
150
LabelStoreMax/lib/resources/pages/wishlist_page_widget.dart
Normal file
@ -0,0 +1,150 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/cached_image_widget.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:woosignal/models/response/products.dart';
|
||||
|
||||
class WishListPageWidget extends StatefulWidget {
|
||||
@override
|
||||
_WishListPageWidgetState createState() => _WishListPageWidgetState();
|
||||
}
|
||||
|
||||
class _WishListPageWidgetState extends State<WishListPageWidget> {
|
||||
List<Product> _products = [];
|
||||
bool isLoading;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
isLoading = true;
|
||||
loadProducts();
|
||||
}
|
||||
|
||||
loadProducts() async {
|
||||
List<dynamic> favouriteProducts = await getWishlistProducts();
|
||||
List<int> productIds =
|
||||
favouriteProducts.map((e) => e['id']).cast<int>().toList();
|
||||
if (productIds.isEmpty) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
_products = await appWooSignal((api) => api.getProducts(
|
||||
include: productIds,
|
||||
perPage: 100,
|
||||
status: "publish",
|
||||
stockStatus: "instock",
|
||||
));
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(trans("Wishlist")),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: isLoading
|
||||
? AppLoaderWidget()
|
||||
: _products.isEmpty && isLoading == false
|
||||
? Center(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.favorite,
|
||||
size: 40,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
),
|
||||
Text(trans("No items found"),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headline6
|
||||
.setColor(
|
||||
context, (color) => color.primaryContent))
|
||||
],
|
||||
),
|
||||
)
|
||||
: ListView.separated(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
Product product = _products[index];
|
||||
return InkWell(
|
||||
onTap: () => Navigator.pushNamed(
|
||||
context, "/product-detail",
|
||||
arguments: product),
|
||||
child: Container(
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
child: CachedImageWidget(
|
||||
image: (product.images.isNotEmpty
|
||||
? product.images.first.src
|
||||
: getEnv("PRODUCT_PLACEHOLDER_IMAGE")),
|
||||
fit: BoxFit.contain,
|
||||
width: double.infinity,
|
||||
),
|
||||
width: MediaQuery.of(context).size.width / 4,
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(product.name),
|
||||
Text(
|
||||
formatStringCurrency(
|
||||
total: product.price),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 100,
|
||||
alignment: Alignment.center,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
Icons.favorite,
|
||||
color: Colors.red,
|
||||
),
|
||||
onPressed: () =>
|
||||
_removeFromWishlist(product),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider();
|
||||
},
|
||||
itemCount: _products.length)),
|
||||
);
|
||||
}
|
||||
|
||||
_removeFromWishlist(Product product) async {
|
||||
await removeWishlistProduct(product: product);
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans('Success'),
|
||||
icon: Icons.shopping_cart,
|
||||
description: trans('Item removed'),
|
||||
);
|
||||
_products.remove(product);
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
@ -17,20 +17,22 @@ import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
ThemeData darkTheme(BaseColorStyles darkColors) {
|
||||
try {
|
||||
appFont = GoogleFonts.getFont(AppHelper.instance.appConfig.themeFont ?? "Poppins");
|
||||
} on Exception catch(e) {
|
||||
appFont = GoogleFonts.getFont(
|
||||
AppHelper.instance.appConfig.themeFont ?? "Poppins");
|
||||
} on Exception catch (e) {
|
||||
if (getEnv('APP_DEBUG') == true) {
|
||||
NyLogger.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
TextTheme darkTheme =
|
||||
getAppTextTheme(appFont, defaultTextTheme.merge(_darkTextTheme(darkColors)));
|
||||
TextTheme darkTheme = getAppTextTheme(
|
||||
appFont, defaultTextTheme.merge(_darkTextTheme(darkColors)));
|
||||
return ThemeData(
|
||||
primaryColor: darkColors.primaryContent,
|
||||
backgroundColor: darkColors.background,
|
||||
colorScheme: ColorScheme.dark(),
|
||||
primaryColorDark: darkColors.primaryContent,
|
||||
brightness: Brightness.dark,
|
||||
focusColor: darkColors.primaryContent,
|
||||
scaffoldBackgroundColor: darkColors.background,
|
||||
appBarTheme: AppBarTheme(
|
||||
@ -55,13 +57,13 @@ ThemeData darkTheme(BaseColorStyles darkColors) {
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
backgroundColor: darkColors.bottomTabBarBackground,
|
||||
unselectedIconTheme:
|
||||
IconThemeData(color: darkColors.bottomTabBarIconUnselected),
|
||||
IconThemeData(color: darkColors.bottomTabBarIconUnselected),
|
||||
selectedIconTheme:
|
||||
IconThemeData(color: darkColors.bottomTabBarIconSelected),
|
||||
IconThemeData(color: darkColors.bottomTabBarIconSelected),
|
||||
unselectedLabelStyle:
|
||||
TextStyle(color: darkColors.bottomTabBarLabelUnselected),
|
||||
TextStyle(color: darkColors.bottomTabBarLabelUnselected),
|
||||
selectedLabelStyle:
|
||||
TextStyle(color: darkColors.bottomTabBarLabelSelected),
|
||||
TextStyle(color: darkColors.bottomTabBarLabelSelected),
|
||||
selectedItemColor: darkColors.bottomTabBarLabelSelected,
|
||||
),
|
||||
textTheme: darkTheme,
|
||||
|
||||
@ -17,15 +17,16 @@ import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
ThemeData lightTheme(BaseColorStyles lightColors) {
|
||||
try {
|
||||
appFont = GoogleFonts.getFont(AppHelper.instance.appConfig.themeFont ?? "Poppins");
|
||||
} on Exception catch(e) {
|
||||
appFont = GoogleFonts.getFont(
|
||||
AppHelper.instance.appConfig.themeFont ?? "Poppins");
|
||||
} on Exception catch (e) {
|
||||
if (getEnv('APP_DEBUG') == true) {
|
||||
NyLogger.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
TextTheme lightTheme =
|
||||
getAppTextTheme(appFont, defaultTextTheme.merge(_lightTextTheme(lightColors)));
|
||||
TextTheme lightTheme = getAppTextTheme(
|
||||
appFont, defaultTextTheme.merge(_lightTextTheme(lightColors)));
|
||||
|
||||
return ThemeData(
|
||||
primaryColor: lightColors.primaryContent,
|
||||
@ -58,13 +59,13 @@ ThemeData lightTheme(BaseColorStyles lightColors) {
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
backgroundColor: lightColors.bottomTabBarBackground,
|
||||
unselectedIconTheme:
|
||||
IconThemeData(color: lightColors.bottomTabBarIconUnselected),
|
||||
IconThemeData(color: lightColors.bottomTabBarIconUnselected),
|
||||
selectedIconTheme:
|
||||
IconThemeData(color: lightColors.bottomTabBarIconSelected),
|
||||
IconThemeData(color: lightColors.bottomTabBarIconSelected),
|
||||
unselectedLabelStyle:
|
||||
TextStyle(color: lightColors.bottomTabBarLabelUnselected),
|
||||
TextStyle(color: lightColors.bottomTabBarLabelUnselected),
|
||||
selectedLabelStyle:
|
||||
TextStyle(color: lightColors.bottomTabBarLabelSelected),
|
||||
TextStyle(color: lightColors.bottomTabBarLabelSelected),
|
||||
selectedItemColor: lightColors.bottomTabBarLabelSelected,
|
||||
),
|
||||
textTheme: lightTheme,
|
||||
|
||||
@ -33,4 +33,4 @@ abstract class BaseColorStyles {
|
||||
Color get bottomTabBarLabelSelected;
|
||||
|
||||
Color get inputPrimaryContent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,33 +10,55 @@ import 'package:flutter_app/resources/themes/styles/base_styles.dart';
|
||||
|
||||
class DarkThemeColors implements BaseColorStyles {
|
||||
// general
|
||||
Color get background => Color(int.parse(AppHelper.instance.appConfig.themeColors['dark']['background']));
|
||||
@override
|
||||
Color get background => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['dark']['background']));
|
||||
@override
|
||||
Color get backgroundContainer => const Color(0xFF4a4a4a);
|
||||
|
||||
Color get primaryContent => Color(int.parse(AppHelper.instance.appConfig.themeColors['dark']['primary_text']));
|
||||
@override
|
||||
Color get primaryContent => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['dark']['primary_text']));
|
||||
@override
|
||||
Color get primaryAccent => const Color(0xFF818181);
|
||||
|
||||
@override
|
||||
Color get surfaceBackground => Color(0xFF818181);
|
||||
@override
|
||||
Color get surfaceContent => Colors.black;
|
||||
|
||||
// app bar
|
||||
Color get appBarBackground => Color(int.parse(AppHelper.instance.appConfig.themeColors['dark']['app_bar_background']));
|
||||
Color get appBarPrimaryContent => Color(int.parse(AppHelper.instance.appConfig.themeColors['dark']['app_bar_text']));
|
||||
@override
|
||||
Color get appBarBackground => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['dark']['app_bar_background']));
|
||||
@override
|
||||
Color get appBarPrimaryContent => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['dark']['app_bar_text']));
|
||||
|
||||
@override
|
||||
Color get inputPrimaryContent => Colors.white;
|
||||
|
||||
// buttons
|
||||
Color get buttonBackground => Color(int.parse(AppHelper.instance.appConfig.themeColors['dark']['button_background']));
|
||||
Color get buttonPrimaryContent => Color(int.parse(AppHelper.instance.appConfig.themeColors['dark']['button_text']));
|
||||
@override
|
||||
Color get buttonBackground => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['dark']['button_background']));
|
||||
@override
|
||||
Color get buttonPrimaryContent => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['dark']['button_text']));
|
||||
|
||||
// bottom tab bar
|
||||
@override
|
||||
Color get bottomTabBarBackground => const Color(0xFF232c33);
|
||||
|
||||
// bottom tab bar - icons
|
||||
@override
|
||||
Color get bottomTabBarIconSelected => Colors.white70;
|
||||
@override
|
||||
Color get bottomTabBarIconUnselected => Colors.white60;
|
||||
|
||||
// bottom tab bar - label
|
||||
@override
|
||||
Color get bottomTabBarLabelUnselected => Colors.white54;
|
||||
@override
|
||||
Color get bottomTabBarLabelSelected => Colors.white;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,32 +11,54 @@ import 'package:flutter_app/resources/themes/styles/base_styles.dart';
|
||||
class LightThemeColors implements BaseColorStyles {
|
||||
// general
|
||||
|
||||
Color get background => Color(int.parse(AppHelper.instance.appConfig.themeColors['light']['background']));
|
||||
@override
|
||||
Color get background => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['light']['background']));
|
||||
@override
|
||||
Color get backgroundContainer => Colors.white;
|
||||
Color get primaryContent => Color(int.parse(AppHelper.instance.appConfig.themeColors['light']['primary_text']));
|
||||
@override
|
||||
Color get primaryContent => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['light']['primary_text']));
|
||||
@override
|
||||
Color get primaryAccent => const Color(0xFF87c694);
|
||||
|
||||
@override
|
||||
Color get surfaceBackground => Colors.white;
|
||||
@override
|
||||
Color get surfaceContent => Colors.black;
|
||||
|
||||
// app bar
|
||||
Color get appBarBackground => Color(int.parse(AppHelper.instance.appConfig.themeColors['light']['app_bar_background']));
|
||||
Color get appBarPrimaryContent => Color(int.parse(AppHelper.instance.appConfig.themeColors['light']['app_bar_text']));
|
||||
@override
|
||||
Color get appBarBackground => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['light']['app_bar_background']));
|
||||
@override
|
||||
Color get appBarPrimaryContent => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['light']['app_bar_text']));
|
||||
|
||||
@override
|
||||
Color get inputPrimaryContent => Colors.black;
|
||||
|
||||
// buttons
|
||||
Color get buttonBackground => Color(int.parse(AppHelper.instance.appConfig.themeColors['light']['button_background']));
|
||||
Color get buttonPrimaryContent => Color(int.parse(AppHelper.instance.appConfig.themeColors['light']['button_text']));
|
||||
@override
|
||||
Color get buttonBackground => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['light']['button_background']));
|
||||
@override
|
||||
Color get buttonPrimaryContent => Color(int.parse(
|
||||
AppHelper.instance.appConfig.themeColors['light']['button_text']));
|
||||
|
||||
// bottom tab bar
|
||||
@override
|
||||
Color get bottomTabBarBackground => Colors.white;
|
||||
|
||||
// bottom tab bar - icons
|
||||
@override
|
||||
Color get bottomTabBarIconSelected => Colors.blue;
|
||||
@override
|
||||
Color get bottomTabBarIconUnselected => Colors.black54;
|
||||
|
||||
// bottom tab bar - label
|
||||
@override
|
||||
Color get bottomTabBarLabelUnselected => Colors.black45;
|
||||
@override
|
||||
Color get bottomTabBarLabelSelected => Colors.black;
|
||||
}
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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_spinkit/flutter_spinkit.dart';
|
||||
import 'package:hexcolor/hexcolor.dart';
|
||||
@ -20,7 +19,6 @@ class AppLoaderWidget extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
bool isDark = (Theme.of(context).brightness == Brightness.dark);
|
||||
return SpinKitDoubleBounce(
|
||||
color: HexColor(!isDark ? "#424242" : "#c7c7c7")
|
||||
);
|
||||
color: HexColor(!isDark ? "#424242" : "#c7c7c7"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -29,8 +29,7 @@ class AppVersionWidget extends StatelessWidget {
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasError) return Text("");
|
||||
return Padding(
|
||||
child: Text(
|
||||
"${trans("Version")}: ${snapshot.data.version}",
|
||||
child: Text("${trans("Version")}: ${snapshot.data.version}",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 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:auto_size_text/auto_size_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:hexcolor/hexcolor.dart';
|
||||
@ -27,11 +28,11 @@ class PrimaryButton extends StatelessWidget {
|
||||
key: key,
|
||||
title: title,
|
||||
action: action,
|
||||
textStyle: Theme.of(context)
|
||||
.textTheme
|
||||
.button
|
||||
.copyWith(fontSize: 16, fontWeight: FontWeight.bold, color: ThemeColor.get(context).buttonPrimaryContent),
|
||||
bgColor: ThemeColor.get(context).buttonBackground,
|
||||
textStyle: Theme.of(context).textTheme.button.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ThemeColor.get(context).buttonPrimaryContent),
|
||||
bgColor: ThemeColor.get(context).buttonBackground,
|
||||
);
|
||||
}
|
||||
|
||||
@ -109,14 +110,14 @@ class WooSignalButton extends StatelessWidget {
|
||||
elevation: 0,
|
||||
primary: bgColor,
|
||||
shadowColor: Colors.transparent),
|
||||
child: Text(
|
||||
child: AutoSizeText(
|
||||
title,
|
||||
style: textStyle,
|
||||
maxLines: (screenWidth >= 385 ? 2 : 1),
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onPressed: action ?? null,
|
||||
onPressed: action,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -19,10 +19,9 @@ class CachedImageWidget extends StatelessWidget {
|
||||
this.width = 70,
|
||||
this.placeholder = const Center(
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
backgroundColor: Colors.black12,
|
||||
color: Colors.black54
|
||||
),
|
||||
strokeWidth: 2,
|
||||
backgroundColor: Colors.black12,
|
||||
color: Colors.black54),
|
||||
),
|
||||
this.fit = BoxFit.contain,
|
||||
}) : super(key: key);
|
||||
@ -37,7 +36,7 @@ class CachedImageWidget extends StatelessWidget {
|
||||
Widget build(BuildContext context) => CachedNetworkImage(
|
||||
imageUrl: image,
|
||||
placeholder: (context, url) => placeholder,
|
||||
errorWidget: (context, url, error) => new Icon(Icons.error),
|
||||
errorWidget: (context, url, error) => Icon(Icons.error),
|
||||
height: height,
|
||||
width: width,
|
||||
alignment: Alignment.center,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2021, WooSignal Ltd. All rights reserved.
|
||||
// 2022, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
@ -48,7 +48,7 @@ class _CartIconWidgetState extends State<CartIconWidget> {
|
||||
List<int> cartItems =
|
||||
snapshot.data.map((e) => e.quantity).toList();
|
||||
String cartValue = "0";
|
||||
if (cartItems.length > 0) {
|
||||
if (cartItems.isNotEmpty) {
|
||||
cartValue = cartItems
|
||||
.reduce((value, element) => value + element)
|
||||
.toString();
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CategorySubcategoryScrollWidget extends StatefulWidget {
|
||||
@override
|
||||
_CategorySubcategoryScrollWidgetState createState() =>
|
||||
_CategorySubcategoryScrollWidgetState();
|
||||
}
|
||||
|
||||
class _CategorySubcategoryScrollWidgetState
|
||||
extends State<CategorySubcategoryScrollWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/models/cart.dart';
|
||||
import 'package:flutter_app/app/models/checkout_session.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
class CheckoutCouponAmountWidget extends StatelessWidget {
|
||||
const CheckoutCouponAmountWidget({Key key, @required this.checkoutSession})
|
||||
: super(key: key);
|
||||
|
||||
final CheckoutSession checkoutSession;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<String>(
|
||||
future: Cart.getInstance.couponDiscountAmount(),
|
||||
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.waiting:
|
||||
return AppLoaderWidget();
|
||||
default:
|
||||
if (snapshot.hasError) {
|
||||
return Text("");
|
||||
} else {
|
||||
if (checkoutSession.coupon == null) {
|
||||
return Container();
|
||||
}
|
||||
return Padding(
|
||||
child: CheckoutMetaLine(
|
||||
title: "${trans('Coupon')}: ${checkoutSession.coupon.code}",
|
||||
amount: "-" + formatStringCurrency(total: snapshot.data),
|
||||
),
|
||||
padding: EdgeInsets.only(bottom: 0, top: 0),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/models/checkout_session.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
class CheckoutPaymentTypeWidget extends StatelessWidget {
|
||||
const CheckoutPaymentTypeWidget(
|
||||
{Key key,
|
||||
@required this.context,
|
||||
@required this.checkoutSession,
|
||||
this.resetState})
|
||||
: super(key: key);
|
||||
final CheckoutSession checkoutSession;
|
||||
final BuildContext context;
|
||||
final Function resetState;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool hasPaymentType = checkoutSession.paymentType != null;
|
||||
return CheckoutRowLine(
|
||||
heading: trans(hasPaymentType ? "Payment method" : "Pay with"),
|
||||
leadImage: hasPaymentType
|
||||
? Container(
|
||||
color: Colors.white,
|
||||
child: Image.asset(
|
||||
getImageAsset(checkoutSession.paymentType.assetImage),
|
||||
width: 70,
|
||||
),
|
||||
)
|
||||
: Icon(Icons.payment),
|
||||
leadTitle: hasPaymentType
|
||||
? checkoutSession.paymentType.desc
|
||||
: trans("Select a payment method"),
|
||||
action: _actionPayWith,
|
||||
showBorderBottom: true,
|
||||
);
|
||||
}
|
||||
|
||||
_actionPayWith() {
|
||||
Navigator.pushNamed(context, "/checkout-payment-type")
|
||||
.then((value) => resetState());
|
||||
}
|
||||
}
|
||||
@ -24,50 +24,51 @@ class PayPalCheckout extends StatefulWidget {
|
||||
|
||||
class WebViewState extends NyState<PayPalCheckout> {
|
||||
final Completer<WebViewController> _controller =
|
||||
Completer<WebViewController>();
|
||||
Completer<WebViewController>();
|
||||
|
||||
String payerId = '';
|
||||
int intCount = 0;
|
||||
StreamSubscription<String> _onUrlChanged;
|
||||
WooSignalApp _wooSignalApp = AppHelper.instance.appConfig;
|
||||
final WooSignalApp _wooSignalApp = AppHelper.instance.appConfig;
|
||||
String formCheckoutShippingAddress;
|
||||
|
||||
setCheckoutShippingAddress(CustomerAddress customerAddress) {
|
||||
String tmp = "";
|
||||
if (customerAddress.firstName != null) {
|
||||
tmp +=
|
||||
'<input type="hidden" name="first_name" value="${customerAddress.firstName.replaceAll(new RegExp(r'[^\d\w\s,\-+]+'),'')}">\n';
|
||||
'<input type="hidden" name="first_name" value="${customerAddress.firstName.replaceAll(RegExp(r'[^\d\w\s,\-+]+'), '')}">\n';
|
||||
}
|
||||
if (customerAddress.lastName != null) {
|
||||
tmp +=
|
||||
'<input type="hidden" name="last_name" value="${customerAddress.lastName.replaceAll(new RegExp(r'[^\d\w\s,\-+]+'),'')}">\n';
|
||||
'<input type="hidden" name="last_name" value="${customerAddress.lastName.replaceAll(RegExp(r'[^\d\w\s,\-+]+'), '')}">\n';
|
||||
}
|
||||
if (customerAddress.addressLine != null) {
|
||||
tmp +=
|
||||
'<input type="hidden" name="address1" value="${customerAddress.addressLine.replaceAll(new RegExp(r'[^\d\w\s,\-+]+'),'')}">\n';
|
||||
'<input type="hidden" name="address1" value="${customerAddress.addressLine.replaceAll(RegExp(r'[^\d\w\s,\-+]+'), '')}">\n';
|
||||
}
|
||||
if (customerAddress.city != null) {
|
||||
tmp +=
|
||||
'<input type="hidden" name="city" value="${customerAddress.city.replaceAll(new RegExp(r'[^\d\w\s,\-+]+'),'')}">\n';
|
||||
'<input type="hidden" name="city" value="${customerAddress.city.replaceAll(RegExp(r'[^\d\w\s,\-+]+'), '')}">\n';
|
||||
}
|
||||
if (customerAddress.customerCountry.hasState() &&
|
||||
customerAddress.customerCountry.state.name != null) {
|
||||
tmp +=
|
||||
'<input type="hidden" name="state" value="${customerAddress.customerCountry.state.name.replaceAll(new RegExp(r'[^\d\w\s,\-+]+'),'')}">\n';
|
||||
'<input type="hidden" name="state" value="${customerAddress.customerCountry.state.name.replaceAll(RegExp(r'[^\d\w\s,\-+]+'), '')}">\n';
|
||||
}
|
||||
if (customerAddress.postalCode != null) {
|
||||
tmp +=
|
||||
'<input type="hidden" name="zip" value="${customerAddress.postalCode.replaceAll(new RegExp(r'[^\d\w\s,\-+]+'),'')}">\n';
|
||||
'<input type="hidden" name="zip" value="${customerAddress.postalCode.replaceAll(RegExp(r'[^\d\w\s,\-+]+'), '')}">\n';
|
||||
}
|
||||
if (customerAddress.customerCountry.countryCode != null) {
|
||||
tmp +=
|
||||
'<input type="hidden" name="country" value="${customerAddress.customerCountry.countryCode.replaceAll(new RegExp(r'[^\d\w\s,\-+]+'),'')}">\n';
|
||||
'<input type="hidden" name="country" value="${customerAddress.customerCountry.countryCode.replaceAll(RegExp(r'[^\d\w\s,\-+]+'), '')}">\n';
|
||||
}
|
||||
formCheckoutShippingAddress = tmp;
|
||||
}
|
||||
|
||||
String getPayPalItemName() {
|
||||
return truncateString(widget.description.replaceAll(new RegExp(r'[^\w\s]+'),''), 124);
|
||||
return truncateString(
|
||||
widget.description.replaceAll(RegExp(r'[^\w\s]+'), ''), 124);
|
||||
}
|
||||
|
||||
String getPayPalPaymentType() {
|
||||
@ -75,7 +76,8 @@ class WebViewState extends NyState<PayPalCheckout> {
|
||||
}
|
||||
|
||||
String getPayPalUrl() {
|
||||
bool liveMode = envVal('PAYPAL_LIVE_MODE', defaultValue: _wooSignalApp.paypalLiveMode);
|
||||
bool liveMode =
|
||||
envVal('PAYPAL_LIVE_MODE', defaultValue: _wooSignalApp.paypalLiveMode);
|
||||
return liveMode == true
|
||||
? "https://www.paypal.com/cgi-bin/webscr"
|
||||
: "https://www.sandbox.paypal.com/cgi-bin/webscr";
|
||||
@ -100,8 +102,10 @@ class WebViewState extends NyState<PayPalCheckout> {
|
||||
|
||||
String _loadHTML() {
|
||||
final String strProcessingPayment = trans("Processing Payment");
|
||||
final String strPleaseWait = trans("Please wait, your order is being processed and you will be redirected to the PayPal website.");
|
||||
final String strRedirectMessage = trans("If you are not automatically redirected to PayPal within 5 seconds");
|
||||
final String strPleaseWait = trans(
|
||||
"Please wait, your order is being processed and you will be redirected to the PayPal website.");
|
||||
final String strRedirectMessage = trans(
|
||||
"If you are not automatically redirected to PayPal within 5 seconds");
|
||||
|
||||
return '''
|
||||
<html><head><title>$strProcessingPayment...</title></head>
|
||||
@ -125,7 +129,8 @@ $formCheckoutShippingAddress
|
||||
<center><br><br>$strRedirectMessage...<br><br>
|
||||
<input type="submit" value="Click Here"></center>
|
||||
</form></body></html>
|
||||
'''.toString();
|
||||
'''
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -134,18 +139,17 @@ $formCheckoutShippingAddress
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: SafeArea(
|
||||
child: WebView(
|
||||
initialUrl: Uri.dataFromString(_loadHTML(), mimeType: 'text/html').toString(),
|
||||
initialUrl:
|
||||
Uri.dataFromString(_loadHTML(), mimeType: 'text/html').toString(),
|
||||
javascriptMode: JavascriptMode.unrestricted,
|
||||
onWebViewCreated: (WebViewController webViewController) {
|
||||
_controller.complete(webViewController);
|
||||
},
|
||||
onProgress: (int progress) {
|
||||
},
|
||||
onProgress: (int progress) {},
|
||||
navigationDelegate: (NavigationRequest request) {
|
||||
return NavigationDecision.navigate;
|
||||
},
|
||||
onPageStarted: (String url) {
|
||||
},
|
||||
onPageStarted: (String url) {},
|
||||
onPageFinished: (String url) {
|
||||
if (intCount > 0) {
|
||||
url = url.replaceAll("~", "_");
|
||||
@ -157,7 +161,10 @@ $formCheckoutShippingAddress
|
||||
setState(() {
|
||||
payerId = uri.queryParameters['PayerID'];
|
||||
});
|
||||
Navigator.pop(context, {"status": payerId == null ? "cancelled" : "success", "payerId": payerId});
|
||||
Navigator.pop(context, {
|
||||
"status": payerId == null ? "cancelled" : "success",
|
||||
"payerId": payerId
|
||||
});
|
||||
} else if (url.contains("payment_failure")) {
|
||||
Navigator.pop(context, {"status": "cancelled"});
|
||||
}
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/models/checkout_session.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
class CheckoutSelectCouponWidget extends StatelessWidget {
|
||||
const CheckoutSelectCouponWidget(
|
||||
{Key key,
|
||||
@required this.context,
|
||||
@required this.checkoutSession,
|
||||
@required this.resetState})
|
||||
: super(key: key);
|
||||
|
||||
final CheckoutSession checkoutSession;
|
||||
final BuildContext context;
|
||||
final Function resetState;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool hasCoupon = checkoutSession.coupon != null;
|
||||
return InkWell(
|
||||
onTap: _actionCoupon,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 5),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
hasCoupon == true
|
||||
? IconButton(
|
||||
padding: EdgeInsets.symmetric(vertical: 3),
|
||||
onPressed: _clearCoupon,
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
size: 19,
|
||||
))
|
||||
: null,
|
||||
Text(
|
||||
hasCoupon
|
||||
? "Coupon Applied: " + checkoutSession.coupon.code
|
||||
: trans('Apply Coupon'),
|
||||
style: Theme.of(context).textTheme.subtitle2,
|
||||
),
|
||||
].where((element) => element != null).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_clearCoupon() {
|
||||
CheckoutSession.getInstance.coupon = null;
|
||||
resetState();
|
||||
}
|
||||
|
||||
_actionCoupon() {
|
||||
if (checkoutSession.billingDetails.billingAddress == null) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
description:
|
||||
trans("Please select add your billing/shipping address to proceed"),
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
icon: Icons.local_shipping,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
if (checkoutSession.billingDetails.billingAddress.hasMissingFields()) {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Your billing/shipping details are incomplete"),
|
||||
style: ToastNotificationStyleType.WARNING,
|
||||
icon: Icons.local_shipping,
|
||||
);
|
||||
return;
|
||||
}
|
||||
Navigator.pushNamed(context, "/checkout-coupons")
|
||||
.then((value) => resetState());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/models/checkout_session.dart';
|
||||
import 'package:flutter_app/app/models/customer_address.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:woosignal/models/response/woosignal_app.dart';
|
||||
|
||||
class CheckoutShippingTypeWidget extends StatelessWidget {
|
||||
const CheckoutShippingTypeWidget(
|
||||
{Key key,
|
||||
@required this.context,
|
||||
@required this.wooSignalApp,
|
||||
@required this.checkoutSession,
|
||||
this.resetState})
|
||||
: super(key: key);
|
||||
|
||||
final CheckoutSession checkoutSession;
|
||||
final BuildContext context;
|
||||
final Function resetState;
|
||||
final WooSignalApp wooSignalApp;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool hasDisableShipping = wooSignalApp.disableShipping == 1;
|
||||
if (hasDisableShipping == true) {
|
||||
return null;
|
||||
}
|
||||
bool hasSelectedShippingType = checkoutSession.shippingType != null;
|
||||
return CheckoutRowLine(
|
||||
heading: trans(
|
||||
hasSelectedShippingType ? "Shipping selected" : "Select shipping"),
|
||||
leadImage: Icon(Icons.local_shipping),
|
||||
leadTitle: hasSelectedShippingType
|
||||
? checkoutSession.shippingType.getTitle()
|
||||
: trans("Select a shipping option"),
|
||||
action: _actionSelectShipping,
|
||||
showBorderBottom: false,
|
||||
);
|
||||
}
|
||||
|
||||
_actionSelectShipping() {
|
||||
CustomerAddress shippingAddress =
|
||||
checkoutSession.billingDetails.shippingAddress;
|
||||
if (shippingAddress == null || shippingAddress.customerCountry == null) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Add your shipping details first"),
|
||||
icon: Icons.local_shipping);
|
||||
return;
|
||||
}
|
||||
Navigator.pushNamed(context, "/checkout-shipping-type")
|
||||
.then((value) => resetState());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
|
||||
class CheckoutStoreHeadingWidget extends StatelessWidget {
|
||||
const CheckoutStoreHeadingWidget({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: (Theme.of(context).brightness == Brightness.light)
|
||||
? wsBoxShadow(blurRadius: 10)
|
||||
: null,
|
||||
color: Colors.transparent,
|
||||
),
|
||||
padding: EdgeInsets.all(2),
|
||||
margin: EdgeInsets.only(top: 16),
|
||||
child: ClipRRect(
|
||||
child: StoreLogo(height: 65),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/app/models/checkout_session.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
class CheckoutUserDetailsWidget extends StatelessWidget {
|
||||
const CheckoutUserDetailsWidget(
|
||||
{Key key,
|
||||
@required this.context,
|
||||
@required this.checkoutSession,
|
||||
this.resetState})
|
||||
: super(key: key);
|
||||
final CheckoutSession checkoutSession;
|
||||
final BuildContext context;
|
||||
final Function resetState;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool hasUserCheckoutInfo = (checkoutSession.billingDetails != null &&
|
||||
checkoutSession.billingDetails.billingAddress != null);
|
||||
return CheckoutRowLine(
|
||||
heading: trans("Billing/shipping details"),
|
||||
leadImage: Icon(Icons.home),
|
||||
leadTitle: hasUserCheckoutInfo
|
||||
? (checkoutSession.billingDetails == null ||
|
||||
checkoutSession.billingDetails.billingAddress
|
||||
.hasMissingFields()
|
||||
? trans("Billing address is incomplete")
|
||||
: checkoutSession.billingDetails.billingAddress.addressFull())
|
||||
: trans("Add billing & shipping details"),
|
||||
action: _actionCheckoutDetails,
|
||||
showBorderBottom: true,
|
||||
);
|
||||
}
|
||||
|
||||
_actionCheckoutDetails() {
|
||||
Navigator.pushNamed(context, "/checkout-details").then((e) {
|
||||
resetState();
|
||||
// setState(() {
|
||||
// _showFullLoader = true;
|
||||
// });
|
||||
// _getTaxes();
|
||||
});
|
||||
}
|
||||
}
|
||||
186
LabelStoreMax/lib/resources/widgets/compo_home_widget.dart
Normal file
186
LabelStoreMax/lib/resources/widgets/compo_home_widget.dart
Normal file
@ -0,0 +1,186 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.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/cached_image_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/home_drawer_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
import 'package:flutter_swiper/flutter_swiper.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:woosignal/models/response/product_category.dart';
|
||||
import 'package:woosignal/models/response/woosignal_app.dart';
|
||||
import 'package:woosignal/models/response/products.dart';
|
||||
|
||||
class CompoHomeWidget extends StatefulWidget {
|
||||
CompoHomeWidget({Key key, @required this.wooSignalApp}) : super(key: key);
|
||||
|
||||
final WooSignalApp wooSignalApp;
|
||||
|
||||
@override
|
||||
_CompoHomeWidgetState createState() => _CompoHomeWidgetState();
|
||||
}
|
||||
|
||||
class _CompoHomeWidgetState extends State<CompoHomeWidget> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadHome();
|
||||
}
|
||||
|
||||
_loadHome() async {
|
||||
categories = await appWooSignal((api) =>
|
||||
api.getProductCategories(parent: 0, perPage: 20, hideEmpty: true));
|
||||
categories.sort((category1, category2) =>
|
||||
category1.menuOrder.compareTo(category2.menuOrder));
|
||||
|
||||
for (var category in categories) {
|
||||
List<Product> products = await appWooSignal((api) => api.getProducts(
|
||||
perPage: 10,
|
||||
category: category.id.toString(),
|
||||
status: "publish",
|
||||
stockStatus: "instock"));
|
||||
if (products.isNotEmpty) {
|
||||
categoryAndProducts.addAll({category: products});
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<ProductCategory> categories = [];
|
||||
Map<ProductCategory, List<Product>> categoryAndProducts = {};
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size size = MediaQuery.of(context).size;
|
||||
List<String> bannerImages = widget.wooSignalApp.bannerImages;
|
||||
return Scaffold(
|
||||
drawer: HomeDrawerWidget(wooSignalApp: widget.wooSignalApp),
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: StoreLogo(),
|
||||
elevation: 0,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: categoryAndProducts.isEmpty
|
||||
? AppLoaderWidget()
|
||||
: ListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
if (bannerImages.isNotEmpty)
|
||||
Container(
|
||||
child: Swiper(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return CachedImageWidget(
|
||||
image: bannerImages[index],
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
},
|
||||
itemCount: bannerImages.length,
|
||||
viewportFraction: 0.8,
|
||||
scale: 0.9,
|
||||
),
|
||||
height: size.height / 2.5,
|
||||
),
|
||||
...categoryAndProducts.entries.map((catProds) {
|
||||
double containerHeight = size.height / 1.1;
|
||||
bool hasImage = catProds.key.image != null;
|
||||
if (hasImage == false) {
|
||||
containerHeight = (containerHeight / 2);
|
||||
}
|
||||
return Container(
|
||||
height: containerHeight,
|
||||
width: size.width,
|
||||
margin: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
hasImage
|
||||
? InkWell(
|
||||
child: CachedImageWidget(
|
||||
image: catProds.key.image.src,
|
||||
height: containerHeight / 2,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
onTap: () => _showCategory(catProds.key))
|
||||
: null,
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: 50,
|
||||
minWidth: double.infinity,
|
||||
maxHeight: 80.0,
|
||||
maxWidth: double.infinity,
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
catProds.key.name,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.subtitle1
|
||||
.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Container(
|
||||
width: size.width / 4,
|
||||
child: LinkButton(
|
||||
title: trans("View All"),
|
||||
action: () =>
|
||||
_showCategory(catProds.key),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: hasImage
|
||||
? (containerHeight / 2) / 1.2
|
||||
: containerHeight / 1.2,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
shrinkWrap: false,
|
||||
itemBuilder: (cxt, i) {
|
||||
Product product = catProds.value[i];
|
||||
return Container(
|
||||
height: MediaQuery.of(cxt).size.height,
|
||||
width: size.width / 2.5,
|
||||
child: ProductItemContainer(
|
||||
product: product, onTap: _showProduct),
|
||||
);
|
||||
},
|
||||
itemCount: catProds.value.length,
|
||||
),
|
||||
)
|
||||
].where((e) => e != null).toList(),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_showCategory(ProductCategory productCategory) =>
|
||||
Navigator.pushNamed(context, "/browse-category",
|
||||
arguments: productCategory);
|
||||
|
||||
_showProduct(Product product) =>
|
||||
Navigator.pushNamed(context, "/product-detail", arguments: product);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user