From 63f734177c8ada2bf5080bab755483c8d7a89aa7 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 01:35:08 +0000 Subject: [PATCH 01/15] Updating to latest FlutterFlow output. Has undefined errors from custom widget compile. --- lib/custom_code/widgets/index.dart | 1 + .../widgets/p_f_h_credit_card_widget.dart | 64 +++++++++++++++++++ pubspec.yaml | 1 + 3 files changed, 66 insertions(+) create mode 100644 lib/custom_code/widgets/index.dart create mode 100644 lib/custom_code/widgets/p_f_h_credit_card_widget.dart diff --git a/lib/custom_code/widgets/index.dart b/lib/custom_code/widgets/index.dart new file mode 100644 index 0000000..a8b5af8 --- /dev/null +++ b/lib/custom_code/widgets/index.dart @@ -0,0 +1 @@ +export 'p_f_h_credit_card_widget.dart' show PFHCreditCardWidget; diff --git a/lib/custom_code/widgets/p_f_h_credit_card_widget.dart b/lib/custom_code/widgets/p_f_h_credit_card_widget.dart new file mode 100644 index 0000000..be72b69 --- /dev/null +++ b/lib/custom_code/widgets/p_f_h_credit_card_widget.dart @@ -0,0 +1,64 @@ +// Automatic FlutterFlow imports +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom widgets +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom widget code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +import 'package:flutter_credit_card/flutter_credit_card.dart'; +import 'package:flutter_credit_card/credit_card_brand.dart'; + +const Map CardTypeIconAsset = { + CardType.visa: 'icons/visa.png', + CardType.americanExpress: 'icons/amex.png', + CardType.mastercard: 'icons/mastercard.png', + CardType.unionpay: 'icons/unionpay.png', + CardType.discover: 'icons/discover.png', + CardType.elo: 'icons/elo.png', + CardType.hipercard: 'icons/hipercard.png', +}; + +class PFHCreditCardWidget extends StatefulWidget { + const PFHCreditCardWidget({ + Key? key, + this.width, + this.height, + required this.cardNumber, + required this.cardHolderName, + required this.cvvCode, + required this.expiryDate, + required this.onCreditCardWidgetChange, + required this.showBackView, + }) : super(key: key); + + final double? width; + final double? height; + final String cardNumber; + final String cardHolderName; + final String cvvCode; + final String expiryDate; + final void Function(CreditCardBrand) onCreditCardWidgetChange; + final bool showBackView; + + @override + _PFHCreditCardWidgetState createState() => _PFHCreditCardWidgetState(); +} + +class _PFHCreditCardWidgetState extends State { + @override + Widget build(BuildContext context) { + return CreditCardWidget( + width: widget.width, + height: widget.height, + cardNumber: widget.cardNumber, + cardHolderName: widget.cardHolderName, + cvvCode: widget.cvvCode, + expiryDate: widget.expiryDate, + onCreditCardWidgetChange: widget.onCreditCardWidgetChange, + showBackView: widget.showBackView, + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 6129b67..da1335b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,7 @@ dependencies: firebase_dynamic_links_platform_interface: 0.2.3+24 flutter_animate: 1.0.0 flutter_cache_manager: 3.3.0 + flutter_credit_card: ^3.0.6 flutter_secure_storage: 6.0.0 font_awesome_flutter: 10.1.0 from_css_color: 2.0.0 From 6eefa98480c9eefdde818abf1e898a7458ad1a3d Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 18:03:59 +0000 Subject: [PATCH 02/15] Updating to latest FlutterFlow output. Unknown compile error. Possibly related to labelValidThru --- .../widgets/custom_credit_card_widget.dart | 211 ++++++++++++++++++ lib/custom_code/widgets/index.dart | 2 +- .../widgets/p_f_h_credit_card_widget.dart | 64 ------ lib/pages/account/account_widget.dart | 64 +++--- lib/pages/donation/donation_widget.dart | 38 ++-- lib/pages/payment/payment_widget.dart | 38 ++-- web/manifest.json | 23 -- 7 files changed, 282 insertions(+), 158 deletions(-) create mode 100644 lib/custom_code/widgets/custom_credit_card_widget.dart delete mode 100644 lib/custom_code/widgets/p_f_h_credit_card_widget.dart delete mode 100644 web/manifest.json diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart new file mode 100644 index 0000000..29cc71a --- /dev/null +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -0,0 +1,211 @@ +// Automatic FlutterFlow imports +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom widgets +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom widget code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +import 'package:flutter_credit_card/flutter_credit_card.dart'; +import 'package:flutter_credit_card/constants.dart'; +import 'package:flutter_credit_card/credit_card_brand.dart'; + +const Map CardTypeIconAsset = { + CardType.visa: 'icons/visa.png', + CardType.americanExpress: 'icons/amex.png', + CardType.mastercard: 'icons/mastercard.png', + CardType.unionpay: 'icons/unionpay.png', + CardType.discover: 'icons/discover.png', + CardType.elo: 'icons/elo.png', + CardType.hipercard: 'icons/hipercard.png', +}; + +class CustomCreditCardWidget extends StatefulWidget { + const CustomCreditCardWidget({ + Key? key, + this.width, + this.height, + required this.cardNumber, + required this.expiryDate, + required this.cardHolderName, + required this.cvvCode, + required this.showBackView, + this.bankName, + this.animationDuration = const Duration(milliseconds: 500), + this.cardHeight, + this.cardWidth, + this.textStyle, + this.cardBgColor = const Color(0xff1b447b), + this.obscureCardNumber = true, + this.obscureCardCvv = true, + this.labelCardHolder = 'CARD HOLDER', + this.labelExpiredDate = 'MM/YY', + // this.labelValidThru = 'VALID\nTHRU', + this.cardType, + this.isHolderNameVisible = false, + this.backgroundImage, + this.backgroundNetworkImage, + this.glassmorphismConfig, + this.isChipVisible = true, + this.isSwipeGestureEnabled = true, + this.customCardTypeIcons = const [], + required this.onCreditCardWidgetChange, + this.padding = AppConstants.creditCardPadding, + this.chipColor, + this.frontCardBorder, + this.backCardBorder, + this.obscureInitialCardNumber = false, + }) : super(key: key); + + final double? width; + final double? height; + + /// A string indicating number on the card. + final String cardNumber; + + /// A string indicating expiry date for the card. + final String expiryDate; + + /// A string indicating name of the card holder. + final String cardHolderName; + + /// A String indicating cvv code. + final String cvvCode; + + /// Shows back side of the card at initial level when setting it to true./// This is helpful when focusing on cvv. + final bool showBackView; + + /// A string indicating name of the bank. + final String? bankName; + + /// Duration for flip animation. Defaults to 500 milliseconds. + final Duration animationDuration; + + /// Sets height of the front and back side of the card. + final double? cardHeight; + + /// Sets width of the front and back side of the card. + final double? cardWidth; + + /// Applies text style to cardNumber, expiryDate, cardHolderName and cvvCode. + final TextStyle? textStyle; + + /// Applies background color for card UI. + final Color cardBgColor; + + /// If this flag is enabled then card number is replaced with obscuring + /// characters to hide the content. Initial 4 and last 4 character + /// doesn't get obscured. Defaults to true. + final bool obscureCardNumber; + + /// If this flag is enabled then cvv is replaced with obscuring characters + /// to hide the content. Defaults to true. + final bool obscureCardCvv; + + /// Default label for card holder name. This is shown when user hasn't + /// entered any text for card holder name. + final String labelCardHolder; + + /// Default label for expiry date. This is shown when user hasn't entered any + /// text for expiry date. + final String labelExpiredDate; + + /// Default label for valid thru. This is shown when user hasn't entered any + /// text for valid thru. + // final String labelValidThru; + + /// Sets type of the card. An small image is shown based on selected type + /// of the card at bottom right corner. If this is set to null then image + /// shown automatically based on credit card number. + final CardType? cardType; + + /// Enable/disable card holder name. Defaults to false. + final bool isHolderNameVisible; + + /// Shows image as background of the card widget. This should be available + /// locally in your assets folder. + final String? backgroundImage; + + /// Shows image as background of the card widget from the network. + final String? backgroundNetworkImage; + + /// Used to provide glassmorphism effect to credit card widget. + final Glassmorphism? glassmorphismConfig; + + /// Enable/disable showcasing EMV chip UI. Defaults to true. + final bool isChipVisible; + + /// Enable/disable gestures on credit card widget. If enabled then flip + /// animation is started when swiped or tapped. Defaults to true. + final bool isSwipeGestureEnabled; + + /// Replaces credit card image with provided widget. + final List customCardTypeIcons; + + /// Provides a callback any time there is a change in credit card brand. + final void Function(CreditCardBrand) onCreditCardWidgetChange; + + /// Provides equal padding inside the credit card widget in all directions. + /// Defaults to 16. + final double padding; + + /// Provides color to EMV chip on the card. + final Color? chipColor; + + /// Provides border in front of credit card widget. + final BoxBorder? frontCardBorder; + + /// Provides border at back of credit card widget. + final BoxBorder? backCardBorder; + + /// Also obscures initial 4 card numbers with obscuring characters. This + /// flag requires [obscureCardNumber] to be true. This flag defaults to false. + final bool obscureInitialCardNumber; + + @override + _CustomCreditCardWidgetState createState() => _CustomCreditCardWidgetState(); +} + +class _CustomCreditCardWidgetState extends State { + @override + Widget build(BuildContext context) { + return Container( + width: widget.width, + height: widget.height, + child: CreditCardWidget( + cardNumber: widget.cardNumber, + expiryDate: widget.expiryDate, + cardHolderName: widget.cardHolderName, + cvvCode: widget.cvvCode, + showBackView: widget.showBackView, + bankName: widget.bankName, + animationDuration: widget.animationDuration, + height: widget.cardHeight, + width: widget.cardWidth, + textStyle: widget.textStyle, + cardBgColor: widget.cardBgColor, + obscureCardNumber: widget.obscureCardNumber, + obscureCardCvv: widget.obscureCardCvv, + labelCardHolder: widget.labelCardHolder, + labelExpiredDate: widget.labelExpiredDate, + // labelValidThru: widget.labelValidThru, + cardType: widget.cardType, + isHolderNameVisible: widget.isHolderNameVisible, + backgroundImage: widget.backgroundImage, + backgroundNetworkImage: widget.backgroundNetworkImage, + glassmorphismConfig: widget.glassmorphismConfig, + isChipVisible: widget.isChipVisible, + isSwipeGestureEnabled: widget.isSwipeGestureEnabled, + customCardTypeIcons: widget.customCardTypeIcons, + onCreditCardWidgetChange: widget.onCreditCardWidgetChange, + padding: widget.padding, + chipColor: widget.chipColor, + frontCardBorder: widget.frontCardBorder, + backCardBorder: widget.backCardBorder, + obscureInitialCardNumber: widget.obscureInitialCardNumber, + ), + ); + } +} diff --git a/lib/custom_code/widgets/index.dart b/lib/custom_code/widgets/index.dart index a8b5af8..f148a7e 100644 --- a/lib/custom_code/widgets/index.dart +++ b/lib/custom_code/widgets/index.dart @@ -1 +1 @@ -export 'p_f_h_credit_card_widget.dart' show PFHCreditCardWidget; +export 'custom_credit_card_widget.dart' show CustomCreditCardWidget; diff --git a/lib/custom_code/widgets/p_f_h_credit_card_widget.dart b/lib/custom_code/widgets/p_f_h_credit_card_widget.dart deleted file mode 100644 index be72b69..0000000 --- a/lib/custom_code/widgets/p_f_h_credit_card_widget.dart +++ /dev/null @@ -1,64 +0,0 @@ -// Automatic FlutterFlow imports -import '/backend/backend.dart'; -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import 'index.dart'; // Imports other custom widgets -import '/flutter_flow/custom_functions.dart'; // Imports custom functions -import 'package:flutter/material.dart'; -// Begin custom widget code -// DO NOT REMOVE OR MODIFY THE CODE ABOVE! - -import 'package:flutter_credit_card/flutter_credit_card.dart'; -import 'package:flutter_credit_card/credit_card_brand.dart'; - -const Map CardTypeIconAsset = { - CardType.visa: 'icons/visa.png', - CardType.americanExpress: 'icons/amex.png', - CardType.mastercard: 'icons/mastercard.png', - CardType.unionpay: 'icons/unionpay.png', - CardType.discover: 'icons/discover.png', - CardType.elo: 'icons/elo.png', - CardType.hipercard: 'icons/hipercard.png', -}; - -class PFHCreditCardWidget extends StatefulWidget { - const PFHCreditCardWidget({ - Key? key, - this.width, - this.height, - required this.cardNumber, - required this.cardHolderName, - required this.cvvCode, - required this.expiryDate, - required this.onCreditCardWidgetChange, - required this.showBackView, - }) : super(key: key); - - final double? width; - final double? height; - final String cardNumber; - final String cardHolderName; - final String cvvCode; - final String expiryDate; - final void Function(CreditCardBrand) onCreditCardWidgetChange; - final bool showBackView; - - @override - _PFHCreditCardWidgetState createState() => _PFHCreditCardWidgetState(); -} - -class _PFHCreditCardWidgetState extends State { - @override - Widget build(BuildContext context) { - return CreditCardWidget( - width: widget.width, - height: widget.height, - cardNumber: widget.cardNumber, - cardHolderName: widget.cardHolderName, - cvvCode: widget.cvvCode, - expiryDate: widget.expiryDate, - onCreditCardWidgetChange: widget.onCreditCardWidgetChange, - showBackView: widget.showBackView, - ); - } -} diff --git a/lib/pages/account/account_widget.dart b/lib/pages/account/account_widget.dart index 9cdbf74..c5c24a2 100644 --- a/lib/pages/account/account_widget.dart +++ b/lib/pages/account/account_widget.dart @@ -40,41 +40,41 @@ class _AccountWidgetState extends State { Widget build(BuildContext context) { context.watch(); - return Scaffold( - key: scaffoldKey, - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: AppBar( + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + child: Scaffold( + key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - leading: FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: Icon( - Icons.arrow_back_rounded, - color: FlutterFlowTheme.of(context).secondaryBackground, - size: 30.0, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, ), - onPressed: () async { - context.pop(); - }, - ), - title: Text( - 'Account', - style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', - color: FlutterFlowTheme.of(context).secondaryBackground, - fontSize: 22.0, - ), + title: Text( + 'Account', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, ), - actions: [], - centerTitle: true, - elevation: 0.0, - ), - body: SafeArea( - child: GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + body: SafeArea( child: Column( mainAxisSize: MainAxisSize.max, children: [], diff --git a/lib/pages/donation/donation_widget.dart b/lib/pages/donation/donation_widget.dart index 362d43a..cf7b2ed 100644 --- a/lib/pages/donation/donation_widget.dart +++ b/lib/pages/donation/donation_widget.dart @@ -44,27 +44,27 @@ class _DonationWidgetState extends State { Widget build(BuildContext context) { context.watch(); - return Scaffold( - key: scaffoldKey, - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: AppBar( + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + child: Scaffold( + key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - title: Text( - 'Donation', - style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', - color: FlutterFlowTheme.of(context).secondaryBackground, - fontSize: 22.0, - ), + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text( + 'Donation', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, ), - actions: [], - centerTitle: true, - elevation: 0.0, - ), - body: SafeArea( - child: GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + body: SafeArea( child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, diff --git a/lib/pages/payment/payment_widget.dart b/lib/pages/payment/payment_widget.dart index f5d6f17..8a8746f 100644 --- a/lib/pages/payment/payment_widget.dart +++ b/lib/pages/payment/payment_widget.dart @@ -47,27 +47,27 @@ class _PaymentWidgetState extends State { Widget build(BuildContext context) { context.watch(); - return Scaffold( - key: scaffoldKey, - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: AppBar( + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + child: Scaffold( + key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - title: Text( - 'Donation', - style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', - color: FlutterFlowTheme.of(context).secondaryBackground, - fontSize: 22.0, - ), + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text( + 'Donation', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, ), - actions: [], - centerTitle: true, - elevation: 0.0, - ), - body: SafeArea( - child: GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + body: SafeArea( child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, diff --git a/web/manifest.json b/web/manifest.json deleted file mode 100644 index d73b900..0000000 --- a/web/manifest.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "Pennies From Heaven", - "short_name": "Pennies From Heaven", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] -} From 8c1bc8ad9795c4ab326719e9ac5f86169ef28870 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 21:25:19 +0000 Subject: [PATCH 03/15] Updating to latest FlutterFlow output. April 13 ... Reproducing compile error (online) not occuring when compiled natively. --- lib/auth/anonymous_auth.dart | 9 - lib/auth/auth_manager.dart | 68 ++++++ lib/auth/auth_util.dart | 219 ------------------ lib/auth/base_auth_user_provider.dart | 34 +++ lib/auth/email_auth.dart | 18 -- lib/auth/firebase_auth/anonymous_auth.dart | 4 + lib/auth/{ => firebase_auth}/apple_auth.dart | 6 - lib/auth/firebase_auth/auth_util.dart | 73 ++++++ lib/auth/firebase_auth/email_auth.dart | 17 ++ .../firebase_auth/firebase_auth_manager.dart | 215 +++++++++++++++++ .../firebase_auth/firebase_user_provider.dart | 55 +++++ lib/auth/firebase_auth/google_auth.dart | 23 ++ lib/auth/firebase_auth/jwt_token_auth.dart | 4 + lib/auth/firebase_user_provider.dart | 23 -- lib/auth/google_auth.dart | 29 --- lib/auth/jwt_token_auth.dart | 8 - lib/backend/backend.dart | 2 +- lib/backend/schema/serializers.dart | 3 + lib/flutter_flow/custom_functions.dart | 2 +- .../flutter_flow_icon_button.dart | 12 +- lib/flutter_flow/nav/nav.dart | 8 +- lib/main.dart | 6 +- 22 files changed, 516 insertions(+), 322 deletions(-) delete mode 100644 lib/auth/anonymous_auth.dart create mode 100644 lib/auth/auth_manager.dart delete mode 100644 lib/auth/auth_util.dart create mode 100644 lib/auth/base_auth_user_provider.dart delete mode 100644 lib/auth/email_auth.dart create mode 100644 lib/auth/firebase_auth/anonymous_auth.dart rename lib/auth/{ => firebase_auth}/apple_auth.dart (92%) create mode 100644 lib/auth/firebase_auth/auth_util.dart create mode 100644 lib/auth/firebase_auth/email_auth.dart create mode 100644 lib/auth/firebase_auth/firebase_auth_manager.dart create mode 100644 lib/auth/firebase_auth/firebase_user_provider.dart create mode 100644 lib/auth/firebase_auth/google_auth.dart create mode 100644 lib/auth/firebase_auth/jwt_token_auth.dart delete mode 100644 lib/auth/firebase_user_provider.dart delete mode 100644 lib/auth/google_auth.dart delete mode 100644 lib/auth/jwt_token_auth.dart diff --git a/lib/auth/anonymous_auth.dart b/lib/auth/anonymous_auth.dart deleted file mode 100644 index 9db07cb..0000000 --- a/lib/auth/anonymous_auth.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/material.dart'; - -import 'auth_util.dart'; - -Future signInAnonymously(BuildContext context) async { - final signInFunc = () => FirebaseAuth.instance.signInAnonymously(); - return signInOrCreateAccount(context, signInFunc, 'ANONYMOUS'); -} diff --git a/lib/auth/auth_manager.dart b/lib/auth/auth_manager.dart new file mode 100644 index 0000000..81a64cb --- /dev/null +++ b/lib/auth/auth_manager.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; + +import 'base_auth_user_provider.dart'; + +abstract class AuthManager { + Future signOut(); + Future deleteUser(BuildContext context); + Future resetPassword({required String email, required BuildContext context}); + Future sendEmailVerification() async => currentUser?.sendEmailVerification(); +} + +mixin EmailSignInManager on AuthManager { + Future signInWithEmail( + BuildContext context, + String email, + String password, + ); + + Future createAccountWithEmail( + BuildContext context, + String email, + String password, + ); +} + +mixin AnonymousSignInManager on AuthManager { + Future signInAnonymously(BuildContext context); +} + +mixin AppleSignInManager on AuthManager { + Future signInWithApple(BuildContext context); +} + +mixin GoogleSignInManager on AuthManager { + Future signInWithGoogle(BuildContext context); +} + +mixin JwtSignInManager on AuthManager { + Future signInWithJwtToken( + BuildContext context, + String jwtToken, + ); +} + +mixin PhoneSignInManager on AuthManager { + Future beginPhoneAuth({ + required BuildContext context, + required String phoneNumber, + required VoidCallback onCodeSent, + }); + + Future verifySmsCode({ + required BuildContext context, + required String smsCode, + }); +} + +mixin FacebookSignInManager on AuthManager { + Future signInWithFacebook(BuildContext context); +} + +mixin MicrosoftSignInManager on AuthManager { + Future signInWithMicrosoft( + BuildContext context, + List scopes, + String tenantId, + ); +} diff --git a/lib/auth/auth_util.dart b/lib/auth/auth_util.dart deleted file mode 100644 index 1369182..0000000 --- a/lib/auth/auth_util.dart +++ /dev/null @@ -1,219 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/foundation.dart' show kIsWeb; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/material.dart'; -import '../flutter_flow/flutter_flow_util.dart'; - -import '../backend/backend.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:stream_transform/stream_transform.dart'; -import 'firebase_user_provider.dart'; - -export 'anonymous_auth.dart'; -export 'apple_auth.dart'; -export 'email_auth.dart'; -export 'google_auth.dart'; -export 'jwt_token_auth.dart'; - -/// Tries to sign in or create an account using Firebase Auth. -/// Returns the User object if sign in was successful. -Future signInOrCreateAccount( - BuildContext context, - Future Function() signInFunc, - String authProvider, -) async { - try { - final userCredential = await signInFunc(); - if (userCredential?.user != null) { - await maybeCreateUser(userCredential!.user!); - } - return userCredential?.user; - } on FirebaseAuthException catch (e) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: ${e.message!}')), - ); - return null; - } -} - -Future signOut() { - return FirebaseAuth.instance.signOut(); -} - -Future deleteUser(BuildContext context) async { - try { - if (currentUser?.user == null) { - print('Error: delete user attempted with no logged in user!'); - return; - } - await currentUser?.user?.delete(); - } on FirebaseAuthException catch (e) { - if (e.code == 'requires-recent-login') { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Too long since most recent sign in. Sign in again before deleting your account.')), - ); - } - } -} - -Future resetPassword( - {required String email, required BuildContext context}) async { - try { - await FirebaseAuth.instance.sendPasswordResetEmail(email: email); - } on FirebaseAuthException catch (e) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: ${e.message!}')), - ); - return null; - } - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Password reset email sent')), - ); -} - -Future sendEmailVerification() async => - currentUser?.user?.sendEmailVerification(); - -String get currentUserEmail => - currentUserDocument?.email ?? currentUser?.user?.email ?? ''; - -String get currentUserUid => currentUser?.user?.uid ?? ''; - -String get currentUserDisplayName => - currentUserDocument?.displayName ?? currentUser?.user?.displayName ?? ''; - -String get currentUserPhoto => - currentUserDocument?.photoUrl ?? currentUser?.user?.photoURL ?? ''; - -String get currentPhoneNumber => - currentUserDocument?.phoneNumber ?? currentUser?.user?.phoneNumber ?? ''; - -String get currentJwtToken => _currentJwtToken ?? ''; - -bool get currentUserEmailVerified { - // Reloads the user when checking in order to get the most up to date - // email verified status. - if (currentUser?.user != null && !currentUser!.user!.emailVerified) { - currentUser!.user! - .reload() - .then((_) => currentUser!.user = FirebaseAuth.instance.currentUser); - } - return currentUser?.user?.emailVerified ?? false; -} - -/// Create a Stream that listens to the current user's JWT Token, since Firebase -/// generates a new token every hour. -String? _currentJwtToken; -final jwtTokenStream = FirebaseAuth.instance - .idTokenChanges() - .map((user) async => _currentJwtToken = await user?.getIdToken()) - .asBroadcastStream(); - -// Set when using phone verification (after phone number is provided). -String? _phoneAuthVerificationCode; -// Set when using phone sign in in web mode (ignored otherwise). -ConfirmationResult? _webPhoneAuthConfirmationResult; - -Future beginPhoneAuth({ - required BuildContext context, - required String phoneNumber, - required VoidCallback onCodeSent, -}) async { - if (kIsWeb) { - _webPhoneAuthConfirmationResult = - await FirebaseAuth.instance.signInWithPhoneNumber(phoneNumber); - onCodeSent(); - return; - } - final completer = Completer(); - // If you'd like auto-verification, without the user having to enter the SMS - // code manually. Follow these instructions: - // * For Android: https://firebase.google.com/docs/auth/android/phone-auth?authuser=0#enable-app-verification (SafetyNet set up) - // * For iOS: https://firebase.google.com/docs/auth/ios/phone-auth?authuser=0#start-receiving-silent-notifications - // * Finally modify verificationCompleted below as instructed. - await FirebaseAuth.instance.verifyPhoneNumber( - phoneNumber: phoneNumber, - timeout: Duration(seconds: 5), - verificationCompleted: (phoneAuthCredential) async { - await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential); - // If you've implemented auto-verification, navigate to home page or - // onboarding page here manually. Uncomment the lines below and replace - // DestinationPage() with the desired widget. - // await Navigator.push( - // context, - // MaterialPageRoute(builder: (_) => DestinationPage()), - // ); - }, - verificationFailed: (e) { - completer.complete(false); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Error: ${e.message!}'), - )); - }, - codeSent: (verificationId, _) { - _phoneAuthVerificationCode = verificationId; - completer.complete(true); - onCodeSent(); - }, - codeAutoRetrievalTimeout: (_) {}, - ); - - return completer.future; -} - -Future verifySmsCode({ - required BuildContext context, - required String smsCode, -}) async { - if (kIsWeb) { - return signInOrCreateAccount( - context, - () => _webPhoneAuthConfirmationResult!.confirm(smsCode), - 'PHONE', - ); - } else { - final authCredential = PhoneAuthProvider.credential( - verificationId: _phoneAuthVerificationCode!, smsCode: smsCode); - return signInOrCreateAccount( - context, - () => FirebaseAuth.instance.signInWithCredential(authCredential), - 'PHONE', - ); - } -} - -DocumentReference? get currentUserReference => currentUser?.user != null - ? UsersRecord.collection.doc(currentUser!.user!.uid) - : null; - -UsersRecord? currentUserDocument; -final authenticatedUserStream = FirebaseAuth.instance - .authStateChanges() - .map((user) => user?.uid ?? '') - .switchMap( - (uid) => uid.isEmpty - ? Stream.value(null) - : UsersRecord.getDocument(UsersRecord.collection.doc(uid)) - .handleError((_) {}), - ) - .map((user) => currentUserDocument = user) - .asBroadcastStream(); - -class AuthUserStreamWidget extends StatelessWidget { - const AuthUserStreamWidget({Key? key, required this.builder}) - : super(key: key); - - final WidgetBuilder builder; - - @override - Widget build(BuildContext context) => StreamBuilder( - stream: authenticatedUserStream, - builder: (context, _) => builder(context), - ); -} diff --git a/lib/auth/base_auth_user_provider.dart b/lib/auth/base_auth_user_provider.dart new file mode 100644 index 0000000..39e2097 --- /dev/null +++ b/lib/auth/base_auth_user_provider.dart @@ -0,0 +1,34 @@ +class AuthUserInfo { + const AuthUserInfo({ + this.uid, + this.email, + this.displayName, + this.photoUrl, + this.phoneNumber, + }); + + final String? uid; + final String? email; + final String? displayName; + final String? photoUrl; + final String? phoneNumber; +} + +abstract class BaseAuthUser { + bool get loggedIn; + bool get emailVerified; + + AuthUserInfo get authUserInfo; + + Future? delete(); + Future? sendEmailVerification(); + + String? get uid => authUserInfo.uid; + String? get email => authUserInfo.email; + String? get displayName => authUserInfo.displayName; + String? get photoUrl => authUserInfo.photoUrl; + String? get phoneNumber => authUserInfo.phoneNumber; +} + +BaseAuthUser? currentUser; +bool get loggedIn => currentUser?.loggedIn ?? false; diff --git a/lib/auth/email_auth.dart b/lib/auth/email_auth.dart deleted file mode 100644 index 40d7d25..0000000 --- a/lib/auth/email_auth.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/material.dart'; - -import 'auth_util.dart'; - -Future signInWithEmail( - BuildContext context, String email, String password) async { - final signInFunc = () => FirebaseAuth.instance - .signInWithEmailAndPassword(email: email.trim(), password: password); - return signInOrCreateAccount(context, signInFunc, 'EMAIL'); -} - -Future createAccountWithEmail( - BuildContext context, String email, String password) async { - final createAccountFunc = () => FirebaseAuth.instance - .createUserWithEmailAndPassword(email: email.trim(), password: password); - return signInOrCreateAccount(context, createAccountFunc, 'EMAIL'); -} diff --git a/lib/auth/firebase_auth/anonymous_auth.dart b/lib/auth/firebase_auth/anonymous_auth.dart new file mode 100644 index 0000000..bf6502c --- /dev/null +++ b/lib/auth/firebase_auth/anonymous_auth.dart @@ -0,0 +1,4 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +Future anonymousSignInFunc() => + FirebaseAuth.instance.signInAnonymously(); diff --git a/lib/auth/apple_auth.dart b/lib/auth/firebase_auth/apple_auth.dart similarity index 92% rename from lib/auth/apple_auth.dart rename to lib/auth/firebase_auth/apple_auth.dart index f15938f..df1e6d4 100644 --- a/lib/auth/apple_auth.dart +++ b/lib/auth/firebase_auth/apple_auth.dart @@ -4,11 +4,8 @@ import 'dart:math'; import 'package:crypto/crypto.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:sign_in_with_apple/sign_in_with_apple.dart'; -import 'auth_util.dart'; - /// Generates a cryptographically secure random nonce, to be included in a /// credential request. String generateNonce([int length = 32]) { @@ -61,6 +58,3 @@ Future appleSignIn() async { // not match the nonce in `appleCredential.identityToken`, sign in will fail. return await FirebaseAuth.instance.signInWithCredential(oauthCredential); } - -Future signInWithApple(BuildContext context) => - signInOrCreateAccount(context, appleSignIn, 'APPLE'); diff --git a/lib/auth/firebase_auth/auth_util.dart b/lib/auth/firebase_auth/auth_util.dart new file mode 100644 index 0000000..05cc89b --- /dev/null +++ b/lib/auth/firebase_auth/auth_util.dart @@ -0,0 +1,73 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import '../auth_manager.dart'; +import '../base_auth_user_provider.dart'; +import '../../flutter_flow/flutter_flow_util.dart'; + +import '../../backend/backend.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:stream_transform/stream_transform.dart'; +import 'firebase_auth_manager.dart'; + +export 'firebase_auth_manager.dart'; + +final _authManager = FirebaseAuthManager(); +FirebaseAuthManager get authManager => _authManager; + +String get currentUserEmail => + currentUserDocument?.email ?? currentUser?.email ?? ''; + +String get currentUserUid => currentUser?.uid ?? ''; + +String get currentUserDisplayName => + currentUserDocument?.displayName ?? currentUser?.displayName ?? ''; + +String get currentUserPhoto => + currentUserDocument?.photoUrl ?? currentUser?.photoUrl ?? ''; + +String get currentPhoneNumber => + currentUserDocument?.phoneNumber ?? currentUser?.phoneNumber ?? ''; + +String get currentJwtToken => _currentJwtToken ?? ''; + +bool get currentUserEmailVerified => currentUser?.emailVerified ?? false; + +/// Create a Stream that listens to the current user's JWT Token, since Firebase +/// generates a new token every hour. +String? _currentJwtToken; +final jwtTokenStream = FirebaseAuth.instance + .idTokenChanges() + .map((user) async => _currentJwtToken = await user?.getIdToken()) + .asBroadcastStream(); + +DocumentReference? get currentUserReference => + loggedIn ? UsersRecord.collection.doc(currentUser!.uid) : null; + +UsersRecord? currentUserDocument; +final authenticatedUserStream = FirebaseAuth.instance + .authStateChanges() + .map((user) => user?.uid ?? '') + .switchMap( + (uid) => uid.isEmpty + ? Stream.value(null) + : UsersRecord.getDocument(UsersRecord.collection.doc(uid)) + .handleError((_) {}), + ) + .map((user) => currentUserDocument = user) + .asBroadcastStream(); + +class AuthUserStreamWidget extends StatelessWidget { + const AuthUserStreamWidget({Key? key, required this.builder}) + : super(key: key); + + final WidgetBuilder builder; + + @override + Widget build(BuildContext context) => StreamBuilder( + stream: authenticatedUserStream, + builder: (context, _) => builder(context), + ); +} diff --git a/lib/auth/firebase_auth/email_auth.dart b/lib/auth/firebase_auth/email_auth.dart new file mode 100644 index 0000000..f917ce8 --- /dev/null +++ b/lib/auth/firebase_auth/email_auth.dart @@ -0,0 +1,17 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +Future emailSignInFunc( + String email, + String password, +) => + FirebaseAuth.instance + .signInWithEmailAndPassword(email: email.trim(), password: password); + +Future emailCreateAccountFunc( + String email, + String password, +) => + FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email.trim(), + password: password, + ); diff --git a/lib/auth/firebase_auth/firebase_auth_manager.dart b/lib/auth/firebase_auth/firebase_auth_manager.dart new file mode 100644 index 0000000..22ede42 --- /dev/null +++ b/lib/auth/firebase_auth/firebase_auth_manager.dart @@ -0,0 +1,215 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import '../auth_manager.dart'; +import '../base_auth_user_provider.dart'; +import '../../flutter_flow/flutter_flow_util.dart'; + +import '../../backend/backend.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:stream_transform/stream_transform.dart'; +import 'anonymous_auth.dart'; +import 'apple_auth.dart'; +import 'email_auth.dart'; +import 'firebase_user_provider.dart'; +import 'google_auth.dart'; +import 'jwt_token_auth.dart'; + +export '../base_auth_user_provider.dart'; + +class FirebaseAuthManager extends AuthManager + with + EmailSignInManager, + AnonymousSignInManager, + AppleSignInManager, + GoogleSignInManager, + JwtSignInManager, + PhoneSignInManager { + // Set when using phone verification (after phone number is provided). + String? _phoneAuthVerificationCode; + // Set when using phone sign in in web mode (ignored otherwise). + ConfirmationResult? _webPhoneAuthConfirmationResult; + + @override + Future signOut() { + return FirebaseAuth.instance.signOut(); + } + + @override + Future deleteUser(BuildContext context) async { + try { + if (!loggedIn) { + print('Error: delete user attempted with no logged in user!'); + return; + } + await currentUser?.delete(); + } on FirebaseAuthException catch (e) { + if (e.code == 'requires-recent-login') { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Too long since most recent sign in. Sign in again before deleting your account.')), + ); + } + } + } + + @override + Future resetPassword({ + required String email, + required BuildContext context, + }) async { + try { + await FirebaseAuth.instance.sendPasswordResetEmail(email: email); + } on FirebaseAuthException catch (e) { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error: ${e.message!}')), + ); + return null; + } + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Password reset email sent')), + ); + } + + @override + Future signInWithEmail( + BuildContext context, + String email, + String password, + ) => + _signInOrCreateAccount( + context, + () => emailSignInFunc(email, password), + 'EMAIL', + ); + + @override + Future createAccountWithEmail( + BuildContext context, + String email, + String password, + ) => + _signInOrCreateAccount( + context, + () => emailCreateAccountFunc(email, password), + 'EMAIL', + ); + + @override + Future signInAnonymously( + BuildContext context, + ) => + _signInOrCreateAccount(context, anonymousSignInFunc, 'ANONYMOUS'); + + @override + Future signInWithApple(BuildContext context) => + _signInOrCreateAccount(context, appleSignIn, 'APPLE'); + + @override + Future signInWithGoogle(BuildContext context) => + _signInOrCreateAccount(context, googleSignInFunc, 'GOOGLE'); + + @override + Future signInWithJwtToken( + BuildContext context, String jwtToken) => + _signInOrCreateAccount(context, () => jwtTokenSignIn(jwtToken), 'JWT'); + + @override + Future beginPhoneAuth({ + required BuildContext context, + required String phoneNumber, + required VoidCallback onCodeSent, + }) async { + if (kIsWeb) { + _webPhoneAuthConfirmationResult = + await FirebaseAuth.instance.signInWithPhoneNumber(phoneNumber); + onCodeSent(); + return; + } + final completer = Completer(); + // If you'd like auto-verification, without the user having to enter the SMS + // code manually. Follow these instructions: + // * For Android: https://firebase.google.com/docs/auth/android/phone-auth?authuser=0#enable-app-verification (SafetyNet set up) + // * For iOS: https://firebase.google.com/docs/auth/ios/phone-auth?authuser=0#start-receiving-silent-notifications + // * Finally modify verificationCompleted below as instructed. + await FirebaseAuth.instance.verifyPhoneNumber( + phoneNumber: phoneNumber, + timeout: Duration(seconds: 5), + verificationCompleted: (phoneAuthCredential) async { + await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential); + // If you've implemented auto-verification, navigate to home page or + // onboarding page here manually. Uncomment the lines below and replace + // DestinationPage() with the desired widget. + // await Navigator.push( + // context, + // MaterialPageRoute(builder: (_) => DestinationPage()), + // ); + }, + verificationFailed: (e) { + completer.complete(false); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('Error: ${e.message!}'), + )); + }, + codeSent: (verificationId, _) { + _phoneAuthVerificationCode = verificationId; + completer.complete(true); + onCodeSent(); + }, + codeAutoRetrievalTimeout: (_) {}, + ); + + return completer.future; + } + + @override + Future verifySmsCode({ + required BuildContext context, + required String smsCode, + }) { + if (kIsWeb) { + return _signInOrCreateAccount( + context, + () => _webPhoneAuthConfirmationResult!.confirm(smsCode), + 'PHONE', + ); + } else { + final authCredential = PhoneAuthProvider.credential( + verificationId: _phoneAuthVerificationCode!, smsCode: smsCode); + return _signInOrCreateAccount( + context, + () => FirebaseAuth.instance.signInWithCredential(authCredential), + 'PHONE', + ); + } + } + + /// Tries to sign in or create an account using Firebase Auth. + /// Returns the User object if sign in was successful. + Future _signInOrCreateAccount( + BuildContext context, + Future Function() signInFunc, + String authProvider, + ) async { + try { + final userCredential = await signInFunc(); + if (userCredential?.user != null) { + await maybeCreateUser(userCredential!.user!); + } + return userCredential == null + ? null + : PenniesFromHeavenFirebaseUser.fromUserCredential(userCredential); + } on FirebaseAuthException catch (e) { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error: ${e.message!}')), + ); + return null; + } + } +} diff --git a/lib/auth/firebase_auth/firebase_user_provider.dart b/lib/auth/firebase_auth/firebase_user_provider.dart new file mode 100644 index 0000000..7226895 --- /dev/null +++ b/lib/auth/firebase_auth/firebase_user_provider.dart @@ -0,0 +1,55 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:rxdart/rxdart.dart'; + +import '../base_auth_user_provider.dart'; + +export '../base_auth_user_provider.dart'; + +class PenniesFromHeavenFirebaseUser extends BaseAuthUser { + PenniesFromHeavenFirebaseUser(this.user); + User? user; + bool get loggedIn => user != null; + + @override + AuthUserInfo get authUserInfo => AuthUserInfo( + uid: user?.uid, + email: user?.email, + displayName: user?.displayName, + photoUrl: user?.photoURL, + phoneNumber: user?.phoneNumber, + ); + + @override + Future? delete() => user?.delete(); + + @override + Future? sendEmailVerification() => user?.sendEmailVerification(); + + @override + bool get emailVerified { + // Reloads the user when checking in order to get the most up to date + // email verified status. + if (loggedIn && user!.emailVerified) { + user!.reload().then((_) => user = FirebaseAuth.instance.currentUser); + } + return currentUser?.emailVerified ?? false; + } + + static BaseAuthUser fromUserCredential(UserCredential userCredential) => + fromFirebaseUser(userCredential.user); + static BaseAuthUser fromFirebaseUser(User? user) => + PenniesFromHeavenFirebaseUser(user); +} + +Stream penniesFromHeavenFirebaseUserStream() => + FirebaseAuth.instance + .authStateChanges() + .debounce((user) => user == null && !loggedIn + ? TimerStream(true, const Duration(seconds: 1)) + : Stream.value(user)) + .map( + (user) { + currentUser = PenniesFromHeavenFirebaseUser(user); + return currentUser!; + }, + ); diff --git a/lib/auth/firebase_auth/google_auth.dart b/lib/auth/firebase_auth/google_auth.dart new file mode 100644 index 0000000..ff860b2 --- /dev/null +++ b/lib/auth/firebase_auth/google_auth.dart @@ -0,0 +1,23 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/foundation.dart'; +import 'package:google_sign_in/google_sign_in.dart'; + +final _googleSignIn = GoogleSignIn(); + +Future googleSignInFunc() async { + if (kIsWeb) { + // Once signed in, return the UserCredential + return await FirebaseAuth.instance.signInWithPopup(GoogleAuthProvider()); + } + + await signOutWithGoogle().catchError((_) => null); + final auth = await (await _googleSignIn.signIn())?.authentication; + if (auth == null) { + return null; + } + final credential = GoogleAuthProvider.credential( + idToken: auth.idToken, accessToken: auth.accessToken); + return FirebaseAuth.instance.signInWithCredential(credential); +} + +Future signOutWithGoogle() => _googleSignIn.signOut(); diff --git a/lib/auth/firebase_auth/jwt_token_auth.dart b/lib/auth/firebase_auth/jwt_token_auth.dart new file mode 100644 index 0000000..35cd56c --- /dev/null +++ b/lib/auth/firebase_auth/jwt_token_auth.dart @@ -0,0 +1,4 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +Future jwtTokenSignIn(String jwtToken) => + FirebaseAuth.instance.signInWithCustomToken(jwtToken); diff --git a/lib/auth/firebase_user_provider.dart b/lib/auth/firebase_user_provider.dart deleted file mode 100644 index a72c33b..0000000 --- a/lib/auth/firebase_user_provider.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:rxdart/rxdart.dart'; - -class PenniesFromHeavenFirebaseUser { - PenniesFromHeavenFirebaseUser(this.user); - User? user; - bool get loggedIn => user != null; -} - -PenniesFromHeavenFirebaseUser? currentUser; -bool get loggedIn => currentUser?.loggedIn ?? false; -Stream penniesFromHeavenFirebaseUserStream() => - FirebaseAuth.instance - .authStateChanges() - .debounce((user) => user == null && !loggedIn - ? TimerStream(true, const Duration(seconds: 1)) - : Stream.value(user)) - .map( - (user) { - currentUser = PenniesFromHeavenFirebaseUser(user); - return currentUser!; - }, - ); diff --git a/lib/auth/google_auth.dart b/lib/auth/google_auth.dart deleted file mode 100644 index fecd905..0000000 --- a/lib/auth/google_auth.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:google_sign_in/google_sign_in.dart'; - -import 'auth_util.dart'; - -final _googleSignIn = GoogleSignIn(); - -Future signInWithGoogle(BuildContext context) async { - final signInFunc = () async { - if (kIsWeb) { - // Once signed in, return the UserCredential - return await FirebaseAuth.instance.signInWithPopup(GoogleAuthProvider()); - } - - await signOutWithGoogle().catchError((_) => null); - final auth = await (await _googleSignIn.signIn())?.authentication; - if (auth == null) { - return null; - } - final credential = GoogleAuthProvider.credential( - idToken: auth.idToken, accessToken: auth.accessToken); - return FirebaseAuth.instance.signInWithCredential(credential); - }; - return signInOrCreateAccount(context, signInFunc, 'GOOGLE'); -} - -Future signOutWithGoogle() => _googleSignIn.signOut(); diff --git a/lib/auth/jwt_token_auth.dart b/lib/auth/jwt_token_auth.dart deleted file mode 100644 index 74dadd9..0000000 --- a/lib/auth/jwt_token_auth.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/material.dart'; - -import 'auth_util.dart'; - -Future signInWithJwtToken(BuildContext context, String jwtToken) => - signInOrCreateAccount(context, - () => FirebaseAuth.instance.signInWithCustomToken(jwtToken), 'JWT'); diff --git a/lib/backend/backend.dart b/lib/backend/backend.dart index 3b82234..94228c8 100644 --- a/lib/backend/backend.dart +++ b/lib/backend/backend.dart @@ -1,7 +1,7 @@ import 'package:built_value/serializer.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; -import '../auth/auth_util.dart'; +import '../auth/firebase_auth/auth_util.dart'; import '../flutter_flow/flutter_flow_util.dart'; diff --git a/lib/backend/schema/serializers.dart b/lib/backend/schema/serializers.dart index 8407fc6..b4fbf15 100644 --- a/lib/backend/schema/serializers.dart +++ b/lib/backend/schema/serializers.dart @@ -198,6 +198,9 @@ Map mapToFirestore(Map data) => return MapEntry(key, value); }); +List? convertToGeoPointList(List? list) => + list?.map((e) => e.toGeoPoint()).toList(); + extension GeoPointExtension on LatLng { GeoPoint toGeoPoint() => GeoPoint(latitude, longitude); } diff --git a/lib/flutter_flow/custom_functions.dart b/lib/flutter_flow/custom_functions.dart index f56ffd9..56c6095 100644 --- a/lib/flutter_flow/custom_functions.dart +++ b/lib/flutter_flow/custom_functions.dart @@ -9,7 +9,7 @@ import 'lat_lng.dart'; import 'place.dart'; import '../backend/backend.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; -import '../../auth/auth_util.dart'; +import '../../auth/firebase_auth/auth_util.dart'; double getDoubleValueFromString(String? testString) { // returns non-negative double parse of string, otherwise returns 0.0 diff --git a/lib/flutter_flow/flutter_flow_icon_button.dart b/lib/flutter_flow/flutter_flow_icon_button.dart index 8e6970f..7e829a3 100644 --- a/lib/flutter_flow/flutter_flow_icon_button.dart +++ b/lib/flutter_flow/flutter_flow_icon_button.dart @@ -43,6 +43,17 @@ class _FlutterFlowIconButtonState extends State { @override void initState() { + super.initState(); + _updateIcon(); + } + + @override + void didUpdateWidget(FlutterFlowIconButton oldWidget) { + super.didUpdateWidget(oldWidget); + _updateIcon(); + } + + void _updateIcon() { final isFontAwesome = widget.icon is FaIcon; if (isFontAwesome) { FaIcon icon = widget.icon as FaIcon; @@ -61,7 +72,6 @@ class _FlutterFlowIconButtonState extends State { iconSize = icon.size; iconColor = icon.color; } - super.initState(); } @override diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index 9981725..8eb64b5 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -6,7 +6,7 @@ import 'package:page_transition/page_transition.dart'; import '../flutter_flow_theme.dart'; import '../../backend/backend.dart'; -import '../../auth/firebase_user_provider.dart'; +import '../../auth/base_auth_user_provider.dart'; import '../../backend/firebase_dynamic_links/firebase_dynamic_links.dart' show DynamicLinksHandler; @@ -24,8 +24,8 @@ export '../../backend/firebase_dynamic_links/firebase_dynamic_links.dart' const kTransitionInfoKey = '__transition_info__'; class AppStateNotifier extends ChangeNotifier { - PenniesFromHeavenFirebaseUser? initialUser; - PenniesFromHeavenFirebaseUser? user; + BaseAuthUser? initialUser; + BaseAuthUser? user; bool showSplashImage = true; String? _redirectLocation; @@ -50,7 +50,7 @@ class AppStateNotifier extends ChangeNotifier { /// to perform subsequent actions (such as navigation) afterwards. void updateNotifyOnAuthChange(bool notify) => notifyOnAuthChange = notify; - void update(PenniesFromHeavenFirebaseUser newUser) { + void update(BaseAuthUser newUser) { initialUser ??= newUser; user = newUser; // Refresh the app on auth change unless explicitly marked otherwise. diff --git a/lib/main.dart b/lib/main.dart index bae37e3..e84e5db 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:firebase_core/firebase_core.dart'; -import 'auth/firebase_user_provider.dart'; -import 'auth/auth_util.dart'; +import 'auth/firebase_auth/firebase_user_provider.dart'; +import 'auth/firebase_auth/auth_util.dart'; import 'backend/firebase/firebase_config.dart'; import 'flutter_flow/flutter_flow_theme.dart'; @@ -40,7 +40,7 @@ class _MyAppState extends State { Locale? _locale; ThemeMode _themeMode = ThemeMode.system; - late Stream userStream; + late Stream userStream; late AppStateNotifier _appStateNotifier; late GoRouter _router; From 85a9df40f845181939ae5c5f500d21f47ea80ae9 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 21:35:09 +0000 Subject: [PATCH 04/15] Updating to latest FlutterFlow output. // This code produces an error when compiled online // But does not produce an error when compiled natively --- lib/custom_code/widgets/custom_credit_card_widget.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart index 29cc71a..c4727dd 100644 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -8,6 +8,9 @@ import 'package:flutter/material.dart'; // Begin custom widget code // DO NOT REMOVE OR MODIFY THE CODE ABOVE! +// This code produces an error when compiled online +// But does not produce an error when compiled natively + import 'package:flutter_credit_card/flutter_credit_card.dart'; import 'package:flutter_credit_card/constants.dart'; import 'package:flutter_credit_card/credit_card_brand.dart'; From f96d87f6431815853b92833ecc18f90b00b8421d Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 05:08:22 +0000 Subject: [PATCH 05/15] Updating to latest FlutterFlow output. Implement pub.dev CreditCard example. --- .../firebase_auth/firebase_user_provider.dart | 2 +- lib/components/test_components_model.dart | 16 + lib/components/test_components_widget.dart | 51 ++ .../widgets/custom_credit_card_widget.dart | 435 ++++++++++-------- lib/flutter_flow/nav/nav.dart | 5 + lib/index.dart | 1 + lib/pages/payment/payment_model.dart | 1 + lib/pages/payment/payment_widget.dart | 34 +- lib/pages/test_page/test_page_model.dart | 17 + lib/pages/test_page/test_page_widget.dart | 109 +++++ pubspec.yaml | 4 + 11 files changed, 493 insertions(+), 182 deletions(-) create mode 100644 lib/components/test_components_model.dart create mode 100644 lib/components/test_components_widget.dart create mode 100644 lib/pages/test_page/test_page_model.dart create mode 100644 lib/pages/test_page/test_page_widget.dart diff --git a/lib/auth/firebase_auth/firebase_user_provider.dart b/lib/auth/firebase_auth/firebase_user_provider.dart index 7226895..fdd8a07 100644 --- a/lib/auth/firebase_auth/firebase_user_provider.dart +++ b/lib/auth/firebase_auth/firebase_user_provider.dart @@ -32,7 +32,7 @@ class PenniesFromHeavenFirebaseUser extends BaseAuthUser { if (loggedIn && user!.emailVerified) { user!.reload().then((_) => user = FirebaseAuth.instance.currentUser); } - return currentUser?.emailVerified ?? false; + return user?.emailVerified ?? false; } static BaseAuthUser fromUserCredential(UserCredential userCredential) => diff --git a/lib/components/test_components_model.dart b/lib/components/test_components_model.dart new file mode 100644 index 0000000..6c62e97 --- /dev/null +++ b/lib/components/test_components_model.dart @@ -0,0 +1,16 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class TestComponentsModel extends FlutterFlowModel { + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() {} + + /// Additional helper methods are added here. + +} diff --git a/lib/components/test_components_widget.dart b/lib/components/test_components_widget.dart new file mode 100644 index 0000000..548b911 --- /dev/null +++ b/lib/components/test_components_widget.dart @@ -0,0 +1,51 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'test_components_model.dart'; +export 'test_components_model.dart'; + +class TestComponentsWidget extends StatefulWidget { + const TestComponentsWidget({ + Key? key, + this.onCreditCardChange, + }) : super(key: key); + + final Future Function()? onCreditCardChange; + + @override + _TestComponentsWidgetState createState() => _TestComponentsWidgetState(); +} + +class _TestComponentsWidgetState extends State { + late TestComponentsModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => TestComponentsModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Container(); + } +} diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart index c4727dd..2d37c61 100644 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -8,207 +8,282 @@ import 'package:flutter/material.dart'; // Begin custom widget code // DO NOT REMOVE OR MODIFY THE CODE ABOVE! -// This code produces an error when compiled online -// But does not produce an error when compiled natively - -import 'package:flutter_credit_card/flutter_credit_card.dart'; -import 'package:flutter_credit_card/constants.dart'; import 'package:flutter_credit_card/credit_card_brand.dart'; +import 'package:flutter_credit_card/flutter_credit_card.dart'; -const Map CardTypeIconAsset = { - CardType.visa: 'icons/visa.png', - CardType.americanExpress: 'icons/amex.png', - CardType.mastercard: 'icons/mastercard.png', - CardType.unionpay: 'icons/unionpay.png', - CardType.discover: 'icons/discover.png', - CardType.elo: 'icons/elo.png', - CardType.hipercard: 'icons/hipercard.png', -}; +import 'dart:ui'; + +class AppColors { + AppColors._(); + + static const Color cardBgColor = Color(0xff363636); + static const Color colorB58D67 = Color(0xffB58D67); + static const Color colorE5D1B2 = Color(0xffE5D1B2); + static const Color colorF9EED2 = Color(0xffF9EED2); + static const Color colorFFFFFD = Color(0xffFFFFFD); +} class CustomCreditCardWidget extends StatefulWidget { const CustomCreditCardWidget({ Key? key, this.width, this.height, - required this.cardNumber, - required this.expiryDate, - required this.cardHolderName, - required this.cvvCode, - required this.showBackView, - this.bankName, - this.animationDuration = const Duration(milliseconds: 500), - this.cardHeight, - this.cardWidth, - this.textStyle, - this.cardBgColor = const Color(0xff1b447b), - this.obscureCardNumber = true, - this.obscureCardCvv = true, - this.labelCardHolder = 'CARD HOLDER', - this.labelExpiredDate = 'MM/YY', - // this.labelValidThru = 'VALID\nTHRU', - this.cardType, - this.isHolderNameVisible = false, - this.backgroundImage, - this.backgroundNetworkImage, - this.glassmorphismConfig, - this.isChipVisible = true, - this.isSwipeGestureEnabled = true, - this.customCardTypeIcons = const [], - required this.onCreditCardWidgetChange, - this.padding = AppConstants.creditCardPadding, - this.chipColor, - this.frontCardBorder, - this.backCardBorder, - this.obscureInitialCardNumber = false, }) : super(key: key); final double? width; final double? height; - /// A string indicating number on the card. - final String cardNumber; - - /// A string indicating expiry date for the card. - final String expiryDate; - - /// A string indicating name of the card holder. - final String cardHolderName; - - /// A String indicating cvv code. - final String cvvCode; - - /// Shows back side of the card at initial level when setting it to true./// This is helpful when focusing on cvv. - final bool showBackView; - - /// A string indicating name of the bank. - final String? bankName; - - /// Duration for flip animation. Defaults to 500 milliseconds. - final Duration animationDuration; - - /// Sets height of the front and back side of the card. - final double? cardHeight; - - /// Sets width of the front and back side of the card. - final double? cardWidth; - - /// Applies text style to cardNumber, expiryDate, cardHolderName and cvvCode. - final TextStyle? textStyle; - - /// Applies background color for card UI. - final Color cardBgColor; - - /// If this flag is enabled then card number is replaced with obscuring - /// characters to hide the content. Initial 4 and last 4 character - /// doesn't get obscured. Defaults to true. - final bool obscureCardNumber; - - /// If this flag is enabled then cvv is replaced with obscuring characters - /// to hide the content. Defaults to true. - final bool obscureCardCvv; - - /// Default label for card holder name. This is shown when user hasn't - /// entered any text for card holder name. - final String labelCardHolder; - - /// Default label for expiry date. This is shown when user hasn't entered any - /// text for expiry date. - final String labelExpiredDate; - - /// Default label for valid thru. This is shown when user hasn't entered any - /// text for valid thru. - // final String labelValidThru; - - /// Sets type of the card. An small image is shown based on selected type - /// of the card at bottom right corner. If this is set to null then image - /// shown automatically based on credit card number. - final CardType? cardType; - - /// Enable/disable card holder name. Defaults to false. - final bool isHolderNameVisible; - - /// Shows image as background of the card widget. This should be available - /// locally in your assets folder. - final String? backgroundImage; - - /// Shows image as background of the card widget from the network. - final String? backgroundNetworkImage; - - /// Used to provide glassmorphism effect to credit card widget. - final Glassmorphism? glassmorphismConfig; - - /// Enable/disable showcasing EMV chip UI. Defaults to true. - final bool isChipVisible; - - /// Enable/disable gestures on credit card widget. If enabled then flip - /// animation is started when swiped or tapped. Defaults to true. - final bool isSwipeGestureEnabled; - - /// Replaces credit card image with provided widget. - final List customCardTypeIcons; - - /// Provides a callback any time there is a change in credit card brand. - final void Function(CreditCardBrand) onCreditCardWidgetChange; - - /// Provides equal padding inside the credit card widget in all directions. - /// Defaults to 16. - final double padding; - - /// Provides color to EMV chip on the card. - final Color? chipColor; - - /// Provides border in front of credit card widget. - final BoxBorder? frontCardBorder; - - /// Provides border at back of credit card widget. - final BoxBorder? backCardBorder; - - /// Also obscures initial 4 card numbers with obscuring characters. This - /// flag requires [obscureCardNumber] to be true. This flag defaults to false. - final bool obscureInitialCardNumber; - @override _CustomCreditCardWidgetState createState() => _CustomCreditCardWidgetState(); } class _CustomCreditCardWidgetState extends State { + String cardNumber = ''; + String expiryDate = ''; + String cardHolderName = ''; + String cvvCode = ''; + bool isCvvFocused = false; + bool useGlassMorphism = false; + bool useBackgroundImage = false; + OutlineInputBorder? border; + final GlobalKey formKey = GlobalKey(); + + @override + void initState() { + border = OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey.withOpacity(0.7), + width: 2.0, + ), + ); + super.initState(); + } + @override Widget build(BuildContext context) { - return Container( - width: widget.width, - height: widget.height, - child: CreditCardWidget( - cardNumber: widget.cardNumber, - expiryDate: widget.expiryDate, - cardHolderName: widget.cardHolderName, - cvvCode: widget.cvvCode, - showBackView: widget.showBackView, - bankName: widget.bankName, - animationDuration: widget.animationDuration, - height: widget.cardHeight, - width: widget.cardWidth, - textStyle: widget.textStyle, - cardBgColor: widget.cardBgColor, - obscureCardNumber: widget.obscureCardNumber, - obscureCardCvv: widget.obscureCardCvv, - labelCardHolder: widget.labelCardHolder, - labelExpiredDate: widget.labelExpiredDate, - // labelValidThru: widget.labelValidThru, - cardType: widget.cardType, - isHolderNameVisible: widget.isHolderNameVisible, - backgroundImage: widget.backgroundImage, - backgroundNetworkImage: widget.backgroundNetworkImage, - glassmorphismConfig: widget.glassmorphismConfig, - isChipVisible: widget.isChipVisible, - isSwipeGestureEnabled: widget.isSwipeGestureEnabled, - customCardTypeIcons: widget.customCardTypeIcons, - onCreditCardWidgetChange: widget.onCreditCardWidgetChange, - padding: widget.padding, - chipColor: widget.chipColor, - frontCardBorder: widget.frontCardBorder, - backCardBorder: widget.backCardBorder, - obscureInitialCardNumber: widget.obscureInitialCardNumber, + return MaterialApp( + title: 'Flutter Credit Card View Demo', + debugShowCheckedModeBanner: false, + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: Scaffold( + resizeToAvoidBottomInset: false, + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: ExactAssetImage('assets/bg.png'), + fit: BoxFit.fill, + ), + color: Colors.black, + ), + child: SafeArea( + child: Column( + children: [ + const SizedBox( + height: 30, + ), + CreditCardWidget( + glassmorphismConfig: + useGlassMorphism ? Glassmorphism.defaultConfig() : null, + cardNumber: cardNumber, + expiryDate: expiryDate, + cardHolderName: cardHolderName, + cvvCode: cvvCode, + bankName: 'Axis Bank', + frontCardBorder: + !useGlassMorphism ? Border.all(color: Colors.grey) : null, + backCardBorder: + !useGlassMorphism ? Border.all(color: Colors.grey) : null, + showBackView: isCvvFocused, + obscureCardNumber: true, + obscureCardCvv: true, + isHolderNameVisible: true, + cardBgColor: AppColors.cardBgColor, + backgroundImage: + useBackgroundImage ? 'assets/card_bg.png' : null, + isSwipeGestureEnabled: true, + onCreditCardWidgetChange: + (CreditCardBrand creditCardBrand) {}, + customCardTypeIcons: [ + CustomCardTypeIcon( + cardType: CardType.mastercard, + cardImage: Image.asset( + 'assets/mastercard.png', + height: 48, + width: 48, + ), + ), + ], + ), + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + CreditCardForm( + formKey: formKey, + obscureCvv: true, + obscureNumber: true, + cardNumber: cardNumber, + cvvCode: cvvCode, + isHolderNameVisible: true, + isCardNumberVisible: true, + isExpiryDateVisible: true, + cardHolderName: cardHolderName, + expiryDate: expiryDate, + themeColor: Colors.blue, + textColor: Colors.white, + cardNumberDecoration: InputDecoration( + labelText: 'Number', + hintText: 'XXXX XXXX XXXX XXXX', + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, + ), + expiryDateDecoration: InputDecoration( + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, + labelText: 'Expired Date', + hintText: 'XX/XX', + ), + cvvCodeDecoration: InputDecoration( + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, + labelText: 'CVV', + hintText: 'XXX', + ), + cardHolderDecoration: InputDecoration( + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, + labelText: 'Card Holder', + ), + onCreditCardModelChange: onCreditCardModelChange, + ), + const SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Glassmorphism', + style: TextStyle( + color: Colors.white, + fontSize: 18, + ), + ), + const Spacer(), + Switch( + value: useGlassMorphism, + inactiveTrackColor: Colors.grey, + activeColor: Colors.white, + activeTrackColor: AppColors.colorE5D1B2, + onChanged: (bool value) => setState(() { + useGlassMorphism = value; + }), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Card Image', + style: TextStyle( + color: Colors.white, + fontSize: 18, + ), + ), + const Spacer(), + Switch( + value: useBackgroundImage, + inactiveTrackColor: Colors.grey, + activeColor: Colors.white, + activeTrackColor: AppColors.colorE5D1B2, + onChanged: (bool value) => setState(() { + useBackgroundImage = value; + }), + ), + ], + ), + ), + const SizedBox( + height: 20, + ), + GestureDetector( + onTap: _onValidate, + child: Container( + margin: const EdgeInsets.symmetric( + horizontal: 16, vertical: 8), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [ + AppColors.colorB58D67, + AppColors.colorB58D67, + AppColors.colorE5D1B2, + AppColors.colorF9EED2, + AppColors.colorFFFFFD, + AppColors.colorF9EED2, + AppColors.colorB58D67, + ], + begin: Alignment(-1, -4), + end: Alignment(1, 4), + ), + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(vertical: 15), + width: double.infinity, + alignment: Alignment.center, + child: const Text( + 'Validate', + style: TextStyle( + color: Colors.black, + fontFamily: 'halter', + fontSize: 14, + package: 'flutter_credit_card', + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), ), ); } + + void _onValidate() { + if (formKey.currentState!.validate()) { + print('valid!'); + } else { + print('invalid!'); + } + } + + void onCreditCardModelChange(CreditCardModel? creditCardModel) { + setState(() { + cardNumber = creditCardModel!.cardNumber; + expiryDate = creditCardModel.expiryDate; + cardHolderName = creditCardModel.cardHolderName; + cvvCode = creditCardModel.cvvCode; + isCvvFocused = creditCardModel.isCvvFocused; + }); + } } diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index 8eb64b5..095facb 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -105,6 +105,11 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter( builder: (context, params) => params.isEmpty ? NavBarPage(initialPage: 'Account') : AccountWidget(), + ), + FFRoute( + name: 'TestPage', + path: 'testPage', + builder: (context, params) => TestPageWidget(), ) ].map((r) => r.toRoute(appStateNotifier)).toList(), ), diff --git a/lib/index.dart b/lib/index.dart index aafb63a..9ac71b4 100644 --- a/lib/index.dart +++ b/lib/index.dart @@ -2,3 +2,4 @@ export '/pages/donation/donation_widget.dart' show DonationWidget; export '/pages/payment/payment_widget.dart' show PaymentWidget; export '/pages/account/account_widget.dart' show AccountWidget; +export '/pages/test_page/test_page_widget.dart' show TestPageWidget; diff --git a/lib/pages/payment/payment_model.dart b/lib/pages/payment/payment_model.dart index ac59915..94bd7c0 100644 --- a/lib/pages/payment/payment_model.dart +++ b/lib/pages/payment/payment_model.dart @@ -2,6 +2,7 @@ import '/components/get_donation_amount_widget.dart'; import '/components/row_logo_and_name_widget.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; diff --git a/lib/pages/payment/payment_widget.dart b/lib/pages/payment/payment_widget.dart index 8a8746f..7544811 100644 --- a/lib/pages/payment/payment_widget.dart +++ b/lib/pages/payment/payment_widget.dart @@ -2,6 +2,7 @@ import '/components/get_donation_amount_widget.dart'; import '/components/row_logo_and_name_widget.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; @@ -56,7 +57,7 @@ class _PaymentWidgetState extends State { backgroundColor: FlutterFlowTheme.of(context).primaryBackground, automaticallyImplyLeading: false, title: Text( - 'Donation', + 'Payment', style: FlutterFlowTheme.of(context).headlineMedium.override( fontFamily: 'Poppins', color: FlutterFlowTheme.of(context).secondaryBackground, @@ -82,6 +83,37 @@ class _PaymentWidgetState extends State { updateCallback: () => setState(() {}), child: GetDonationAmountWidget(), ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FFButtonWidget( + onPressed: () async { + context.pushNamed('TestPage'); + }, + text: 'Test Page ', + options: FFButtonOptions( + width: 130.0, + height: 40.0, + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: + FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: 'Poppins', + color: Colors.white, + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ], + ), ], ), ), diff --git a/lib/pages/test_page/test_page_model.dart b/lib/pages/test_page/test_page_model.dart new file mode 100644 index 0000000..beef6d8 --- /dev/null +++ b/lib/pages/test_page/test_page_model.dart @@ -0,0 +1,17 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class TestPageModel extends FlutterFlowModel { + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() {} + + /// Additional helper methods are added here. + +} diff --git a/lib/pages/test_page/test_page_widget.dart b/lib/pages/test_page/test_page_widget.dart new file mode 100644 index 0000000..08135ee --- /dev/null +++ b/lib/pages/test_page/test_page_widget.dart @@ -0,0 +1,109 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'test_page_model.dart'; +export 'test_page_model.dart'; + +class TestPageWidget extends StatefulWidget { + const TestPageWidget({Key? key}) : super(key: key); + + @override + _TestPageWidgetState createState() => _TestPageWidgetState(); +} + +class _TestPageWidgetState extends State { + late TestPageModel _model; + + final scaffoldKey = GlobalKey(); + final _unfocusNode = FocusNode(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => TestPageModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + _unfocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Test Page', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: Color(0xFF2978A0), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Hello World', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).warning, + fontSize: 30.0, + ), + ), + ], + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index da1335b..c7d2bdd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,6 +62,10 @@ dependencies: provider: 6.0.4 rxdart: 0.27.4 shared_preferences: 2.0.15 + shared_preferences_android: 2.1.0 + shared_preferences_ios: 2.1.1 + shared_preferences_platform_interface: 2.2.0 + shared_preferences_web: 2.1.0 sign_in_with_apple: 4.1.0 sign_in_with_apple_platform_interface: 1.0.0 sign_in_with_apple_web: 1.0.1 From 505723993cabba58bb8f47cae8e65c5e1e3059e7 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 06:09:51 +0000 Subject: [PATCH 06/15] Updating to latest FlutterFlow output. --- lib/pages/donation/donation_widget.dart | 13 +++++++++---- lib/pages/test_page/test_page_model.dart | 1 + lib/pages/test_page/test_page_widget.dart | 15 ++++++++------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/pages/donation/donation_widget.dart b/lib/pages/donation/donation_widget.dart index cf7b2ed..7029ac0 100644 --- a/lib/pages/donation/donation_widget.dart +++ b/lib/pages/donation/donation_widget.dart @@ -69,10 +69,15 @@ class _DonationWidgetState extends State { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, children: [ - wrapWithModel( - model: _model.rowLogoAndNameModel, - updateCallback: () => setState(() {}), - child: RowLogoAndNameWidget(), + InkWell( + onTap: () async { + context.pushNamed('TestPage'); + }, + child: wrapWithModel( + model: _model.rowLogoAndNameModel, + updateCallback: () => setState(() {}), + child: RowLogoAndNameWidget(), + ), ), wrapWithModel( model: _model.donationLoggedInModel, diff --git a/lib/pages/test_page/test_page_model.dart b/lib/pages/test_page/test_page_model.dart index beef6d8..b25e7d4 100644 --- a/lib/pages/test_page/test_page_model.dart +++ b/lib/pages/test_page/test_page_model.dart @@ -1,6 +1,7 @@ import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; diff --git a/lib/pages/test_page/test_page_widget.dart b/lib/pages/test_page/test_page_widget.dart index 08135ee..49687f5 100644 --- a/lib/pages/test_page/test_page_widget.dart +++ b/lib/pages/test_page/test_page_widget.dart @@ -1,6 +1,7 @@ import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; @@ -89,13 +90,13 @@ class _TestPageWidgetState extends State { mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - 'Hello World', - style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: 'Poppins', - color: FlutterFlowTheme.of(context).warning, - fontSize: 30.0, - ), + Container( + width: 390.0, + height: 844.0, + child: custom_widgets.CustomCreditCardWidget( + width: 390.0, + height: 844.0, + ), ), ], ), From 712ef8eeec176af4d673a37f66839c8532086c67 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 03:36:05 +0000 Subject: [PATCH 07/15] Updating to latest FlutterFlow output. --- .../widgets/custom_credit_card_widget.dart | 372 +++++++++--------- lib/pages/donation/donation_widget.dart | 31 ++ lib/pages/test_page/test_page_widget.dart | 8 +- 3 files changed, 217 insertions(+), 194 deletions(-) diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart index 2d37c61..14e6977 100644 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -16,7 +16,8 @@ import 'dart:ui'; class AppColors { AppColors._(); - static const Color cardBgColor = Color(0xff363636); + static const Color cardBgColor = Color(0xffAA3636); + // static const Color cardBgColor = Color(0xff363636); static const Color colorB58D67 = Color(0xffB58D67); static const Color colorE5D1B2 = Color(0xffE5D1B2); static const Color colorF9EED2 = Color(0xffF9EED2); @@ -43,8 +44,8 @@ class _CustomCreditCardWidgetState extends State { String cardHolderName = ''; String cvvCode = ''; bool isCvvFocused = false; - bool useGlassMorphism = false; - bool useBackgroundImage = false; + bool useGlassMorphism = true; + bool useBackgroundImage = true; OutlineInputBorder? border; final GlobalKey formKey = GlobalKey(); @@ -61,211 +62,202 @@ class _CustomCreditCardWidgetState extends State { @override Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Credit Card View Demo', - debugShowCheckedModeBanner: false, - theme: ThemeData( - primarySwatch: Colors.blue, + return Container( + width: widget.width, + height: widget.height, + decoration: const BoxDecoration( + image: DecorationImage( + image: ExactAssetImage('assets/assets/bg.png'), + fit: BoxFit.fill, + ), + color: Colors.black, ), - home: Scaffold( - resizeToAvoidBottomInset: false, - body: Container( - decoration: const BoxDecoration( - image: DecorationImage( - image: ExactAssetImage('assets/bg.png'), - fit: BoxFit.fill, - ), - color: Colors.black, + // child: SafeArea( + child: Column( + children: [ + const SizedBox( + height: 30, ), - child: SafeArea( - child: Column( - children: [ - const SizedBox( - height: 30, + CreditCardWidget( + glassmorphismConfig: + useGlassMorphism ? Glassmorphism.defaultConfig() : null, + cardNumber: cardNumber, + expiryDate: expiryDate, + cardHolderName: cardHolderName, + cvvCode: cvvCode, + bankName: 'Axis Bank', + frontCardBorder: + !useGlassMorphism ? Border.all(color: Colors.grey) : null, + backCardBorder: + !useGlassMorphism ? Border.all(color: Colors.grey) : null, + showBackView: isCvvFocused, + obscureCardNumber: false, + obscureCardCvv: false, + isHolderNameVisible: true, + cardBgColor: AppColors.cardBgColor, + backgroundImage: + useBackgroundImage ? 'assets/assets/card_bg.png' : null, + isSwipeGestureEnabled: true, + onCreditCardWidgetChange: (CreditCardBrand creditCardBrand) {}, + customCardTypeIcons: [ + CustomCardTypeIcon( + cardType: CardType.mastercard, + cardImage: Image.asset( + 'assets/mastercard.png', + height: 48, + width: 48, ), - CreditCardWidget( - glassmorphismConfig: - useGlassMorphism ? Glassmorphism.defaultConfig() : null, - cardNumber: cardNumber, - expiryDate: expiryDate, - cardHolderName: cardHolderName, - cvvCode: cvvCode, - bankName: 'Axis Bank', - frontCardBorder: - !useGlassMorphism ? Border.all(color: Colors.grey) : null, - backCardBorder: - !useGlassMorphism ? Border.all(color: Colors.grey) : null, - showBackView: isCvvFocused, - obscureCardNumber: true, - obscureCardCvv: true, - isHolderNameVisible: true, - cardBgColor: AppColors.cardBgColor, - backgroundImage: - useBackgroundImage ? 'assets/card_bg.png' : null, - isSwipeGestureEnabled: true, - onCreditCardWidgetChange: - (CreditCardBrand creditCardBrand) {}, - customCardTypeIcons: [ - CustomCardTypeIcon( - cardType: CardType.mastercard, - cardImage: Image.asset( - 'assets/mastercard.png', - height: 48, - width: 48, - ), + ), + ], + ), + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + CreditCardForm( + formKey: formKey, + obscureCvv: true, + obscureNumber: true, + cardNumber: cardNumber, + cvvCode: cvvCode, + isHolderNameVisible: true, + isCardNumberVisible: true, + isExpiryDateVisible: true, + cardHolderName: cardHolderName, + expiryDate: expiryDate, + themeColor: Colors.blue, + textColor: Colors.white, + cardNumberDecoration: InputDecoration( + labelText: 'Number', + hintText: 'XXXX XXXX XXXX XXXX', + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, ), - ], - ), - Expanded( - child: SingleChildScrollView( - child: Column( + expiryDateDecoration: InputDecoration( + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, + labelText: 'Expiry Date', + hintText: 'XX/XX', + ), + cvvCodeDecoration: InputDecoration( + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, + labelText: 'CVV', + hintText: 'XXX', + ), + cardHolderDecoration: InputDecoration( + hintStyle: const TextStyle(color: Colors.white), + labelStyle: const TextStyle(color: Colors.white), + focusedBorder: border, + enabledBorder: border, + labelText: 'Card Holder', + ), + onCreditCardModelChange: onCreditCardModelChange, + ), + const SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - CreditCardForm( - formKey: formKey, - obscureCvv: true, - obscureNumber: true, - cardNumber: cardNumber, - cvvCode: cvvCode, - isHolderNameVisible: true, - isCardNumberVisible: true, - isExpiryDateVisible: true, - cardHolderName: cardHolderName, - expiryDate: expiryDate, - themeColor: Colors.blue, - textColor: Colors.white, - cardNumberDecoration: InputDecoration( - labelText: 'Number', - hintText: 'XXXX XXXX XXXX XXXX', - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - ), - expiryDateDecoration: InputDecoration( - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - labelText: 'Expired Date', - hintText: 'XX/XX', + const Text( + 'Glassmorphism', + style: TextStyle( + color: Colors.white, + fontSize: 18, ), - cvvCodeDecoration: InputDecoration( - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - labelText: 'CVV', - hintText: 'XXX', - ), - cardHolderDecoration: InputDecoration( - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - labelText: 'Card Holder', - ), - onCreditCardModelChange: onCreditCardModelChange, ), - const SizedBox( - height: 20, + const Spacer(), + Switch( + value: useGlassMorphism, + inactiveTrackColor: Colors.grey, + activeColor: Colors.white, + activeTrackColor: AppColors.colorE5D1B2, + onChanged: (bool value) => setState(() { + useGlassMorphism = value; + }), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Glassmorphism', - style: TextStyle( - color: Colors.white, - fontSize: 18, - ), - ), - const Spacer(), - Switch( - value: useGlassMorphism, - inactiveTrackColor: Colors.grey, - activeColor: Colors.white, - activeTrackColor: AppColors.colorE5D1B2, - onChanged: (bool value) => setState(() { - useGlassMorphism = value; - }), - ), - ], + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Card Image', + style: TextStyle( + color: Colors.white, + fontSize: 18, ), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Card Image', - style: TextStyle( - color: Colors.white, - fontSize: 18, - ), - ), - const Spacer(), - Switch( - value: useBackgroundImage, - inactiveTrackColor: Colors.grey, - activeColor: Colors.white, - activeTrackColor: AppColors.colorE5D1B2, - onChanged: (bool value) => setState(() { - useBackgroundImage = value; - }), - ), - ], - ), + const Spacer(), + Switch( + value: useBackgroundImage, + inactiveTrackColor: Colors.grey, + activeColor: Colors.white, + activeTrackColor: AppColors.colorE5D1B2, + onChanged: (bool value) => setState(() { + useBackgroundImage = value; + }), ), - const SizedBox( - height: 20, + ], + ), + ), + const SizedBox( + height: 20, + ), + GestureDetector( + onTap: _onValidate, + child: Container( + margin: const EdgeInsets.symmetric( + horizontal: 16, vertical: 8), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [ + AppColors.colorB58D67, + AppColors.colorB58D67, + AppColors.colorE5D1B2, + AppColors.colorF9EED2, + AppColors.colorFFFFFD, + AppColors.colorF9EED2, + AppColors.colorB58D67, + ], + begin: Alignment(-1, -4), + end: Alignment(1, 4), ), - GestureDetector( - onTap: _onValidate, - child: Container( - margin: const EdgeInsets.symmetric( - horizontal: 16, vertical: 8), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - AppColors.colorB58D67, - AppColors.colorB58D67, - AppColors.colorE5D1B2, - AppColors.colorF9EED2, - AppColors.colorFFFFFD, - AppColors.colorF9EED2, - AppColors.colorB58D67, - ], - begin: Alignment(-1, -4), - end: Alignment(1, 4), - ), - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(vertical: 15), - width: double.infinity, - alignment: Alignment.center, - child: const Text( - 'Validate', - style: TextStyle( - color: Colors.black, - fontFamily: 'halter', - fontSize: 14, - package: 'flutter_credit_card', - ), - ), - ), + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(vertical: 15), + width: double.infinity, + alignment: Alignment.center, + child: const Text( + 'Validate', + style: TextStyle( + color: Colors.black, + fontFamily: 'halter', + fontSize: 14, + package: 'flutter_credit_card', ), - ], + ), ), ), - ), - ], + ], + ), ), ), - ), + ], ), + // ), ); } diff --git a/lib/pages/donation/donation_widget.dart b/lib/pages/donation/donation_widget.dart index 7029ac0..d4b89bb 100644 --- a/lib/pages/donation/donation_widget.dart +++ b/lib/pages/donation/donation_widget.dart @@ -84,6 +84,37 @@ class _DonationWidgetState extends State { updateCallback: () => setState(() {}), child: GetDonationAmountWidget(), ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FFButtonWidget( + onPressed: () async { + context.pushNamed('TestPage'); + }, + text: 'Test Page ', + options: FFButtonOptions( + width: 130.0, + height: 40.0, + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: + FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: 'Poppins', + color: Colors.white, + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ], + ), Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/pages/test_page/test_page_widget.dart b/lib/pages/test_page/test_page_widget.dart index 49687f5..80d3b51 100644 --- a/lib/pages/test_page/test_page_widget.dart +++ b/lib/pages/test_page/test_page_widget.dart @@ -91,11 +91,11 @@ class _TestPageWidgetState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - width: 390.0, - height: 844.0, + width: MediaQuery.of(context).size.width * 1.0, + height: MediaQuery.of(context).size.height * 1.0, child: custom_widgets.CustomCreditCardWidget( - width: 390.0, - height: 844.0, + width: MediaQuery.of(context).size.width * 1.0, + height: MediaQuery.of(context).size.height * 1.0, ), ), ], From 6e95d5b568c0cc9d6d57669e49e11978a96cc751 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 07:12:41 +0000 Subject: [PATCH 08/15] Updating to latest FlutterFlow output. --- lib/custom_code/widgets/custom_credit_card_widget.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart index 14e6977..9157bc3 100644 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -67,7 +67,7 @@ class _CustomCreditCardWidgetState extends State { height: widget.height, decoration: const BoxDecoration( image: DecorationImage( - image: ExactAssetImage('assets/assets/bg.png'), + image: ExactAssetImage('assets/bg.png'), fit: BoxFit.fill, ), color: Colors.black, @@ -95,15 +95,14 @@ class _CustomCreditCardWidgetState extends State { obscureCardCvv: false, isHolderNameVisible: true, cardBgColor: AppColors.cardBgColor, - backgroundImage: - useBackgroundImage ? 'assets/assets/card_bg.png' : null, + backgroundImage: useBackgroundImage ? 'images/card_bg.png' : null, isSwipeGestureEnabled: true, onCreditCardWidgetChange: (CreditCardBrand creditCardBrand) {}, customCardTypeIcons: [ CustomCardTypeIcon( cardType: CardType.mastercard, cardImage: Image.asset( - 'assets/mastercard.png', + 'images/mastercard.png', height: 48, width: 48, ), From d2f1d41ae7fd2a8a0bc3f083ecf46e12eeb60c54 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 07:26:36 +0000 Subject: [PATCH 09/15] Change "assets" in filepath to 'images' Updating to latest FlutterFlow output. --- lib/custom_code/widgets/custom_credit_card_widget.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart index 9157bc3..72234c9 100644 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -24,6 +24,7 @@ class AppColors { static const Color colorFFFFFD = Color(0xffFFFFFD); } +// Version 1 class CustomCreditCardWidget extends StatefulWidget { const CustomCreditCardWidget({ Key? key, From c44de5e970ba07d819da8d242c215ef95c6a5245 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 07:54:50 +0000 Subject: [PATCH 10/15] Deleted/Reloaded missing images to Flutterflow. Updating to latest FlutterFlow output. From 8156c11b613407c7624a55026c5f9cdbad852d77 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 08:17:59 +0000 Subject: [PATCH 11/15] Add Ghost Page Updating to latest FlutterFlow output. --- assets/images/bg.png | Bin 0 -> 159876 bytes assets/images/card_bg.png | Bin 0 -> 20431 bytes assets/images/mastercard.png | Bin 0 -> 1036 bytes lib/flutter_flow/nav/nav.dart | 5 + lib/index.dart | 2 + .../ghost_image_page_model.dart | 17 +++ .../ghost_image_page_widget.dart | 105 ++++++++++++++++++ 7 files changed, 129 insertions(+) create mode 100644 assets/images/bg.png create mode 100644 assets/images/card_bg.png create mode 100644 assets/images/mastercard.png create mode 100644 lib/pages/ghost_image_page/ghost_image_page_model.dart create mode 100644 lib/pages/ghost_image_page/ghost_image_page_widget.dart diff --git a/assets/images/bg.png b/assets/images/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..053e4e09ca38fa0d84553fe2b66ef39a9ea9bd45 GIT binary patch literal 159876 zcmYg&2Q=I7_kX8RN>QtXR@AOpQDSrvTBB;$-ZetijMdhjQJWIlYVECdP^HwakrE;H zNQ{tJrSzX~)t2PPqZPIFI~HI=FFMP8tM<9o;h=F^UN74 zV;U;*D?ROyD)JxN7wRUSXU?$Q{NL|cji>xuAw=Jag^^r^ds3`hI8Ek8x>seIDF#hD+`0ub+Lq%QW^-W9$cKC(AtarY`ee+Q_eG z6WNE6y1DhWnT-$!!(6;uO>OZ@0>_k+1KrRBI5#&Zr+jE=NN0R)*Xfm^m9bXy`+4I# zp~*7QjyNf|m6>rN37U}W|NFrzi0|en%{+R!CYx_>9d}2DQv?dB7UV~!edwxKd%O4V zO(C;-9RZyHTJX6AZ5m1cpC;U-#hQT&{>QqTa7fZ1i1yx<3;+As5}y6Yhficjo=jLl z9E;J8R@DAOBggZGdj@^2agovaMJJma;@V-8xC|Bs| zdbez(CbH0?!0qW{T-V*tN;l^R^?3iSapi(LfR{VfnlX9a`(}$EBix3&t0Ynn^&sDG z0N(PxZ2j!yvvO_(?dkFO);ah6%M{1rKGl$xGpK2+9}{>)rmLGs`v761Fy;TGa8CL9 zW&zgi;<9;#2SCG!>%#Kf%yzE}7RuLj`@h3MJ90dXAQt+QJtlj4AyWud-xVyPz(VQZ z+J75kVqYrCQAV016uWxyV-Tv2*6XNv0|Ke$Z@WZ%94JM8^$6*g6^i) zIcq%_v#}Cxmy9G!6Jf{mPm?=6f-*?F?e9^Wd&@vC3!I-riLhCyu^U$7wf<%_$P%hQb43WfUMA-Xd}}L1 zIZ(T4$CCTsJ@;HTSjAV;BHeo7r4S}pDxZGUo~Q2VMb#P8>j&`);}%N|?z|LXhRkBV zErDl#503H?R8F=NEYBhKkx5o+9|i5QVfBD9xigwPq>~bt6eGg_cTT^3o_$s9s}oXg z8wu$PF#`$k`0jx?9^OPBND2c{dOApAb>8M?;pLh(Q9X(sT~WLyq4G5>$CrN?u2@6b z1ar^qd?cd&BujetUsU02H|loE>B(~25^JduK0Uq#9pU&T-pDd&H_Q<`e0~r)wEkug zK^JT>sMFdaVLqfKB*}`~5hz8?2!(_}^=8b4 z2GS0`zp1xl9ir0$K4dw4EaBUCCcQwbR0Pnm``MQ3(S^aIvPEI{W{g?kQOvst#IPge z)ql#7_0U~ukrRPAGG_WftT>wLI}5#5Z#i0cI_PPYAU8N77+VZKmfM~BV!O-SQe1N= z5eb}g%<)(nRbwhgdNK z64UbaQg3hhEpV#2&F`PVze2D$vW@K36MXtb(!hmzUoF&)x5r?`d_b%j8#Jk9&qw2KC@hI+F76 z|CCTaKM&7u*gE`*4>tHjd=8dOX!|A%Lpc?FAzWw%-{bbPQksk8v5=(V7@@df+%4br$ zAx0G-(oY>)N#Lxp$H~!Yx-rn9V1)hLX?(bYL>hD{Wk*k3*r{(j-gw-^TDK`G zKh0SBaRtD;rSH!t-I^(4VIv9K2u(%44x%B36IM~}>|a}?dw3e=&TMZM(t``i;K^px&Bsgl2qbnMGc6{}I=%7w*?>y^7e zEk9R>c@sm3b(7b+Vz8D`pGgIZ^I&vAoFxPfahm_nxUZy(zX9$NXq(KQD@PpGan_ow zf-X(hpPx?T^j*$|4NnheY|^(XjLyI|9?YJu75`Ytc_h)Ct(zz_B-3k}v)}eRs|^Oh zqICg^hu;*@)1ie1g1vZn->iI4g!W8p+dC4`Pigwoe@b8zKdAgfDwPSDK`2#xT@YD& zgYtG=hNv7e-8|vw@_O&;IBsV0&(FF=q>X8yi@DBMDdbVdNXb*?A*E^ zB);T#rl2X5YAl~ zCGWR1svv^~u+K=iI}zSiiQhq0CNGHfb8UjCraeC3?Fk?*XVNGxJ4J>9Xa~q`qJp~b zqCIo4M3EU|X}Jtx6*f~14vGC_j7X@+aZ%*)!lSzv6sJA%a8l`RH7N_y6s217V2{q` zvv}pK>Xj-U(3NlvHV-XU4!x`B(n9Xy|NQA$zBtq+qa=$UO>~oZ{>f--=|d3UQ;5Ic zj&6>xk1N%#@A&lZ0L_HE1Vz%XJaGX%gjP2hL}V)Ly8iEp*>68?ofrtYO9lH}$bq%& z%kpI5;2+0omiyWA*@r$G$s<~v^IkWVFzkL6#=qD#>iYp-Jyl4qgay2}a^bo`OtNf5cKVJGCq63*o}q)kc`8(|?fX-y zf=1u95<0!CI_o3Kj8r$N4RZ&wY$hD;BOu+kg(AaCY$aG4MdB~n&fJ%5p0}rf^1;g& z9$^UU;WbqG8uvmH_*b07$Dm{3zgfFU2tdQBE|;V~skHs0-c z{?moOc;Jw2tgDIT)>iCX;%vc}k0p_e6e*uad6ciW_?gv?+VD$($&3YBoaPBiUBNd@Guzx3V zRlAP#(RW7SKT#`-uVz}@P3nbvtgl^Kif@gf7SD{k6^SsNVJxk-G%kbK6t_G#y@_(G zd7a}+ujgc-SknW&FrjF*^pRRt&LnTVEZMA`E*AU-ZLvlWe)pq(evr1KN?A`I!i@08*8%3 z>f&n&${*@YVAxFM{mW;-Di*uzL+{v>@S1F*KrBI}R=3bcy4qqC+l)SSeXIZ$HpR)L zC@-;zTq$_L7%q~<2K!smc36_m>onHmFecO)U$O>L38>hNK{B-%Ap~PV-cdj+W z=?Q2wT!Dkb#F6WY+L+1oovi(->NgV&Y^N4^sn=-Y87fpLh0LniQhgvtO2U~3NVnIPPjGfy)d ztT;9xA>ey(^5gGH7b-}z&5~1BD}gswGYuC3P+j|{-H)AvccH4sY#&Nw>P&ECywr+Q z_;`D}c%@MDpFy@`x&z!(@6GDcEg2Btot3vmO7Y5x-GgomnZ5<}z+Jdz9=EsaMSJOE z5#BT{>!wDVrOOl{l9y)k^Ca!zf)+J?0*pgwBQRiC4N;7E;yA!^nw+#_y26$8aXd|CRu_=W z57m~X+*@W~98%pf7@<&{^$K#lDzoiRUt8c|%gj*=qn)M_s#v*lsHN&RcyU>yi&_xSh=J(WiKXau7)?IX_O>`-s{u&&9058lY6aMFhg41?o`HZhN~pd+=!UD@aO~*MAdn zxxDp>cv|xJ#=N_y!mp2vCDlnZ)QqSzBdBu{M+PyQ@Syh)1lpoUj2W{8vvkC+oi9-@ zG-)k6d?ao(JOk~O-HSI`DzCo!;(X_%^dhBrp53_1lUj5Eek@Nci+Z6o3JcR^ z%s0ro_&Ggs(0ln<;$&XJg2(uK{F~4k#x|zHaS`66-CHHSh>7k=`=mWIH_OxiETX%k zPohBKTi5HwFTi;*GXzrw4|JKeYXRuj+0|3(^lK#;(@#X|^ge+SqHYHRUwf1erbgyK zuNY^#0IDQeTUAh0H$I(i3iDkR5P)t#krdAYGlkek-AX+-c3lIGA9yW#Chjl6Djc!R zz+3p|(IwP%=uB=%d-aFGcRH{saPw3>@IN6X#PZ<>7tDuYNrHE7M#A}ZI-X$nknY4y z5Wo6+bUj0_o(1UxeSh;pCU@Q3%dFSQ@tMS?ap~!5T{?>L-MUp(B@=v=@&-mWw+qz7q`V{y;mT&u`HWjHGG;6lA39P1bM}HiLMR z)YDAHFUahw)F#b4g_!oJ83xOV3a^JIn+MU8VwE~e$6eCWFPpyYoi9O=;7(&L=W6Wl zzixJC6X>?&o=61n|DC8qm7iMC!dy#zuUDt$=Lg>iibVX`o=d)U*|5k|F~`v~-M%lQ zRWbyFd3Lcu|`>Sh}Jr;-uUiQ`7X>ak(1?!kH`Uz@}G$ZJs$Lq z$(K3~E_wgCFnVh!K#4SHCtclFuG@;?C~D|Y`%L;eetTLDSReeD5(%#$87zY34er5= zQhg6Bu4~xwxInI>bs763aj9`Z%R!00D>u9IlsLL}ghK|2v-Q_xwNM3K-U`kD+ZIuI zM5M|ofQn(6_7ArlAYH65I~b?JOG1=*gl||iuqH0shVxfdrpjNE%B$ar`LrT$9G@^Y z77x9H1035G*Uc0r4J)ePf-g-nryNeRiv~tszp3eMI`1zRc<;3E5YXQs)m(2445u z__2P7$qIePM!Od_tNoQ`GuX;I06XpQfyWXCVk{_rSrQ)$KI{NVt!m|_jFVheJ0&3_3bfu}U{Stof6(XSbS;UdshzG>7oa zwq^mHtyB4;aa@va!r2dH@&c5idCR{+pU*^Ta&_9G5a-PCcm+A5nNGYfY7=i~^!eV= zTY4ix!z0s;62?;Pb=wyZJ$+6cdoAxVKcjSnd2LP;IqFc5QC_^?GiH33MFSI-EmcvL zWI8IzczgL(1huf>%ymupTcLApmAuB&j#&3?kf=m6vAEe?-k3W=g>kS-l$@B_B5Gcm z_tev$ep*linIz~6dp-SVa7y6JlIXc&Bq`=kwPFER0<<1XHlPoeH!XUe_(<7c0XLp{ z4@Ak~@lnBw>y*b6x&u_c>Z`~pFuGg>!$&@QTlXdhUP|v~dYbBH%bR7g2xvLh(~&=7 zvre*r4WN{|wAOTMKY$ruJ?6Sd`2-$zehiHoQ6Z$RW9?{8%I%yZrbo>tsUl)w?N4<~^#WW4dfhJwE&#v|w-tq1Tc$w)T#C)XT>^EB4eg z>B%&kKCMLy0Uoa(G7huO6l@4dH0@8Y@LMq{w{Mr0&dT6fUUC4r6HgX+{~p{7T&ZxX zn(ECP#KYe}g;LU|dUSsqw4fS-20+5H8xLPmJngH8b+>$ZJT;GoOoWkqe+^Qlfa{D} zUE-DkSgITor!S-<)1d$&IlkI+Bq$R4F>y=f+hXSXw>k#Lp;5-LCj{CLhPz7BW}R!4 zBIgA>mT!Yj1P)7NiVGW8)THjJsw`%dqZO(c?E!HaQ!NEKRh~y;gTE-cvn*V3M}F_ae72(zlY!bdbPHb4HS$@vF3$!rA5Xa(56AOK9*;>?r!2fe20P{fjtckp17f*lXMj+IMW@0 zX5b!TrJngN+Ys^N_`7>hnzs*2Y{8|-tR$39mWRP>)@lz7|v*Oqz-Y((BsAmF-Aia%F_gj*!z1E9qi9U|JNnVf)fIK8i z!TnV|I&0@M#fu~^6O}f_%wUkrbT*PyNKm7h^41GccURPB*J9jH@%|Ff_0n~NuIfg- z6-W}iwi|4<+fAm=A0IxW)^sT2H55=i+%`QAiE3`L^FYDfI=UA{xGKdch+(O)7%){} zVFan!FK+PyEr6FW)xMQmf<+Rga#GH1R2-sw2n^hH~N!pnPalG6~DxM)$R$b z7yjygEkzEgT-i(0NP48B4!i6b)`r(3PRWUam3micf?FJybUjXY$0x47`8M0yES!u; zBl5c+rHKhS`%SPXznSVMJ}dSLg)Uj|xr-4klnClRtZxjOww}}1RCF0gG(FhA6)BRN z+z!85C0(q{_HSofH|M@7ep6pBUTHWFJeFmsVEz4o3$*nNmLu3Cy0z|?`q|a6I-~xb zbpg8Dp>D+-*Wq7OS6yAX^-TKHb8-SqM!;?r|4LlK_t~ ze_qVjYIo|4QrdP^lfk^QbsHaWNWYiF`xW!EYtNvsi*ISFEYIv~I>bAUi`}XTNYa5K zuWYyeGwrRn zi{2-}A1%qP54IFeiUJzv0Uk4poC)70%?5NiSK?b7fs()1y}Wa5G)wFnnmoQ|x9`2Uz%$w~a8Jv!?~^M71>ZzUpKW>Y;aMJ}uT^SzMxPh1)ZJ{)VDzCwVm;G{uE zF@pnRl9_4sY=Fy0~=_f&i%;%xBV*$u}v|#@8vL&{g~l>=QNX?nzpF*(@$(2`=Z>Lnmb;3!Sx+RCxQ`&?53y<$g`1IUC*HwrQtMvvF z383|~GryNw1|+Tf^R@N1kn2znL5tPHuOh*rUy-Z*X~G^3dj{3zlO7|j>lmh`)b9A# zYq|Y&6gGZKem1W`F2 z*hDjdJy;fJd+I-zumL6XK##b)&^sZEimNP)Qp?uk zEHClpCav$ZVShLiA6D!z*v@6-^mu_J#1evnF!ad_gRM0K$$U+vIS5yzk+o71a|Fi);Ur!Lxxw;)+i)PKvpdwk~Zxzxa)96#@q|>~`#6E$CER_40N1Ldwq6tX zum8{&rLGy|~=(#682J4#kjYRu+P%zo{0!pb_;#$_ar$4PK2$E$y?csVV1F=mTQ zxIJ40Bn-?(d|EEa^$UxxU9DwxfupViC3lVv#XwHMm#WJ58f--kBx-We7SPh)9;8q%L5Jqz+#oSWK-TYyzq@U% z`*bD!ZeOBtx*qCS7p}&@QikoCNyFX3_|Ou|sjJdxS+Rfh;OwmhK%YI#6w1?9sdUX%}dj61|xAQa{-H}qZD#?l(}zY%q4K>Xe^-Z z$;@F$XD+}9wvS^x4kwI*H^Mb2-wvMebm?6hi|wKsM6)4G6)u^$0KVmQ!uaf z7E&?0Nrm%`eU6#x{FQaT5K@Em(*f6qM@>Ku0}vLR;JJVKbq&j?Z3QGNm38Jh@zg5=i?5;35g zMxQ%&@LXI-qutNMnkL7fGtsS&W4~&3;fzmd6D{Qac}>4BHh2%ahudNN8#;>kuQbLe z-1;i$LdE4TpGi;L8;I5Jbk2$qK&CP)N36m02TlH=BR$wy^MLLx-rgX8|7!s_bF(s) zf=H#vY_m5b5jy`RWn>J&^9Ac4pPq$FLr3Jy{zhdyqMIe2y^XaGk8{4_i`rfgj zpn)G^`5i}yR&psO74hh8rcrAzGJHpY5sI?x_|>>oM(3>)m5s5Il#mUs{^J~~YcDcl z)^5QX4Z8EPwD;+TwUfR=t<%$>H}{~-sha5^3UHLoene)7AwyvLtnGSXfR+wf1Q78& z7Z@drg~f8>ItQrpeXCtEum1jC?fzalEfVLj@d0FO;JyN@Aetj;Kn_mYvxkiNw*FIc z09oanoqxK+Dy#=gaaLt_<%y|w`SS2D8L;{1BzE5T@Q^P~;R)4f^!WP3MIcdAxr9BX z-K)lL>dX6MvDRf2N_&3C*Bmml_%5 zu9B$|ijhF(mdd1AzIoF*S?4@eEnO1?I?B4jKBFS?l3djShZzLgZ2ImYHub_Ar9Wu< z#AjWsV_Kz=tg&A*A&@6jN{hA9C$B3eO8d-B{MG+$GRfe#9tm|5fI0h7K(D*&Gggw> zpaU#<=lwHF z{RNwPxj5boQKbdB+&z$9tWqy^w{d-R_u|x4RTB-RlQC=inkV(1W=nnQn3shvKX%t_ z-}{BxM{KjqT)*1qm8-qw@aH57xNoYLzY0&ep0bbZ(rNkfNTPQWzEXLc+_7EtovXhK_0!gv<3H|P zXd79VAv}WYM&+dk7IC1B-l`m(qrc8>@I^xZR~-Do;EenCdH>dVNT^O4lwv zydu7XU!rTSmd_UKdcVt;TT}-4w_lBQxg5=CSu_yd5iRH+S>lf&i`UY4qZflN+?hA= zni6_n?q>V-ka)FpXm**xJkHwAK26{es*rnJ^EJv(E7nefNqFz4;K#|XDB~5?@+>Au zYo^7{xA6c0#-98pEKXG8yNf}Df5MX0p$nkK$7;!fOeCKa{N2gL!m!QmkDWPs+x_a> z3zzim5a?$F6O0wI+5q~;xaB{zLhc)Ks=4}d=i6=rZWw;@jubvO0n_A^a=371f(n>V50A5LDrVd$@i@AsAvM|uqF#Sv;6R7B^Z8f?AlE-(8a%3);}mNg@BB>S79p2rkK1wQ`3IpD-rC>K$~?8d&Yvia$X3w^?LFT zCmw5ehrKR8c!YJiQ=|I53MkEzrH?4u0k_sAJPL?K6t@Y(Ct- z0UmAP+1UBv9Pa%WpNfD{dO<=ZeXpuDbRX^{HWaMu*_4f}H<2+}wCND>OKaD4L3XrT zy@9U#Abb69I>vd2dtb9 zbH>z#=Q|K)s!>&ntO!SB4cD&H<-YvhD3B}B;?<{~TGnMk?=r}w#6;KB-c_*+Ouo+bkn39r-yP ztX;0S^`~4M1$oQUT&=3uHHp$-s=ed)1W0Jc?lj`B36$)L1wau&uigyW< zSIFy5N~|Abc{Zw(@JJF(ub!4~_Y3yGM3I!Ovs2hmgov~9&9VFfvxR=khiGWO4m#KK zd!$*30N{Xi`4p1R+SNP|k9qH9we;}F_zpfRQ0AXE+?(CPu3b;vuZfsrWR~aqGOGQm zb2UX>TVu8M_ny`LFD}`Wm4!QkbF9t}+7%~U^=j}f`I!CsyC~Tby1ly0WcS-|O9@^8 zU85OSD|6Hx2r^Yst>1++pG%gV!X3YE5K7?l7equpVL}gjD&4Sno_s$&{j(=5MOp?w9ud_zAt6N=6(s4&VF$ zx%SU(rb1)E0^iEnuSQ!xgu_Bg*ik)&I1zmwZ^Haf0f@FB|2WQO71<;kKS|@wbp=w1 z&VN+fU2~_c40ItD`4^Xaf(xjKDaBQlXF^$;oip&F(^WSh#pvaE9L{OItRhRSbL>?7 zu|P21y`Wt&=F6DNN~Tecz3RJ6r9tKV$4pN&hd|Qih(dQMZGuU5QXl9#SZl?@hfAa& z64hRw=j}?>)9jp8g1*}jOz!Pr%uN(binY=CuW>ee<374XN|0d_pZ1_b8d}3YiG+kX zu`*>bbE*!4i2)ZYUZU!U!pBMTF=I_YRsb#8s)EOAM-fSi{JXV^{h|G?wlinO0t@p_ z)RXxt&0lrY88{6$Z>-xlWr}?{f5iU_;Ns#a=R!#s&UGHdf$zg?rQonqR)vqf^V!^E zCF&V;nBNE^9+J;qb>u^noWZL!%&324JdC0wC4O z$?YCwnf0frB5afq*j*}yz{dAfai-=ny?|gjX?^E7DnJ1&=Cwf;i(K#`Eeb5MvO}09 z2NPS0vNxaKr{;et>-x?;CYsu-n(1zJqkV30-rOc@ll%P)B%lB!wi}F3#9CuW*cOp$ zFt{A_y1Z0GXWCWkh<4e-u4VEU6gdz5SIpd<3ptzG@ILZw&_DvVlQz>Pcei4>L&axj zc`@qzdAyoLkX8Y)@;2TA<_pkO& zL}w=20z=go;*INtL#LSbV#sv$!mB?Cgdfd(bG_yMfB*auljDbf^|cn~UMRU$KBT$S z6i-osrGWBQgUtQO_C#g1*{hsLRbIT|C!PwO-l#e)kk}xLDIpaSjOQeL(>H&wT$lOe zr6d79<2b*~6?lLSU@J<#WZQ#f%LveE;!b z?dj2Ubn8)akMk7C%_f!-tYtZ}FX0@pXFXn6Fbv02-CV)yVM`RaP|>RjaMqJdjI7fn z<$Nk}B=>Kv=35+|@B}Vvbt?`HNage_mymwSG>XLqWl@fh{w6(7y1x$t)8SMYk-GVw zUeHIs^747+B9?^b0|by*{V$_}SJ%3JeB`T4*1GW6bCOM#akoW;Rxl*_5v6Rs`P*7`t`+w9kIa_8PlKQMiu5tK`Y=H7`Z?qj~Vy1<5PMJH^Qu- zM!QATh00|+Re=+2#tOBZ|E`A2_I)GIAz5E|!(`asu_>x>E@m+TdhVA8`_h}uAE3$a zKTMUhLw}bbz<|kt-eRvCS8qIcn(#0?acR>uF{qB0Rvw5fjvsdW;}C&5TX*rX-rv0{ zPJROX51$!WxI+GXT1BtV{-yF6*PuIwQx3+vB#Im*%s8CXm_Pqm7!2K4e<{a(uPj%6 z*@v51hgvN#JLejlyda_;09{@846B$72aOv^Y;NuPu&LU}`CRMo`{7l4zAu(5V-mzL zkssx(cazYdVddSiSSh(A?6_Y}AkRB=RRYJ{^vpVp|E_jXE-U0xlNr-EKA}{hjU$G* z{_8g!Ux~MkZm6^3jqLGJSNxaubAbtBLGh6L#jlqfokTMY>&E;IxNe|M)YCGL^@tTC zRwr86{Sv+^dU03G_njgi`5Wy8cH9_-wqe~}&uUtVI7#0x(xOlFAKHY=4~dYL4X+PR z5IB7;bOacq*^~O5C2E*xORE!^3>^e(#?c{rBHspF4frvMe}l%NmUMkKhw#(BVeCtW z=DnMTJ?hVQkpyZ(6xBUcZZ+*NG{=nR7ekES_({y10Tmr&+8`20nGXm&^n=|=J=?kfNpZUS%l#f2>CE$a2ye0{Okx_7Gp*!V~wLiFi|m-mZ@h#q~rz>m}# z^}U2BmB}u}Sxt6emKbl1tu?g&W);xVO_*`8B_h>&u#vAm){e9 znSLlir+)$Z!0W}mm#-}rE~>f$(380_l~P`x0+M*z)kTu{zx*Dn!*zXwCjF$cr>jqhCQ!o1}H1U4@cCrMzw5~*mn^kC*LSpV%2SbqC@9y=Kc?^aQ!M`^Q7*j^j z0(lN*=f?K=`nc5f-(6D0@5%37^JV08JXCo3P4SmtlaGZOKHom`7b4jpVYcwLNcmA( zD70GJOGuKhM1AR#x#6qBWR>5^`#%C|rxT66m7K`){Y$!8cU7wqlM|VIFaBZP<#g>S$JD2N>s+VtYdO0z6K54 zIghCd6Z_gf#ZQMtC;!F$;=D=K+=8M!MMbd+|& z@xN5R9rNuXEeHsW+w%TY#(XW6O(P(_V}VOdi`-G&dIw1q{6g2)N%Kt5x0HBeuS>POS~+L-z~V^LCAU`DsFG&yIdR zv`&qGk;VAMoH7$RJK7Q3ZO$a9NHt4inrc80y^4DfWB`f~Zn%>&K$8aaem>gT?WcM$ z%#fD;9ra>md&AYizQIBzP>8js3b^R{;44VR{MC!yb`bw_m8AVk^;Ml-2P<|c#nP53 zSs=ESM;C_Tqwd8A_&k60E4 zDGBonqBC)|Al^*1TLwR=ozBEiDs~oj<~y{3x)ay z6?PwsAd5xflRO@|A&k84?;vhzLRP{J=3=gDDb+rLq?ZG2_VJE{joif!#R5ALc0lL* zNn$=8mKzu=d84B|ernm~86Du|)J>rGdTXC0$qTC3IAfjcrMaSAPd4pjUkBb2 zjGL$2_MptiGGfC3@7}%oL|sv@yBYY?h-fMb96W(GUs{fsAt8N=>YCkn!7Ii0yOYME) z-7z3%+y&|12a!%9KS={oyuhz4)m`g0`(g=6J?nSDE}4}r#!AJ99nwP0#@sFewQq2T z%)NG8;;QOZJjMvIN?RFIwH601Db*Jx&_Qj(<-?*@+PeT2_ZIxhqw;E5%9JM-BtA&@ z<3}tXRUEyH1n}`p;yxn6oDi@KsMwE7DIr$BEL3>X>HTPNSglsdrcOk<9A7NTUISgx zTe^3Yp|pN&$?!-rZuhbQgQi}>fK}#`+{tyR-{!~UJ5_iLz4|v4Rd=F$emV~Aq@Vc@ zX8pMQwi`tGByU8<7&q>~-+J4bBz6nGosx8~9W4M|62v;D=_Fb@{0+16Udp)AgmA+n z?6agk$0nM2tK4W234~$)F6x{tw#X2iJANjvYqUAm`EG>U>k}us3M^!rr1@ErnuE* z>RvEp(yohsdboA1N|8XG6q6xf1iqBG1Q<{)0c-?cUTj?9o!bC=>;g&SM;CW9*}Y`Z=r zwF1-NU8g-#SpR42Xt%NFXb;&OuThH*7uAsk=Cb1^W3iLE7Utt=+A}F z*6tS4h}6(jr%S(`HVwCb17~|C*`z1DEV`CIaUhjTExY%>#b@N!Fql zU26$@0xNFznQ_FHtROzCD#@Cqnk4=?Hd)hr0~M>qf>(V!A2_^`L#9x%l^ zJYiv}dPk7wx5l%vc$~?}BM^WIUC8q+T%UmD}qd9=!L!QdjHB2RdV5NWV_-KQSHQhEwH=jS2v&aapZ!f|L zP-^6ZJ7jV=(|Cva|GUT>HBWng_Ahj-_AqJ-MF zREDV^l3e9>HF-NSj1r>;q@pj+AD}`((n^|aqY3s!9$-r)P$)>)RB{mZU8-%8+lpg! zXtEmP_klqW)1&YGkDY4o?ha>CQtgtviZ1n#ZS|K(bp7C11AOd9pm`4**N!A%$B9X3v{IS ztl|v(OUY%Q0n3Ui9x0XHf0N_0n2zsE7OEdX0(7vIL?aKqka(hkspQ6PvCSWwfk)a`G}Z;Hb_S#0U}q@&NLxFI73O?~rn+OJb9 z&BZ0(6y<)JW`G+sd&XLQFSsli-fyWW$O_dXmMS)oM}5%8SL-L>ojo|i3oeoJ$Nes? z1oP?2KLuIhDS7IjNGBhI%K!R2Om0~Lv_;>|O!o1pD{{{i5r$+U01fRPzw0k&M1+G! zC^c3$nPFAajP5Hc#VybBWWRl!4sRJcw!jc}9SjlpAd;+ky}VwX7R~yFX)1@01(@fW zu2W>L5K1MdGwPnsG3SW&s6!Wf7zp}LBIxVUy1VluMK8N4vxvOBDGj;)J#GA6pOzCl zkNDwpJfX>+|bB(cC$F{eKN74%$tRG)@_glV)rq}Z*tdns%3 z@cB?F@xJXf2S+0Z_E+S~8l<%G%AokV@fVIVT5XNJIpML zE3A^~Pu5CO2+<`-<)9N@T!=@*U#>A-PQ&7SK*C%ZC(jtxAIFqRn`a?KhXMp+5gxg3 zEm3k;8?hc4+Dm$MB|b0xjXD2^3bUBIH*wy_mTefKJPfOHeG~BE-pA4(C8j^X^Yc-e zBY9EO%o=0eFYql6`~avyHEY$BM{;~5=B`j7kj?xEY=S6gPR78Z5n`HP^p7#J#R9U> z(9%Pvjq}=nHO!5IQ1Al5wi~v`vGG7|Jx#`5Z~uSG+P;DPT6=apO$gqv*+#YjH{o_7 zNgayiej9ee*AwkJAHV`q0q{;Kn+X_$;04df4+GDeN5db!OWn@&Yana~SNq#vs7mWu z(u02dQ3^zx3gRIj`$ybNirdC^8g6t_8)lZ7=UUkzpc!w?YED9b3tHJm^}O)UXzlU) zS9Oiw54w_ChLD|Jxr>!hf6B()^EDuiZ6UF8E_XzC$;Q@-yBQJ$j_2!e27Wu?FtM|% z>_Q}otBr_O*>G`w;Uv`%e1-mM^28&-#j2;?FK#K{&5tZXsjln zFw%oeXgF9Pf2V|@d|iCpPg_``ri|&B zKs%GafzKCM^$jcg87r;}1@6xZX!r@2YFmxl>~SX7AaE((2ql#xcjs*SF&Wwlg{Ibj z6mP;;fjNLv_ZIo)hn@hz@_12D<@fiduivq(JfqX|_O^@pUEVPE{0lKX(;gKYH?n{D zI%TB$So$uy7295NtzdZL5=~v3i?T*k9D25wMcg2 zY!Ul7+DoU+A-9)Q4l?dF9Ct8Ii{8&kotg9UZ1R0L^?sb4(Fh$5n+Wa1+M(g6%lx(D`&Ez9$IAGVo2oI zt_JTq=!{6vxGyXDO9O&F?6Ipl8|25nZ2;l}sB{K)E@uNp$W zMTA4{@ahoKGG*WM{=4mW)8P5e7x&K~s7+x{GL@H2x&p=Gyf67$cCdbUaO8fYQ$2@m z*iJz~l6e~a3GX(-hS@WvnTalcCO2C5aE#aKpFqeyXGs(+OjD3Fde5c8$oQs0mT}#Rri;MRUc!reOTUEZ=i#+PI zpSlfmdwZ3={z|NaUx>}Kr!He!+utNExmD^EI;Cll@46g}UnteP-Gy*dqyhzxM?v)0 z|97l+cx(MS%r8$A+6FX~4U(&eYAT6C(4l(r9_t49Ub}DPgHsp+sAb+yDYcI}a8XZ7 z7Bg1FnZ@S+Ob8p&hs%nJlsmr$QNCr(4VS5JSG^rLbilpq?&J5o|F%y@k+rE~$d~yJ zjd3^J2lZmzkyUsjm%EyZx+&X@HQ=@g&XKdLDekk@XU%QQrs9 z6IcIN?RUP!dc}Im9mZ7{*U2V|R$w$PKd^h#fMqM_PI9HlnIQ@(I3d}3jf~HeZ?7`I zXK`F3!rk3n;f`9nuFCaz9y7-(nT;b4)=JY?&B0+eZ>)N%6*bOANxt77kac5Jp` zn@W@SDz?p>mVk-{?eO^93Y4`skbxU=e7FV9`7n8SMP{i$^mx~ZxlPZ4pLyK-qCZa` zTH4#1SBz4d-zH=Fb@Eny;b~<c54Jzv$G@Y>5KVYIuEyY^hW#+fdN~B#{U^{5Mw;@%OL-n@hl8i2B>5fV7#< zQoNk&IaR0u|3{A#i8spPgZ|YJQnFCV#r}m?olD9n?cVEm7GyaU#9fkew zE;4!@@}<5DVS4@{Ah2+W)-l%}TS79$D4M8+%2yMvV|mqJa=14CQixvSmhtDFYbK7E zV_&9aIqUF2#Cy7{4)zK+w$HkhvNFOpJ;sA=c-&NqPPisIw^rcE6+?QdDJy$g6zdQ0 zzt85=vCM61;tf5)(*2>NUlQe_RFcw`3ICXsO*UrcCxi9mmhVH%wD$Y4y}pe*cMvuX z?hhqQ`G{%-UgF>1T-*u%*>LML_^Rku!Q=F#9l?Z??>l`{UAx>-&7mt4H;v29*8kV_ zPwbCxJEY^{y|~L5ml*uYpHn9yXBvn&zhxJ6&aoAft-n23j`)WNPurxKoWo^=^5N?u z(H~1kA6zi7C-M!*lJ?5PuSNz879hY#IaOgXc2Tgl;cWlip`X-1qLH318GUPNBhUPL`+bMiFg^-=T?xTYuVW?S>?z3mH%1cgA?prt*;E_Y z9!bS}#h137cI0HODv14iDx;_OUwkYH4(9x3ErXN?%M>l!Y(vgR&@6Sy1Z^Da6C{=U z6=gNl+?M-G_n%?Un->Jr?3IY|?C)}19Uvfq`HbZ*;&0+6mg)W6{X_MT-d?kgwN2_v zmjPrD#babX>MH{I{q$Iq5Ll3(%GqKLD4_(E zArLgN{UBDiyfI=?b|v4cY=x>7A8({oOPBBa8$_xj+3{GHhw9+amPLUM-?3a=N{Vl4 zG&SCfq+uCM0(DQ4S?9!z-)%K^s2tdLd95QT|JhXM*?Bv+m8v{ZGu|~wcr7xeC=`>K zTtxfFZO!jvf-wvXy|(OItkyG58}IQmIj}hc2U59Li4(Dg=$Uin}b$Egt9kki_ zV?U_B&N&zzHkgwNQIzo~A_%s=ez}~>>0f=^EN1k@R{zGi6&pe}MbWuw!z&04@BFUF zRU2WBy)4&Wv6OKHsJ%+U#sYC#-EcKuIbBp4HR$;iziOZ#F| zdQPXdNXfF}_lwBV8i`SA-ynADJIGw@l=Zg;(L%9MkxM>kg?CIM>Bqrrf z_~Q^2Ueo$b)ZmHQ1iMy*7m#l#1<6ef#)w?Kovv;{-&75yxMcqX6OgP7(- z&ecHiqB7#P&$dKcggK!wqm9L7L`FKZdg3r~!;)#^EW7X2q)l4wU&a3s&MfSqL(Nh)o6Y4bFsv)j!mVY zCnRXAF)i}lrRS&Q@c$uxIMs_>;TDdH1--_8MnNiylh3HTb1`&xb(6Y}_U~vl3#`-J9IBvI1f91_%_qwX`u)4VGBh=%1yp{8U$Y z37UOL_b*xfC8*G6S7e0&jb*IJr7&?1Lx$dY(Lu1Ga>aJ9SAw_z&c=n1t_bnWYjg0c zi$1T#&N*q%j_~V^P|jqj@fJL_iPxm748MGOU2v@3COw*3)KYdLht|aF5`fMlv%|i#y6|!u{ovVphdA=O8LWXAR$IgUfD*?lll6O7XSqrZp zLORFaTrQ%YyXJrVNriywNKWi!`MVyy_#ZIN4BvXEpj$KfeNZ!~z!!$Gu8Hz{NVjFP z(rqcuFD_u1zT%-iPeX-CS<}mTM z`4T$kOPjPz=&=8=c^;pZon>8eMMBrhVD=PqsD#xAP-`f`;|#2bpa)~;rUmORWZ-6B z(kWQ&cCwbXrQZQ5AOY1gcMJ*$0#|;l=ZpFpK2Q16Im9j8n)ixPU5cbw1pfa;j6=iHdK29tZ21|@p#WWLw^0B}Bd3pU95!#|Vm zo1n8kUGygXql+WrH-_h5Ap=~&6>KXA&#gRZOpZ;qGaD_MXd3cah`c77$&AJ=|7X-Y z)4~V*#M8>O8evm-_BJk?ezLHIuJv#Z%KxfUt1QE4>2MgWlkxXOZila5Qu4RoJG?HD zY|?J@!Sap8zXDCZnN!Brz0oc=EE0zk@9718XgMX>$o*{)mY6$Ay?%pu_H~!9eoI=` zh@tT=W<~LC)C@weqw6iQ0*~sw+P`Fo6e!Lkt}oJ#>nKGjWL#x8W_F!XTKXnWx~E(9 zZghfNSoP>ocl*s%1^y3uw~gjTv$vU5d?)#>A&IoNxoYSRly$r{N{Fd9XbjGd=Kt#m zI4S4p!ck{US?)l2sy{!7^}3FTp7C8iqP<_2xI(#ct8U(Q{arm?kK<@$SemO$(EkCU z>!hvNlK_x>+w2Xm(J4%Bny%Ieqmqz#aUjHfpZ4CDH*t%wSG>1f8%)sww?w;5(k^Vu zshghG?FI!@zFRDQe2pPIr~0tNxAZ`8(b9{V#zql#RzY{jmwJVt&;6od(jFNyPfzmy z=yA2l_Mv?n9c9j&= zI5bThq*|+dd`E7E(m9mhC)!=Vd`{5N>8NDR>Qw0sX8 zV{?QimkIv|eUqp0+q|rmiayD-*|%v-Avy$Al{gPYOr-?1{dNkr6~{57BT^S_H;jc% zGR}xSYOCc;>MEe|uTk!^=I(~+gyri{TU*du<+93KM2&!lTjD3j;^}`+IdrULlvkDR zVYIlz-DL<2>REAYDj7T;MJ`+$6@8(PtGCF)PJ8ni9uBG>#)w*>p2k{GjL1e$Yiv%R zMbtUXCCB{dJbf#(BV4hH;~(2*6;!*>q^EU5MOn1*Tv8TIfm%XxiJRCJ%Z5g=-njWAos2W%AcSJ9PqKjHm;g^_h9km*FJ^^ilh ziH;Y}>PSKocm2$%tIcnQ;pda1IG?yuk#2D`_ARg2^znxFq>JkbQgZwl4zcofs721x z+EjH@1jdK3=kG9IAqtgEemnJF`BIOma`Abj!#Z{O&3a>Fls9cWm8|!VuFO&^@MOig z_chA-+^i|AJ!=-@3gB^5sPS%PPOQdBu#o6LSZYXrdC|4FFaW)sz5X{j2PCRk)Qtqw z>X^qI{SQ7L-^EC3S0Ckteyl>L728XM;;oq~7l-0^)3{e(KV*b(cEA)woD60w?NY*+ zM;?@blxOyi_k;PoyyG=*-By&oWcs2NLP_F=_9GSMtTKuw-`=GqdSL`dl-a-~OPZCL z0V`+b^NXLoXuxGWG3jSs8$BDQSHjSDJ~6wo{1RJoB@mcMh=)`y*)6&R0(bg2Q-x0^ z9vjBfzxo&Y8~vP_**9c0q#{1i*s;Ssx>WEwxyV<4P%>e8gHn&GU$cJ#b|nOk)C_m| zX)-_;i{qZGT^Eh2Q4#&A^`#^9b#|v?os617r6x~j+J*ZjGL#>tWOM6cuDW{D{oF*ZOA*O^~v&2Ujr}A;j*`j8Y+dxqIU92 zT*lpdYBr{8o|vgbnX1a_>HW>@J)d`85pipGV2pEJ->UZ5UoBZ=SG7;uAa=J-YFI;Zv$G%aWhB4UKQwcdqAgzk4cMSPYvK7O$c1%GZ z44DcR;MZoz&sHbh1ybW>!U|5Xt4LO3?JFYM6dsy)&pWK`ECu?{6)EMZOPv?pm$Iaq zAmvn{yvO$y%TZr_S_G)W@9&VMTSd2`wP{OcICudIBy@r1oR zCSEuX4t&-)2(mEBxxJN2JS{JN-Qw=jzxu0bIaDnhJU0_b|8a#HgjV83>eWYj$R6$o zC2ec&jz%&BQhVS z0M3f@Evs^PQ}6e(+WtF1_ZzL3RF|xoRQ_%JpINn4?i#OY+N|&E=QG~jMdyqCZj#~! zl?>r+)$AkIb)o(3Y+L)dKFF*>ZB_zsig!=NJ_cphZy2fuz7MPM7%)?L=TlXzkF4L` z)#@1XJ!~iVx&VGAsKaTgu8k^) zEfSS=p5bZdLQxXLMc|W(FPE(za6aZ$UY{lVA|ENI{R2@xi{actgpBIm8mxpD@Z)3D zp~~Ie?cIy$AetCP7&0mXB!hn=XLwbb{PIHxyx@=;6Z+C0BxAdz&rZCq{Z2-jy-rC3 zv!`xo7nqWxA7ACfwu4*sJs(Dyu@!E+FBrA@&&^04hiCUGk<9p-)4Qd#{!%R!HqXNYzA>KtZCP!(p`TGgFrUik8v!z=bhIBOiTTZkjD{4Q)xUBNCabH=j&0YI2n#dmZ``MvTMq00nIIGStV()?>fs*=C~`W)|zb`@$XU2@X&It@(|2jG0)-;=aA-ecI7 zy7-ezCXAl^VsVCM*9bGAoCGaV6s*PX$;-=O5yE@F$(*mONZHV&;YE{zuG3nNi6DD7c|ily1ZRb=VjF%=Ui@H< zhT)3Q?7t6~s2FMb?TI-5$?8yz zl-|Cx*z9f0jQqtn`K2=RU}+QY-i{v?n9IZXvm~UNmfBU-=YepzjrkLaR9ul1hrOfY zY?Wl5^Z6$OhNqY8R$@Z#lad&}aS-V4$P4F=sfa<0e)(SUp+LB|GoU^*)zoDT4Mm5X z*ylud>{l8A<%Vgne~M)JBa$3B-sJ=;s#mo5fG#lA&XsWvNAW<2UIG9_Ij>s|9deHh4&C8CN_e)s%`g@}`P`}5Ak+k@8yzXK0cBLp{ zm+h448D#Gn15(Uh&M7|peedpBo5qBI+wlLY&$dGPLD_@?+PxbRQbKq`VYHWE(i~!| ze1jlAtd?5U^&;e$BjK3IkSrZ(1KCp`Ct>(A3kA&DG_YOqhwR;DKlZm9x7Dd(buphJ z%hq2hmF{&M^qdyRNllCwRu;Ztu(j#A0Sqd3hQE>Da8_=W&B!U<%~0@?_G8c;R@;z| z=8F1Ms*dc1+QGx-KW&o}OYFg8>hC%YI`^OLud<~Y+uxS&9VDya3j63{z!z`v>(MR`pHr&rB%7#tpigDi->3Zj_jpWQ16tn3I_xwlOl~ zA(Ii*bb60s9d`I9W8z@GXeb_J3WA9#LsF%_)=6dng5bOjnQlfpyyW<$MUawmLZW{K`;J%b%TtR?7L{gE>*A#{GX5c!Bld63i_lvubnks)5^2(z|4^^!b04|Ia+u zKPAq1_GCNT@3huEaj%qs?;qHvuE~?YQx`^C*M3yCRNzd_E=;`K>>ZlZx!NiJ<%02` zbdYPoPq_aUauFWswoihvG0WcKsi101s_7#S{F}N4}Hb~Y)HUB)%{Y&@LdL?tBy|X`PQ!4 zKJ&6o?2%=$>?*kou&4k1@$=j3bscQNbxe+hL5mnU9RGgL_J>hDor;<362bdqSFPo67Q9;nRq??R+X6$krK~@ zC`*GkdF2{<+}WxETLV2s#DNSU9ezQcga(O`hM-E<2a96*^f=+EQVwX2x$__zToL_Yk!`+4uk0Rq53J5_RKqb?&4Z>>zU@AbdM zdiVJ5%4+(E=#yFO)(-`58v#tUV*S~)A*S^uf2p@3>6q78-4{~xhFP!MCLT_jEo9!i z+{Jxc{87nKUPpE2Mp_aafpXQU%4dgLBwdUe#jOx!- zl4o2_>GFO2;GzYzD8Z&iUSYp%M&-8pe;#^Rzv#;Kq~Fu(^KG(9cRn{r=u4mHaxMsd z_6khEyuCf|7)T68UkN{?xoNz=Pq;TCM0d#FyS)Uk8Big*VlE7)CjS)vrSBCgR;5`O zUBz~@Ec-){>R+Jmlyixlk5aZ%6Y|hM&<|v(51Id&UIjYFgZBv%&_~V{$rm7gW0(8- zFfJ1QGc9ivnk57+X63SyM=#3u^bg+2iY=4~rnbOaQPMr3JbsENW0E+uW>f2fvO^D7 zM6bk6+KbmJIa~$m8(G@dGq*({U0kmAq&~RtLkk1E=&!E6gaJ7VD9diwxZ$(=*mYxd zUF9yEM@I9X*gu$kOhLw5XEWoF!pIit*QXjTcgfW*8V4Kz1LB>5k3v+r^`tL@bv&EB zBlz^J72SL={BYpXl8?dOfShrwzec;LIRAwz_sO7+0Q58n>|PMER;bGpJNrQKji}Q0 zL+MprO~46;H?CttZhH3V-G`(b`;UVK(whH3g}Wo>p6{CNxo^kiUt=T#GJa#*Kr?z_ zbK9%M%U+DGC`z#!PXcnhSh&2*%yFuW?_*-T`jb_02g`WFQ_4by zLX1s#-4~86fL#XMi+Me*hZJjdq1O2=_l6=bMa%Uw)i27Ct>ILaq|r#p!#K}!#0d|{@i1Y>{eN`_NJzE<=$26NO0c3eaCzepSb(B8e->Gu!I3IlRjr|EB`&q4qL}! zZ)5)9`c%kb;T$r^<*KB(WFjHNx?E%a=`B%vj4L!s;@lC^U`6d#D7d)lyl6DW&9Lg4 zenE;5za}Fnc)YGLw(1VNc#Ol8t+>B%y}>dx?`jn$oZ+{5gdQMIRSzdw=g z1G_&om2I;4yshZ6%=xlmrg8O0T}sS`tnfSS;52~>CmKX|>rFn^mjm;%I5G2wVbyI_ z8G+HBiy9OUgVX2?a>){6sB!1du)Yjqq(_*wF5I-)<2p*@lw^pipy}U(pND?m++5D! zsd`!(aC3&_XHuQA`!~p4H1PS|2=lqV@AWmIeAvbRo|cz#HMu7KA0Qm3_cFL7;L6eE zNXwEtJw>hLefCs1CeA`L1j`{qGm1PLdr}XVCRP0#%!hk~)O_|G)JpW*y>PoV$y?hQ zqI@DtT_)ioKBmw8AF#UfE96OtZSs6YjzR`#qsKwzQk;|c$&Vz#1h-qlVfjU9*vTr0 zLs#~-f;~Sy&10j#^~50B->Ey^ZefFD;3ZbuwRCuL*{?bI2fmkG+eyb+{5yQj&{6M| zK*fxjqVSA}gd1v&jLzbkyTM|RYq;opHA9xh$E#IVx>RqJq&9_)$Ffr~*$PnJEmacU z&l0XN{MBzjQT^ZURp{0BJ1t*nmHhwk?2Eq!-}a6~ma{yk4NlTJvAfuVnD_*>oGpY> zr|uscQ032NwUkbPgTE4pSoBIZ0##G6NZ|Jo^K7$P6JN^WO{EM*P#trEy-4MUoPfY;(=u#GqHZB*L1fow| zWWVw65T`Na(}>*dNL;@@t!&=Mb7iRu`(w{nggPrYp%md~Tnj4;Hwe*TYLXz8_(_o& zB^y`62mAuWND1H`C^pZ7m08&B3d$dq2_my;=7Bh)DY@6-%RxFYwfRw8<9LX7^CTYm zZ`B4(P(Br15`WB7990x)mV^(nR!2%DmPadw!fJc6Q|SC%Ef1y#{k)7?JOwY%h6K@s z0{)(WcmiLVHwbQt>K#DU29tOgE*LlTOk`x;o?}YnAj6fhx300-IIgs*TR;8ZJ35x{`$q1`?J>SwUZ-1Yyz(Z<8xIV=KTi^P^4J-~ zYwd=3j2K0OO0f#V@b0cb4CiIPgKOiQT7Qn0%Ip1zC*;nE*d5!(|i32o4 zp>zYI^0B%Lwq=(|IJaVo7~ejDy`6y)-fz83cPQaKP3|zxsM$a3sy!TjuCN?XlTGqY znkTqC(57WsBKvoQUYDpoGdVQ!6yRpk>yBVGL7uiyaSIpI0|!oj?+aJ7hXsCq|IJxd zBl#%H5?VCEewD9T#iTvKAg|$e-U*B0v@Fw)LGfOganmD2*#j@`V_hc9LCz1D4615p z_Xbih9Yv|+1N?CQU9^cv?)2HpcKt6i^yVk`mH=M<6G}&bsTsPJnd6i;Aco@V?rrBP zFG4%c#CEpSp4q>b0&JrB{j?Mr)!VxKU^qn)Hs|F9F@dv_ClDO9hkYau>E{^cp{1O^@qQwTnZJCynw{i&r8>{;Lg5+@p`! zFfqP`>kYsi&h}sCcg-x?gQnQT+cW!@%El!#hF_xFGn0+h(%hU0076%D%3a!;!c<>z zUR|kSABv{99yxBxquXj5gLh9^APW5aXFrvUK8s2pBJK4L`Z6@F6u7#{>D`UCH{V{= z6+5$eC*o&-_I>>8rzX^zALZ@YBhTl`gR4AY!5~$|Vo~KvtKaEV!e(J}`?RbkiADmoT^QoM0D*;m}VaZSY`q0(J7b&7H=gBXeLkS1ozx zCwiNz8<=Tm5T(@U3$1f;P-0h?;?#iUgx>m!Q7b^k?!s%*OD#2YhurK;Ysz7IpSd&9 znr+EVjj@M&47}zJ`hL8mSe}*sXaGnHJ@Y(%L5E+3-^(s+MT!0OCrl%WkpKzyIh7de|vXz0FpU;!u{s%mxF8_N^Xly3tWd*K31egu)YP=Y& zS6U?mM(qu3>Jh3cF&CdPtm(WD%<;Jd@qe}*}jHo{Wg?uHG_)lBK;QjxKU{mB>T(ke^sWy0bu2qaU_6^a=JP`{ldR zX0@dPCEK0N=4$x@{{QCZ4EG+ZY`!x;my{}_4;EcXUHi!V11!HH97*cerQa2I z>4<4?F6pQqvq`0$sbv;^^Z}NV6nU`wS?+fiZQGgKjLBhqx!kV|h3JiU)|^WCrb;(D z?nAo+3KZtAuG)M&uSH1|UV)G7>4!$H@b12iVGEFONe>GL^w~;|tCHU^6M=(X2eN@( zLdr5`ME8gy*9`Re*OT23ZY@83$rv--H3$jj5cTKp$sJgaEHUcMO7;K3y}7m_m&Sa; zrYNxBkA|Vxn72b?HY;Xa0^oDGeU&m2SrUna@HthDnZ7rmHjK!H${FAMj!pv*-LB8U zHxMe&1v0DmACY0bu`E=f90PkZP7?=}^;qdnJZac%ZZq*J+da@7ulx4sQT;}@l4!8FW!bmaOJtihX&@dJ8@?Bs*6mP;VRB)yDt%ded zrKAgez|9gJAJMX;K6*#4Rxl|wKO;X&DmLNdq`E~WwG!K%64WkudmbUkfh^iky#yT^ z)?cnUi|K{)>n+WFn6**GWa8*%ja-Q$wipOHL|ghy>O8rZHwDnm31{q%1CZ8(dW^lR zxMDb21udN0ej=kFQ$T>Ne=-s#B>%CR*6hmhdUEr$sH+71XbeHyjwtMs8*n=dQqQ8F zTYjoj>DaP1lDRtQ&wu>8uX-WHeHGzZ|E|;4&D%|h4{TWyeWkM0FU{<#MGXWDt4=kk z`_R+*CE%evRz2lO4)k7f80osM&^*H7Gj@T!*7yw<`!l`P!8>VZDjN8AQk0D3QOm(P z{)miNAA-akwcco3=8?qPwY+xL-~DcYY7}tq;!1@BmIgedR6QCd#M6?fR+(Mbs3Hw4 zkh2!@T(x7&18=E!;-HsJ6ZaiQ!Y5_pZpehnBgzQ68)KIi26KuV+*dS6?`(@T1p3pK z8cN%`FE;jJjpIkW;wH-~M(&hN8mYV5LQ!AN;5RQ5>Pe>&qRErE2-{uy{4w$4H-AIe zh9Yf?)uihGjdn`aHfp2%Hctd+yEzM7mP1k$bCS)PY0Y!^T}$gR!dO5{W8Q|Q^8ujQ z%Ba`m$3L&sVLF+xsX)YS@|%{BHg1W2a{FEakaocDCP#d1rz6l+^})z`YWk<%Ht=`} z{H${cY>!$wqg_2R>EOHJVaAe6fK&EmCR#p3-`O|K?hZv|nBT0PCf>IVw|pcL?t61F z@K;$|+XcrJ&*6@@H9=zBB z1VK@jRC@4&=nR-BkxAPPGhx)N;HK?heE=n8*8Rox!Z$48#L{cZX%T?RplVFP3c`>+ z^SYm{Ixb9YXgt@#C9M&XFjQ%s89tlh_Hej9>STSnn;oL$UuGZDvHNCb$;BZ>hKWYU zv~nP8$)6Rv4&FGza;~7Tu-#lsY_Al^A5meKtk4#Gc&F?cLM0Fi41bqxaz%+q~hHn)d-6zrKQqlpOyKtdb7SnoYyTU$n!QlRRxjr-Z2G5h(Nk|TV z7mlu4$HwJZ$-Bgv(3INDz%GBHc|Uyg_AXA!?l7zo_l?Qy*$WB|A?QNQO5U=&>jV@3 z)0e=uOX{@@O_m2LO5cHdl znD~y2{usDxa`4F;6Tg&pFjCxR&j50JjuNCjEF@T0IdMk7sFiN%drqL*kbpnIHWQ=X z6Q%8XS}fxl>IG;*LACn$=(c|tYu0Nb_5HR^Zh;NwyL`%2c9)&g`(fQV%o7+2&!1U6 za^z-b*I$t^21!|@%Ukg$EPpztC}s_}4t|prYcoC+<}S!W)qB*$!1WHKRv?-Ww25+p zR`%&Js|$}rG*SE~o2%b-X5!m58#mU!Cr!DoEHl5WWC@Ihh7QLEs8o3C`y=KMZ{V=tz-R{@Z7oW6~no@$EpLp!{ zSZsqYJk3{Etiz2+gs`5fVbGS8oKjjK&*B`nAUhT7YX4R?&(ML1u*HtC+(4C z_4EcTP}q%&0Uyo`h!YJ}T#Fiv1`VqLy29v1hakAdmG%v{-Tv3Z`V_EsRb6j*IRf*E z4z>Uop%)u~X@s(V7;tXet3!@B&v$dU?=lVN7}w6uytkCJTYBo*i*?Psmz?smGv~)6 z-~0gi5wj)(Ca?}<%Oucnq9NrB?fD#$Gn(kPRT!XbHie+|*RY9y9!iIMM z4Kty!{qrBc#U(^#1PR(;l97n(1yH<~J$by1!1LhDjAK2av6k>hOA*@@{+p#4tr7yZ z{@YSqnq~)`LH!#P&DsB?gt5_pYmaLeGgGPpK}3_h?FGsikr5@Hj>CHwUse9V^$RK~ zzHoloo44wJmG+8wxhVU6XdG-8%L(D4<@y%Yr+_j6r_GO}J2pZl{<@k&q&fe&fJ=_* zw>-rc-Fruw=V5qAbZkx>zityVC!s&fBiTL zaY!C0Ba~$MSd5zy!NEPx>I4K5RkUI@J(UZLpR1|k;(|u%+kJI^dV$g1C7Ou?{ez`j zOB>m=+99hY&a;+6+m$t|+p@4_O5KXqIHe~w{d6lj(CeQ`@d%56G`Arxt5!2rPqv~B zyMW$zAR-|b*LMWb7W_5@S?zjv5aQc%IbIZ)%knHb1VRzs5gpQh zo<+yn2fAECe?sxQ**ZF`XF(kCqI$7Uvvki&B}z^}>a6P)H)I>&AsU>^_;qIr&cUQ% z2c4QOG)2oDDw!?2N8hoAgd?TaW_#)e`{&vH)*Q-x;rr!&-@PGS@_dv6=B1O(GoJlB z6A0S+6+;ww%Q`t&&5wRlNi$)K zw&#mYLU2t`)#~YdcVo-yNnHk&*&N(;_3x+4AE62kLD!dESJ%j1x7I*6`<)w_|M2uh zi5ue5tB0tlM*MVVtVV8Q2+Q$y+frG|==VDtg?65-zqyRI|_~nF-4q zo}`ml`MKax;|7T|_t!Q~UMX$Mb}2lx>4C~G=@73sC zQ+|}niWiJ;yNnOe^8jnUH&ot5j5=n{8i8d$d8DW^an4`uKcOxj`xtr&mfKa;D3Ox515DR4N7sj*@oyfOP|il1Qdj;!}CB~l|j!m0XfPPNSKY2r9A31he3J3GCBxq>x&@fuutNXxCpE60V!Cnv z=YVQx9XZ}}?Rogu2gzp0Tvx3cXO)i)XxPHb9Ja?bT{Oz*=3-X^Q~r|0=BlrvF!@+H zryF8-1AO5{&x-K#@|NLuQ^=h5k5~y%?=oij(K*dhwi*XD9{7>P1b7& zvbu|Eb?UBRRjSf-QTU7wuf|59OHVB)EUi!l789P0_G*uMSC)m`Qa@uwp;1OusL7$j z!Mnu=U>J_k_nr5Jw(r0u?yV8!r`%fk^+8296!^vs=L;(P#7LeQ@o(M)Z#B(ed=rMB zlmu5NcIIN0QQ1`aqA)T0=o?P{AQK$f*`nm3?2(RZHuR zCna6&40DYShASg|#})!R2*kaNj|B{HDy)~i?_(cs=+tbWEZgY^o(UH1VYgPC8F7 z?HBdAYoz~By<>ghqz{m~R|7aQHb>OP=e%~u(kacoo#KJ1;|U9Dm&E5(N+yi>S5d8= zMJTHD{5~FStvOiHmoIakI*#-`cLrUwoe(hWn-Y0;hAQ%wz(b{iwkHzsn)ybWX;v?y zmwI{<%>5J%K)O%0NE0NsltjliZ~6T+f#Had$CaWfhK{5vKc*#KaLVD({~^s~d=GFW zBp3=|XLMMYoWf7X+?HsxPMdATm*7)mI~7#Cyd|sco=O$m{Oi9=QOX4UWd&Zp9auny zKcRfY=j1}QQYV_BW?Zzm%pRKcmit0F4WaR~1wOQHrt|Xk)xLDsj zod&?f(9l~MZ8PfF>T0z{fUxyY`AE_UW?wmve_VyO-N+i3z?V;`5rvKs?)$XV2J}0k)mQDtM*JCMZ<{{7O$Cbo(52EN`|VQ z;tia@$2y!l-A$1e$r{&5w^*{4HkVlQ4J`_LaA7QAac3ewq}NdK<--A9vHanX@&(sc z)sqXoAY~AtXkMhJE;rK-$B}}BQ(NX6RxOUB^L*??0-LVva7HG_+g^bgz{+}l9o|n1 zI$w@0wcu@%pwRVY>GvmL^2@|=|0-W={i#Vz>hL?l%m)GDeu!mZqv2!ZvQtCmFT_+r zajh_qcS;eqTqh8eHafrRb}w~;8SkV%;mmS6D4EG=aBJ7g2CqJAeC=!SE>ZM*O5~u=a7CgEdkO9 zYz-6(;3)u>o&5H+w`|KT$SPr_)b_^jc8RXSS$ua8v$bf%CPkDI_CmjUs{x=)3@X$@ zjuwgKbJKhMDwnFd9SQGe6t5)&l22d(6HV!x)faNyPDlb6e@Px~F2ycJxT(RnoU!kyZe-GI&x22fVa7@1lh)qMO{TXU1B`ZV7pBkyKs zmI;=gU#ZxB$c&KAiRUMsE!Z0k>)`fUHg&XfyyND1?`!SlmYL>{l04-{hb!+4ec4kDc{VO~_VX0w+uxtaTtS>&qu1XY*2RPb(e-Sj*&$XvXq(W$Ps z9)|;iiQX#e5N%jgY)lr$72*f0KC8lqc?k!TeJxgpN_A7m7hewlEo51nVMqP%7U0Y} zBj1^YN>7onWZs41>t}+1ddmBn)L`R;kk8s)o9nNQ8O8FP$ef;0Carh0Fgj9UG>wCI zeElj1VuQ%c>BM=NCR__6m_WK$T+M7h5oHO-%VJ*ymWogi>YG-;QuoC#gdq$B3o_8_ zcD*ksrTH;!(Q#uv6f_{a2I*Kb4W|~JMh!O20T4WYowmimX~ZYVCX6<@;DaTK3y&Q) zXK`RO-ka7DADC74xGn?GeapC$WmB6k{rlIh<=?;7n=+4u?L>#|Gy|^1W#NY-y}?rT z{4V?DzvZ>Y8fnpC-PrS{UkkX3VW(ymMxL-6{eKO^&xK=pB0Tt zTLk}XJ{=(KLyA|b*|Sr+vtLJ~d!D$&EIamg&JVfR0&OyMvJ5SzT*EC14;2z>s_;`w zLtp(5ojUM=UjbTaN)c@nV04>*9Ji$@%Z{U>d%eU#03W&4_u%f}(Uq|ED}Opr!+V3h z3`kC0PJ(?EM81v$n%;m6sw*>CmtEuiU3`EcintejZ*0y##3p&cf13qN4-}i*Kd9(( zm?2t#g_X>hH(!=YPUd2-Qf^#5RxuD2TzM{wih)>)w{sN z7C!FI+|#@8GRAWzEXS#%x?>D8bFW|2%FnBNFAP5>*g-C8`I`4lr+xLw>-9tlZW2`{H--^osulWj^+Vqw6`kH_7YQ zFaE@;Jt$80sh{u%M?P2fHiDp&7d<8C6p%Kmmiw~cK>q+&hW^`Qn0;OFyS?8eS-Jqo zzrJsxgG}d$*@9R5>rCC@5_tmiO|ZAQUD{zR=lX$a1Ez`WpN`9gBcE=S(XxF({1(53 zz%pxbl^w0lErG^!zWE7Gl~IN`7Ch}I){(#X@NF17g->sXeX6ZXdRD2eQ1)o}!heP~ z6`hN=6Y`%%%m=b+jk!7;(n8xaRuGV;B0Y;sB|*DAMUzn~&lY^C(@aRkL24x0=fv6PH;DcBtY4F?#_!adWeA8F&2X##=}<&GkeLv_ z?4_=jSn!8h7qdV&nd-N0yi>mUIvltXfG(y`5OJ1TX?@vtSVsm&ihb;D!PkX zr!xd$q2X2-H)P%=JOYmS+dezad6*d#$Zr?$a$nF~kl+V!Ltiy#Grifr7NrQ9EEZ1G zp)V`%6hjj0v#G0WBXZl%A6v>}mR@P+8qFHocc+Lp;*LZ{2}?lfv7mUAh#$K9Ugc=m zyaS{Bez^|DSwMnc;#6GtW?@SGweUg)M~{{4$Z45c1q;R)o8DFKI+mpuS2_rB(o>p=!NLb zdqiP2blkP4#qr&L+8+nSZr_=53^1DRJp(yEpp}YWXUjNYJDG*qaS17(^CeeP+TDE! z2XV#O@G0OipAXa**Zqt3=Rrr~nd*g%Es^iI(V6{*<(ez~LjFBTz)6$gKnSRAqc|If zvxD34E#~&f&b3J{pnFmk-W?UxW14MmhudzB)X}{YE^5lXX1-DVL_W|uz*ifMe5rZ% z%_&UFtO}8`JiaUi{_q%j-sODd@7J#~kLbrVdgkJU*9-Sw{n6=T53)4g~e-5CF=hT3eMoOgxo%?{5FK&8GJXMkQQEN z*2dDV`~x~}%IhR9$SVSJDl|8u8J~gwW%RV_1o3WvW*g_+F2~hj_1GWq$6qShq(jSP zC~?O~w5_!I+M?K(Ah~T|Y!q8c9<>2TP4eyScu=?#y*c2HAf zYMfU*Aw|36HY6n;CDE%TXhWD1hmL%nH}C*#gICg-i<)2JFaUM?d@0dNQsCJazf&!p_pxi>cLczcB(=VTCFlVS247Fb#*QOe*#T9?->~m#H|;@XNQAlGDtuJ>LM9>Rz zn3A+J+{46i#8EnyX9q2hjFlWB^TMKkl=yw5rcT(Z6jHR(F&LGrD2`ZXkWwQAfHfns zwrfOu9K6+E`OEmrZJUmQzn3&d!2lxX)d6W=_@0l-a>aR3fjHZ|a(g)zlz{PyG)o;g zY~89pyfIXGqO#z>uIFSpY3y>RpIS}+AH23j#`N}`99vV-hD>|S) z(3Jl*XWl!_=TePy=kwZ-9ElwmAkN8LG>m+;Eniuu*_Q5Zf_bZvZM9a=pa00eUmAPa z!&opi%h1mKh^aM9--kGaP`xrWJ$;O21ilLyHg;-RDxW90FPrFwJoF!2f92P4UKp zIN907If;U2h;RQNEW{2go`~*gZ;i0G)Avc&sfJB*VoP;o)*84~v@1xR8z3`$6;_&D zq=iNgaHKZ;J^P*ZO;Kk~XRXQCn)?f>xk;9e$E7+|hP!(v1t!w3Qi6_TH+rs1r^&}h zV|6e&h#8kEXr0K#`vF&K?oKNwXRh^>5e~T*`-v^iOBn?`3Tw5?*=yUygDl^Gm~_9z zw}74esiT8um-U8ToKMs18p=XMuHB|jv03y}AjRJsIx=?&hGQ7^a6gcr`+Z(7K1afj z;Cwo6ekHfm?_cD}@Aa`HLq4|2C{P9lr@MYql&gZxDxr&F?bqKom(!P@e>WaV1w0}|a3ZT<)ilpAhxaVRv;wy)Su!C%9-rdZg zre>j;q?&WX76q3sI)MurJ8$M)D^052r>(YOhmN}vI!g7Y6utJ#KbkG^@L9(-mhY|j zg`ts(m2W3WvaaNV;-7yG5bFsE?6Z!7Ow48?H@aKO>LB}if>02>GRklNx&%?p@+Fc| z&rVG1R7Leew-q{-l7)@UP)Nu^5}0L{EFJvj;vG|VI~N@U&!7nyxw>YwWc(^{3a{`EFJ)q`cm87fxXoSsvx}REkIpvVc31~& zN(qQ-WZAmu?90R{N%xND-`P0ak3Zvn+une!@FA(?z4qT4-voJR2@ z%L^mu80Hzpbh7#6NGRo3+nGkQXM&M=F*utFGD&@T(FHxe4D8Qd;J@Rn>`=6K0wK5O zT_~XWO3IwuL*1Hf)cQD7aQ~jA${j3}Rd@y{KkWZmvA9HzV4Uh&>zWQ_Hf_iR+*sIO zKEv_pll57<%uX}JJr!-s%WR&)5l4RIzg!CUuI6zUbN)X2t)HZDr2`*kD;uC(g-l5i zYEIJ8X+Hlk_UB61a$2TG3I0(v&UrNaNI^K;>S;_Am%U+a`q#%iijKY9@VI*~#}cmg zkq<=vS5@6Mux-cDPeAUj&AwK9`ezp=7&_5rWipqu4IQ0cm!0c`)BUfV-mz{{+fLqI zb96XLDQta#Pjb;QYeu{9L{mTBj$m{54Uyy;+UQ8(N<%lq1y&fOU7r$SeC$wiBBjSK zFDf4lMM8UfIE~dSXM9lg>iH){&H134Il(y{Es*S&^Dxj`_70%zeeb^cs%_t66?W88 zwod|0lbVmtI&P6(Ko5M#+Yt=g(cUgp7PO61XJ__dXUS@VS5ucju=`y6%{$w|L+Nq5 zDfYgW&CYyztGQiqjQYAhv#HfJ8=oYL_QzHJ3NGTmNyH5)o&Nml!k5CQg}DXKH7X-j zpSOG2#4qRVi&DxcAmj8BuO`?l^=xMh%9&(DgR3WXWdSx3n9WI_mGXt^_VKBiT6r4y z#gNtbKW{wHQtX^`X5bH(0280LX0=n9MkC8ju;f?D$5y@xVH0#Yot5ZN&_U4`j)XGY zdH`+}>u4%$#oZcTCJ&NLpRh42#TP7Jftkv9b>cZ5#Bdb*7KwfK9Unn(E4?=EjyB_^6yR$oT;;>u!F#x)}vJh~c=+dm}BxzmZ zEF@}!X-3*3i^~J>7D%t$lG2W)4dWt3P%;EMx)b<5{BG45*rLPCt8iErZkH*vz$Uld zzq_Fq-k$+-IC{fU?d zYhh}9-`=!Lw%g+;9``n3(5WNTev??^cT1C8oqyuk(erwzaM}7hR9`o_v^4I1;;QBd z>bh?)WCQy}WW=tv+e$(bbIC=ep{`YtVIdGi=R+`<{%zCW8BZXV^luQ@t!hH5@4REimBZd({-`py21B*`WhXIH0 zG`D4vNKs6|?3K`wu#)jK1bx@?Xv^|2GKdjJ)x>d~@^@W%QuW+oLwt*BIuutmcTKg7bm=c_$od-O;%nbELx#5R;+2ffen*-h5t}hjPJZefV@FQgSrBz=N!1#to&O31wRkr*}{GB6xq^ zC&u8JItlp{+pfU5U~RX`<5GW@Xxvaa=eWO|*6$4$wJvPH6eF9P@M>gu)O^T=%$k&F z#uJ~yLW^24;?JLQGmBJN{<%taW)}BUxAJim|V~QfXy#rW+XG*M*rA1Br4|jIS);tn@ID zHoLxnu!GJIGb*El?$ELRt`^3Oyvt-|6cF6FMPB!Cj|`_Z1Fyf{?13rS3ovN;+?zlN1rEXmd|8zQq|&2 z8D#p&Abk;;Z?9j#gpBW9qHgFk-58w33*9?l$3Q_kLoWYX^+H#*LC(Ic9L6`kM?{6# z5`XI!sOAaDd>IKvG>IyiZ~`C+XY@N?%@fLUY(}~Cc{!J`Iv`25^a7Wv3ad{VZgR=9 znmA2ti&~*$rIBkE@1PZVB{tPC6$p_P>}Nc8I*(p-Amuj1#qebdxSkswk@NQ&w2D9Dyqx#%#_Si#Kx0o{Z(6rYG6)|j0)L>)UL1y8OR*u z-9rbXA(Z%Yw}cTZ4BDaOUiAkG9N}YIL;JwR%PS*(p=Go)a2KO*;RLAPL?*S;APhE-!&Q@EH4!p zLT;`sYe_eW*Ww+J1J5ny0whbYm%4<=e*hu7@E=80B(11i zqT7msJCnY@_Oz$)O=f>o92*HP+~L5Vmn#7MB*itjlk4iRSx5;AFzG$8E%oj^Dq|IG zBO_TN`@c&V-vZQj4?Rkb<@?p|W>pR&Zf0WvKqHmx&3Bb&jeJ&7mUWV8Wr7q17d6#0 zW2$e|a`)EC=!i7ySXO9Neq+exz>5{H#vk8=@S}ogHu6k0Iv{eoRu7cR9qiK?oD(fo zb7tH+tb=s5#Eb$yx2UzRS=kIP@oX7h+rn%>R8?KDBQvY`(cD>>I%;YjwfuK8S`JM8 zVdjtVB;aZ=ODnsDU1E)krxc{&>DzvD(p4(X{}S8Am+|=>>d6qu!rS;o#mg}_Dd>W5 ztl5y?!ho??q35V_Dwu?1!iEe!z3guIVzG08J0+fXcHj_wzwAT6FLq>=ohk0KIahq) zP7TU#WRE_QStL_tTKnPbInuE$x_6m={$VXG`tFZ3GgPIEJX=<>K`Wbh+F*+>Z68L- z`1@KSs>)pc$rxOIpq5=|GsbKr75`ZII}+?eEl+hp2j1OeOPR8!+={K&IuviZrn~dg zMonD1X6=O+pFzL-c5nPZW3kzhrdN!Lm_dT5iA;32jn3JgCm@~fZkIJXkMl}c(7hvV z;?w9;rN(SBISt?opsId?EN;gEpC4y>bCEnsCQF%Sg(|Ob&_;sN`q+3PoVve!7S3_P ztnBY@Zn_hDS{6#*k)@2;E1I9Pmm5;^J45;2x{=Xzm7w{DN<;DOFprH82Inqt3fOTV z=SZFipQLo|s=9G9@LH;SnhbK={ONn;dbl&$Bw463#jffj%1yB#uUOb4jTY zCVht0eu+@-YveDwN};yv64Y<{tB#i*L;LF*UVKfV05*efhKWbjw79ur1C@^P^^NhB*qzzQ!r>qJjO~-P2!kIby zy_tdLLPO6;Ll7+A`yQZw#pnGcDPMpv}kY^V5UO44+X6 zr3Q8Ad?{o*j9RE2vXMOT$|OF2C3pn8>cEWflt~{6pGO?VTzzK(IX`s$3-6C{Anu;v zJ!qEI{tBWyGVR2?gu2lh3NL$!T9LiSD&7(8ioHYhSf}3o7&`Onv*`L?-HH9=-Jf{K zzjt)y1aEPs)Vg`8w{;MS6C!f?zQ{@Ird3_2T^su9H+=;%`66pV5LJ0kyxr(;*00r* zXpd_FPA9piTwULl5Kxm44{g!@A~j5jU=Yt09o$_0d!xn&AFx;8t?bZ0*erd^LH!Ta zRuJ>m8{!RQ0baN09w+VQZSF{A`Y#QJP^52#A8sIol(owr?|QrfY8ExnCOJd zfbud@dlY*8@X{2_UA8JPcbCmi3p%3t-3dpIqS9J^jM-%SsDw&!2~HutXk1sG;D!Y( z&FL=S_p_Xio_@;z8BQ}Tf4+AGL0w1fZ4UE}&yg2J9>6~53*;+`w4U;@B8|N3P)@f6 z@(-5MsP*MT7>eJ?j=pw{j-BCw+m?%(1Lbc?f>zu7ozSm0#h%4nXr^!sKn6hS_v&}6 zlU}eDs|mI}>{r6S;emKEUl8B}OjZ3c3G2VK9_NUp(R3VJ1fAG0A(CTdO z@dQ>Ra^l)6-E+js*NNA53fwjxMIjjTTMyG=uEjccLl((_48A}ms}dHD{^c+~h>25w zI|`GuU$XwXxO-!-3Lo$qknI<~5@H}vRG1*&sC39xlV7GgMde$n(%pHa?@F%?5fs{( zP{F#_iCED*uWVgv&2+7%oq&hoV=DVLJkuG z1kRDXQ69Y;$>8NZzChF)JPXH0MW9Ca)?`0ZyzjYtdP~jA&kjamjPgbO@j|Whhf;Sk z#P|%4BJH8ak$-1;e2e&nIpPo7xmL4Yt7h4ZYUu?0OgUZtSIYfsk3!mR@+FVUNwc_h z828c~E?Y1a#bfT;Y^d%PzN83E$5m@hXWg1I2jll{r%UMdU<7!z&pxiq_3A0cc7+YW7*AC1 zZfYM7$wXHt9O* zQUYJqd+p!}{|oyM*WYVwKC-xJnkO<&*<<4?G`Qy+KxM%@uN>+NW=_F61yxAQN%UA0Lo9891#GMAUS0TY zMw(q)=UICSPSH&6pexr)EM~d}eS+{Cbq!R%UUV8Iqmh{}RXuvTQCpblZOinGSpXjt zF-HMPEB8GiYo(B)5nA};1h%^Th=g!xQ z#`z32cwO48`30#F5ewgW`;V3QnW8OSCsiOYp)4QAF`{woUcjpr=1J~s%Nw$xd{rxShkKo8S8wLO#a?qru+_5A zRs@gEH;`*k&?As$HydOpHq{ z2pU1b$jgYeKk#R&h;>B>AIox53tT+*#Vro={shN(gzmpPxnJ4C^X8VM`_c8*P>I3sUkm770b$n&qhjz@?|aumOvUQL1*Px{xR5fbns5J&e`7fZ*0!!3uoo(R zyQ{*3TvP|AQ67x~v|~U#mh?ObPpuK zjd!EzBUkQBi3#6N+MhRFzmyz_!8g2=Rpg`3W={`b3{{|;L1-L^P9;tYU{AUxB?D%Q zv4$@WlQ12PH02S6#-mFaXa85Nc|+N{=)**M$~HujWtTd_X$cGrI0}M3 zr$!&Jc7<7#)b51&B3*4^^CClGNbHZ_T3;0{+w}Jt)e^6yguX&bBwM*j%6OxtYe7oi z;T}J%lNqRY5Owt9{*gV=<+cZTMZjb!und%-yyTxU*xNVF5ZtSe4r1*Du_j9EA~5;9 zSfNbSw1JR#4ZD!dRI@4UC->Utfvz-pe_&B53#W|Bu3g}HQ@~K}@K8AEB{l!7!!gk^ zsT1s$`N$%Nmn2))f0;?!4sr--o|)7fN%rJn1`2NZJ3*>#Seinlqk2j`fu42Jkl-b7As8L z#s{;-TsM$q`W$P&IrS9wIQ#Wj>xIWq0PQ3+KS5(fb$NQ@P~Knlg-=cohY6`pC}sw# zj+8YhQMQLk{a4_1Oa?FDR+?K}voOE&*$}1vdGD}Zo3|W~p-=Ywi4{gl6Y6u(-(q4z zsWD}+Zg;s-u*7iNjwW-c-hoV_|B_!ELdmiwCxGsV6rLBIPeTWoh0t^t?8K z->f?}Bcv;c>+RoB{{r27OPFo+{+zl?uDWRxB=7zea!7}plq5)k0d^9z@Mp4UfT`3Z z$Z}&}o@FF6ph8VrHI|+8FI0T=y?HO`VY}^=ta^WOjcw&@>gqGU8v|_(9xEI7_WofS zd2^U}w1Mb7-=U?BDrN(_cZ2~dS>B+7SBgFPHD1MohjTbABONo@e zS&3v=6c|yp(4UBc!5$qWy8Ml8A~#=D8j=L02Xe>iFDfy-HdLaM>a3%P_3r%p(VpDq z^Z)R^K_8ZhB?Hk&@F$8PB~Nifg~&(G*Ulh5nd=xPt4u5rNC%y{i#mEi5`O^(5Q)nRE}n}u9wq4=7Mv#mpk>_P7dvFdy}I47 zZI#1tnBW>%CsUyMRJQYv>8CMe7w9cdXNjA+w;;PYhZgQc-zxv)w5enk)tj8KA8HJ( zH`x5)y)i7NV>|whHxBRXa2)W-OON_qmyowy6;%D{+s^4Ui9B&3#KSM!pj&Gm72H~5NKKekSIY|RIQ8SAUpuD zD>8%EL~zYWc(9v%re%4ddJ^A#Y!nFX6zuJF=hAViJ{9P9Y12?wo~YDoMItLGMP!sX zq=2L{cqTJ*$8s~;)5CjUx_Szqg}bMHzW1&1qovRgYU!39@7WH{y7Mn(XIJe^`?dgZ_Ln#5j=4`3UuhtU zro7S)hAmw@{$_!ME?A_3^gzHn8Hp_XbLHi--!J>!Tmlyaeez0bd91L;tp5ugTIhSA?HIk6W0RRWhwLC}c_9Jj zGxdheX_oZ75Y!qA;M_|AD8fek;)Dca+$P0IvW8t$dA@NK8$92g#dPIJ-gxQPyRZ8G z%LLK6VaSvS$5XOm6>-&^qWi1YX9W4g6|)(JzSD_LqL}*kYb_hDR~I(HgLBr> z6W{Rtt3c)XFy5z*+{i^RZ8=nQLwAqeh)*4FS5A%lWIPbY=Avw3LOvyV;16|_BNhiR zDB_UAZjj6bi^@nsU;<)UAdjM#pqY_ng~H1qh4>iI&AZ%-v97LNjbs4>g@O>;!U>j^Q$ zjtz-k7r^4HjQ#q+g1`~}8>~A!$k{ieky3B!-O+IP{g9x4#MbscliEERsxGo%h8k8y z4R<{&t#WSVQ?9+rdrxSqp@eC*QQ|)F#l09YC`#F8=Dpa_&OA-hT`_H_(+v$-E_$C8 z+(`i~I=N!1GH2WI`Sw1T^Qi97{xR6o4Z-&jlF_j8@U;i30CmK1%HLubLUo4BW7S68 zLg3Q8E+3s_Mj~}k4#(0yK?m&cITT8<+KN7_$5?f$rXjzM z4zZ1JmZk1N{Vp$SHZ?oobtSAeWk9;TCoT!GNB0e}J*6I->mQoIowOfimlF`oPK){R zmNw3Uy>lrAGdPZRUcWl&rsN4JWgTWx~;LMXCDbaUP{ehQl%@dJ;1sn z7d#5KR+g@s$ePh@+KBd|q4U@9KOWb7qy&#D;GuKw?w~`h8GZf_+S8zjQO-M4x^OV1 zxBtMj#+bB_vUAO^z?p&cQq9=S_i7E9U-t#7e&W^`qQ59eJ$I+4Q+wu z1XO_@WXwEKX7H&C#l2z7b4*C7-@rsl3gB!U%o17R5TkCIXUBYa3UvRTyI;g?n3r}1 zd+5CE0s(^e!@|Ef#xyYEx5mg`niW8YksM6F3Yj7O^*?Z48%93(@?#)$+S#>)QDj9U zwHx5Y0=`0KvY*W{d|l24WnS15wXCb7!F=T1+D63MBDk=c#Lm8|;J=KtJDkm|l0!1wRg#5;ht1Y#~)wicW;<`;mU!RD(Kr1rNLKI+q* z-RwEEWWY4~;}uU3QNKz%gwvYSJdcei;OFRkrZ)3k}Oc8KD9<` zI2O5S_l0guKL=8ZPDC{djU z*l`5it`A#cj^qCmZhbP7HJa5Ht432T+{^^$dhfUOAXZN*oY|uEP0bs$0;7rrc5=OS z6(ibjY#4YsO)^Yd-yQ8BCw!p00RG5}Km}T`d=%nYxx`s0BE27IhVn01NH_w!VhH`k zq(yC2ouM(ty$SR5I|M+WzO3;fT3wlLE!VCCgu_u?2p>3plIk`g@XGS_v!ns-7CS-x zHkeG|fpVDd-Pg}H`L=KE2`^GhX=R(zY&~*Sp7gPDa;$uKYMEtbZIFR5WQJ3t`etem zZb^PQ5xE%@236X5H}I*)O$-e1uS>dx46Rj+{e}8*?M018G}BY}>S*61Mvg}M6N~#2 z3Re;4y)~H1N4M&EOJK_eaM$9<#D2(LN+Zt`^K+NuitH*El z_(~k{s1buBqM8;dEvdbrDY#0{*F(HnqI&be*Ojf{EpMHOsB67wb&?14T!OiAFLEW0 z0wR;UvkoWvGz({fZ>9zTto0te!11Z9*|jUmr;QKkIrAl9l9yk zudT#ByExJC>?USNEO7JTK@`F|*5*;@`2LfgzD()=3HKHN$tGhcWL12)S-X>c!h$l_Xn*bbm)2})}e|9nn zbC6k$Zgf9rIJcPacbQ@fh9{4%3?e@Gi9MPPSOHW{74}MB^Yn~1j7{c+`wM{O2D%yc z35p9Pk5tC`e%6ti%HOa9XhC%G={@DU8Y=~Df^IzjxX5o9%XQGoT*Y%oENj3zy*1v2 z@nB`_){{}6=I(}tLHWR*4< zR$%rMyb;dShx3EB@~yH;Q}e78OLn&bqUQ-s*TnXE6@Yp%-jDEFweXFE%Updq`G+t3 zgP@JAPrGyX5Ts=`(k|$D(r?r-B%}uK?Fqa!?Yx^^Tt=9LNjEG?4GKyV&E}OiykgGC zVo8V+%e$(d+9zc~%X+l7;i~PPo4FZFPLV5?*J#o81A)h(DMtL?%rdVH`}agyjyA+| z!@PdJ#dp75QBE*-d}0LWFnKu0YmyL@%o*eJyNyx?{u9PD-pXCp+W#--hA&U|cs$q2 z@eM`1i;dHl;lQDfx)BMn^KdWO_s26D6;TNIrdC~qq$-?P6wks^y<;4?WXcB zhf-d4i-38R?w2kM7W?s5HR<}RJfFC!+Vt#fXPXA}3o^1UZrT6y=8E@TOwdUDJG*3% zPpY@a+O*AfYNu9wx2HMhZI;AdeGj#Vu;DQ~bEu4V@X0+ZvSvgplln1b?2<8%Our4^ zt{=MPkB(beljSg%muKKc0T6zN@&#>ajGIH)m|2=@TIYqtJ^G*n)-Z>VU(T7qSh@Vp zRefINSo*}upZ&FkOiJ9~i|zyqZ>)=vx~Ffof&(in<;(PTEwj=Bwc+&?ei~8m5$JxH zt%`NMM`(b@gw@|RUW^u|9PJOWea&fa6vU+(xMOl%4J|XRNjyTC^tX8X3m(8pHcvV^ zbZq8M@)ykN3uTb54z$I)a6lkk0;o!xeTx_EGMo7i60g*L*FpZVleei-3zR`09GH(7 zyC1KS?NO4-%EuNgPVDsshtr3VJue4s@W`$w%UkEm$6MJ|ccGOop2MVUZm3K;LjBE; zLB|oulpRnR?46h2`_3SR-a~xKv^Cd!W^K5~_^1jVT#@%^BE5C7z^udLE@U}4V5wXAYHaO4^+rv_`V?;> zO6mCsjV8bX?)QIVzVyKQ$It0l^D*7)T8ft!y5#U4-@_N@MF#ap-h0D7EM^P5TTR)( z3KhR|a!FxdH5KUf?9uzE{gG_Wyr57ttUb9!T4C4Gd@pPnN7F<#r*Cw#S;8{=2scBi-+0q9mC9Zk>`kIkJT+49$!)4k ziC!^5!5=U|p}-A~6Qf`1+}ppWh#Wp0kFV;XVgEDS&htj_zQ6biJd`E@;>mbA_MxP4 z=0{Y_BmH@EtHUxruuZ~=R9~VdS+2*fX4-7=u!<|h={NzV;}y#y*ASq6;x{W$CEo=# z7LwbNL=_%IFPz>XTujS1v}8{K>ptf#2^l$vwH-P#($jq;P$6e$|Fuu)mDWNAsdUl^H7m|T8?}S zR>c7X)Af@@0{Qiao>Hve$3QlN6fE-VjKHA4Xr!2hIm+1vqPU7hE9@mR{DEVf{rG9)S9+*43dPqr zbN?*xptD=7{yMlnbnkYI)T6YZz1bh?)XvmjNFya5 zP4Dtv))0?BY*JQ^){w=*b*Yv>^_1s|?VcW(*~ph}4llRZPvF7=kG&P#mZ z$ij4L45}>Ww$c8u&g_O78_SbLDT4+xAU~drjh~Ss-;Ebt*9;E9-Wo!}^~nbn4SQ#Z zCg}yBHFlx<64_9V9Yn{da1sy>AcIR1rrJ}k1#K`Xxcl8Yr1L3Z$WeP$xF#ll%-PhT z#n=;M>Z(Q(`j~M)ZVgoj@#->c*WU#PRbt|W82>)yYwPimeO~p3@9?XrX9Yj}oe|Qfpax+yj=PffU z%#E;&&)V|b&%-zSrv(`aK%9oyGjVmc6ZN((FAjliyD~I?rK1UwXw#JuGh(vPD*M$b zjKYHbV{Vpk>O3_vhn9?-!#pH6$3tp*Wmr-WaiykgA1F<)Q%nouc(2YfZc*Yg8)cl|Y zyFMf!6u>|4Y%(lx+eIoXi-1KX! zs|!A7>ud`D{fe*|yRq`i=9dzS{z4F?h1~_gs=nT;i+qOd_sqbUa#|PWkL(2xX&QawzymixvD@`K- zhyF6#iOlqNsB?{~%2kFnSDutYUi@ou=yCV#BJa@F9bmy`fy3*J0ggA9W&(qil{2;_ z(!FG(6^6-tWf#_rYA-`2Bs>f9+B1QerArm-UF`&X-&_&-l6hhyaG zaCPkWLH`dMag@c~JGI!BHM0+8L1Z5_5;g_dD!ulhCQwHyJa_pxZAG+4o|8)P5BafG zTe1ULkHw9@1|KA9l1jynvVR=Xwh;JRg}roC^gse)w4ZLqXu>{fcC&I z8LDm-JLUbGQ=UiZPh^50;o#P$Qli>H*^LlQ-0bPKCi`#%TvZt(|h=#TL=Q#CIO5P<>c$_H58m z{+pGX#b8d}>=wYt*R3Ts_I2VKT0#bF32<)QsC0@D%;<3dRp_cGTs91n$BycttnU|w z^S?ZPh>pE~m!Ih{jxcxQY2pwsuLEE2DYd+=Jed=>`7KthJ%My+NnGwZ$P_}#C2>)7 zcC&$TZ)0iV_OauYXSp>BtM{J`FrSykWRXf81!Csn1Xa*%nILjb*ETcB(!DZT@aTaX z{i9Zt_jh5Wt;IKH_o?sZ!xPV&tDMFq-w+*2mUX;6fBdp=?s=CN8uzfT^zgK!*Rx4x zsIfnnJnq}<2jsLc^~c+!bd7|`7hxIT>w&kUBQ(hCMFFibLuZJ*>+-9v-3ihH%Jt$? zrBN=uPeuFhWgzfb0-BZ#fj~LB5g79I9OmvO6Ljb1S7*gV>f%a zDwf5u-UI3f9AAuK@Wc!>h(Ii!RBr1u`{sDV8I8)VHo+{h;Et=GeElvdu3;4+|Mg|P z!k@Kb@21&aqFlQ7CNN1YS(-U)IO4-Bw

A7BQqf9K80=Rt|6##onQxm4}!`cUHxU~WS(`? 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 diff --git a/lib/pages/ghost_image_page/ghost_image_page_widget.dart b/lib/pages/ghost_image_page/ghost_image_page_widget.dart index 292c919..da39e5a 100644 --- a/lib/pages/ghost_image_page/ghost_image_page_widget.dart +++ b/lib/pages/ghost_image_page/ghost_image_page_widget.dart @@ -88,7 +88,7 @@ class _GhostImagePageWidgetState extends State { padding: EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), child: Image.asset( - 'assets/images/bg.png', + 'assets/images/Logo_-_Two_Heart_and_Hand.png', width: 100.0, height: 100.0, fit: BoxFit.cover, @@ -98,7 +98,7 @@ class _GhostImagePageWidgetState extends State { padding: EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), child: Image.asset( - 'assets/images/mastercard.png', + 'assets/images/Logo_-_Two_Heart_and_Hand.png', width: 100.0, height: 100.0, fit: BoxFit.cover, @@ -108,7 +108,7 @@ class _GhostImagePageWidgetState extends State { padding: EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), child: Image.asset( - 'assets/images/card_bg.png', + 'assets/images/Logo_-_Two_Heart_and_Hand.png', width: 100.0, height: 100.0, fit: BoxFit.cover, From 3907ac54254f61156d97a7a972005c9ab06283da Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Fri, 21 Jul 2023 00:37:13 +0000 Subject: [PATCH 15/15] Update with List of Charities --- README.md | 11 - android/app/build.gradle | 3 +- android/app/google-services.json | 52 +- android/app/src/debug/AndroidManifest.xml | 2 +- android/app/src/main/AndroidManifest.xml | 5 +- .../com/example/my_project/MainActivity.kt | 2 +- android/app/src/profile/AndroidManifest.xml | 2 +- android/build.gradle | 6 +- android/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- assets/fonts/Lexend Deca-Medium.ttf | Bin 0 -> 78216 bytes assets/fonts/Lexend Deca-Regular.ttf | Bin 0 -> 77904 bytes .../Pay_with_Apple_Pay_button-pay-with@2x.png | Bin 0 -> 4852 bytes assets/images/User_Placeholder.jpg | Bin 0 -> 3028 bytes ios/Runner.xcodeproj/project.pbxproj | 6 +- ios/Runner/GoogleService-Info.plist | 10 +- ios/Runner/Info.plist | 6 +- ios/Runner/Runner.entitlements | 4 +- lib/app_state.dart | 137 +- lib/auth/auth_manager.dart | 8 +- lib/auth/base_auth_user_provider.dart | 2 + lib/auth/firebase_auth/apple_auth.dart | 14 +- lib/auth/firebase_auth/auth_util.dart | 2 +- .../firebase_auth/firebase_auth_manager.dart | 111 +- .../firebase_auth/firebase_user_provider.dart | 14 +- lib/auth/firebase_auth/github_auth.dart | 11 + lib/backend/backend.dart | 214 ++- .../firebase_dynamic_links.dart | 92 -- lib/backend/schema/charities_record.dart | 142 ++ lib/backend/schema/clients_record.dart | 113 ++ .../schema/donation_solicitation_record.dart | 119 ++ lib/backend/schema/donations_record.dart | 165 ++ lib/backend/schema/firestore.rules | 36 + lib/backend/schema/index.dart | 6 +- lib/backend/schema/serializers.g.dart | 12 - .../schema/structs/address_struct.dart | 248 +++ .../schema/structs/currency_struct.dart | 179 ++ lib/backend/schema/structs/index.dart | 7 + .../schema/structs/permissions_struct.dart | 250 +++ lib/backend/schema/structs/roles_struct.dart | 251 +++ .../structs/smart_image_location_struct.dart | 169 ++ lib/backend/schema/users_record.dart | 211 ++- lib/backend/schema/users_record.g.dart | 279 ---- .../firestore_util.dart} | 142 +- lib/backend/schema/util/schema_util.dart | 102 ++ .../client_donation_model.dart} | 15 +- .../client_donation_widget.dart} | 44 +- .../amount_button_model.dart | 4 +- .../amount_button/amount_button_widget.dart | 147 ++ lib/components/amount_button_widget.dart | 125 -- .../get_donation_amount_model.dart | 6 +- .../get_donation_amount_widget.dart | 37 +- lib/components/heading2/heading2_model.dart | 21 + lib/components/heading2/heading2_widget.dart | 82 + .../navi_btn_grey/navi_btn_grey_model.dart | 21 + .../navi_btn_grey/navi_btn_grey_widget.dart | 132 ++ .../row_logo_and_name_model.dart | 4 +- .../row_logo_and_name_widget.dart | 5 +- .../test_components_model.dart | 4 +- .../test_components_widget.dart | 1 + .../text_list_empty_model.dart} | 7 +- .../text_list_empty_widget.dart | 59 + .../user_photo/user_photo_model.dart} | 7 +- .../user_photo/user_photo_widget.dart | 81 + .../widgets/credit_card_icon_widget.dart | 93 ++ .../widgets/custom_credit_card_widget.dart | 282 ---- .../widgets/custom_image_widget.dart | 39 - lib/custom_code/widgets/get_c_c_n_widget.dart | 538 ++++++ lib/custom_code/widgets/index.dart | 4 +- .../add_charity/add_charity_model.dart | 77 + .../add_charity/add_charity_widget.dart | 1275 ++++++++++++++ .../charities_list/charities_list_model.dart | 27 + .../charities_list/charities_list_widget.dart | 359 ++++ .../charity_details_model.dart | 33 + .../charity_details_widget.dart | 353 ++++ .../charity_update/charity_update_model.dart | 78 + .../charity_update/charity_update_widget.dart | 1462 +++++++++++++++++ lib/dashboard/dashboard/dashboard_model.dart | 33 + lib/dashboard/dashboard/dashboard_widget.dart | 152 ++ .../donation_wizard_model.dart | 67 + .../donation_wizard_widget.dart | 622 +++++++ lib/donations_list/donations_list_model.dart | 26 + lib/donations_list/donations_list_widget.dart | 968 +++++++++++ lib/flutter_flow/custom_functions.dart | 6 +- lib/flutter_flow/flutter_flow_animations.dart | 7 +- lib/flutter_flow/flutter_flow_drop_down.dart | 234 +++ .../flutter_flow_icon_button.dart | 74 +- lib/flutter_flow/flutter_flow_model.dart | 4 +- .../flutter_flow_radio_button.dart | 264 +++ lib/flutter_flow/flutter_flow_theme.dart | 264 ++- lib/flutter_flow/flutter_flow_util.dart | 33 +- lib/flutter_flow/flutter_flow_widgets.dart | 8 +- lib/flutter_flow/nav/nav.dart | 213 ++- lib/flutter_flow/nav/serialization_util.dart | 35 +- lib/flutter_flow/uploaded_file.dart | 10 +- lib/index.dart | 35 +- lib/main.dart | 72 +- lib/pages/account/account_widget.dart | 86 - .../account_pages/account/account_model.dart | 94 ++ .../account_pages/account/account_widget.dart | 698 ++++++++ .../account_pages/country/country_model.dart | 41 + .../account_pages/country/country_widget.dart | 193 +++ .../notifications/notifications_model.dart | 40 + .../notifications/notifications_widget.dart | 202 +++ .../payment_options_model.dart | 29 + .../payment_options_widget.dart | 180 ++ .../account_pages/profile/profile_model.dart | 49 + .../account_pages/profile/profile_widget.dart | 463 ++++++ .../account_pages/support/support_model.dart | 39 + .../account_pages/support/support_widget.dart | 459 ++++++ .../term_of_service_model.dart | 28 + .../term_of_service_widget.dart | 161 ++ .../create_account/create_account_model.dart | 125 ++ .../create_account/create_account_widget.dart | 766 +++++++++ .../login/login_model.dart | 46 + .../login/login_widget.dart | 893 ++++++++++ .../password_rules/password_rules_model.dart | 31 + .../password_rules/password_rules_widget.dart | 229 +++ lib/pages/donation/donation_model.dart | 20 +- lib/pages/donation/donation_widget.dart | 233 +-- .../ghost_image_page_widget.dart | 126 -- lib/pages/payment/payment_model.dart | 29 +- lib/pages/payment/payment_widget.dart | 141 +- .../temp_login_page_model.dart | 24 + .../temp_login_page_widget.dart | 56 + lib/pages/thank_you/thank_you_model.dart | 30 + lib/pages/thank_you/thank_you_widget.dart | 156 ++ pubspec.yaml | 59 +- 128 files changed, 15579 insertions(+), 1845 deletions(-) create mode 100644 assets/fonts/Lexend Deca-Medium.ttf create mode 100644 assets/fonts/Lexend Deca-Regular.ttf create mode 100644 assets/images/Pay_with_Apple_Pay_button-pay-with@2x.png create mode 100644 assets/images/User_Placeholder.jpg create mode 100644 lib/auth/firebase_auth/github_auth.dart delete mode 100644 lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart create mode 100644 lib/backend/schema/charities_record.dart create mode 100644 lib/backend/schema/clients_record.dart create mode 100644 lib/backend/schema/donation_solicitation_record.dart create mode 100644 lib/backend/schema/donations_record.dart delete mode 100644 lib/backend/schema/serializers.g.dart create mode 100644 lib/backend/schema/structs/address_struct.dart create mode 100644 lib/backend/schema/structs/currency_struct.dart create mode 100644 lib/backend/schema/structs/index.dart create mode 100644 lib/backend/schema/structs/permissions_struct.dart create mode 100644 lib/backend/schema/structs/roles_struct.dart create mode 100644 lib/backend/schema/structs/smart_image_location_struct.dart delete mode 100644 lib/backend/schema/users_record.g.dart rename lib/backend/schema/{serializers.dart => util/firestore_util.dart} (51%) create mode 100644 lib/backend/schema/util/schema_util.dart rename lib/{pages/test_page/test_page_model.dart => client_pages/client_donation/client_donation_model.dart} (59%) rename lib/{pages/test_page/test_page_widget.dart => client_pages/client_donation/client_donation_widget.dart} (65%) rename lib/components/{ => amount_button}/amount_button_model.dart (88%) create mode 100644 lib/components/amount_button/amount_button_widget.dart delete mode 100644 lib/components/amount_button_widget.dart rename lib/components/{ => get_donation_amount}/get_donation_amount_model.dart (92%) rename lib/components/{ => get_donation_amount}/get_donation_amount_widget.dart (88%) create mode 100644 lib/components/heading2/heading2_model.dart create mode 100644 lib/components/heading2/heading2_widget.dart create mode 100644 lib/components/navi_btn_grey/navi_btn_grey_model.dart create mode 100644 lib/components/navi_btn_grey/navi_btn_grey_widget.dart rename lib/components/{ => row_logo_and_name}/row_logo_and_name_model.dart (82%) rename lib/components/{ => row_logo_and_name}/row_logo_and_name_widget.dart (86%) rename lib/components/{ => test_components}/test_components_model.dart (82%) rename lib/components/{ => test_components}/test_components_widget.dart (95%) rename lib/{pages/ghost_image_page/ghost_image_page_model.dart => components/text_list_empty/text_list_empty_model.dart} (72%) create mode 100644 lib/components/text_list_empty/text_list_empty_widget.dart rename lib/{pages/account/account_model.dart => components/user_photo/user_photo_model.dart} (73%) create mode 100644 lib/components/user_photo/user_photo_widget.dart create mode 100644 lib/custom_code/widgets/credit_card_icon_widget.dart delete mode 100644 lib/custom_code/widgets/custom_credit_card_widget.dart delete mode 100644 lib/custom_code/widgets/custom_image_widget.dart create mode 100644 lib/custom_code/widgets/get_c_c_n_widget.dart create mode 100644 lib/dashboard/add_charity/add_charity_model.dart create mode 100644 lib/dashboard/add_charity/add_charity_widget.dart create mode 100644 lib/dashboard/charities_list/charities_list_model.dart create mode 100644 lib/dashboard/charities_list/charities_list_widget.dart create mode 100644 lib/dashboard/charity_details/charity_details_model.dart create mode 100644 lib/dashboard/charity_details/charity_details_widget.dart create mode 100644 lib/dashboard/charity_update/charity_update_model.dart create mode 100644 lib/dashboard/charity_update/charity_update_widget.dart create mode 100644 lib/dashboard/dashboard/dashboard_model.dart create mode 100644 lib/dashboard/dashboard/dashboard_widget.dart create mode 100644 lib/donation/donation_wizard/donation_wizard_model.dart create mode 100644 lib/donation/donation_wizard/donation_wizard_widget.dart create mode 100644 lib/donations_list/donations_list_model.dart create mode 100644 lib/donations_list/donations_list_widget.dart create mode 100644 lib/flutter_flow/flutter_flow_drop_down.dart create mode 100644 lib/flutter_flow/flutter_flow_radio_button.dart delete mode 100644 lib/pages/account/account_widget.dart create mode 100644 lib/pages/account_pages/account/account_model.dart create mode 100644 lib/pages/account_pages/account/account_widget.dart create mode 100644 lib/pages/account_pages/country/country_model.dart create mode 100644 lib/pages/account_pages/country/country_widget.dart create mode 100644 lib/pages/account_pages/notifications/notifications_model.dart create mode 100644 lib/pages/account_pages/notifications/notifications_widget.dart create mode 100644 lib/pages/account_pages/payment_options/payment_options_model.dart create mode 100644 lib/pages/account_pages/payment_options/payment_options_widget.dart create mode 100644 lib/pages/account_pages/profile/profile_model.dart create mode 100644 lib/pages/account_pages/profile/profile_widget.dart create mode 100644 lib/pages/account_pages/support/support_model.dart create mode 100644 lib/pages/account_pages/support/support_widget.dart create mode 100644 lib/pages/account_pages/term_of_service/term_of_service_model.dart create mode 100644 lib/pages/account_pages/term_of_service/term_of_service_widget.dart create mode 100644 lib/pages/authentication_pages/create_account/create_account_model.dart create mode 100644 lib/pages/authentication_pages/create_account/create_account_widget.dart create mode 100644 lib/pages/authentication_pages/login/login_model.dart create mode 100644 lib/pages/authentication_pages/login/login_widget.dart create mode 100644 lib/pages/authentication_pages/password_rules/password_rules_model.dart create mode 100644 lib/pages/authentication_pages/password_rules/password_rules_widget.dart delete mode 100644 lib/pages/ghost_image_page/ghost_image_page_widget.dart create mode 100644 lib/pages/temp_login_page/temp_login_page_model.dart create mode 100644 lib/pages/temp_login_page/temp_login_page_widget.dart create mode 100644 lib/pages/thank_you/thank_you_model.dart create mode 100644 lib/pages/thank_you/thank_you_widget.dart diff --git a/README.md b/README.md index 63c90a3..f67c5a7 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,6 @@ A new Flutter project. FlutterFlow projects are built to run on the Flutter _stable_ release. -### IMPORTANT: - -For projects with Firestore integration, you must first run the following commands to ensure the project compiles: - -``` -flutter pub get -flutter packages pub run build_runner build --delete-conflicting-outputs -``` - -This command creates the generated files that parse each Record from Firestore into a schema object. - ### Getting started continued: This project is a starting point for a Flutter application. diff --git a/android/app/build.gradle b/android/app/build.gradle index a66dd8b..d4e0208 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -35,6 +35,7 @@ if (keystorePropertiesFile.exists()) { android { compileSdkVersion 33 + sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -47,7 +48,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.mycompany.penniesfromheaven" + applicationId "com.humansunlimited.penniesfromheaven" minSdkVersion 21 targetSdkVersion 33 versionCode flutterVersionCode.toInteger() diff --git a/android/app/google-services.json b/android/app/google-services.json index b93d639..6e06a3e 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -8,61 +8,17 @@ "client": [ { "client_info": { - "mobilesdk_app_id": "1:1002814025305:android:426c4c246fe69e5c72cb48", + "mobilesdk_app_id": "1:1002814025305:android:fc4d49917463526272cb48", "android_client_info": { - "package_name": "app.penniesfromheaven" + "package_name": "com.humansunlimited.penniesfromheaven" } }, "oauth_client": [ { - "client_id": "1002814025305-jgpnnldcdb8dmj9lb0g8e3dofj8p3tvj.apps.googleusercontent.com", + "client_id": "1002814025305-al0gl1guhr7j1rb78e8on2ugccpvi1kn.apps.googleusercontent.com", "client_type": 1, "android_info": { - "package_name": "app.penniesfromheaven", - "certificate_hash": "9bbb3186b2189ef16d8f272bdab59362c395cbb4" - } - }, - { - "client_id": "1002814025305-ufukfpsmbvr7657phnnm1nl5g0ma9qjt.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyCgiUBFSQCkgjS_s9Q8qHXHysCTimGzad4" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "1002814025305-ufukfpsmbvr7657phnnm1nl5g0ma9qjt.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "1002814025305-f6t2dnusln6tvgln97k0vmpp8hehh0md.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "com.mycompany.penniesfromheaven" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:1002814025305:android:bbfa84eab16d586a72cb48", - "android_client_info": { - "package_name": "com.mycompany.penniesfromheaven" - } - }, - "oauth_client": [ - { - "client_id": "1002814025305-s4lh2e4unur7dc6mjdbv7gqd74a2mnkk.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.mycompany.penniesfromheaven", + "package_name": "com.humansunlimited.penniesfromheaven", "certificate_hash": "9bbb3186b2189ef16d8f272bdab59362c395cbb4" } }, diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 8c6d0e8..0500566 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.humansunlimited.penniesfromheaven"> diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8fdf73c..2eddc2b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ @@ -45,8 +45,7 @@ - - + diff --git a/android/app/src/main/kotlin/com/example/my_project/MainActivity.kt b/android/app/src/main/kotlin/com/example/my_project/MainActivity.kt index af41189..b5be232 100644 --- a/android/app/src/main/kotlin/com/example/my_project/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/my_project/MainActivity.kt @@ -1,4 +1,4 @@ -package com.mycompany.penniesfromheaven +package com.humansunlimited.penniesfromheaven import io.flutter.embedding.android.FlutterActivity diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index 8c6d0e8..0500566 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.humansunlimited.penniesfromheaven"> diff --git a/android/build.gradle b/android/build.gradle index ac59129..dacf67c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,14 +1,14 @@ buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.2' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.4' // Google Services plugin + classpath 'com.google.gms:google-services:4.3.8' // Google Services plugin } } diff --git a/android/gradle.properties b/android/gradle.properties index a673820..498c33b 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,4 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx4608m android.useAndroidX=true android.enableJetifier=true android.enableR8=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index b8793d3..6b66533 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/assets/fonts/Lexend Deca-Medium.ttf b/assets/fonts/Lexend Deca-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5cc0c274380b3c89865a6aae373c4fceb29952ae GIT binary patch literal 78216 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 literal 0 HcmV?d00001 diff --git a/assets/images/Pay_with_Apple_Pay_button-pay-with@2x.png b/assets/images/Pay_with_Apple_Pay_button-pay-with@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4e29a2d4c3325eb61dd2e3a966b0497609be708e GIT binary patch literal 4852 zcmc(ji91y9|Nm_%G9$ED28m2$ANw$sZD=xs%D#q?Eo;`XWvdTHh#^}N62=h9t`ym2 z9lK;5BQ^H@JLCN?{I2VFopYUY?(4kn*LLpf+}HE*!T<>eu=29f(a{0)bhV7==;+<3 z&u-_KsaNFka{%>5?_&hlpu_iqR_N$B@p@W!9t6;@WhbPr%5%kh1hIy*+TNrSryaJ% zbnofj&uW~pJRQ=Be>R}^CFBZh==btzS1!za>nQQ5tl5I_s`Dl|c4Vrl6?uBf&~s7G z&p{03R*f;n{Y>{-nC`t1wvBbyq`isAzCdW5)`Oer)2s-sHGuSRmh=|nIilVAyZq8Z z7V3~_H^EGsWea8^6Z{7ZjR$E?$OLyrQCkL40vCfH5xR1t#F>FQ^dr`s#v`)OL&@2` zuZHDmK^SMQ%PBMjZISj?R#x`bKFus1=pM>4PK3L+C>jvxF(OTzxhmj$ene^O2G913 zs%=VAGoRfVYa(ELE&fPA3aBQ#8c^AHH5+|E0BlaQJSaK}FG6`{w%UXpJq^HM+zD!We)Q9IA8C0uq770WPFxV_74NZ$u!a-=Y29%x2 zr1h$j+6vr)vokFL0xz}f;eK<%|Boq=OuGa7O49-MGP#iS+sGCm6g=n3Wg0;Tq!!!^ z`+HLu)3iGmcgdyVhXwfWewkAL8YBY26|ghq&wlH8_jgC%ouhy4f;i)@t@W4T{M$fi zkNA2lUGF~5CRD|OA!C)0lo|TtDd)LR+}5X=Q0U?2ASyQOBaEa)##N z!AH~&dpi>FZXxlbP#S30%})^X_e;j47{?6N*2f&5QI;6;RX$g_rmrC;B#*D4q%nj6 zg+hV5uKt`8yVb<&h=aWqb|ndh9sV15E9r5Dx~6X4uGZxWZz;+R4Ps_+QeS8{>0^@Q z{t|P;mFzcuUc*Z7Ralh&b;4y=h83@!a}m{Z(#?mIzm$b8`^l`7Dv^P*geAFs^twmm z)<}eRgRv>=^6qr-I=|^}KVnSyxbFP~`%!~rgL40jFK++@sZLc_Z(wAg$8e!($zqE2 zFN-WjH$+~vqd9Zn@ltNs-S4?(gHMuvsdepsc?90n5(pajpWdJMj;f?Il|m(MB!~g{ z2pK#$aUuJ6>z)@3K4RoJNcrMpt`jh#|NXVkVqx^4s1+lUi|77sw--@nHs(WJiS-U9 z#i|o#zHnnFZKK|T(=Mf;swSN-mq~#A`5#6VcqFDU2Wy{(y^*Ha+uj5DQBzaFMCWZ!(4po#V$>d~q`Xf5T09XO{G1rJ zGPx}OYD8;n*{JC3gliZ$J@djkEdRiug@@t{Ahgi?K*l?JKNt5a#j^m`8#b`kIoX4u zNN7HTPN-P%g6%)sm6J!biabMW>-aUPAqog9m8) zt^)dDbrR#w&P-SslJOwkg7+_&T#FyhN3dj#Qp$Kxd@id^U_eIT&${`PjX0NfIfELZ z{5Ec8iCAsV#@KET~Yvv5nn1_9%4fDSXk-F|`b zOY{?0u|<~vYCV*T6P%{#&eo~JQFN}7bis9l`ue!y-aWQ@`SZ^YJDmL?S_=l5AzD0w z6J*9ey!-oioFZ_uxvL+7q@QA~uoc;_k@gNRO~!OAyxY1%m!b}PxD?$G5&uTshOOwG z&5(2~mqfkLw3&1*rUzbP=!TizA2QSBy)i|uH=5_>hxk&UrHHGhA8TrL9*@1txi7u_ zoo$BbbttU#1&-mPGymCFgQ{=YK9cip=QQMIR10rNX`E(!qrM>} zdfFaMG>kE+lqbYob`H9yV`laH_a$+XRM|&aMmu9J!BjJ7Vgo42qU*}Pp%OV$SXk|e;L-a~cQa;n_{mT+FU)y|?S!_xAdDbFq^i;ygzBa3p^^5$ryPhw}$ zL$F)fMf0wd#300-EwM7QL6eT3SKNV(6j&Z`{{52zGpM%$Y9$NS$5?qcaOVQVvX9?LI=E-vn)ih`~aXG)j>l>a*foG|9cw&+Y;XQD5 zg%EG4aj9WcpfhGhrBbtK((bo}H@}bBJKPhjkWaTPu5okgqPov^-hJ2l<&tE3Z7hk) zd&|^k#L$0D=fVmo$&gjE5}{f$<;)+fEG@enw~?$%8m^516g#|gdPIEFZS(Lh^H_*S zB)V5{>29X@Yn#D#H6TgYRnGfTpc=ecZH>CZZWXTTdGod-Hs3T_MEUxt4a%0|6#J!v z&($WBmO*M>KY8YaI6u@C^M=IL#qZ_7SW%Ugr@FLV>g>}h0+D{c4#Suv15t2*Ig$2pQ^;aEQI`MRq zH#Wzg!fxK|xkssa#JFsoTnw49WUuC5hz4RPMXY$?g#2DgRnE&eWcQ)4pu1sA68rY` zsrGNtrPWw_-xm!s;%7`pVSf!LI=WIWtL5huw_7TX)|SfF=$N@luoLyA{86KU!7=zo zkz}^8_mMuad01f4ogj=0GpYfYhS8T+vYt=dyk@N_X;UoW#e266AE~h=S&eX9P`avr zKbAje0T{cg+m%QdZh4vm#`_dyuU^_~16BV~=sg&>9)v6@nMm)OuhkiQ*r+MNH$SYT z;dT|3*UtovzB5&%-TwIZbsVrhS$N=%_NQxwdCLc72!v7eS@{*A*|*^6LJD130hL zyj7InK8zI%RlaEylpy!%7V8mpYjAS(P@nsAGAQf+BZMCt3Gz;6Q-hHXUv`9{I7hF@ zv}~T6ab)39eR%_giAt`3o3B0R!YT^Kp_Few{i^IoLK{G26aZtY;Uj*J$J6>B{vLtF zYEB;)tU8QzN?e)t(LmT}&5!`K#^9Q-0LQZMrcE(FZlN}8W&aD-JzYNDIHC14tp7T} z0-BPcYaUmIZvROsuXhO;?oMT5Hc-~Blo>RLErYPfTMmj}>w7C!#K;7{7*mc^W`@AW zb?Uiw4U1G|va53+1~76|dFU6Nxki+WbF2k(qwd5G+KA7JxUK;Y2Br5k);%lBx~?sE zeiJ_V!)A5-Ygk_3{o zalh+~ML&Tlq{0R)%fPvg7bXkCq}sOK6Z662o$8_I^}uf3UEr^Q*lP8rmoZ~nk}?om z<_i&Uwa%-!zD$p%z*ke0&mX!#-7b3lJ_mGZN7ovDiMnJ0Bsv#Y@_#aGi)Rw-kktU#3XMej~$1*97qE({_Dp4j~Tn zvH)-ouGu~u(*}eI+}vX3Xyb)%_H4wvGX`nTing@$D_xSeIty1Oc~1T?SQ3!)`1jtU zyL1djcI?X3ER($Mq;FlFU~X1DY@VZL4Hi#|0g)l2jwMa!)bT5iW7YGOzD7hpPyVUR z+dlbMUcc`lvecqI3G*7iVBY7&T8F#~eJe?NqiM}%1cL7Q7798i?HDI|j(ttCu7~{3 z%%dz<4~5{ao_A48$;NoMifF9CSZCJupEB6S@*B(iO6N1p)kKR<O8>cW&g?;nZ#XGF-x27f2cctqAd0B zvD(t6Q28-HWvc-+>e<6D3n61_kOIn6?vHK$97{VfRIh#yRm_tY5zZVIn2Hy7{~_{w zO|hv8*&D0a=NoCL6y^&-BW*;AGE0W6K6aQUm#oDLQZVoPHUX!3;5mQuYmKh%)+Cty$8M{pCDBhY4XHmu0`hi110hS z2fl{c2wA(B*eg#vzP$$aV6Mw*i5gJwyPUmT-kb?Wf|EKco1 z*jhuMC}GsRwz2JO=6^rYK9+{u>{~EV&0Fv2heI?J69?_5O?m~{lkNw(vF+W*?orOJ zy;rB;e5F^Eb=cF%vTyu*pCF;8b9HStV(kI}(hX>?0!4c+pHKn32OtdJn7TP-k;T8= zEzp`C2w`fsl5=BLEI*62^4Bqb^2QQJN*`yk%GA*bE%WxV+Rv&_TZO_!$=+ijj`-_< zq6e$@$0PIe-7)(hHEi8_y`j{U_4xB6;1T*^k~J3+-Pydmy|SqY^p5xKHGl!PjDtjKe+gF$B5#0qA!|DlFaC2+65h=bFg&{ zH1%H0?a~P&4Fx$vo<3UT^#y5RN}f2I&EK}-o!#8seQ&7b1sga*pAQ9`7ke?#QzmR> zpJ|F1Q9zGu;|)=(^Zy9%03vXkO$}GFwnXvH1GDdK+gd?-B1uhcE%l|cT$;CT0j=$& z&58E_&6edG zEeD7AuB+W$TZ`M^^&|arJy#lCXp;B84+O8_x?_`zv$|ZLH5iC$5n#RJK*Ww~UDU~m z-C7XIyt%WsZDT$QUc69l!XNEA(akLeUH2QA@b-6~xbR-zpvrH$sqUdu*_xaB4qJWd zQ0E@;QX&sCbe&u`VOY*KH79-7_OV|_-IhW#imKURnut@- zp-)8`9?!;7PaR{ZqH=@B{248xn+Da2s~i7~=6I3HKyv!}IZq>UG34_rHpkDMk_Azj z#Q*R?JG)cw{ow+ADiN7&V!8LPAU~`n+$L()B%Yr(tA(kMD`1N>Y)6&|-ek*UwQdNI zwL;)dIS3RS&d$GD3UyckyNE_V_~pYno5(|CcB7IG4#n{GEMDOK^F~toE4jHjIXQ#b zU-=c^wqo)(5~dYBZ4|>3znRQImZE;T5~r#r!~Tn<2$l%~1p5H2@@S=`--fpUCt^C}_Iz4Tq7GA^l+5Z9MQbIcb literal 0 HcmV?d00001 diff --git a/assets/images/User_Placeholder.jpg b/assets/images/User_Placeholder.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3fe205844384d858efaeb948442c628fe498b9fe GIT binary patch literal 3028 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 literal 0 HcmV?d00001 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 9224877..25366e7 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -407,7 +407,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.mycompany.penniesfromheaven; + PRODUCT_BUNDLE_IDENTIFIER = com.humansunlimited.penniesfromheaven; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -545,7 +545,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.mycompany.penniesfromheaven; + PRODUCT_BUNDLE_IDENTIFIER = com.humansunlimited.penniesfromheaven; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -577,7 +577,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.mycompany.penniesfromheaven; + PRODUCT_BUNDLE_IDENTIFIER = com.humansunlimited.penniesfromheaven; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist index 2c06c82..59d635d 100644 --- a/ios/Runner/GoogleService-Info.plist +++ b/ios/Runner/GoogleService-Info.plist @@ -3,11 +3,11 @@ CLIENT_ID - 1002814025305-f6t2dnusln6tvgln97k0vmpp8hehh0md.apps.googleusercontent.com + 1002814025305-tpk6id4kbcjf15vmfeu9g20249erhf8j.apps.googleusercontent.com REVERSED_CLIENT_ID - com.googleusercontent.apps.1002814025305-f6t2dnusln6tvgln97k0vmpp8hehh0md + com.googleusercontent.apps.1002814025305-tpk6id4kbcjf15vmfeu9g20249erhf8j ANDROID_CLIENT_ID - 1002814025305-jgpnnldcdb8dmj9lb0g8e3dofj8p3tvj.apps.googleusercontent.com + 1002814025305-al0gl1guhr7j1rb78e8on2ugccpvi1kn.apps.googleusercontent.com API_KEY AIzaSyDPROZwQoHWuaQXp4eDisZ_5wVnyU_vXew GCM_SENDER_ID @@ -15,7 +15,7 @@ PLIST_VERSION 1 BUNDLE_ID - com.mycompany.penniesfromheaven + com.humansunlimited.penniesfromheaven PROJECT_ID pennies-from-heaven STORAGE_BUCKET @@ -31,7 +31,7 @@ IS_SIGNIN_ENABLED GOOGLE_APP_ID - 1:1002814025305:ios:796677ec06ebc32372cb48 + 1:1002814025305:ios:97ce1d8ea5d643b872cb48 DATABASE_URL https://pennies-from-heaven.firebaseio.com diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 32cfc28..d7da94f 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -28,7 +28,7 @@ Editor CFBundleURLSchemes - com.googleusercontent.apps.1002814025305-f6t2dnusln6tvgln97k0vmpp8hehh0md + com.googleusercontent.apps.1002814025305-tpk6id4kbcjf15vmfeu9g20249erhf8j @@ -37,10 +37,10 @@ CFBundleTypeRole Editor CFBundleURLName - pennies_from_heaven + penniesfromheaven.app CFBundleURLSchemes - com.mycompany.penniesfromheaven + penniesfromheaven diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements index 7979832..57a4c25 100644 --- a/ios/Runner/Runner.entitlements +++ b/ios/Runner/Runner.entitlements @@ -2,9 +2,9 @@ - com.apple.developer.associated-domains + com.apple.developer.applesignin - applinks:penniesfromheaven.app + Default diff --git a/lib/app_state.dart b/lib/app_state.dart index 6ef4eea..e666cfd 100644 --- a/lib/app_state.dart +++ b/lib/app_state.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; -import 'backend/backend.dart'; +import '/backend/backend.dart'; +import '/backend/schema/structs/index.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:csv/csv.dart'; +import 'package:synchronized/synchronized.dart'; import 'flutter_flow/flutter_flow_util.dart'; class FFAppState extends ChangeNotifier { @@ -11,14 +13,35 @@ class FFAppState extends ChangeNotifier { return _instance; } - FFAppState._internal() { - initializePersistedState(); - } + FFAppState._internal(); Future initializePersistedState() async { secureStorage = FlutterSecureStorage(); - _donationAmount = - await secureStorage.getDouble('ff_donationAmount') ?? _donationAmount; + await _safeInitAsync(() async { + _donationAmount = + await secureStorage.getDouble('ff_donationAmount') ?? _donationAmount; + }); + await _safeInitAsync(() async { + _CCHolderName = + await secureStorage.getString('ff_CCHolderName') ?? _CCHolderName; + }); + await _safeInitAsync(() async { + _CCNumber = await secureStorage.getString('ff_CCNumber') ?? _CCNumber; + }); + await _safeInitAsync(() async { + _CCExpiryDate = + await secureStorage.getString('ff_CCExpiryDate') ?? _CCExpiryDate; + }); + await _safeInitAsync(() async { + _CCSecurityCode = + await secureStorage.getString('ff_CCSecurityCode') ?? _CCSecurityCode; + }); + await _safeInitAsync(() async { + _wizardPage = await secureStorage.getInt('ff_wizardPage') ?? _wizardPage; + }); + await _safeInitAsync(() async { + _clientID = await secureStorage.getString('ff_clientID') ?? _clientID; + }); } void update(VoidCallback callback) { @@ -57,11 +80,84 @@ class FFAppState extends ChangeNotifier { _donationAmounts.removeAt(_index); } + void updateDonationAmountsAtIndex( + int _index, + double Function(double) updateFn, + ) { + _donationAmounts[_index] = updateFn(_donationAmounts[_index]); + } + bool _isCustomAmount = false; bool get isCustomAmount => _isCustomAmount; set isCustomAmount(bool _value) { _isCustomAmount = _value; } + + String _CCHolderName = ''; + String get CCHolderName => _CCHolderName; + set CCHolderName(String _value) { + _CCHolderName = _value; + secureStorage.setString('ff_CCHolderName', _value); + } + + void deleteCCHolderName() { + secureStorage.delete(key: 'ff_CCHolderName'); + } + + String _CCNumber = ''; + String get CCNumber => _CCNumber; + set CCNumber(String _value) { + _CCNumber = _value; + secureStorage.setString('ff_CCNumber', _value); + } + + void deleteCCNumber() { + secureStorage.delete(key: 'ff_CCNumber'); + } + + String _CCExpiryDate = ''; + String get CCExpiryDate => _CCExpiryDate; + set CCExpiryDate(String _value) { + _CCExpiryDate = _value; + secureStorage.setString('ff_CCExpiryDate', _value); + } + + void deleteCCExpiryDate() { + secureStorage.delete(key: 'ff_CCExpiryDate'); + } + + String _CCSecurityCode = ''; + String get CCSecurityCode => _CCSecurityCode; + set CCSecurityCode(String _value) { + _CCSecurityCode = _value; + secureStorage.setString('ff_CCSecurityCode', _value); + } + + void deleteCCSecurityCode() { + secureStorage.delete(key: 'ff_CCSecurityCode'); + } + + int _wizardPage = 0; + int get wizardPage => _wizardPage; + set wizardPage(int _value) { + _wizardPage = _value; + secureStorage.setInt('ff_wizardPage', _value); + } + + void deleteWizardPage() { + secureStorage.delete(key: 'ff_wizardPage'); + } + + String _clientID = ''; + String get clientID => _clientID; + set clientID(String _value) { + _clientID = _value; + secureStorage.setString('ff_clientID', _value); + } + + void deleteClientID() { + secureStorage.delete(key: 'ff_clientID'); + } } LatLng? _latLngFromString(String? val) { @@ -74,26 +170,45 @@ LatLng? _latLngFromString(String? val) { return LatLng(lat, lng); } +void _safeInit(Function() initializeField) { + try { + initializeField(); + } catch (_) {} +} + +Future _safeInitAsync(Function() initializeField) async { + try { + await initializeField(); + } catch (_) {} +} + extension FlutterSecureStorageExtensions on FlutterSecureStorage { + static final _lock = Lock(); + + Future writeSync({required String key, String? value}) async => + await _lock.synchronized(() async { + await write(key: key, value: value); + }); + void remove(String key) => delete(key: key); Future getString(String key) async => await read(key: key); Future setString(String key, String value) async => - await write(key: key, value: value); + await writeSync(key: key, value: value); Future getBool(String key) async => (await read(key: key)) == 'true'; Future setBool(String key, bool value) async => - await write(key: key, value: value.toString()); + await writeSync(key: key, value: value.toString()); Future getInt(String key) async => int.tryParse(await read(key: key) ?? ''); Future setInt(String key, int value) async => - await write(key: key, value: value.toString()); + await writeSync(key: key, value: value.toString()); Future getDouble(String key) async => double.tryParse(await read(key: key) ?? ''); Future setDouble(String key, double value) async => - await write(key: key, value: value.toString()); + await writeSync(key: key, value: value.toString()); Future?> getStringList(String key) async => await read(key: key).then((result) { @@ -107,5 +222,5 @@ extension FlutterSecureStorageExtensions on FlutterSecureStorage { .toList(); }); Future setStringList(String key, List value) async => - await write(key: key, value: ListToCsvConverter().convert([value])); + await writeSync(key: key, value: ListToCsvConverter().convert([value])); } diff --git a/lib/auth/auth_manager.dart b/lib/auth/auth_manager.dart index 81a64cb..b39c357 100644 --- a/lib/auth/auth_manager.dart +++ b/lib/auth/auth_manager.dart @@ -5,8 +5,10 @@ import 'base_auth_user_provider.dart'; abstract class AuthManager { Future signOut(); Future deleteUser(BuildContext context); + Future updateEmail({required String email, required BuildContext context}); Future resetPassword({required String email, required BuildContext context}); Future sendEmailVerification() async => currentUser?.sendEmailVerification(); + Future refreshUser() async => currentUser?.refreshUser(); } mixin EmailSignInManager on AuthManager { @@ -46,7 +48,7 @@ mixin PhoneSignInManager on AuthManager { Future beginPhoneAuth({ required BuildContext context, required String phoneNumber, - required VoidCallback onCodeSent, + required void Function(BuildContext) onCodeSent, }); Future verifySmsCode({ @@ -66,3 +68,7 @@ mixin MicrosoftSignInManager on AuthManager { String tenantId, ); } + +mixin GithubSignInManager on AuthManager { + Future signInWithGithub(BuildContext context); +} diff --git a/lib/auth/base_auth_user_provider.dart b/lib/auth/base_auth_user_provider.dart index 39e2097..1578da1 100644 --- a/lib/auth/base_auth_user_provider.dart +++ b/lib/auth/base_auth_user_provider.dart @@ -21,7 +21,9 @@ abstract class BaseAuthUser { AuthUserInfo get authUserInfo; Future? delete(); + Future? updateEmail(String email); Future? sendEmailVerification(); + Future refreshUser() async {} String? get uid => authUserInfo.uid; String? get email => authUserInfo.email; diff --git a/lib/auth/firebase_auth/apple_auth.dart b/lib/auth/firebase_auth/apple_auth.dart index df1e6d4..39fc206 100644 --- a/lib/auth/firebase_auth/apple_auth.dart +++ b/lib/auth/firebase_auth/apple_auth.dart @@ -56,5 +56,17 @@ Future appleSignIn() async { // Sign in the user with Firebase. If the nonce we generated earlier does // not match the nonce in `appleCredential.identityToken`, sign in will fail. - return await FirebaseAuth.instance.signInWithCredential(oauthCredential); + final user = + await FirebaseAuth.instance.signInWithCredential(oauthCredential); + + final displayName = [appleCredential.givenName, appleCredential.familyName] + .where((name) => name != null) + .join(' '); + + // The display name does not automatically come with the user. + if (displayName.isNotEmpty) { + await user.user?.updateDisplayName(displayName); + } + + return user; } diff --git a/lib/auth/firebase_auth/auth_util.dart b/lib/auth/firebase_auth/auth_util.dart index 05cc89b..d93ab9c 100644 --- a/lib/auth/firebase_auth/auth_util.dart +++ b/lib/auth/firebase_auth/auth_util.dart @@ -7,7 +7,7 @@ import '../auth_manager.dart'; import '../base_auth_user_provider.dart'; import '../../flutter_flow/flutter_flow_util.dart'; -import '../../backend/backend.dart'; +import '/backend/backend.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:stream_transform/stream_transform.dart'; import 'firebase_auth_manager.dart'; diff --git a/lib/auth/firebase_auth/firebase_auth_manager.dart b/lib/auth/firebase_auth/firebase_auth_manager.dart index 22ede42..c489728 100644 --- a/lib/auth/firebase_auth/firebase_auth_manager.dart +++ b/lib/auth/firebase_auth/firebase_auth_manager.dart @@ -7,7 +7,7 @@ import '../auth_manager.dart'; import '../base_auth_user_provider.dart'; import '../../flutter_flow/flutter_flow_util.dart'; -import '../../backend/backend.dart'; +import '/backend/backend.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:stream_transform/stream_transform.dart'; import 'anonymous_auth.dart'; @@ -16,21 +16,47 @@ import 'email_auth.dart'; import 'firebase_user_provider.dart'; import 'google_auth.dart'; import 'jwt_token_auth.dart'; +import 'github_auth.dart'; export '../base_auth_user_provider.dart'; +class FirebasePhoneAuthManager extends ChangeNotifier { + bool? _triggerOnCodeSent; + FirebaseAuthException? phoneAuthError; + // Set when using phone verification (after phone number is provided). + String? phoneAuthVerificationCode; + // Set when using phone sign in in web mode (ignored otherwise). + ConfirmationResult? webPhoneAuthConfirmationResult; + // Used for handling verification codes for phone sign in. + void Function(BuildContext)? _onCodeSent; + + bool get triggerOnCodeSent => _triggerOnCodeSent ?? false; + set triggerOnCodeSent(bool val) => _triggerOnCodeSent = val; + + void Function(BuildContext) get onCodeSent => + _onCodeSent == null ? (_) {} : _onCodeSent!; + set onCodeSent(void Function(BuildContext) func) => _onCodeSent = func; + + void update(VoidCallback callback) { + callback(); + notifyListeners(); + } +} + class FirebaseAuthManager extends AuthManager with EmailSignInManager, AnonymousSignInManager, AppleSignInManager, GoogleSignInManager, + GithubSignInManager, JwtSignInManager, PhoneSignInManager { // Set when using phone verification (after phone number is provided). String? _phoneAuthVerificationCode; // Set when using phone sign in in web mode (ignored otherwise). ConfirmationResult? _webPhoneAuthConfirmationResult; + FirebasePhoneAuthManager phoneAuthManager = FirebasePhoneAuthManager(); @override Future signOut() { @@ -57,6 +83,30 @@ class FirebaseAuthManager extends AuthManager } } + @override + Future updateEmail({ + required String email, + required BuildContext context, + }) async { + try { + if (!loggedIn) { + print('Error: update email attempted with no logged in user!'); + return; + } + await currentUser?.updateEmail(email); + await updateUserDocument(email: email); + } on FirebaseAuthException catch (e) { + if (e.code == 'requires-recent-login') { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Too long since most recent sign in. Sign in again before updating your email.')), + ); + } + } + } + @override Future resetPassword({ required String email, @@ -114,21 +164,48 @@ class FirebaseAuthManager extends AuthManager Future signInWithGoogle(BuildContext context) => _signInOrCreateAccount(context, googleSignInFunc, 'GOOGLE'); + @override + Future signInWithGithub(BuildContext context) => + _signInOrCreateAccount(context, githubSignInFunc, 'GITHUB'); + @override Future signInWithJwtToken( - BuildContext context, String jwtToken) => + BuildContext context, + String jwtToken, + ) => _signInOrCreateAccount(context, () => jwtTokenSignIn(jwtToken), 'JWT'); + void handlePhoneAuthStateChanges(BuildContext context) { + phoneAuthManager.addListener(() { + if (!context.mounted) { + return; + } + + if (phoneAuthManager.triggerOnCodeSent) { + phoneAuthManager.onCodeSent(context); + phoneAuthManager + .update(() => phoneAuthManager.triggerOnCodeSent = false); + } else if (phoneAuthManager.phoneAuthError != null) { + final e = phoneAuthManager.phoneAuthError!; + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('Error: ${e.message!}'), + )); + phoneAuthManager.update(() => phoneAuthManager.phoneAuthError = null); + } + }); + } + @override Future beginPhoneAuth({ required BuildContext context, required String phoneNumber, - required VoidCallback onCodeSent, + required void Function(BuildContext) onCodeSent, }) async { + phoneAuthManager.update(() => phoneAuthManager.onCodeSent = onCodeSent); if (kIsWeb) { - _webPhoneAuthConfirmationResult = + phoneAuthManager.webPhoneAuthConfirmationResult = await FirebaseAuth.instance.signInWithPhoneNumber(phoneNumber); - onCodeSent(); + phoneAuthManager.update(() => phoneAuthManager.triggerOnCodeSent = true); return; } final completer = Completer(); @@ -142,6 +219,10 @@ class FirebaseAuthManager extends AuthManager timeout: Duration(seconds: 5), verificationCompleted: (phoneAuthCredential) async { await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential); + phoneAuthManager.update(() { + phoneAuthManager.triggerOnCodeSent = false; + phoneAuthManager.phoneAuthError = null; + }); // If you've implemented auto-verification, navigate to home page or // onboarding page here manually. Uncomment the lines below and replace // DestinationPage() with the desired widget. @@ -151,15 +232,19 @@ class FirebaseAuthManager extends AuthManager // ); }, verificationFailed: (e) { + phoneAuthManager.update(() { + phoneAuthManager.triggerOnCodeSent = false; + phoneAuthManager.phoneAuthError = e; + }); completer.complete(false); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Error: ${e.message!}'), - )); }, codeSent: (verificationId, _) { - _phoneAuthVerificationCode = verificationId; + phoneAuthManager.update(() { + phoneAuthManager.phoneAuthVerificationCode = verificationId; + phoneAuthManager.triggerOnCodeSent = true; + phoneAuthManager.phoneAuthError = null; + }); completer.complete(true); - onCodeSent(); }, codeAutoRetrievalTimeout: (_) {}, ); @@ -175,12 +260,14 @@ class FirebaseAuthManager extends AuthManager if (kIsWeb) { return _signInOrCreateAccount( context, - () => _webPhoneAuthConfirmationResult!.confirm(smsCode), + () => phoneAuthManager.webPhoneAuthConfirmationResult!.confirm(smsCode), 'PHONE', ); } else { final authCredential = PhoneAuthProvider.credential( - verificationId: _phoneAuthVerificationCode!, smsCode: smsCode); + verificationId: phoneAuthManager.phoneAuthVerificationCode!, + smsCode: smsCode, + ); return _signInOrCreateAccount( context, () => FirebaseAuth.instance.signInWithCredential(authCredential), diff --git a/lib/auth/firebase_auth/firebase_user_provider.dart b/lib/auth/firebase_auth/firebase_user_provider.dart index 0a02f99..a5200b4 100644 --- a/lib/auth/firebase_auth/firebase_user_provider.dart +++ b/lib/auth/firebase_auth/firebase_user_provider.dart @@ -22,6 +22,9 @@ class PenniesFromHeavenFirebaseUser extends BaseAuthUser { @override Future? delete() => user?.delete(); + @override + Future? updateEmail(String email) async => await user?.updateEmail(email); + @override Future? sendEmailVerification() => user?.sendEmailVerification(); @@ -30,13 +33,18 @@ class PenniesFromHeavenFirebaseUser extends BaseAuthUser { // Reloads the user when checking in order to get the most up to date // email verified status. if (loggedIn && !user!.emailVerified) { - FirebaseAuth.instance.currentUser - ?.reload() - .then((_) => user = FirebaseAuth.instance.currentUser); + refreshUser(); } return user?.emailVerified ?? false; } + @override + Future refreshUser() async { + await FirebaseAuth.instance.currentUser + ?.reload() + .then((_) => user = FirebaseAuth.instance.currentUser); + } + static BaseAuthUser fromUserCredential(UserCredential userCredential) => fromFirebaseUser(userCredential.user); static BaseAuthUser fromFirebaseUser(User? user) => diff --git a/lib/auth/firebase_auth/github_auth.dart b/lib/auth/firebase_auth/github_auth.dart new file mode 100644 index 0000000..ff72a73 --- /dev/null +++ b/lib/auth/firebase_auth/github_auth.dart @@ -0,0 +1,11 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/foundation.dart'; + +// https://firebase.flutter.dev/docs/auth/social/#github +Future githubSignInFunc() async { + // Create a new provider + GithubAuthProvider githubProvider = GithubAuthProvider(); + + // Once signed in, return the UserCredential + return await FirebaseAuth.instance.signInWithPopup(githubProvider); +} diff --git a/lib/backend/backend.dart b/lib/backend/backend.dart index 94228c8..6876f84 100644 --- a/lib/backend/backend.dart +++ b/lib/backend/backend.dart @@ -1,19 +1,27 @@ -import 'package:built_value/serializer.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../auth/firebase_auth/auth_util.dart'; import '../flutter_flow/flutter_flow_util.dart'; +import 'schema/util/firestore_util.dart'; import 'schema/users_record.dart'; -import 'schema/serializers.dart'; +import 'schema/charities_record.dart'; +import 'schema/donations_record.dart'; +import 'schema/donation_solicitation_record.dart'; +import 'schema/clients_record.dart'; export 'dart:async' show StreamSubscription; export 'package:cloud_firestore/cloud_firestore.dart'; export 'schema/index.dart'; -export 'schema/serializers.dart'; +export 'schema/util/firestore_util.dart'; +export 'schema/util/schema_util.dart'; export 'schema/users_record.dart'; +export 'schema/charities_record.dart'; +export 'schema/donations_record.dart'; +export 'schema/donation_solicitation_record.dart'; +export 'schema/clients_record.dart'; /// Functions to query UsersRecords (as a Stream and as a Future). Future queryUsersRecordCount({ @@ -33,7 +41,7 @@ Stream> queryUsersRecord({ }) => queryCollection( UsersRecord.collection, - UsersRecord.serializer, + UsersRecord.fromSnapshot, queryBuilder: queryBuilder, limit: limit, singleRecord: singleRecord, @@ -46,25 +54,164 @@ Future> queryUsersRecordOnce({ }) => queryCollectionOnce( UsersRecord.collection, - UsersRecord.serializer, + UsersRecord.fromSnapshot, queryBuilder: queryBuilder, limit: limit, singleRecord: singleRecord, ); -Future> queryUsersRecordPage({ +/// Functions to query CharitiesRecords (as a Stream and as a Future). +Future queryCharitiesRecordCount({ Query Function(Query)? queryBuilder, - DocumentSnapshot? nextPageMarker, - required int pageSize, - required bool isStream, + int limit = -1, }) => - queryCollectionPage( - UsersRecord.collection, - UsersRecord.serializer, + queryCollectionCount( + CharitiesRecord.collection, + queryBuilder: queryBuilder, + limit: limit, + ); + +Stream> queryCharitiesRecord({ + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollection( + CharitiesRecord.collection, + CharitiesRecord.fromSnapshot, + queryBuilder: queryBuilder, + limit: limit, + singleRecord: singleRecord, + ); + +Future> queryCharitiesRecordOnce({ + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollectionOnce( + CharitiesRecord.collection, + CharitiesRecord.fromSnapshot, + queryBuilder: queryBuilder, + limit: limit, + singleRecord: singleRecord, + ); + +/// Functions to query DonationsRecords (as a Stream and as a Future). +Future queryDonationsRecordCount({ + DocumentReference? parent, + Query Function(Query)? queryBuilder, + int limit = -1, +}) => + queryCollectionCount( + DonationsRecord.collection(parent), + queryBuilder: queryBuilder, + limit: limit, + ); + +Stream> queryDonationsRecord({ + DocumentReference? parent, + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollection( + DonationsRecord.collection(parent), + DonationsRecord.fromSnapshot, queryBuilder: queryBuilder, - nextPageMarker: nextPageMarker, - pageSize: pageSize, - isStream: isStream, + limit: limit, + singleRecord: singleRecord, + ); + +Future> queryDonationsRecordOnce({ + DocumentReference? parent, + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollectionOnce( + DonationsRecord.collection(parent), + DonationsRecord.fromSnapshot, + queryBuilder: queryBuilder, + limit: limit, + singleRecord: singleRecord, + ); + +/// Functions to query DonationSolicitationRecords (as a Stream and as a Future). +Future queryDonationSolicitationRecordCount({ + Query Function(Query)? queryBuilder, + int limit = -1, +}) => + queryCollectionCount( + DonationSolicitationRecord.collection, + queryBuilder: queryBuilder, + limit: limit, + ); + +Stream> queryDonationSolicitationRecord({ + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollection( + DonationSolicitationRecord.collection, + DonationSolicitationRecord.fromSnapshot, + queryBuilder: queryBuilder, + limit: limit, + singleRecord: singleRecord, + ); + +Future> queryDonationSolicitationRecordOnce({ + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollectionOnce( + DonationSolicitationRecord.collection, + DonationSolicitationRecord.fromSnapshot, + queryBuilder: queryBuilder, + limit: limit, + singleRecord: singleRecord, + ); + +/// Functions to query ClientsRecords (as a Stream and as a Future). +Future queryClientsRecordCount({ + DocumentReference? parent, + Query Function(Query)? queryBuilder, + int limit = -1, +}) => + queryCollectionCount( + ClientsRecord.collection(parent), + queryBuilder: queryBuilder, + limit: limit, + ); + +Stream> queryClientsRecord({ + DocumentReference? parent, + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollection( + ClientsRecord.collection(parent), + ClientsRecord.fromSnapshot, + queryBuilder: queryBuilder, + limit: limit, + singleRecord: singleRecord, + ); + +Future> queryClientsRecordOnce({ + DocumentReference? parent, + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) => + queryCollectionOnce( + ClientsRecord.collection(parent), + ClientsRecord.fromSnapshot, + queryBuilder: queryBuilder, + limit: limit, + singleRecord: singleRecord, ); Future queryCollectionCount( @@ -83,10 +230,13 @@ Future queryCollectionCount( }).then((value) => value.count); } -Stream> queryCollection(Query collection, Serializer serializer, - {Query Function(Query)? queryBuilder, - int limit = -1, - bool singleRecord = false}) { +Stream> queryCollection( + Query collection, + RecordBuilder recordBuilder, { + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) { final builder = queryBuilder ?? (q) => q; var query = builder(collection); if (limit > 0 || singleRecord) { @@ -97,7 +247,7 @@ Stream> queryCollection(Query collection, Serializer serializer, }).map((s) => s.docs .map( (d) => safeGet( - () => serializers.deserializeWith(serializer, serializedData(d)), + () => recordBuilder(d), (e) => print('Error serializing doc ${d.reference.path}:\n$e'), ), ) @@ -107,10 +257,12 @@ Stream> queryCollection(Query collection, Serializer serializer, } Future> queryCollectionOnce( - Query collection, Serializer serializer, - {Query Function(Query)? queryBuilder, - int limit = -1, - bool singleRecord = false}) { + Query collection, + RecordBuilder recordBuilder, { + Query Function(Query)? queryBuilder, + int limit = -1, + bool singleRecord = false, +}) { final builder = queryBuilder ?? (q) => q; var query = builder(collection); if (limit > 0 || singleRecord) { @@ -119,7 +271,7 @@ Future> queryCollectionOnce( return query.get().then((s) => s.docs .map( (d) => safeGet( - () => serializers.deserializeWith(serializer, serializedData(d)), + () => recordBuilder(d), (e) => print('Error serializing doc ${d.reference.path}:\n$e'), ), ) @@ -153,7 +305,7 @@ class FFFirestorePage { Future> queryCollectionPage( Query collection, - Serializer serializer, { + RecordBuilder recordBuilder, { Query Function(Query)? queryBuilder, DocumentSnapshot? nextPageMarker, required int pageSize, @@ -175,7 +327,7 @@ Future> queryCollectionPage( final getDocs = (QuerySnapshot s) => s.docs .map( (d) => safeGet( - () => serializers.deserializeWith(serializer, serializedData(d)), + () => recordBuilder(d), (e) => print('Error serializing doc ${d.reference.path}:\n$e'), ), ) @@ -207,6 +359,10 @@ Future maybeCreateUser(User user) async { ); await userRecord.set(userData); - currentUserDocument = - serializers.deserializeWith(UsersRecord.serializer, userData); + currentUserDocument = UsersRecord.getDocumentFromData(userData, userRecord); +} + +Future updateUserDocument({String? email}) async { + await currentUserDocument?.reference + .update(createUsersRecordData(email: email)); } diff --git a/lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart b/lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart deleted file mode 100644 index ac89284..0000000 --- a/lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'dart:async'; - -import 'package:firebase_dynamic_links/firebase_dynamic_links.dart'; -import '../../flutter_flow/flutter_flow_util.dart'; -import 'package:flutter/material.dart'; - -const _kDynamicLinksUrl = 'https://penniesfromheaven.app'; -const _kAppBundleId = 'com.mycompany.penniesfromheaven'; - -Future generateCurrentPageLink( - BuildContext context, { - String? title, - String? description, - String? imageUrl, - bool isShortLink = true, - bool forceRedirect = false, -}) async { - final dynamicLinkParams = DynamicLinkParameters( - link: Uri.parse('$_kDynamicLinksUrl${GoRouter.of(context).location}'), - uriPrefix: _kDynamicLinksUrl, - androidParameters: const AndroidParameters(packageName: _kAppBundleId), - iosParameters: const IOSParameters( - bundleId: _kAppBundleId, - ), - socialMetaTagParameters: SocialMetaTagParameters( - title: title, - description: description, - imageUrl: imageUrl != null ? Uri.tryParse(imageUrl) : null, - ), - navigationInfoParameters: forceRedirect - ? NavigationInfoParameters(forcedRedirectEnabled: true) - : null, - ); - return isShortLink - ? FirebaseDynamicLinks.instance - .buildShortLink(dynamicLinkParams) - .then((link) => link.shortUrl.toString()) - : FirebaseDynamicLinks.instance - .buildLink(dynamicLinkParams) - .then((link) => link.toString()); -} - -class DynamicLinksHandler extends StatefulWidget { - const DynamicLinksHandler({Key? key, required this.child}) : super(key: key); - - final Widget child; - - @override - _DynamicLinksHandlerState createState() => _DynamicLinksHandlerState(); -} - -class _DynamicLinksHandlerState extends State { - StreamSubscription? linkSubscription; - - static Set kInitialLinks = {}; - - Future handleOpenedDynamicLink() async { - final linkData = await FirebaseDynamicLinks.instance.getInitialLink(); - final link = linkData?.link.toString(); - if (linkData != null && link != null && !kInitialLinks.contains(link)) { - kInitialLinks.add(link); - _handleDynamicLink(linkData); - } - linkSubscription ??= - FirebaseDynamicLinks.instance.onLink.listen(_handleDynamicLink); - } - - /// Extracts the path from the dynamic link, and routes to it. - void _handleDynamicLink(PendingDynamicLinkData linkData) { - final link = linkData.link.toString(); - final host = linkData.link.host; - final location = link.split(host).last; - context.push(location); - } - - @override - void initState() { - super.initState(); - if (!isWeb) { - handleOpenedDynamicLink(); - } - } - - @override - void dispose() { - linkSubscription?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) => widget.child; -} diff --git a/lib/backend/schema/charities_record.dart b/lib/backend/schema/charities_record.dart new file mode 100644 index 0000000..f2d2456 --- /dev/null +++ b/lib/backend/schema/charities_record.dart @@ -0,0 +1,142 @@ +import 'dart:async'; + +import 'package:collection/collection.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class CharitiesRecord extends FirestoreRecord { + CharitiesRecord._( + DocumentReference reference, + Map data, + ) : super(reference, data) { + _initializeFields(); + } + + // "charityLegalName" field. + String? _charityLegalName; + String get charityLegalName => _charityLegalName ?? ''; + bool hasCharityLegalName() => _charityLegalName != null; + + // "charityRegistrationNumber" field. + String? _charityRegistrationNumber; + String get charityRegistrationNumber => _charityRegistrationNumber ?? ''; + bool hasCharityRegistrationNumber() => _charityRegistrationNumber != null; + + // "administrators" field. + List? _administrators; + List get administrators => _administrators ?? const []; + bool hasAdministrators() => _administrators != null; + + // "address" field. + AddressStruct? _address; + AddressStruct get address => _address ?? AddressStruct(); + bool hasAddress() => _address != null; + + // "governmentLink" field. + String? _governmentLink; + String get governmentLink => _governmentLink ?? ''; + bool hasGovernmentLink() => _governmentLink != null; + + // "charityInformalName" field. + String? _charityInformalName; + String get charityInformalName => _charityInformalName ?? ''; + bool hasCharityInformalName() => _charityInformalName != null; + + void _initializeFields() { + _charityLegalName = snapshotData['charityLegalName'] as String?; + _charityRegistrationNumber = + snapshotData['charityRegistrationNumber'] as String?; + _administrators = getDataList(snapshotData['administrators']); + _address = AddressStruct.maybeFromMap(snapshotData['address']); + _governmentLink = snapshotData['governmentLink'] as String?; + _charityInformalName = snapshotData['charityInformalName'] as String?; + } + + static CollectionReference get collection => + FirebaseFirestore.instance.collection('charities'); + + static Stream getDocument(DocumentReference ref) => + ref.snapshots().map((s) => CharitiesRecord.fromSnapshot(s)); + + static Future getDocumentOnce(DocumentReference ref) => + ref.get().then((s) => CharitiesRecord.fromSnapshot(s)); + + static CharitiesRecord fromSnapshot(DocumentSnapshot snapshot) => + CharitiesRecord._( + snapshot.reference, + mapFromFirestore(snapshot.data() as Map), + ); + + static CharitiesRecord getDocumentFromData( + Map data, + DocumentReference reference, + ) => + CharitiesRecord._(reference, mapFromFirestore(data)); + + @override + String toString() => + 'CharitiesRecord(reference: ${reference.path}, data: $snapshotData)'; + + @override + int get hashCode => reference.path.hashCode; + + @override + bool operator ==(other) => + other is CharitiesRecord && + reference.path.hashCode == other.reference.path.hashCode; +} + +Map createCharitiesRecordData({ + String? charityLegalName, + String? charityRegistrationNumber, + AddressStruct? address, + String? governmentLink, + String? charityInformalName, +}) { + final firestoreData = mapToFirestore( + { + 'charityLegalName': charityLegalName, + 'charityRegistrationNumber': charityRegistrationNumber, + 'address': AddressStruct().toMap(), + 'governmentLink': governmentLink, + 'charityInformalName': charityInformalName, + }.withoutNulls, + ); + + // Handle nested data for "address" field. + addAddressStructData(firestoreData, address, 'address'); + + return firestoreData; +} + +class CharitiesRecordDocumentEquality implements Equality { + const CharitiesRecordDocumentEquality(); + + @override + bool equals(CharitiesRecord? e1, CharitiesRecord? e2) { + const listEquality = ListEquality(); + return e1?.charityLegalName == e2?.charityLegalName && + e1?.charityRegistrationNumber == e2?.charityRegistrationNumber && + listEquality.equals(e1?.administrators, e2?.administrators) && + e1?.address == e2?.address && + e1?.governmentLink == e2?.governmentLink && + e1?.charityInformalName == e2?.charityInformalName; + } + + @override + int hash(CharitiesRecord? e) => const ListEquality().hash([ + e?.charityLegalName, + e?.charityRegistrationNumber, + e?.administrators, + e?.address, + e?.governmentLink, + e?.charityInformalName + ]); + + @override + bool isValidKey(Object? o) => o is CharitiesRecord; +} diff --git a/lib/backend/schema/clients_record.dart b/lib/backend/schema/clients_record.dart new file mode 100644 index 0000000..2be3acd --- /dev/null +++ b/lib/backend/schema/clients_record.dart @@ -0,0 +1,113 @@ +import 'dart:async'; + +import 'package:collection/collection.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class ClientsRecord extends FirestoreRecord { + ClientsRecord._( + DocumentReference reference, + Map data, + ) : super(reference, data) { + _initializeFields(); + } + + // "firstName" field. + String? _firstName; + String get firstName => _firstName ?? ''; + bool hasFirstName() => _firstName != null; + + // "surname" field. + String? _surname; + String get surname => _surname ?? ''; + bool hasSurname() => _surname != null; + + // "dateCreated" field. + DateTime? _dateCreated; + DateTime? get dateCreated => _dateCreated; + bool hasDateCreated() => _dateCreated != null; + + DocumentReference get parentReference => reference.parent.parent!; + + void _initializeFields() { + _firstName = snapshotData['firstName'] as String?; + _surname = snapshotData['surname'] as String?; + _dateCreated = snapshotData['dateCreated'] as DateTime?; + } + + static Query> collection([DocumentReference? parent]) => + parent != null + ? parent.collection('clients') + : FirebaseFirestore.instance.collectionGroup('clients'); + + static DocumentReference createDoc(DocumentReference parent) => + parent.collection('clients').doc(); + + static Stream getDocument(DocumentReference ref) => + ref.snapshots().map((s) => ClientsRecord.fromSnapshot(s)); + + static Future getDocumentOnce(DocumentReference ref) => + ref.get().then((s) => ClientsRecord.fromSnapshot(s)); + + static ClientsRecord fromSnapshot(DocumentSnapshot snapshot) => + ClientsRecord._( + snapshot.reference, + mapFromFirestore(snapshot.data() as Map), + ); + + static ClientsRecord getDocumentFromData( + Map data, + DocumentReference reference, + ) => + ClientsRecord._(reference, mapFromFirestore(data)); + + @override + String toString() => + 'ClientsRecord(reference: ${reference.path}, data: $snapshotData)'; + + @override + int get hashCode => reference.path.hashCode; + + @override + bool operator ==(other) => + other is ClientsRecord && + reference.path.hashCode == other.reference.path.hashCode; +} + +Map createClientsRecordData({ + String? firstName, + String? surname, + DateTime? dateCreated, +}) { + final firestoreData = mapToFirestore( + { + 'firstName': firstName, + 'surname': surname, + 'dateCreated': dateCreated, + }.withoutNulls, + ); + + return firestoreData; +} + +class ClientsRecordDocumentEquality implements Equality { + const ClientsRecordDocumentEquality(); + + @override + bool equals(ClientsRecord? e1, ClientsRecord? e2) { + return e1?.firstName == e2?.firstName && + e1?.surname == e2?.surname && + e1?.dateCreated == e2?.dateCreated; + } + + @override + int hash(ClientsRecord? e) => + const ListEquality().hash([e?.firstName, e?.surname, e?.dateCreated]); + + @override + bool isValidKey(Object? o) => o is ClientsRecord; +} diff --git a/lib/backend/schema/donation_solicitation_record.dart b/lib/backend/schema/donation_solicitation_record.dart new file mode 100644 index 0000000..ed87999 --- /dev/null +++ b/lib/backend/schema/donation_solicitation_record.dart @@ -0,0 +1,119 @@ +import 'dart:async'; + +import 'package:collection/collection.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class DonationSolicitationRecord extends FirestoreRecord { + DonationSolicitationRecord._( + DocumentReference reference, + Map data, + ) : super(reference, data) { + _initializeFields(); + } + + // "ClientID" field. + DocumentReference? _clientID; + DocumentReference? get clientID => _clientID; + bool hasClientID() => _clientID != null; + + // "CharityID" field. + DocumentReference? _charityID; + DocumentReference? get charityID => _charityID; + bool hasCharityID() => _charityID != null; + + // "DonationSoliticitationID" field. + DocumentReference? _donationSoliticitationID; + DocumentReference? get donationSoliticitationID => _donationSoliticitationID; + bool hasDonationSoliticitationID() => _donationSoliticitationID != null; + + // "IsDisabled" field. + bool? _isDisabled; + bool get isDisabled => _isDisabled ?? false; + bool hasIsDisabled() => _isDisabled != null; + + void _initializeFields() { + _clientID = snapshotData['ClientID'] as DocumentReference?; + _charityID = snapshotData['CharityID'] as DocumentReference?; + _donationSoliticitationID = + snapshotData['DonationSoliticitationID'] as DocumentReference?; + _isDisabled = snapshotData['IsDisabled'] as bool?; + } + + static CollectionReference get collection => + FirebaseFirestore.instance.collection('DonationSolicitation'); + + static Stream getDocument( + DocumentReference ref) => + ref.snapshots().map((s) => DonationSolicitationRecord.fromSnapshot(s)); + + static Future getDocumentOnce( + DocumentReference ref) => + ref.get().then((s) => DonationSolicitationRecord.fromSnapshot(s)); + + static DonationSolicitationRecord fromSnapshot(DocumentSnapshot snapshot) => + DonationSolicitationRecord._( + snapshot.reference, + mapFromFirestore(snapshot.data() as Map), + ); + + static DonationSolicitationRecord getDocumentFromData( + Map data, + DocumentReference reference, + ) => + DonationSolicitationRecord._(reference, mapFromFirestore(data)); + + @override + String toString() => + 'DonationSolicitationRecord(reference: ${reference.path}, data: $snapshotData)'; + + @override + int get hashCode => reference.path.hashCode; + + @override + bool operator ==(other) => + other is DonationSolicitationRecord && + reference.path.hashCode == other.reference.path.hashCode; +} + +Map createDonationSolicitationRecordData({ + DocumentReference? clientID, + DocumentReference? charityID, + DocumentReference? donationSoliticitationID, + bool? isDisabled, +}) { + final firestoreData = mapToFirestore( + { + 'ClientID': clientID, + 'CharityID': charityID, + 'DonationSoliticitationID': donationSoliticitationID, + 'IsDisabled': isDisabled, + }.withoutNulls, + ); + + return firestoreData; +} + +class DonationSolicitationRecordDocumentEquality + implements Equality { + const DonationSolicitationRecordDocumentEquality(); + + @override + bool equals(DonationSolicitationRecord? e1, DonationSolicitationRecord? e2) { + return e1?.clientID == e2?.clientID && + e1?.charityID == e2?.charityID && + e1?.donationSoliticitationID == e2?.donationSoliticitationID && + e1?.isDisabled == e2?.isDisabled; + } + + @override + int hash(DonationSolicitationRecord? e) => const ListEquality().hash( + [e?.clientID, e?.charityID, e?.donationSoliticitationID, e?.isDisabled]); + + @override + bool isValidKey(Object? o) => o is DonationSolicitationRecord; +} diff --git a/lib/backend/schema/donations_record.dart b/lib/backend/schema/donations_record.dart new file mode 100644 index 0000000..732817f --- /dev/null +++ b/lib/backend/schema/donations_record.dart @@ -0,0 +1,165 @@ +import 'dart:async'; + +import 'package:collection/collection.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class DonationsRecord extends FirestoreRecord { + DonationsRecord._( + DocumentReference reference, + Map data, + ) : super(reference, data) { + _initializeFields(); + } + + // "donor" field. + DocumentReference? _donor; + DocumentReference? get donor => _donor; + bool hasDonor() => _donor != null; + + // "donorName" field. + String? _donorName; + String get donorName => _donorName ?? ''; + bool hasDonorName() => _donorName != null; + + // "amount" field. + double? _amount; + double get amount => _amount ?? 0.0; + bool hasAmount() => _amount != null; + + // "currency" field. + String? _currency; + String get currency => _currency ?? ''; + bool hasCurrency() => _currency != null; + + // "client" field. + DocumentReference? _client; + DocumentReference? get client => _client; + bool hasClient() => _client != null; + + // "charityPortion" field. + List? _charityPortion; + List get charityPortion => _charityPortion ?? const []; + bool hasCharityPortion() => _charityPortion != null; + + // "timestamp" field. + DateTime? _timestamp; + DateTime? get timestamp => _timestamp; + bool hasTimestamp() => _timestamp != null; + + // "location" field. + LatLng? _location; + LatLng? get location => _location; + bool hasLocation() => _location != null; + + DocumentReference get parentReference => reference.parent.parent!; + + void _initializeFields() { + _donor = snapshotData['donor'] as DocumentReference?; + _donorName = snapshotData['donorName'] as String?; + _amount = castToType(snapshotData['amount']); + _currency = snapshotData['currency'] as String?; + _client = snapshotData['client'] as DocumentReference?; + _charityPortion = getDataList(snapshotData['charityPortion']); + _timestamp = snapshotData['timestamp'] as DateTime?; + _location = snapshotData['location'] as LatLng?; + } + + static Query> collection([DocumentReference? parent]) => + parent != null + ? parent.collection('donations') + : FirebaseFirestore.instance.collectionGroup('donations'); + + static DocumentReference createDoc(DocumentReference parent) => + parent.collection('donations').doc(); + + static Stream getDocument(DocumentReference ref) => + ref.snapshots().map((s) => DonationsRecord.fromSnapshot(s)); + + static Future getDocumentOnce(DocumentReference ref) => + ref.get().then((s) => DonationsRecord.fromSnapshot(s)); + + static DonationsRecord fromSnapshot(DocumentSnapshot snapshot) => + DonationsRecord._( + snapshot.reference, + mapFromFirestore(snapshot.data() as Map), + ); + + static DonationsRecord getDocumentFromData( + Map data, + DocumentReference reference, + ) => + DonationsRecord._(reference, mapFromFirestore(data)); + + @override + String toString() => + 'DonationsRecord(reference: ${reference.path}, data: $snapshotData)'; + + @override + int get hashCode => reference.path.hashCode; + + @override + bool operator ==(other) => + other is DonationsRecord && + reference.path.hashCode == other.reference.path.hashCode; +} + +Map createDonationsRecordData({ + DocumentReference? donor, + String? donorName, + double? amount, + String? currency, + DocumentReference? client, + DateTime? timestamp, + LatLng? location, +}) { + final firestoreData = mapToFirestore( + { + 'donor': donor, + 'donorName': donorName, + 'amount': amount, + 'currency': currency, + 'client': client, + 'timestamp': timestamp, + 'location': location, + }.withoutNulls, + ); + + return firestoreData; +} + +class DonationsRecordDocumentEquality implements Equality { + const DonationsRecordDocumentEquality(); + + @override + bool equals(DonationsRecord? e1, DonationsRecord? e2) { + const listEquality = ListEquality(); + return e1?.donor == e2?.donor && + e1?.donorName == e2?.donorName && + e1?.amount == e2?.amount && + e1?.currency == e2?.currency && + e1?.client == e2?.client && + listEquality.equals(e1?.charityPortion, e2?.charityPortion) && + e1?.timestamp == e2?.timestamp && + e1?.location == e2?.location; + } + + @override + int hash(DonationsRecord? e) => const ListEquality().hash([ + e?.donor, + e?.donorName, + e?.amount, + e?.currency, + e?.client, + e?.charityPortion, + e?.timestamp, + e?.location + ]); + + @override + bool isValidKey(Object? o) => o is DonationsRecord; +} diff --git a/lib/backend/schema/firestore.rules b/lib/backend/schema/firestore.rules index 64fe34d..219c40c 100644 --- a/lib/backend/schema/firestore.rules +++ b/lib/backend/schema/firestore.rules @@ -1,6 +1,42 @@ rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { + match /charities/{document} { + allow create: if true; + allow read: if true; + allow write: if request.auth != null; + allow delete: if false; + } + + match /charities/{parent}/donations/{document} { + allow create: if true; + allow read: if true; + allow write: if request.auth != null; + allow delete: if false; + } + + match /{path=**}/donations/{document} { + allow read: if true; + } + + + match /DonationSolicitation/{document} { + allow create: if true; + allow read: if true; + allow write: if false; + allow delete: if false; + } + + match /charities/{parent}/clients/{document} { + allow create: if true; + allow read: if true; + allow write: if request.auth != null; + allow delete: if false; + } + + match /{path=**}/clients/{document} { + allow read: if true; + } } } diff --git a/lib/backend/schema/index.dart b/lib/backend/schema/index.dart index 01274bb..8dc6357 100644 --- a/lib/backend/schema/index.dart +++ b/lib/backend/schema/index.dart @@ -1,5 +1,5 @@ export 'package:cloud_firestore/cloud_firestore.dart'; -export 'package:built_value/serializer.dart'; -export 'package:built_collection/built_collection.dart'; export 'package:flutter/material.dart' show Color, Colors; -export '../../flutter_flow/lat_lng.dart'; +export '/flutter_flow/lat_lng.dart'; + +export 'structs/index.dart'; diff --git a/lib/backend/schema/serializers.g.dart b/lib/backend/schema/serializers.g.dart deleted file mode 100644 index f55cf77..0000000 --- a/lib/backend/schema/serializers.g.dart +++ /dev/null @@ -1,12 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'serializers.dart'; - -// ************************************************************************** -// BuiltValueGenerator -// ************************************************************************** - -Serializers _$serializers = - (new Serializers().toBuilder()..add(UsersRecord.serializer)).build(); - -// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/lib/backend/schema/structs/address_struct.dart b/lib/backend/schema/structs/address_struct.dart new file mode 100644 index 0000000..f7b0b3d --- /dev/null +++ b/lib/backend/schema/structs/address_struct.dart @@ -0,0 +1,248 @@ +// ignore_for_file: unnecessary_getters_setters +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class AddressStruct extends FFFirebaseStruct { + AddressStruct({ + String? address, + String? unit, + String? city, + String? country, + String? provinceState, + String? postalZipCode, + FirestoreUtilData firestoreUtilData = const FirestoreUtilData(), + }) : _address = address, + _unit = unit, + _city = city, + _country = country, + _provinceState = provinceState, + _postalZipCode = postalZipCode, + super(firestoreUtilData); + + // "address" field. + String? _address; + String get address => _address ?? ''; + set address(String? val) => _address = val; + bool hasAddress() => _address != null; + + // "unit" field. + String? _unit; + String get unit => _unit ?? ''; + set unit(String? val) => _unit = val; + bool hasUnit() => _unit != null; + + // "city" field. + String? _city; + String get city => _city ?? ''; + set city(String? val) => _city = val; + bool hasCity() => _city != null; + + // "country" field. + String? _country; + String get country => _country ?? ''; + set country(String? val) => _country = val; + bool hasCountry() => _country != null; + + // "provinceState" field. + String? _provinceState; + String get provinceState => _provinceState ?? ''; + set provinceState(String? val) => _provinceState = val; + bool hasProvinceState() => _provinceState != null; + + // "postalZipCode" field. + String? _postalZipCode; + String get postalZipCode => _postalZipCode ?? ''; + set postalZipCode(String? val) => _postalZipCode = val; + bool hasPostalZipCode() => _postalZipCode != null; + + static AddressStruct fromMap(Map data) => AddressStruct( + address: data['address'] as String?, + unit: data['unit'] as String?, + city: data['city'] as String?, + country: data['country'] as String?, + provinceState: data['provinceState'] as String?, + postalZipCode: data['postalZipCode'] as String?, + ); + + static AddressStruct? maybeFromMap(dynamic data) => + data is Map ? AddressStruct.fromMap(data) : null; + + Map toMap() => { + 'address': _address, + 'unit': _unit, + 'city': _city, + 'country': _country, + 'provinceState': _provinceState, + 'postalZipCode': _postalZipCode, + }.withoutNulls; + + @override + Map toSerializableMap() => { + 'address': serializeParam( + _address, + ParamType.String, + ), + 'unit': serializeParam( + _unit, + ParamType.String, + ), + 'city': serializeParam( + _city, + ParamType.String, + ), + 'country': serializeParam( + _country, + ParamType.String, + ), + 'provinceState': serializeParam( + _provinceState, + ParamType.String, + ), + 'postalZipCode': serializeParam( + _postalZipCode, + ParamType.String, + ), + }.withoutNulls; + + static AddressStruct fromSerializableMap(Map data) => + AddressStruct( + address: deserializeParam( + data['address'], + ParamType.String, + false, + ), + unit: deserializeParam( + data['unit'], + ParamType.String, + false, + ), + city: deserializeParam( + data['city'], + ParamType.String, + false, + ), + country: deserializeParam( + data['country'], + ParamType.String, + false, + ), + provinceState: deserializeParam( + data['provinceState'], + ParamType.String, + false, + ), + postalZipCode: deserializeParam( + data['postalZipCode'], + ParamType.String, + false, + ), + ); + + @override + String toString() => 'AddressStruct(${toMap()})'; + + @override + bool operator ==(Object other) { + return other is AddressStruct && + address == other.address && + unit == other.unit && + city == other.city && + country == other.country && + provinceState == other.provinceState && + postalZipCode == other.postalZipCode; + } + + @override + int get hashCode => const ListEquality() + .hash([address, unit, city, country, provinceState, postalZipCode]); +} + +AddressStruct createAddressStruct({ + String? address, + String? unit, + String? city, + String? country, + String? provinceState, + String? postalZipCode, + Map fieldValues = const {}, + bool clearUnsetFields = true, + bool create = false, + bool delete = false, +}) => + AddressStruct( + address: address, + unit: unit, + city: city, + country: country, + provinceState: provinceState, + postalZipCode: postalZipCode, + firestoreUtilData: FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + delete: delete, + fieldValues: fieldValues, + ), + ); + +AddressStruct? updateAddressStruct( + AddressStruct? addressStruct, { + bool clearUnsetFields = true, + bool create = false, +}) => + addressStruct + ?..firestoreUtilData = FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + ); + +void addAddressStructData( + Map firestoreData, + AddressStruct? addressStruct, + String fieldName, [ + bool forFieldValue = false, +]) { + firestoreData.remove(fieldName); + if (addressStruct == null) { + return; + } + if (addressStruct.firestoreUtilData.delete) { + firestoreData[fieldName] = FieldValue.delete(); + return; + } + if (!forFieldValue && addressStruct.firestoreUtilData.clearUnsetFields) { + firestoreData[fieldName] = {}; + } + final addressStructData = + getAddressFirestoreData(addressStruct, forFieldValue); + final nestedData = + addressStructData.map((k, v) => MapEntry('$fieldName.$k', v)); + + final create = addressStruct.firestoreUtilData.create; + firestoreData.addAll(create ? mergeNestedFields(nestedData) : nestedData); +} + +Map getAddressFirestoreData( + AddressStruct? addressStruct, [ + bool forFieldValue = false, +]) { + if (addressStruct == null) { + return {}; + } + final firestoreData = mapToFirestore(addressStruct.toMap()); + + // Add any Firestore field values + addressStruct.firestoreUtilData.fieldValues + .forEach((k, v) => firestoreData[k] = v); + + return forFieldValue ? mergeNestedFields(firestoreData) : firestoreData; +} + +List> getAddressListFirestoreData( + List? addressStructs, +) => + addressStructs?.map((e) => getAddressFirestoreData(e, true)).toList() ?? []; diff --git a/lib/backend/schema/structs/currency_struct.dart b/lib/backend/schema/structs/currency_struct.dart new file mode 100644 index 0000000..027d920 --- /dev/null +++ b/lib/backend/schema/structs/currency_struct.dart @@ -0,0 +1,179 @@ +// ignore_for_file: unnecessary_getters_setters +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class CurrencyStruct extends FFFirebaseStruct { + CurrencyStruct({ + String? cad, + String? usd, + String? mxn, + FirestoreUtilData firestoreUtilData = const FirestoreUtilData(), + }) : _cad = cad, + _usd = usd, + _mxn = mxn, + super(firestoreUtilData); + + // "CAD" field. + String? _cad; + String get cad => _cad ?? ''; + set cad(String? val) => _cad = val; + bool hasCad() => _cad != null; + + // "USD" field. + String? _usd; + String get usd => _usd ?? ''; + set usd(String? val) => _usd = val; + bool hasUsd() => _usd != null; + + // "MXN" field. + String? _mxn; + String get mxn => _mxn ?? ''; + set mxn(String? val) => _mxn = val; + bool hasMxn() => _mxn != null; + + static CurrencyStruct fromMap(Map data) => CurrencyStruct( + cad: data['CAD'] as String?, + usd: data['USD'] as String?, + mxn: data['MXN'] as String?, + ); + + static CurrencyStruct? maybeFromMap(dynamic data) => + data is Map ? CurrencyStruct.fromMap(data) : null; + + Map toMap() => { + 'CAD': _cad, + 'USD': _usd, + 'MXN': _mxn, + }.withoutNulls; + + @override + Map toSerializableMap() => { + 'CAD': serializeParam( + _cad, + ParamType.String, + ), + 'USD': serializeParam( + _usd, + ParamType.String, + ), + 'MXN': serializeParam( + _mxn, + ParamType.String, + ), + }.withoutNulls; + + static CurrencyStruct fromSerializableMap(Map data) => + CurrencyStruct( + cad: deserializeParam( + data['CAD'], + ParamType.String, + false, + ), + usd: deserializeParam( + data['USD'], + ParamType.String, + false, + ), + mxn: deserializeParam( + data['MXN'], + ParamType.String, + false, + ), + ); + + @override + String toString() => 'CurrencyStruct(${toMap()})'; + + @override + bool operator ==(Object other) { + return other is CurrencyStruct && + cad == other.cad && + usd == other.usd && + mxn == other.mxn; + } + + @override + int get hashCode => const ListEquality().hash([cad, usd, mxn]); +} + +CurrencyStruct createCurrencyStruct({ + String? cad, + String? usd, + String? mxn, + Map fieldValues = const {}, + bool clearUnsetFields = true, + bool create = false, + bool delete = false, +}) => + CurrencyStruct( + cad: cad, + usd: usd, + mxn: mxn, + firestoreUtilData: FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + delete: delete, + fieldValues: fieldValues, + ), + ); + +CurrencyStruct? updateCurrencyStruct( + CurrencyStruct? currency, { + bool clearUnsetFields = true, + bool create = false, +}) => + currency + ?..firestoreUtilData = FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + ); + +void addCurrencyStructData( + Map firestoreData, + CurrencyStruct? currency, + String fieldName, [ + bool forFieldValue = false, +]) { + firestoreData.remove(fieldName); + if (currency == null) { + return; + } + if (currency.firestoreUtilData.delete) { + firestoreData[fieldName] = FieldValue.delete(); + return; + } + if (!forFieldValue && currency.firestoreUtilData.clearUnsetFields) { + firestoreData[fieldName] = {}; + } + final currencyData = getCurrencyFirestoreData(currency, forFieldValue); + final nestedData = currencyData.map((k, v) => MapEntry('$fieldName.$k', v)); + + final create = currency.firestoreUtilData.create; + firestoreData.addAll(create ? mergeNestedFields(nestedData) : nestedData); +} + +Map getCurrencyFirestoreData( + CurrencyStruct? currency, [ + bool forFieldValue = false, +]) { + if (currency == null) { + return {}; + } + final firestoreData = mapToFirestore(currency.toMap()); + + // Add any Firestore field values + currency.firestoreUtilData.fieldValues + .forEach((k, v) => firestoreData[k] = v); + + return forFieldValue ? mergeNestedFields(firestoreData) : firestoreData; +} + +List> getCurrencyListFirestoreData( + List? currencys, +) => + currencys?.map((e) => getCurrencyFirestoreData(e, true)).toList() ?? []; diff --git a/lib/backend/schema/structs/index.dart b/lib/backend/schema/structs/index.dart new file mode 100644 index 0000000..d636e8e --- /dev/null +++ b/lib/backend/schema/structs/index.dart @@ -0,0 +1,7 @@ +export '/backend/schema/util/schema_util.dart'; + +export 'smart_image_location_struct.dart'; +export 'address_struct.dart'; +export 'currency_struct.dart'; +export 'permissions_struct.dart'; +export 'roles_struct.dart'; diff --git a/lib/backend/schema/structs/permissions_struct.dart b/lib/backend/schema/structs/permissions_struct.dart new file mode 100644 index 0000000..de33ede --- /dev/null +++ b/lib/backend/schema/structs/permissions_struct.dart @@ -0,0 +1,250 @@ +// ignore_for_file: unnecessary_getters_setters +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class PermissionsStruct extends FFFirebaseStruct { + PermissionsStruct({ + bool? active, + bool? donor, + bool? client, + bool? charity, + bool? charityAdmin, + bool? admin, + FirestoreUtilData firestoreUtilData = const FirestoreUtilData(), + }) : _active = active, + _donor = donor, + _client = client, + _charity = charity, + _charityAdmin = charityAdmin, + _admin = admin, + super(firestoreUtilData); + + // "active" field. + bool? _active; + bool get active => _active ?? false; + set active(bool? val) => _active = val; + bool hasActive() => _active != null; + + // "donor" field. + bool? _donor; + bool get donor => _donor ?? false; + set donor(bool? val) => _donor = val; + bool hasDonor() => _donor != null; + + // "client" field. + bool? _client; + bool get client => _client ?? false; + set client(bool? val) => _client = val; + bool hasClient() => _client != null; + + // "charity" field. + bool? _charity; + bool get charity => _charity ?? false; + set charity(bool? val) => _charity = val; + bool hasCharity() => _charity != null; + + // "charityAdmin" field. + bool? _charityAdmin; + bool get charityAdmin => _charityAdmin ?? false; + set charityAdmin(bool? val) => _charityAdmin = val; + bool hasCharityAdmin() => _charityAdmin != null; + + // "admin" field. + bool? _admin; + bool get admin => _admin ?? false; + set admin(bool? val) => _admin = val; + bool hasAdmin() => _admin != null; + + static PermissionsStruct fromMap(Map data) => + PermissionsStruct( + active: data['active'] as bool?, + donor: data['donor'] as bool?, + client: data['client'] as bool?, + charity: data['charity'] as bool?, + charityAdmin: data['charityAdmin'] as bool?, + admin: data['admin'] as bool?, + ); + + static PermissionsStruct? maybeFromMap(dynamic data) => + data is Map ? PermissionsStruct.fromMap(data) : null; + + Map toMap() => { + 'active': _active, + 'donor': _donor, + 'client': _client, + 'charity': _charity, + 'charityAdmin': _charityAdmin, + 'admin': _admin, + }.withoutNulls; + + @override + Map toSerializableMap() => { + 'active': serializeParam( + _active, + ParamType.bool, + ), + 'donor': serializeParam( + _donor, + ParamType.bool, + ), + 'client': serializeParam( + _client, + ParamType.bool, + ), + 'charity': serializeParam( + _charity, + ParamType.bool, + ), + 'charityAdmin': serializeParam( + _charityAdmin, + ParamType.bool, + ), + 'admin': serializeParam( + _admin, + ParamType.bool, + ), + }.withoutNulls; + + static PermissionsStruct fromSerializableMap(Map data) => + PermissionsStruct( + active: deserializeParam( + data['active'], + ParamType.bool, + false, + ), + donor: deserializeParam( + data['donor'], + ParamType.bool, + false, + ), + client: deserializeParam( + data['client'], + ParamType.bool, + false, + ), + charity: deserializeParam( + data['charity'], + ParamType.bool, + false, + ), + charityAdmin: deserializeParam( + data['charityAdmin'], + ParamType.bool, + false, + ), + admin: deserializeParam( + data['admin'], + ParamType.bool, + false, + ), + ); + + @override + String toString() => 'PermissionsStruct(${toMap()})'; + + @override + bool operator ==(Object other) { + return other is PermissionsStruct && + active == other.active && + donor == other.donor && + client == other.client && + charity == other.charity && + charityAdmin == other.charityAdmin && + admin == other.admin; + } + + @override + int get hashCode => const ListEquality() + .hash([active, donor, client, charity, charityAdmin, admin]); +} + +PermissionsStruct createPermissionsStruct({ + bool? active, + bool? donor, + bool? client, + bool? charity, + bool? charityAdmin, + bool? admin, + Map fieldValues = const {}, + bool clearUnsetFields = true, + bool create = false, + bool delete = false, +}) => + PermissionsStruct( + active: active, + donor: donor, + client: client, + charity: charity, + charityAdmin: charityAdmin, + admin: admin, + firestoreUtilData: FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + delete: delete, + fieldValues: fieldValues, + ), + ); + +PermissionsStruct? updatePermissionsStruct( + PermissionsStruct? permissions, { + bool clearUnsetFields = true, + bool create = false, +}) => + permissions + ?..firestoreUtilData = FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + ); + +void addPermissionsStructData( + Map firestoreData, + PermissionsStruct? permissions, + String fieldName, [ + bool forFieldValue = false, +]) { + firestoreData.remove(fieldName); + if (permissions == null) { + return; + } + if (permissions.firestoreUtilData.delete) { + firestoreData[fieldName] = FieldValue.delete(); + return; + } + if (!forFieldValue && permissions.firestoreUtilData.clearUnsetFields) { + firestoreData[fieldName] = {}; + } + final permissionsData = + getPermissionsFirestoreData(permissions, forFieldValue); + final nestedData = + permissionsData.map((k, v) => MapEntry('$fieldName.$k', v)); + + final create = permissions.firestoreUtilData.create; + firestoreData.addAll(create ? mergeNestedFields(nestedData) : nestedData); +} + +Map getPermissionsFirestoreData( + PermissionsStruct? permissions, [ + bool forFieldValue = false, +]) { + if (permissions == null) { + return {}; + } + final firestoreData = mapToFirestore(permissions.toMap()); + + // Add any Firestore field values + permissions.firestoreUtilData.fieldValues + .forEach((k, v) => firestoreData[k] = v); + + return forFieldValue ? mergeNestedFields(firestoreData) : firestoreData; +} + +List> getPermissionsListFirestoreData( + List? permissionss, +) => + permissionss?.map((e) => getPermissionsFirestoreData(e, true)).toList() ?? + []; diff --git a/lib/backend/schema/structs/roles_struct.dart b/lib/backend/schema/structs/roles_struct.dart new file mode 100644 index 0000000..b4376b5 --- /dev/null +++ b/lib/backend/schema/structs/roles_struct.dart @@ -0,0 +1,251 @@ +// ignore_for_file: unnecessary_getters_setters +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class RolesStruct extends FFFirebaseStruct { + RolesStruct({ + String? client, + String? donor, + String? charityStaff, + String? charityAdmin, + String? fieldSupport, + String? superAdministrator, + FirestoreUtilData firestoreUtilData = const FirestoreUtilData(), + }) : _client = client, + _donor = donor, + _charityStaff = charityStaff, + _charityAdmin = charityAdmin, + _fieldSupport = fieldSupport, + _superAdministrator = superAdministrator, + super(firestoreUtilData); + + // "client" field. + String? _client; + String get client => _client ?? ''; + set client(String? val) => _client = val; + bool hasClient() => _client != null; + + // "donor" field. + String? _donor; + String get donor => _donor ?? ''; + set donor(String? val) => _donor = val; + bool hasDonor() => _donor != null; + + // "charityStaff" field. + String? _charityStaff; + String get charityStaff => _charityStaff ?? ''; + set charityStaff(String? val) => _charityStaff = val; + bool hasCharityStaff() => _charityStaff != null; + + // "charityAdmin" field. + String? _charityAdmin; + String get charityAdmin => _charityAdmin ?? ''; + set charityAdmin(String? val) => _charityAdmin = val; + bool hasCharityAdmin() => _charityAdmin != null; + + // "fieldSupport" field. + String? _fieldSupport; + String get fieldSupport => _fieldSupport ?? ''; + set fieldSupport(String? val) => _fieldSupport = val; + bool hasFieldSupport() => _fieldSupport != null; + + // "superAdministrator" field. + String? _superAdministrator; + String get superAdministrator => _superAdministrator ?? ''; + set superAdministrator(String? val) => _superAdministrator = val; + bool hasSuperAdministrator() => _superAdministrator != null; + + static RolesStruct fromMap(Map data) => RolesStruct( + client: data['client'] as String?, + donor: data['donor'] as String?, + charityStaff: data['charityStaff'] as String?, + charityAdmin: data['charityAdmin'] as String?, + fieldSupport: data['fieldSupport'] as String?, + superAdministrator: data['superAdministrator'] as String?, + ); + + static RolesStruct? maybeFromMap(dynamic data) => + data is Map ? RolesStruct.fromMap(data) : null; + + Map toMap() => { + 'client': _client, + 'donor': _donor, + 'charityStaff': _charityStaff, + 'charityAdmin': _charityAdmin, + 'fieldSupport': _fieldSupport, + 'superAdministrator': _superAdministrator, + }.withoutNulls; + + @override + Map toSerializableMap() => { + 'client': serializeParam( + _client, + ParamType.String, + ), + 'donor': serializeParam( + _donor, + ParamType.String, + ), + 'charityStaff': serializeParam( + _charityStaff, + ParamType.String, + ), + 'charityAdmin': serializeParam( + _charityAdmin, + ParamType.String, + ), + 'fieldSupport': serializeParam( + _fieldSupport, + ParamType.String, + ), + 'superAdministrator': serializeParam( + _superAdministrator, + ParamType.String, + ), + }.withoutNulls; + + static RolesStruct fromSerializableMap(Map data) => + RolesStruct( + client: deserializeParam( + data['client'], + ParamType.String, + false, + ), + donor: deserializeParam( + data['donor'], + ParamType.String, + false, + ), + charityStaff: deserializeParam( + data['charityStaff'], + ParamType.String, + false, + ), + charityAdmin: deserializeParam( + data['charityAdmin'], + ParamType.String, + false, + ), + fieldSupport: deserializeParam( + data['fieldSupport'], + ParamType.String, + false, + ), + superAdministrator: deserializeParam( + data['superAdministrator'], + ParamType.String, + false, + ), + ); + + @override + String toString() => 'RolesStruct(${toMap()})'; + + @override + bool operator ==(Object other) { + return other is RolesStruct && + client == other.client && + donor == other.donor && + charityStaff == other.charityStaff && + charityAdmin == other.charityAdmin && + fieldSupport == other.fieldSupport && + superAdministrator == other.superAdministrator; + } + + @override + int get hashCode => const ListEquality().hash([ + client, + donor, + charityStaff, + charityAdmin, + fieldSupport, + superAdministrator + ]); +} + +RolesStruct createRolesStruct({ + String? client, + String? donor, + String? charityStaff, + String? charityAdmin, + String? fieldSupport, + String? superAdministrator, + Map fieldValues = const {}, + bool clearUnsetFields = true, + bool create = false, + bool delete = false, +}) => + RolesStruct( + client: client, + donor: donor, + charityStaff: charityStaff, + charityAdmin: charityAdmin, + fieldSupport: fieldSupport, + superAdministrator: superAdministrator, + firestoreUtilData: FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + delete: delete, + fieldValues: fieldValues, + ), + ); + +RolesStruct? updateRolesStruct( + RolesStruct? roles, { + bool clearUnsetFields = true, + bool create = false, +}) => + roles + ?..firestoreUtilData = FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + ); + +void addRolesStructData( + Map firestoreData, + RolesStruct? roles, + String fieldName, [ + bool forFieldValue = false, +]) { + firestoreData.remove(fieldName); + if (roles == null) { + return; + } + if (roles.firestoreUtilData.delete) { + firestoreData[fieldName] = FieldValue.delete(); + return; + } + if (!forFieldValue && roles.firestoreUtilData.clearUnsetFields) { + firestoreData[fieldName] = {}; + } + final rolesData = getRolesFirestoreData(roles, forFieldValue); + final nestedData = rolesData.map((k, v) => MapEntry('$fieldName.$k', v)); + + final create = roles.firestoreUtilData.create; + firestoreData.addAll(create ? mergeNestedFields(nestedData) : nestedData); +} + +Map getRolesFirestoreData( + RolesStruct? roles, [ + bool forFieldValue = false, +]) { + if (roles == null) { + return {}; + } + final firestoreData = mapToFirestore(roles.toMap()); + + // Add any Firestore field values + roles.firestoreUtilData.fieldValues.forEach((k, v) => firestoreData[k] = v); + + return forFieldValue ? mergeNestedFields(firestoreData) : firestoreData; +} + +List> getRolesListFirestoreData( + List? roless, +) => + roless?.map((e) => getRolesFirestoreData(e, true)).toList() ?? []; diff --git a/lib/backend/schema/structs/smart_image_location_struct.dart b/lib/backend/schema/structs/smart_image_location_struct.dart new file mode 100644 index 0000000..d089cb3 --- /dev/null +++ b/lib/backend/schema/structs/smart_image_location_struct.dart @@ -0,0 +1,169 @@ +// ignore_for_file: unnecessary_getters_setters +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class SmartImageLocationStruct extends FFFirebaseStruct { + SmartImageLocationStruct({ + List? userRecord, + String? defaultAsset, + FirestoreUtilData firestoreUtilData = const FirestoreUtilData(), + }) : _userRecord = userRecord, + _defaultAsset = defaultAsset, + super(firestoreUtilData); + + // "userRecord" field. + List? _userRecord; + List get userRecord => _userRecord ?? const []; + set userRecord(List? val) => _userRecord = val; + void updateUserRecord(Function(List) updateFn) => + updateFn(_userRecord ??= []); + bool hasUserRecord() => _userRecord != null; + + // "defaultAsset" field. + String? _defaultAsset; + String get defaultAsset => _defaultAsset ?? ''; + set defaultAsset(String? val) => _defaultAsset = val; + bool hasDefaultAsset() => _defaultAsset != null; + + static SmartImageLocationStruct fromMap(Map data) => + SmartImageLocationStruct( + userRecord: getDataList(data['userRecord']), + defaultAsset: data['defaultAsset'] as String?, + ); + + static SmartImageLocationStruct? maybeFromMap(dynamic data) => + data is Map + ? SmartImageLocationStruct.fromMap(data) + : null; + + Map toMap() => { + 'userRecord': _userRecord, + 'defaultAsset': _defaultAsset, + }.withoutNulls; + + @override + Map toSerializableMap() => { + 'userRecord': serializeParam( + _userRecord, + ParamType.DocumentReference, + true, + ), + 'defaultAsset': serializeParam( + _defaultAsset, + ParamType.String, + ), + }.withoutNulls; + + static SmartImageLocationStruct fromSerializableMap( + Map data) => + SmartImageLocationStruct( + userRecord: deserializeParam( + data['userRecord'], + ParamType.DocumentReference, + true, + collectionNamePath: ['users'], + ), + defaultAsset: deserializeParam( + data['defaultAsset'], + ParamType.String, + false, + ), + ); + + @override + String toString() => 'SmartImageLocationStruct(${toMap()})'; + + @override + bool operator ==(Object other) { + const listEquality = ListEquality(); + return other is SmartImageLocationStruct && + listEquality.equals(userRecord, other.userRecord) && + defaultAsset == other.defaultAsset; + } + + @override + int get hashCode => const ListEquality().hash([userRecord, defaultAsset]); +} + +SmartImageLocationStruct createSmartImageLocationStruct({ + String? defaultAsset, + Map fieldValues = const {}, + bool clearUnsetFields = true, + bool create = false, + bool delete = false, +}) => + SmartImageLocationStruct( + defaultAsset: defaultAsset, + firestoreUtilData: FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + delete: delete, + fieldValues: fieldValues, + ), + ); + +SmartImageLocationStruct? updateSmartImageLocationStruct( + SmartImageLocationStruct? smartImageLocation, { + bool clearUnsetFields = true, + bool create = false, +}) => + smartImageLocation + ?..firestoreUtilData = FirestoreUtilData( + clearUnsetFields: clearUnsetFields, + create: create, + ); + +void addSmartImageLocationStructData( + Map firestoreData, + SmartImageLocationStruct? smartImageLocation, + String fieldName, [ + bool forFieldValue = false, +]) { + firestoreData.remove(fieldName); + if (smartImageLocation == null) { + return; + } + if (smartImageLocation.firestoreUtilData.delete) { + firestoreData[fieldName] = FieldValue.delete(); + return; + } + if (!forFieldValue && smartImageLocation.firestoreUtilData.clearUnsetFields) { + firestoreData[fieldName] = {}; + } + final smartImageLocationData = + getSmartImageLocationFirestoreData(smartImageLocation, forFieldValue); + final nestedData = + smartImageLocationData.map((k, v) => MapEntry('$fieldName.$k', v)); + + final create = smartImageLocation.firestoreUtilData.create; + firestoreData.addAll(create ? mergeNestedFields(nestedData) : nestedData); +} + +Map getSmartImageLocationFirestoreData( + SmartImageLocationStruct? smartImageLocation, [ + bool forFieldValue = false, +]) { + if (smartImageLocation == null) { + return {}; + } + final firestoreData = mapToFirestore(smartImageLocation.toMap()); + + // Add any Firestore field values + smartImageLocation.firestoreUtilData.fieldValues + .forEach((k, v) => firestoreData[k] = v); + + return forFieldValue ? mergeNestedFields(firestoreData) : firestoreData; +} + +List> getSmartImageLocationListFirestoreData( + List? smartImageLocations, +) => + smartImageLocations + ?.map((e) => getSmartImageLocationFirestoreData(e, true)) + .toList() ?? + []; diff --git a/lib/backend/schema/users_record.dart b/lib/backend/schema/users_record.dart index 383febc..6f76727 100644 --- a/lib/backend/schema/users_record.dart +++ b/lib/backend/schema/users_record.dart @@ -1,60 +1,115 @@ import 'dart:async'; -import 'index.dart'; -import 'serializers.dart'; -import 'package:built_value/built_value.dart'; - -part 'users_record.g.dart'; - -abstract class UsersRecord implements Built { - static Serializer get serializer => _$usersRecordSerializer; - - String? get email; - - @BuiltValueField(wireName: 'display_name') - String? get displayName; - - @BuiltValueField(wireName: 'photo_url') - String? get photoUrl; - - String? get uid; +import 'package:collection/collection.dart'; - @BuiltValueField(wireName: 'created_time') - DateTime? get createdTime; +import '/backend/schema/util/firestore_util.dart'; +import '/backend/schema/util/schema_util.dart'; - @BuiltValueField(wireName: 'phone_number') - String? get phoneNumber; - - @BuiltValueField(wireName: kDocumentReferenceField) - DocumentReference? get ffRef; - DocumentReference get reference => ffRef!; - - static void _initializeBuilder(UsersRecordBuilder builder) => builder - ..email = '' - ..displayName = '' - ..photoUrl = '' - ..uid = '' - ..phoneNumber = ''; +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class UsersRecord extends FirestoreRecord { + UsersRecord._( + DocumentReference reference, + Map data, + ) : super(reference, data) { + _initializeFields(); + } + + // "email" field. + String? _email; + String get email => _email ?? ''; + bool hasEmail() => _email != null; + + // "display_name" field. + String? _displayName; + String get displayName => _displayName ?? ''; + bool hasDisplayName() => _displayName != null; + + // "photo_url" field. + String? _photoUrl; + String get photoUrl => _photoUrl ?? ''; + bool hasPhotoUrl() => _photoUrl != null; + + // "uid" field. + String? _uid; + String get uid => _uid ?? ''; + bool hasUid() => _uid != null; + + // "created_time" field. + DateTime? _createdTime; + DateTime? get createdTime => _createdTime; + bool hasCreatedTime() => _createdTime != null; + + // "phone_number" field. + String? _phoneNumber; + String get phoneNumber => _phoneNumber ?? ''; + bool hasPhoneNumber() => _phoneNumber != null; + + // "country" field. + String? _country; + String get country => _country ?? ''; + bool hasCountry() => _country != null; + + // "permissions" field. + PermissionsStruct? _permissions; + PermissionsStruct get permissions => _permissions ?? PermissionsStruct(); + bool hasPermissions() => _permissions != null; + + // "first_name" field. + String? _firstName; + String get firstName => _firstName ?? ''; + bool hasFirstName() => _firstName != null; + + // "surname" field. + String? _surname; + String get surname => _surname ?? ''; + bool hasSurname() => _surname != null; + + void _initializeFields() { + _email = snapshotData['email'] as String?; + _displayName = snapshotData['display_name'] as String?; + _photoUrl = snapshotData['photo_url'] as String?; + _uid = snapshotData['uid'] as String?; + _createdTime = snapshotData['created_time'] as DateTime?; + _phoneNumber = snapshotData['phone_number'] as String?; + _country = snapshotData['country'] as String?; + _permissions = PermissionsStruct.maybeFromMap(snapshotData['permissions']); + _firstName = snapshotData['first_name'] as String?; + _surname = snapshotData['surname'] as String?; + } static CollectionReference get collection => FirebaseFirestore.instance.collection('users'); - static Stream getDocument(DocumentReference ref) => ref - .snapshots() - .map((s) => serializers.deserializeWith(serializer, serializedData(s))!); + static Stream getDocument(DocumentReference ref) => + ref.snapshots().map((s) => UsersRecord.fromSnapshot(s)); - static Future getDocumentOnce(DocumentReference ref) => ref - .get() - .then((s) => serializers.deserializeWith(serializer, serializedData(s))!); + static Future getDocumentOnce(DocumentReference ref) => + ref.get().then((s) => UsersRecord.fromSnapshot(s)); - UsersRecord._(); - factory UsersRecord([void Function(UsersRecordBuilder) updates]) = - _$UsersRecord; + static UsersRecord fromSnapshot(DocumentSnapshot snapshot) => UsersRecord._( + snapshot.reference, + mapFromFirestore(snapshot.data() as Map), + ); static UsersRecord getDocumentFromData( - Map data, DocumentReference reference) => - serializers.deserializeWith(serializer, - {...mapFromFirestore(data), kDocumentReferenceField: reference})!; + Map data, + DocumentReference reference, + ) => + UsersRecord._(reference, mapFromFirestore(data)); + + @override + String toString() => + 'UsersRecord(reference: ${reference.path}, data: $snapshotData)'; + + @override + int get hashCode => reference.path.hashCode; + + @override + bool operator ==(other) => + other is UsersRecord && + reference.path.hashCode == other.reference.path.hashCode; } Map createUsersRecordData({ @@ -64,19 +119,63 @@ Map createUsersRecordData({ String? uid, DateTime? createdTime, String? phoneNumber, + String? country, + PermissionsStruct? permissions, + String? firstName, + String? surname, }) { - final firestoreData = serializers.toFirestore( - UsersRecord.serializer, - UsersRecord( - (u) => u - ..email = email - ..displayName = displayName - ..photoUrl = photoUrl - ..uid = uid - ..createdTime = createdTime - ..phoneNumber = phoneNumber, - ), + final firestoreData = mapToFirestore( + { + 'email': email, + 'display_name': displayName, + 'photo_url': photoUrl, + 'uid': uid, + 'created_time': createdTime, + 'phone_number': phoneNumber, + 'country': country, + 'permissions': PermissionsStruct().toMap(), + 'first_name': firstName, + 'surname': surname, + }.withoutNulls, ); + // Handle nested data for "permissions" field. + addPermissionsStructData(firestoreData, permissions, 'permissions'); + return firestoreData; } + +class UsersRecordDocumentEquality implements Equality { + const UsersRecordDocumentEquality(); + + @override + bool equals(UsersRecord? e1, UsersRecord? e2) { + return e1?.email == e2?.email && + e1?.displayName == e2?.displayName && + e1?.photoUrl == e2?.photoUrl && + e1?.uid == e2?.uid && + e1?.createdTime == e2?.createdTime && + e1?.phoneNumber == e2?.phoneNumber && + e1?.country == e2?.country && + e1?.permissions == e2?.permissions && + e1?.firstName == e2?.firstName && + e1?.surname == e2?.surname; + } + + @override + int hash(UsersRecord? e) => const ListEquality().hash([ + e?.email, + e?.displayName, + e?.photoUrl, + e?.uid, + e?.createdTime, + e?.phoneNumber, + e?.country, + e?.permissions, + e?.firstName, + e?.surname + ]); + + @override + bool isValidKey(Object? o) => o is UsersRecord; +} diff --git a/lib/backend/schema/users_record.g.dart b/lib/backend/schema/users_record.g.dart deleted file mode 100644 index e30c91e..0000000 --- a/lib/backend/schema/users_record.g.dart +++ /dev/null @@ -1,279 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'users_record.dart'; - -// ************************************************************************** -// BuiltValueGenerator -// ************************************************************************** - -Serializer _$usersRecordSerializer = new _$UsersRecordSerializer(); - -class _$UsersRecordSerializer implements StructuredSerializer { - @override - final Iterable types = const [UsersRecord, _$UsersRecord]; - @override - final String wireName = 'UsersRecord'; - - @override - Iterable serialize(Serializers serializers, UsersRecord object, - {FullType specifiedType = FullType.unspecified}) { - final result = []; - Object? value; - value = object.email; - if (value != null) { - result - ..add('email') - ..add(serializers.serialize(value, - specifiedType: const FullType(String))); - } - value = object.displayName; - if (value != null) { - result - ..add('display_name') - ..add(serializers.serialize(value, - specifiedType: const FullType(String))); - } - value = object.photoUrl; - if (value != null) { - result - ..add('photo_url') - ..add(serializers.serialize(value, - specifiedType: const FullType(String))); - } - value = object.uid; - if (value != null) { - result - ..add('uid') - ..add(serializers.serialize(value, - specifiedType: const FullType(String))); - } - value = object.createdTime; - if (value != null) { - result - ..add('created_time') - ..add(serializers.serialize(value, - specifiedType: const FullType(DateTime))); - } - value = object.phoneNumber; - if (value != null) { - result - ..add('phone_number') - ..add(serializers.serialize(value, - specifiedType: const FullType(String))); - } - value = object.ffRef; - if (value != null) { - result - ..add('Document__Reference__Field') - ..add(serializers.serialize(value, - specifiedType: const FullType( - DocumentReference, const [const FullType.nullable(Object)]))); - } - return result; - } - - @override - UsersRecord deserialize(Serializers serializers, Iterable serialized, - {FullType specifiedType = FullType.unspecified}) { - final result = new UsersRecordBuilder(); - - final iterator = serialized.iterator; - while (iterator.moveNext()) { - final key = iterator.current! as String; - iterator.moveNext(); - final Object? value = iterator.current; - switch (key) { - case 'email': - result.email = serializers.deserialize(value, - specifiedType: const FullType(String)) as String?; - break; - case 'display_name': - result.displayName = serializers.deserialize(value, - specifiedType: const FullType(String)) as String?; - break; - case 'photo_url': - result.photoUrl = serializers.deserialize(value, - specifiedType: const FullType(String)) as String?; - break; - case 'uid': - result.uid = serializers.deserialize(value, - specifiedType: const FullType(String)) as String?; - break; - case 'created_time': - result.createdTime = serializers.deserialize(value, - specifiedType: const FullType(DateTime)) as DateTime?; - break; - case 'phone_number': - result.phoneNumber = serializers.deserialize(value, - specifiedType: const FullType(String)) as String?; - break; - case 'Document__Reference__Field': - result.ffRef = serializers.deserialize(value, - specifiedType: const FullType(DocumentReference, const [ - const FullType.nullable(Object) - ])) as DocumentReference?; - break; - } - } - - return result.build(); - } -} - -class _$UsersRecord extends UsersRecord { - @override - final String? email; - @override - final String? displayName; - @override - final String? photoUrl; - @override - final String? uid; - @override - final DateTime? createdTime; - @override - final String? phoneNumber; - @override - final DocumentReference? ffRef; - - factory _$UsersRecord([void Function(UsersRecordBuilder)? updates]) => - (new UsersRecordBuilder()..update(updates))._build(); - - _$UsersRecord._( - {this.email, - this.displayName, - this.photoUrl, - this.uid, - this.createdTime, - this.phoneNumber, - this.ffRef}) - : super._(); - - @override - UsersRecord rebuild(void Function(UsersRecordBuilder) updates) => - (toBuilder()..update(updates)).build(); - - @override - UsersRecordBuilder toBuilder() => new UsersRecordBuilder()..replace(this); - - @override - bool operator ==(Object other) { - if (identical(other, this)) return true; - return other is UsersRecord && - email == other.email && - displayName == other.displayName && - photoUrl == other.photoUrl && - uid == other.uid && - createdTime == other.createdTime && - phoneNumber == other.phoneNumber && - ffRef == other.ffRef; - } - - @override - int get hashCode { - var _$hash = 0; - _$hash = $jc(_$hash, email.hashCode); - _$hash = $jc(_$hash, displayName.hashCode); - _$hash = $jc(_$hash, photoUrl.hashCode); - _$hash = $jc(_$hash, uid.hashCode); - _$hash = $jc(_$hash, createdTime.hashCode); - _$hash = $jc(_$hash, phoneNumber.hashCode); - _$hash = $jc(_$hash, ffRef.hashCode); - _$hash = $jf(_$hash); - return _$hash; - } - - @override - String toString() { - return (newBuiltValueToStringHelper(r'UsersRecord') - ..add('email', email) - ..add('displayName', displayName) - ..add('photoUrl', photoUrl) - ..add('uid', uid) - ..add('createdTime', createdTime) - ..add('phoneNumber', phoneNumber) - ..add('ffRef', ffRef)) - .toString(); - } -} - -class UsersRecordBuilder implements Builder { - _$UsersRecord? _$v; - - String? _email; - String? get email => _$this._email; - set email(String? email) => _$this._email = email; - - String? _displayName; - String? get displayName => _$this._displayName; - set displayName(String? displayName) => _$this._displayName = displayName; - - String? _photoUrl; - String? get photoUrl => _$this._photoUrl; - set photoUrl(String? photoUrl) => _$this._photoUrl = photoUrl; - - String? _uid; - String? get uid => _$this._uid; - set uid(String? uid) => _$this._uid = uid; - - DateTime? _createdTime; - DateTime? get createdTime => _$this._createdTime; - set createdTime(DateTime? createdTime) => _$this._createdTime = createdTime; - - String? _phoneNumber; - String? get phoneNumber => _$this._phoneNumber; - set phoneNumber(String? phoneNumber) => _$this._phoneNumber = phoneNumber; - - DocumentReference? _ffRef; - DocumentReference? get ffRef => _$this._ffRef; - set ffRef(DocumentReference? ffRef) => _$this._ffRef = ffRef; - - UsersRecordBuilder() { - UsersRecord._initializeBuilder(this); - } - - UsersRecordBuilder get _$this { - final $v = _$v; - if ($v != null) { - _email = $v.email; - _displayName = $v.displayName; - _photoUrl = $v.photoUrl; - _uid = $v.uid; - _createdTime = $v.createdTime; - _phoneNumber = $v.phoneNumber; - _ffRef = $v.ffRef; - _$v = null; - } - return this; - } - - @override - void replace(UsersRecord other) { - ArgumentError.checkNotNull(other, 'other'); - _$v = other as _$UsersRecord; - } - - @override - void update(void Function(UsersRecordBuilder)? updates) { - if (updates != null) updates(this); - } - - @override - UsersRecord build() => _build(); - - _$UsersRecord _build() { - final _$result = _$v ?? - new _$UsersRecord._( - email: email, - displayName: displayName, - photoUrl: photoUrl, - uid: uid, - createdTime: createdTime, - phoneNumber: phoneNumber, - ffRef: ffRef); - replace(_$result); - return _$result; - } -} - -// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/lib/backend/schema/serializers.dart b/lib/backend/schema/util/firestore_util.dart similarity index 51% rename from lib/backend/schema/serializers.dart rename to lib/backend/schema/util/firestore_util.dart index b4fbf15..7418847 100644 --- a/lib/backend/schema/serializers.dart +++ b/lib/backend/schema/util/firestore_util.dart @@ -1,88 +1,23 @@ -import 'package:built_value/standard_json_plugin.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; import 'package:from_css_color/from_css_color.dart'; -import 'users_record.dart'; +import '/backend/schema/util/schema_util.dart'; +import '/flutter_flow/flutter_flow_util.dart'; -import 'index.dart'; +typedef RecordBuilder = T Function(DocumentSnapshot snapshot); -export 'index.dart'; - -part 'serializers.g.dart'; - -const kDocumentReferenceField = 'Document__Reference__Field'; - -@SerializersFor(const [ - UsersRecord, -]) -final Serializers serializers = (_$serializers.toBuilder() - ..add(DocumentReferenceSerializer()) - ..add(DateTimeSerializer()) - ..add(LatLngSerializer()) - ..add(FirestoreUtilDataSerializer()) - ..add(ColorSerializer()) - ..addPlugin(StandardJsonPlugin())) - .build(); - -extension SerializerExtensions on Serializers { - Map toFirestore(Serializer serializer, T object) => - mapToFirestore(serializeWith(serializer, object) as Map); -} - -class DocumentReferenceSerializer - implements PrimitiveSerializer { - final bool structured = false; - @override - final Iterable types = new BuiltList([DocumentReference]); - @override - final String wireName = 'DocumentReference'; - - @override - Object serialize(Serializers serializers, DocumentReference reference, - {FullType specifiedType: FullType.unspecified}) { - return reference; - } - - @override - DocumentReference deserialize(Serializers serializers, Object serialized, - {FullType specifiedType: FullType.unspecified}) => - serialized as DocumentReference; +abstract class FirestoreRecord { + FirestoreRecord(this.reference, this.snapshotData); + Map snapshotData; + DocumentReference reference; } -class DateTimeSerializer implements PrimitiveSerializer { - @override - final Iterable types = new BuiltList([DateTime]); - @override - final String wireName = 'DateTime'; - - @override - Object serialize(Serializers serializers, DateTime dateTime, - {FullType specifiedType: FullType.unspecified}) { - return dateTime; - } - - @override - DateTime deserialize(Serializers serializers, Object serialized, - {FullType specifiedType: FullType.unspecified}) => - serialized as DateTime; -} - -class LatLngSerializer implements PrimitiveSerializer { - final bool structured = false; - @override - final Iterable types = new BuiltList([LatLng]); - @override - final String wireName = 'LatLng'; - - @override - Object serialize(Serializers serializers, LatLng location, - {FullType specifiedType: FullType.unspecified}) { - return location; - } +abstract class FFFirebaseStruct extends BaseStruct { + FFFirebaseStruct(this.firestoreUtilData); - @override - LatLng deserialize(Serializers serializers, Object serialized, - {FullType specifiedType: FullType.unspecified}) => - serialized as LatLng; + /// Utility class for Firestore updates + FirestoreUtilData firestoreUtilData = FirestoreUtilData(); } class FirestoreUtilData { @@ -99,49 +34,6 @@ class FirestoreUtilData { static String get name => 'firestoreUtilData'; } -class FirestoreUtilDataSerializer - implements PrimitiveSerializer { - final bool structured = false; - @override - final Iterable types = new BuiltList([FirestoreUtilData]); - @override - final String wireName = 'FirestoreUtilData'; - - @override - Object serialize(Serializers serializers, FirestoreUtilData firestoreUtilData, - {FullType specifiedType: FullType.unspecified}) { - return firestoreUtilData; - } - - @override - FirestoreUtilData deserialize(Serializers serializers, Object serialized, - {FullType specifiedType: FullType.unspecified}) => - serialized as FirestoreUtilData; -} - -class ColorSerializer implements PrimitiveSerializer { - @override - final Iterable types = new BuiltList([Color]); - @override - final String wireName = 'Color'; - - @override - Object serialize(Serializers serializers, Color color, - {FullType specifiedType: FullType.unspecified}) { - return color.toCssString(); - } - - @override - Color deserialize(Serializers serializers, Object serialized, - {FullType specifiedType: FullType.unspecified}) => - fromCssColor(serialized as String); -} - -Map serializedData(DocumentSnapshot doc) => { - ...mapFromFirestore(doc.data() as Map), - kDocumentReferenceField: doc.reference - }; - Map mapFromFirestore(Map data) => mergeNestedFields(data) .where((k, _) => k != FirestoreUtilData.name) @@ -185,6 +77,14 @@ Map mapToFirestore(Map data) => if (value is Iterable && value.isNotEmpty && value.first is LatLng) { value = value.map((v) => (v as LatLng).toGeoPoint()).toList(); } + // Handle Color + if (value is Color) { + value = value.toCssString(); + } + // Handle list of Color + if (value is Iterable && value.isNotEmpty && value.first is Color) { + value = value.map((v) => (v as Color).toCssString()).toList(); + } // Handle nested data. if (value is Map) { value = mapFromFirestore(value as Map); diff --git a/lib/backend/schema/util/schema_util.dart b/lib/backend/schema/util/schema_util.dart new file mode 100644 index 0000000..a4cd871 --- /dev/null +++ b/lib/backend/schema/util/schema_util.dart @@ -0,0 +1,102 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:from_css_color/from_css_color.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +export 'package:collection/collection.dart' show ListEquality; +export 'package:flutter/material.dart' show Color, Colors; +export 'package:from_css_color/from_css_color.dart'; + +typedef StructBuilder = T Function(Map data); + +abstract class BaseStruct { + Map toSerializableMap(); + String serialize() => json.encode(toSerializableMap()); +} + +dynamic deserializeStructParam( + dynamic param, + ParamType paramType, + bool isList, { + required StructBuilder structBuilder, +}) { + if (param == null) { + return null; + } else if (isList) { + final paramValues; + try { + paramValues = param is Iterable ? param : json.decode(param); + } catch (e) { + return null; + } + if (paramValues is! Iterable) { + return null; + } + return paramValues + .map((e) => deserializeStructParam(e, paramType, false, + structBuilder: structBuilder)) + .toList(); + } else if (param is Map) { + return structBuilder(param); + } else { + return deserializeParam( + param, + paramType, + isList, + structBuilder: structBuilder, + ); + } +} + +List? getStructList( + dynamic value, + StructBuilder structBuilder, +) => + value is! List + ? null + : value + .where((e) => e is Map) + .map((e) => structBuilder(e as Map)) + .toList(); + +Color? getSchemaColor(dynamic value) => value is String + ? fromCssColor(value) + : value is Color + ? value + : null; + +List? getColorsList(dynamic value) => + value is! List ? null : value.map(getSchemaColor).withoutNulls; + +List? getDataList(dynamic value) => + value is! List ? null : value.map((e) => castToType(e)!).toList(); + +T? castToType(dynamic value) { + if (value == null) { + return null; + } + switch (T) { + case double: + // Doubles may be stored as ints in some cases. + return value.toDouble() as T; + case int: + // Likewise, ints may be stored as doubles. If this is the case + // (i.e. no decimal value), return the value as an int. + if (value is num && value.toInt() == value) { + return value.toInt() as T; + } + break; + default: + break; + } + return value as T; +} + +extension MapDataExtensions on Map { + Map get withoutNulls => Map.fromEntries( + entries + .where((e) => e.value != null) + .map((e) => MapEntry(e.key, e.value!)), + ); +} diff --git a/lib/pages/test_page/test_page_model.dart b/lib/client_pages/client_donation/client_donation_model.dart similarity index 59% rename from lib/pages/test_page/test_page_model.dart rename to lib/client_pages/client_donation/client_donation_model.dart index b25e7d4..fe9b2a1 100644 --- a/lib/pages/test_page/test_page_model.dart +++ b/lib/client_pages/client_donation/client_donation_model.dart @@ -1,18 +1,25 @@ import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; -import '/custom_code/widgets/index.dart' as custom_widgets; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; -class TestPageModel extends FlutterFlowModel { +class ClientDonationModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + /// Initialization and disposal methods. void initState(BuildContext context) {} - void dispose() {} + void dispose() { + unfocusNode.dispose(); + } - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/pages/test_page/test_page_widget.dart b/lib/client_pages/client_donation/client_donation_widget.dart similarity index 65% rename from lib/pages/test_page/test_page_widget.dart rename to lib/client_pages/client_donation/client_donation_widget.dart index 80d3b51..d5cf8bf 100644 --- a/lib/pages/test_page/test_page_widget.dart +++ b/lib/client_pages/client_donation/client_donation_widget.dart @@ -1,30 +1,29 @@ import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; -import '/custom_code/widgets/index.dart' as custom_widgets; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; -import 'test_page_model.dart'; -export 'test_page_model.dart'; +import 'client_donation_model.dart'; +export 'client_donation_model.dart'; -class TestPageWidget extends StatefulWidget { - const TestPageWidget({Key? key}) : super(key: key); +class ClientDonationWidget extends StatefulWidget { + const ClientDonationWidget({Key? key}) : super(key: key); @override - _TestPageWidgetState createState() => _TestPageWidgetState(); + _ClientDonationWidgetState createState() => _ClientDonationWidgetState(); } -class _TestPageWidgetState extends State { - late TestPageModel _model; +class _ClientDonationWidgetState extends State { + late ClientDonationModel _model; final scaffoldKey = GlobalKey(); - final _unfocusNode = FocusNode(); @override void initState() { super.initState(); - _model = createModel(context, () => TestPageModel()); + _model = createModel(context, () => ClientDonationModel()); WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); } @@ -33,7 +32,6 @@ class _TestPageWidgetState extends State { void dispose() { _model.dispose(); - _unfocusNode.dispose(); super.dispose(); } @@ -42,7 +40,7 @@ class _TestPageWidgetState extends State { context.watch(); return GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), child: Scaffold( key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, @@ -64,23 +62,26 @@ class _TestPageWidgetState extends State { }, ), title: Text( - 'Test Page', + 'Page Title', style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, color: FlutterFlowTheme.of(context).secondaryBackground, fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), ), ), actions: [], centerTitle: true, - elevation: 2.0, + elevation: 0.0, ), body: SafeArea( + top: true, child: Container( width: double.infinity, height: double.infinity, decoration: BoxDecoration( - color: Color(0xFF2978A0), + color: FlutterFlowTheme.of(context).primaryBackground, ), child: Column( mainAxisSize: MainAxisSize.max, @@ -89,16 +90,7 @@ class _TestPageWidgetState extends State { Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: MediaQuery.of(context).size.width * 1.0, - height: MediaQuery.of(context).size.height * 1.0, - child: custom_widgets.CustomCreditCardWidget( - width: MediaQuery.of(context).size.width * 1.0, - height: MediaQuery.of(context).size.height * 1.0, - ), - ), - ], + children: [], ), ], ), diff --git a/lib/components/amount_button_model.dart b/lib/components/amount_button/amount_button_model.dart similarity index 88% rename from lib/components/amount_button_model.dart rename to lib/components/amount_button/amount_button_model.dart index 492c13f..8b404a2 100644 --- a/lib/components/amount_button_model.dart +++ b/lib/components/amount_button/amount_button_model.dart @@ -5,6 +5,7 @@ import '/flutter_flow/flutter_flow_widgets.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; @@ -19,6 +20,7 @@ class AmountButtonModel extends FlutterFlowModel { void dispose() {} - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/components/amount_button/amount_button_widget.dart b/lib/components/amount_button/amount_button_widget.dart new file mode 100644 index 0000000..514aa6c --- /dev/null +++ b/lib/components/amount_button/amount_button_widget.dart @@ -0,0 +1,147 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'amount_button_model.dart'; +export 'amount_button_model.dart'; + +class AmountButtonWidget extends StatefulWidget { + const AmountButtonWidget({ + Key? key, + int? amountIndex, + }) : this.amountIndex = amountIndex ?? 0, + super(key: key); + + final int amountIndex; + + @override + _AmountButtonWidgetState createState() => _AmountButtonWidgetState(); +} + +class _AmountButtonWidgetState extends State + with TickerProviderStateMixin { + late AmountButtonModel _model; + + final animationsMap = { + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(1.0, 1.0), + end: Offset(1.0, 1.0), + ), + ], + ), + 'buttonOnActionTriggerAnimation': AnimationInfo( + trigger: AnimationTrigger.onActionTrigger, + applyInitialState: true, + effects: [ + RotateEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + ], + ), + }; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => AmountButtonModel()); + + setupAnimations( + animationsMap.values.where((anim) => + anim.trigger == AnimationTrigger.onActionTrigger || + !anim.applyInitialState), + this, + ); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + ), + child: FFButtonWidget( + onPressed: () async { + // Set the donationAmount + _model.updatePage(() { + FFAppState().donationAmount = + FFAppState().donationAmounts[widget.amountIndex]; + FFAppState().isCustomAmount = false; + }); + // Spin the Button + if (animationsMap['buttonOnActionTriggerAnimation'] != null) { + await animationsMap['buttonOnActionTriggerAnimation']! + .controller + .forward(from: 0.0); + } + }, + text: formatNumber( + FFAppState().donationAmounts[widget.amountIndex], + formatType: FormatType.decimal, + decimalType: DecimalType.periodDecimal, + currency: '', + ), + options: FFButtonOptions( + width: 100.0, + height: 100.0, + padding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: !FFAppState().isCustomAmount && + (FFAppState().donationAmounts[widget.amountIndex] == + FFAppState().donationAmount) + ? FlutterFlowTheme.of(context).tertiary + : Color(0xFFA4BDED), + textStyle: FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: FlutterFlowTheme.of(context).titleSmallFamily, + color: Colors.white, + fontSize: 25.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context).titleSmallFamily), + ), + elevation: 0.0, + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ).animateOnActionTrigger( + animationsMap['buttonOnActionTriggerAnimation']!, + ), + ).animateOnPageLoad(animationsMap['containerOnPageLoadAnimation']!); + } +} diff --git a/lib/components/amount_button_widget.dart b/lib/components/amount_button_widget.dart deleted file mode 100644 index 1b9e9ef..0000000 --- a/lib/components/amount_button_widget.dart +++ /dev/null @@ -1,125 +0,0 @@ -import '/flutter_flow/flutter_flow_animations.dart'; -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import '/flutter_flow/flutter_flow_widgets.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:flutter_animate/flutter_animate.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:provider/provider.dart'; -import 'amount_button_model.dart'; -export 'amount_button_model.dart'; - -class AmountButtonWidget extends StatefulWidget { - const AmountButtonWidget({ - Key? key, - int? amountIndex, - }) : this.amountIndex = amountIndex ?? 0, - super(key: key); - - final int amountIndex; - - @override - _AmountButtonWidgetState createState() => _AmountButtonWidgetState(); -} - -class _AmountButtonWidgetState extends State - with TickerProviderStateMixin { - late AmountButtonModel _model; - - final animationsMap = { - 'buttonOnActionTriggerAnimation': AnimationInfo( - trigger: AnimationTrigger.onActionTrigger, - applyInitialState: true, - effects: [ - RotateEffect( - curve: Curves.easeInOut, - delay: 0.ms, - duration: 600.ms, - begin: 0.0, - end: 1.0, - ), - ], - ), - }; - - @override - void setState(VoidCallback callback) { - super.setState(callback); - _model.onUpdate(); - } - - @override - void initState() { - super.initState(); - _model = createModel(context, () => AmountButtonModel()); - - setupAnimations( - animationsMap.values.where((anim) => - anim.trigger == AnimationTrigger.onActionTrigger || - !anim.applyInitialState), - this, - ); - - WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); - } - - @override - void dispose() { - _model.maybeDispose(); - - super.dispose(); - } - - @override - Widget build(BuildContext context) { - context.watch(); - - return FFButtonWidget( - onPressed: () async { - // Set the donationAmount - _model.updatePage(() { - FFAppState().donationAmount = - FFAppState().donationAmounts[widget.amountIndex]; - FFAppState().isCustomAmount = false; - }); - // Spin the Button - if (animationsMap['buttonOnActionTriggerAnimation'] != null) { - await animationsMap['buttonOnActionTriggerAnimation']! - .controller - .forward(from: 0.0); - } - }, - text: formatNumber( - FFAppState().donationAmounts[widget.amountIndex], - formatType: FormatType.decimal, - decimalType: DecimalType.periodDecimal, - currency: '', - ), - options: FFButtonOptions( - width: double.infinity, - height: double.infinity, - padding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - iconPadding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - color: !FFAppState().isCustomAmount && - (FFAppState().donationAmounts[widget.amountIndex] == - FFAppState().donationAmount) - ? FlutterFlowTheme.of(context).tertiary - : Color(0xFFA4BDED), - textStyle: FlutterFlowTheme.of(context).titleSmall.override( - fontFamily: 'Poppins', - color: Colors.white, - fontSize: 25.0, - ), - elevation: 2.0, - borderSide: BorderSide( - color: Colors.transparent, - width: 1.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ).animateOnActionTrigger( - animationsMap['buttonOnActionTriggerAnimation']!, - ); - } -} diff --git a/lib/components/get_donation_amount_model.dart b/lib/components/get_donation_amount/get_donation_amount_model.dart similarity index 92% rename from lib/components/get_donation_amount_model.dart rename to lib/components/get_donation_amount/get_donation_amount_model.dart index 750c0ad..e92fd71 100644 --- a/lib/components/get_donation_amount_model.dart +++ b/lib/components/get_donation_amount/get_donation_amount_model.dart @@ -1,4 +1,4 @@ -import '/components/amount_button_widget.dart'; +import '/components/amount_button/amount_button_widget.dart'; import '/flutter_flow/flutter_flow_animations.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; @@ -8,6 +8,7 @@ import 'package:easy_debounce/easy_debounce.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; @@ -47,6 +48,7 @@ class GetDonationAmountModel extends FlutterFlowModel { amountButtonModel5.dispose(); } - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/components/get_donation_amount_widget.dart b/lib/components/get_donation_amount/get_donation_amount_widget.dart similarity index 88% rename from lib/components/get_donation_amount_widget.dart rename to lib/components/get_donation_amount/get_donation_amount_widget.dart index fbc110d..e0d389f 100644 --- a/lib/components/get_donation_amount_widget.dart +++ b/lib/components/get_donation_amount/get_donation_amount_widget.dart @@ -1,4 +1,4 @@ -import '/components/amount_button_widget.dart'; +import '/components/amount_button/amount_button_widget.dart'; import '/flutter_flow/flutter_flow_animations.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; @@ -8,6 +8,7 @@ import 'package:easy_debounce/easy_debounce.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'get_donation_amount_model.dart'; @@ -109,14 +110,19 @@ class _GetDonationAmountWidgetState extends State style: FlutterFlowTheme.of(context) .bodyMedium .override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, color: FlutterFlowTheme.of(context).tertiary, fontSize: 35.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .bodyMediumFamily), ), ), ), Container( width: 200.0, + decoration: BoxDecoration(), child: Visibility( visible: FFAppState().isCustomAmount, child: Padding( @@ -141,10 +147,15 @@ class _GetDonationAmountWidgetState extends State hintStyle: FlutterFlowTheme.of(context) .bodySmall .override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context) + .bodySmallFamily, color: FlutterFlowTheme.of(context).tertiary, fontSize: 35.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), ), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( @@ -192,10 +203,15 @@ class _GetDonationAmountWidgetState extends State style: FlutterFlowTheme.of(context) .bodyMedium .override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, color: FlutterFlowTheme.of(context).tertiary, fontSize: 35.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), ), textAlign: TextAlign.center, keyboardType: TextInputType.number, @@ -208,10 +224,14 @@ class _GetDonationAmountWidgetState extends State Text( 'Donation Amount', style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: 'Poppins', + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, color: FlutterFlowTheme.of(context) .secondaryBackground, fontSize: 12.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), ), ), ], @@ -325,9 +345,14 @@ class _GetDonationAmountWidgetState extends State textStyle: FlutterFlowTheme.of(context) .titleSmall .override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context) + .titleSmallFamily, color: Colors.white, fontSize: 25.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), ), elevation: 2.0, borderSide: BorderSide( diff --git a/lib/components/heading2/heading2_model.dart b/lib/components/heading2/heading2_model.dart new file mode 100644 index 0000000..337d7fa --- /dev/null +++ b/lib/components/heading2/heading2_model.dart @@ -0,0 +1,21 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class Heading2Model extends FlutterFlowModel { + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() {} + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/components/heading2/heading2_widget.dart b/lib/components/heading2/heading2_widget.dart new file mode 100644 index 0000000..44cc38a --- /dev/null +++ b/lib/components/heading2/heading2_widget.dart @@ -0,0 +1,82 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'heading2_model.dart'; +export 'heading2_model.dart'; + +class Heading2Widget extends StatefulWidget { + const Heading2Widget({ + Key? key, + required this.headingText, + }) : super(key: key); + + final String? headingText; + + @override + _Heading2WidgetState createState() => _Heading2WidgetState(); +} + +class _Heading2WidgetState extends State + with TickerProviderStateMixin { + late Heading2Model _model; + + final animationsMap = { + 'rowOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + FadeEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + ], + ), + }; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => Heading2Model()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 16.0, 0.0, 16.0), + child: Text( + widget.headingText!, + style: FlutterFlowTheme.of(context).titleLarge, + ), + ), + ], + ).animateOnPageLoad(animationsMap['rowOnPageLoadAnimation']!); + } +} diff --git a/lib/components/navi_btn_grey/navi_btn_grey_model.dart b/lib/components/navi_btn_grey/navi_btn_grey_model.dart new file mode 100644 index 0000000..b392105 --- /dev/null +++ b/lib/components/navi_btn_grey/navi_btn_grey_model.dart @@ -0,0 +1,21 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class NaviBtnGreyModel extends FlutterFlowModel { + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() {} + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/components/navi_btn_grey/navi_btn_grey_widget.dart b/lib/components/navi_btn_grey/navi_btn_grey_widget.dart new file mode 100644 index 0000000..e4b4440 --- /dev/null +++ b/lib/components/navi_btn_grey/navi_btn_grey_widget.dart @@ -0,0 +1,132 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'navi_btn_grey_model.dart'; +export 'navi_btn_grey_model.dart'; + +class NaviBtnGreyWidget extends StatefulWidget { + const NaviBtnGreyWidget({ + Key? key, + String? buttonText, + required this.buttonIcon, + }) : this.buttonText = buttonText ?? 'Button Text', + super(key: key); + + final String buttonText; + final Widget? buttonIcon; + + @override + _NaviBtnGreyWidgetState createState() => _NaviBtnGreyWidgetState(); +} + +class _NaviBtnGreyWidgetState extends State + with TickerProviderStateMixin { + late NaviBtnGreyModel _model; + + final animationsMap = { + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + FadeEffect( + curve: Curves.easeIn, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeIn, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => NaviBtnGreyModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 12.0), + child: Container( + width: double.infinity, + height: 60.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).accent4, + borderRadius: BorderRadius.circular(12.0), + shape: BoxShape.rectangle, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(8.0, 8.0, 8.0, 8.0), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB(10.0, 0.0, 0.0, 0.0), + child: widget.buttonIcon!, + ), + Expanded( + child: Align( + alignment: AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB(12.0, 0.0, 0.0, 0.0), + child: Text( + widget.buttonText, + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context).bodyLarge.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).secondaryText, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyLargeFamily), + ), + ), + ), + ), + ), + Align( + alignment: AlignmentDirectional(0.9, 0.0), + child: Icon( + Icons.arrow_forward_ios, + color: FlutterFlowTheme.of(context).secondaryText, + size: 18.0, + ), + ), + ], + ), + ), + ).animateOnPageLoad(animationsMap['containerOnPageLoadAnimation']!), + ); + } +} diff --git a/lib/components/row_logo_and_name_model.dart b/lib/components/row_logo_and_name/row_logo_and_name_model.dart similarity index 82% rename from lib/components/row_logo_and_name_model.dart rename to lib/components/row_logo_and_name/row_logo_and_name_model.dart index d3669c2..6bf2216 100644 --- a/lib/components/row_logo_and_name_model.dart +++ b/lib/components/row_logo_and_name/row_logo_and_name_model.dart @@ -1,6 +1,7 @@ import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; @@ -11,6 +12,7 @@ class RowLogoAndNameModel extends FlutterFlowModel { void dispose() {} - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/components/row_logo_and_name_widget.dart b/lib/components/row_logo_and_name/row_logo_and_name_widget.dart similarity index 86% rename from lib/components/row_logo_and_name_widget.dart rename to lib/components/row_logo_and_name/row_logo_and_name_widget.dart index f117a20..801f0bb 100644 --- a/lib/components/row_logo_and_name_widget.dart +++ b/lib/components/row_logo_and_name/row_logo_and_name_widget.dart @@ -1,6 +1,7 @@ import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'row_logo_and_name_model.dart'; @@ -57,9 +58,11 @@ class _RowLogoAndNameWidgetState extends State { Text( 'pennies from heaven', style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, color: FlutterFlowTheme.of(context).primary, fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), ), ), ], diff --git a/lib/components/test_components_model.dart b/lib/components/test_components/test_components_model.dart similarity index 82% rename from lib/components/test_components_model.dart rename to lib/components/test_components/test_components_model.dart index 6c62e97..18b17ce 100644 --- a/lib/components/test_components_model.dart +++ b/lib/components/test_components/test_components_model.dart @@ -1,6 +1,7 @@ import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; @@ -11,6 +12,7 @@ class TestComponentsModel extends FlutterFlowModel { void dispose() {} - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/components/test_components_widget.dart b/lib/components/test_components/test_components_widget.dart similarity index 95% rename from lib/components/test_components_widget.dart rename to lib/components/test_components/test_components_widget.dart index 548b911..a1b8daa 100644 --- a/lib/components/test_components_widget.dart +++ b/lib/components/test_components/test_components_widget.dart @@ -1,6 +1,7 @@ import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'test_components_model.dart'; diff --git a/lib/pages/ghost_image_page/ghost_image_page_model.dart b/lib/components/text_list_empty/text_list_empty_model.dart similarity index 72% rename from lib/pages/ghost_image_page/ghost_image_page_model.dart rename to lib/components/text_list_empty/text_list_empty_model.dart index 115fe1b..a889bd2 100644 --- a/lib/pages/ghost_image_page/ghost_image_page_model.dart +++ b/lib/components/text_list_empty/text_list_empty_model.dart @@ -1,17 +1,18 @@ -import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; -class GhostImagePageModel extends FlutterFlowModel { +class TextListEmptyModel extends FlutterFlowModel { /// Initialization and disposal methods. void initState(BuildContext context) {} void dispose() {} - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/components/text_list_empty/text_list_empty_widget.dart b/lib/components/text_list_empty/text_list_empty_widget.dart new file mode 100644 index 0000000..143efb5 --- /dev/null +++ b/lib/components/text_list_empty/text_list_empty_widget.dart @@ -0,0 +1,59 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'text_list_empty_model.dart'; +export 'text_list_empty_model.dart'; + +class TextListEmptyWidget extends StatefulWidget { + const TextListEmptyWidget({ + Key? key, + String? listEmptyMessage, + }) : this.listEmptyMessage = listEmptyMessage ?? 'No Items', + super(key: key); + + final String listEmptyMessage; + + @override + _TextListEmptyWidgetState createState() => _TextListEmptyWidgetState(); +} + +class _TextListEmptyWidgetState extends State { + late TextListEmptyModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => TextListEmptyModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Align( + alignment: AlignmentDirectional(0.0, 0.0), + child: Text( + widget.listEmptyMessage, + style: FlutterFlowTheme.of(context).titleMedium, + ), + ); + } +} diff --git a/lib/pages/account/account_model.dart b/lib/components/user_photo/user_photo_model.dart similarity index 73% rename from lib/pages/account/account_model.dart rename to lib/components/user_photo/user_photo_model.dart index 6ac1083..e7b8eb2 100644 --- a/lib/pages/account/account_model.dart +++ b/lib/components/user_photo/user_photo_model.dart @@ -1,17 +1,18 @@ -import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; -class AccountModel extends FlutterFlowModel { +class UserPhotoModel extends FlutterFlowModel { /// Initialization and disposal methods. void initState(BuildContext context) {} void dispose() {} - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/components/user_photo/user_photo_widget.dart b/lib/components/user_photo/user_photo_widget.dart new file mode 100644 index 0000000..bebc4d5 --- /dev/null +++ b/lib/components/user_photo/user_photo_widget.dart @@ -0,0 +1,81 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'user_photo_model.dart'; +export 'user_photo_model.dart'; + +class UserPhotoWidget extends StatefulWidget { + const UserPhotoWidget({ + Key? key, + this.parameter1, + this.parameter2, + }) : super(key: key); + + final bool? parameter1; + final String? parameter2; + + @override + _UserPhotoWidgetState createState() => _UserPhotoWidgetState(); +} + +class _UserPhotoWidgetState extends State { + late UserPhotoModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => UserPhotoModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Container( + width: double.infinity, + height: double.infinity, + child: Stack( + children: [ + if (widget.parameter1 ?? true) + ClipRRect( + borderRadius: BorderRadius.circular(50.0), + child: Image.network( + widget.parameter2!, + width: 100.0, + height: MediaQuery.sizeOf(context).height * 100.0, + fit: BoxFit.cover, + ), + ), + if (widget.parameter1 == false) + ClipRRect( + borderRadius: BorderRadius.circular(50.0), + child: Image.asset( + 'assets/images/User_Placeholder.jpg', + width: double.infinity, + height: double.infinity, + fit: BoxFit.cover, + ), + ), + ], + ), + ); + } +} diff --git a/lib/custom_code/widgets/credit_card_icon_widget.dart b/lib/custom_code/widgets/credit_card_icon_widget.dart new file mode 100644 index 0000000..4986bbd --- /dev/null +++ b/lib/custom_code/widgets/credit_card_icon_widget.dart @@ -0,0 +1,93 @@ +// Automatic FlutterFlow imports +import '/backend/backend.dart'; +import '/backend/schema/structs/index.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom widgets +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom widget code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class CreditCardIconWidget extends StatefulWidget { + const CreditCardIconWidget({ + Key? key, + this.width, + this.height, + this.cardSystem, + }) : super(key: key); + + final double? width; + final double? height; + final String? cardSystem; + + @override + _CreditCardIconWidgetState createState() => _CreditCardIconWidgetState(); +} + +class _CreditCardIconWidgetState extends State { + late Widget _iconWidget; + @override + Widget build(BuildContext context) { + switch (widget.cardSystem) { + case null: + _iconWidget = FaIcon(null); + break; + + case "Amex": + _iconWidget = FaIcon(FontAwesomeIcons.ccAmex); + break; + + case "Visa": + // Card Prefix(es): 4 + _iconWidget = FaIcon(FontAwesomeIcons.ccVisa); + break; + + case "Mastercard": + // Card Prefix(es): 5 222 2720 + _iconWidget = FaIcon(FontAwesomeIcons.ccMastercard); + break; + + case "DinersClub": + // Card Prefix(es): 14 36 54 30 + _iconWidget = FaIcon(FontAwesomeIcons.ccDinersClub); + break; + + case "JCB": + // Card Prefix(es): 35 + _iconWidget = FaIcon(FontAwesomeIcons.ccJcb); + break; + + case "Discover": + // Card Prefix(es): 60 + _iconWidget = FaIcon(FontAwesomeIcons.ccDiscover); + break; + +/* + case "Maestro": + // Card Prefix(es): 67 + _iconWidget = NO FONT AWESOME ICON + break; + + case "MIR": + // Card Prefix(es): 2200 2204 + _iconWidget = NO FONT AWESOME ICON + break; + + case "UnionPay": + // Card Prefix(es): 62 + _iconWidget = NO FONT AWESOME ICON + break; +*/ + default: + _iconWidget = FaIcon(FontAwesomeIcons.creditCard); + } + return Align( + alignment: Alignment(-0.5, 0.0), + widthFactor: 1.2, + heightFactor: 1.2, + child: _iconWidget); + } +} diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart deleted file mode 100644 index 364d935..0000000 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ /dev/null @@ -1,282 +0,0 @@ -// Automatic FlutterFlow imports -import '/backend/backend.dart'; -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import 'index.dart'; // Imports other custom widgets -import '/flutter_flow/custom_functions.dart'; // Imports custom functions -import 'package:flutter/material.dart'; -// Begin custom widget code -// DO NOT REMOVE OR MODIFY THE CODE ABOVE! - -import 'package:flutter_credit_card/credit_card_brand.dart'; -import 'package:flutter_credit_card/flutter_credit_card.dart'; - -import 'dart:ui'; - -class AppColors { - AppColors._(); - - static const Color cardBgColor = Color(0xffAA3636); - // static const Color cardBgColor = Color(0xff363636); - static const Color colorB58D67 = Color(0xffB58D67); - static const Color colorE5D1B2 = Color(0xffE5D1B2); - static const Color colorF9EED2 = Color(0xffF9EED2); - static const Color colorFFFFFD = Color(0xffFFFFFD); -} - -// Version 1 -class CustomCreditCardWidget extends StatefulWidget { - const CustomCreditCardWidget({ - Key? key, - this.width, - this.height, - }) : super(key: key); - - final double? width; - final double? height; - - @override - _CustomCreditCardWidgetState createState() => _CustomCreditCardWidgetState(); -} - -class _CustomCreditCardWidgetState extends State { - String cardNumber = ''; - String expiryDate = ''; - String cardHolderName = ''; - String cvvCode = ''; - bool isCvvFocused = false; - bool useGlassMorphism = true; - bool useBackgroundImage = true; - OutlineInputBorder? border; - final GlobalKey formKey = GlobalKey(); - - @override - void initState() { - border = OutlineInputBorder( - borderSide: BorderSide( - color: Colors.grey.withOpacity(0.7), - width: 2.0, - ), - ); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Container( - width: widget.width, - height: widget.height, - decoration: const BoxDecoration( - image: DecorationImage( - image: ExactAssetImage('assets/images/bg.png'), - fit: BoxFit.fill, - ), - color: Colors.black, - ), - // child: SafeArea( - child: Column( - children: [ - const SizedBox( - height: 30, - ), - CreditCardWidget( - glassmorphismConfig: - useGlassMorphism ? Glassmorphism.defaultConfig() : null, - cardNumber: cardNumber, - expiryDate: expiryDate, - cardHolderName: cardHolderName, - cvvCode: cvvCode, - bankName: 'Axis Bank', - frontCardBorder: - !useGlassMorphism ? Border.all(color: Colors.grey) : null, - backCardBorder: - !useGlassMorphism ? Border.all(color: Colors.grey) : null, - showBackView: isCvvFocused, - obscureCardNumber: false, - obscureCardCvv: false, - isHolderNameVisible: true, - cardBgColor: AppColors.cardBgColor, - backgroundImage: - useBackgroundImage ? 'assets/images/card_bg.png' : null, - isSwipeGestureEnabled: true, - onCreditCardWidgetChange: (CreditCardBrand creditCardBrand) {}, - customCardTypeIcons: [ - CustomCardTypeIcon( - cardType: CardType.mastercard, - cardImage: Image.asset( - 'assets/images/mastercard.png', - height: 48, - width: 48, - ), - ), - ], - ), - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - CreditCardForm( - formKey: formKey, - obscureCvv: true, - obscureNumber: true, - cardNumber: cardNumber, - cvvCode: cvvCode, - isHolderNameVisible: true, - isCardNumberVisible: true, - isExpiryDateVisible: true, - cardHolderName: cardHolderName, - expiryDate: expiryDate, - themeColor: Colors.blue, - textColor: Colors.white, - cardNumberDecoration: InputDecoration( - labelText: 'Number', - hintText: 'XXXX XXXX XXXX XXXX', - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - ), - expiryDateDecoration: InputDecoration( - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - labelText: 'Expiry Date', - hintText: 'XX/XX', - ), - cvvCodeDecoration: InputDecoration( - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - labelText: 'CVV', - hintText: 'XXX', - ), - cardHolderDecoration: InputDecoration( - hintStyle: const TextStyle(color: Colors.white), - labelStyle: const TextStyle(color: Colors.white), - focusedBorder: border, - enabledBorder: border, - labelText: 'Card Holder', - ), - onCreditCardModelChange: onCreditCardModelChange, - ), - const SizedBox( - height: 20, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Glassmorphism', - style: TextStyle( - color: Colors.white, - fontSize: 18, - ), - ), - const Spacer(), - Switch( - value: useGlassMorphism, - inactiveTrackColor: Colors.grey, - activeColor: Colors.white, - activeTrackColor: AppColors.colorE5D1B2, - onChanged: (bool value) => setState(() { - useGlassMorphism = value; - }), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Card Image', - style: TextStyle( - color: Colors.white, - fontSize: 18, - ), - ), - const Spacer(), - Switch( - value: useBackgroundImage, - inactiveTrackColor: Colors.grey, - activeColor: Colors.white, - activeTrackColor: AppColors.colorE5D1B2, - onChanged: (bool value) => setState(() { - useBackgroundImage = value; - }), - ), - ], - ), - ), - const SizedBox( - height: 20, - ), - GestureDetector( - onTap: _onValidate, - child: Container( - margin: const EdgeInsets.symmetric( - horizontal: 16, vertical: 8), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - AppColors.colorB58D67, - AppColors.colorB58D67, - AppColors.colorE5D1B2, - AppColors.colorF9EED2, - AppColors.colorFFFFFD, - AppColors.colorF9EED2, - AppColors.colorB58D67, - ], - begin: Alignment(-1, -4), - end: Alignment(1, 4), - ), - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(vertical: 15), - width: double.infinity, - alignment: Alignment.center, - child: const Text( - 'Validate', - style: TextStyle( - color: Colors.black, - fontFamily: 'halter', - fontSize: 14, - package: 'flutter_credit_card', - ), - ), - ), - ), - ], - ), - ), - ), - ], - ), - // ), - ); - } - - void _onValidate() { - if (formKey.currentState!.validate()) { - print('valid!'); - } else { - print('invalid!'); - } - } - - void onCreditCardModelChange(CreditCardModel? creditCardModel) { - setState(() { - cardNumber = creditCardModel!.cardNumber; - expiryDate = creditCardModel.expiryDate; - cardHolderName = creditCardModel.cardHolderName; - cvvCode = creditCardModel.cvvCode; - isCvvFocused = creditCardModel.isCvvFocused; - }); - } -} diff --git a/lib/custom_code/widgets/custom_image_widget.dart b/lib/custom_code/widgets/custom_image_widget.dart deleted file mode 100644 index 0b940dd..0000000 --- a/lib/custom_code/widgets/custom_image_widget.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Automatic FlutterFlow imports -import '/backend/backend.dart'; -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import 'index.dart'; // Imports other custom widgets -import '/flutter_flow/custom_functions.dart'; // Imports custom functions -import 'package:flutter/material.dart'; -// Begin custom widget code -// DO NOT REMOVE OR MODIFY THE CODE ABOVE! - -class CustomImageWidget extends StatefulWidget { - const CustomImageWidget({ - Key? key, - this.width, - this.height, - }) : super(key: key); - - final double? width; - final double? height; - - @override - _CustomImageWidgetState createState() => _CustomImageWidgetState(); -} - -class _CustomImageWidgetState extends State { - @override - Widget build(BuildContext context) { - return Container( - width: 100, - height: 100, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage("images/mastercard.png"), - fit: BoxFit.cover, - ), - ), - ); - } -} diff --git a/lib/custom_code/widgets/get_c_c_n_widget.dart b/lib/custom_code/widgets/get_c_c_n_widget.dart new file mode 100644 index 0000000..759de66 --- /dev/null +++ b/lib/custom_code/widgets/get_c_c_n_widget.dart @@ -0,0 +1,538 @@ +// Automatic FlutterFlow imports +import '/backend/backend.dart'; +import '/backend/schema/structs/index.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom widgets +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom widget code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +// This widget requires the following App State Variables: +// String CCHolderName '' +// String CCNumber '' +// String CCExpiryDate '' +// String CCSecurityCode '' +// +// and the following callback Actions: +// refreshPageUI +// goToNextPage + +import 'dart:async'; + +// 🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦 Custom IMPORTS 🟦🟦🟦🟦🟦🟦🟦🟦🟦 + +import 'package:flutter/services.dart'; +import 'package:flutter_multi_formatter/flutter_multi_formatter.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +// 🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦 Custom CONSTANTS 🟦🟦🟦🟦🟦🟦🟦🟦🟦 + +enum CreditCardType { Unknown, Visa, Mastercard, Amex, Discover } + +// 🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦 Custom WIDGET 🟦🟦🟦🟦🟦🟦🟦🟦🟦 + +class GetCCNWidget extends StatefulWidget { + const GetCCNWidget({ + Key? key, + this.width, + this.height, + required saveOnly, + required this.refreshPageUI, + required this.goToNextPage, + }) : super(key: key); + + final double? width; + final double? height; + + final String cardCVCHintText = ''; + + final Future Function() refreshPageUI; + final Future Function() goToNextPage; + + final bool saveOnly = false; + + @override + _GetCCNWidgetState createState() => _GetCCNWidgetState(); +} // + +// 🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦 Custom STATE 🟦🟦🟦🟦🟦🟦🟦🟦🟦 + +class _GetCCNWidgetState extends State { + GlobalKey _formKey = GlobalKey(); + TextEditingController _textEditingControllerCCN = TextEditingController(); + CardSystemData? _cardSystemData; + + String _CCHolderName = ''; + String _CCNumber = ''; + String _CCExpiryDate = ''; + String _CCSecurityCode = ''; + + bool _CCHolderNameDirty = false; + + static const String _cardHolderNameLabelText = 'Name on Card'; + static const String _cardHolderNameHintText = 'Name on Card'; + + static const String _cardNumberLabelText = 'Card Number'; + static const String _cardNumberHintText = '0000 0000 0000 0000'; + + static const String _cardExpiryDateLabelText = 'Expiry Date'; + static const String _cardExpiryDateHintText = 'MM/DD'; + + static const String _cardCVCLabelText = 'Security Code'; + + static const double _formFieldPadding = 20.0; + + CreditCardType getCreditCardType(String cardNumber) { + if (RegExp(r'4[0-9]{12}(?:[0-9]{3})?').hasMatch(cardNumber)) { + return CreditCardType.Visa; + } else if (RegExp(r'^5[1-5][0-9]{14}$').hasMatch(cardNumber)) { + return CreditCardType.Mastercard; + } else if (RegExp(r'^3[47][0-9]{13}$').hasMatch(cardNumber)) { + return CreditCardType.Amex; + } else if (RegExp(r'^6(?:011|5[0-9]{2})[0-9]{12}$').hasMatch(cardNumber)) { + return CreditCardType.Discover; + } else { + return CreditCardType.Unknown; + } + } + + bool _validateCreditCardNumber(String? input) { + if (input == null) { + print("PFH: Null input"); + return true; + } + // Strip out the blank spaces + + input = input.replaceAll(RegExp(r'\s+'), ''); + + // Determine credit card type + CreditCardType cardType = getCreditCardType(input); + if (cardType == CreditCardType.Unknown) { + return false; + } + + // Get the valid number of digits for the given card type + + int requiredLength = 0; + + switch (cardType) { + case CreditCardType.Visa: + requiredLength = 16; + break; + + case CreditCardType.Mastercard: + requiredLength = 16; + break; + + case CreditCardType.Amex: + requiredLength = 15; + break; + + case CreditCardType.Discover: + requiredLength = 16; + break; + + case CreditCardType.Unknown: + return false; + } + + // Credit Card Number = required length? + + if (input.length != requiredLength) { + return false; + } + + // Input consists of only digits? + + if (!RegExp(r'^\d+$').hasMatch(input)) { + return false; + } + + // Run Luhn checksum algorithm + + int sum = 0; + bool isSecondDigit = false; + for (int i = input.length - 1; i >= 0; i--) { + int digit = int.parse(input[i]); + if (isSecondDigit) { + digit *= 2; + if (digit > 9) { + digit -= 9; + } + } + sum += digit; + isSecondDigit = !isSecondDigit; + } + return sum % 10 != 0; + } + + @override + Widget build(BuildContext context) { + return Container( + width: MediaQuery.of(context).size.width, + height: 300, + decoration: BoxDecoration(), + child: Form( + autovalidateMode: AutovalidateMode.always, + key: _formKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ +// --------------------------------------------------------------------- +// CARD HOLDER NAME + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Expanded( + child: TextFormField( + keyboardType: TextInputType.text, + textCapitalization: TextCapitalization.characters, +// + decoration: InputDecoration( + border: OutlineInputBorder(), + + label: Text(_cardHolderNameLabelText), + + labelStyle: TextStyle( + color: FlutterFlowTheme.of(context).secondaryText, + ), + + floatingLabelStyle: TextStyle( + color: FlutterFlowTheme.of(context).tertiary), + + hintText: _cardHolderNameHintText, + + hintStyle: TextStyle( + color: FlutterFlowTheme.of(context).accent3, + ), + + errorStyle: TextStyle( + color: FlutterFlowTheme.of(context).error, + ), // Theme.of(context).colorScheme.errorContainer, + ), +// + inputFormatters: [ + MaskedInputFormatter("########################", + allowedCharMatcher: RegExp(r'[a-zA-Z -]+')), + UppercaseTextInputFormatter(), + ], + onChanged: (String? value) { + if (value == null) { + return; + } + setState(() { + _CCHolderNameDirty = true; + }); + FFAppState().CCHolderName = _CCHolderName; + widget.refreshPageUI(); + }, + + onFieldSubmitted: (String value) { + print("PFH: onFieldSubmitted ... The form was submitted"); + + setState( + () { + _CCHolderNameDirty = true; + }, + ); + }, + + validator: (String? input) { + print("PFH: validator ... The form was validated"); + + if (input == null) { + return null; + } + ; + print("PFH: _CCholderNameDirty = " + + _CCHolderNameDirty.toString()); + print("PFH: _CCholderName = " + _CCHolderName); + if (_CCHolderNameDirty && input.length == 0) { + return 'Invalid Cardholder Name'; + } + ; + return null; + }, + ), + ), + ], + ), +// --------------------------------------------------------------------- + SizedBox(height: _formFieldPadding), +// --------------------------------------------------------------------- +// CREDIT CARD NUMBER + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + children: [ + // Column children + TextFormField( + controller: _textEditingControllerCCN, + keyboardType: TextInputType.number, + decoration: InputDecoration( + suffixIcon: CreditCardIconWidget( + width: 0.0, + height: 0.0, + cardSystem: _cardSystemData?.system), + border: OutlineInputBorder(), + label: Text(_cardNumberLabelText), + labelStyle: TextStyle( + color: FlutterFlowTheme.of(context).secondaryText, + ), + floatingLabelStyle: TextStyle( + color: FlutterFlowTheme.of(context).tertiary), + hintText: _cardNumberHintText, + hintStyle: TextStyle( + color: FlutterFlowTheme.of(context).accent3, + ), + errorStyle: TextStyle( + color: FlutterFlowTheme.of(context).error, + ), + suffixIconColor: + FlutterFlowTheme.of(context).secondaryText, + ), + inputFormatters: [ + CreditCardNumberInputFormatter( + onCardSystemSelected: + (CardSystemData? cardSystemData) { + setState(() { + _cardSystemData = cardSystemData; + }); + }, + ), + ], + onChanged: (String? value) { + setState(() {}); + + if (value == null) { + return; + } + setState(() { + _CCNumber = value; + }); + FFAppState().CCNumber = _CCNumber; + widget.refreshPageUI(); + }, + validator: (String? value) { + if (value == null || value.isEmpty) { + return null; + } + + return _validateCreditCardNumber(value) + ? 'Invalid Card Number' + : null; + }, + ) + ], // Column children + ), + ), + ], + ), +// --------------------------------------------------------------------- + SizedBox(height: _formFieldPadding), +// --------------------------------------------------------------------- +// EXPIRY DATE + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: TextFormField( + keyboardType: TextInputType.number, + decoration: InputDecoration( + border: OutlineInputBorder(), + label: Text(_cardExpiryDateLabelText), + labelStyle: TextStyle( + color: FlutterFlowTheme.of(context).secondaryText, + ), + floatingLabelStyle: TextStyle( + color: FlutterFlowTheme.of(context).tertiary), + hintText: _cardExpiryDateHintText, + hintStyle: TextStyle( + color: FlutterFlowTheme.of(context).accent3, + ), + errorStyle: TextStyle( + color: FlutterFlowTheme.of(context).error, + ), + ), + inputFormatters: [ + CreditCardExpirationDateFormatter(), + ], + onChanged: (String? value) { + setState(() {}); + + if (value == null) { + return; + } + setState(() { + _CCExpiryDate = value; + }); + FFAppState().CCExpiryDate = _CCExpiryDate; + widget.refreshPageUI(); + }, + validator: (value) { + if (value == null || value.isEmpty || value.length < 5) { + return null; + } + + if (value.substring(0, 2) == "00") { + return "Invalid month"; + } + + final inputDate = value.split('/'); + if (inputDate.length != 2) { + return 'Use MM/YY format'; + } + + final inputMonth = int.tryParse(inputDate[0]); + final inputYear = int.tryParse(inputDate[1]); + + if (inputMonth == null || inputYear == null) { + return 'Use MM/YY format'; + } + + final now = DateTime.now(); + final currentMonth = now.month; + final currentYear = now.year % 100; + + final currentDate = DateTime(currentYear, currentMonth); + final inputDateObj = DateTime(inputYear, inputMonth); + + final difference = inputDateObj.difference(currentDate); + + if (difference.isNegative) { + return 'Date too early'; + } + + // Card issuers don't allow Expiry Dates more than 5 years from now. + final maxAllowedDifference = + Duration(days: 60 * 30); // 60 months * 30 days + if (difference > maxAllowedDifference) { + return 'Date more than 5 years out'; + } + return null; + }, + ), + ), +// --------------------------------------------------------------------- + SizedBox(width: _formFieldPadding), +// --------------------------------------------------------------------- +// SECURITY NUMBER + Expanded( + child: TextFormField( + keyboardType: TextInputType.number, + decoration: InputDecoration( + border: OutlineInputBorder(), + label: Text(_cardCVCLabelText), + labelStyle: TextStyle( + color: FlutterFlowTheme.of(context).secondaryText, + ), + floatingLabelStyle: TextStyle( + color: FlutterFlowTheme.of(context).tertiary), + hintText: + _cardSystemData?.system == "Amex" ? '0000' : '000', + hintStyle: TextStyle( + color: FlutterFlowTheme.of(context).accent3, + ), + errorStyle: TextStyle( + color: FlutterFlowTheme.of(context).error, + ), + ), + inputFormatters: [ + CreditCardCvcInputFormatter( + isAmericanExpress: _cardSystemData?.system == "Amex", + ), + ], + onChanged: (String? value) { + setState(() {}); + + if (value == null) { + return; + } + setState(() { + _CCSecurityCode = value; + }); + FFAppState().CCSecurityCode = _CCSecurityCode; + widget.refreshPageUI(); + }, + ), // TextFormField + ), // Expanded + ], // Row children + ), +// --------------------------------------------------------------------- + SizedBox(height: _formFieldPadding * 2), +// --------------------------------------------------------------------- + +// Pay With Credit Card Button + ElevatedButton( + child: widget.saveOnly + ? const Text( + 'Save Credit Card Details', + style: TextStyle( + fontSize: 20.0, + ), + ) + : const Text( + 'Pay with Credit Card', + style: TextStyle( + fontSize: 20.0, + ), + ), + style: ElevatedButton.styleFrom( + fixedSize: Size.fromHeight( + 44.0, + ), + elevation: 0.0, + ), + onPressed: () { + // Validate returns true if the form is valid, or false otherwise. + if (_formKey.currentState!.validate()) { + // If the form is valid, display a snackbar. In the real world, + // you'd often call a server or save the information in a database. + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Column( + children: [ + Text('Processing Data'), + Text(FFAppState().CCHolderName), + Text(FFAppState().CCNumber), + Text(FFAppState().CCExpiryDate), + Text(FFAppState().CCSecurityCode), + ], + ), + ), + ); + widget.goToNextPage(); + } else { + const SnackBar( + content: Text('Please correct payment errors')); + } + }), +// --------------------------------------------------------------------- + SizedBox(height: _formFieldPadding), +// --------------------------------------------------------------------- + ], + ), + ), + ); + } +} + +// 🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦 Custom EXTENSIONS 🟦🟦🟦🟦🟦🟦🟦🟦🟦 + +class UppercaseTextInputFormatter extends TextInputFormatter { + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, TextEditingValue newValue) { + return TextEditingValue( + text: newValue.text.toUpperCase(), + selection: newValue.selection, + ); + } +} diff --git a/lib/custom_code/widgets/index.dart b/lib/custom_code/widgets/index.dart index 5d97b04..fc12363 100644 --- a/lib/custom_code/widgets/index.dart +++ b/lib/custom_code/widgets/index.dart @@ -1,2 +1,2 @@ -export 'custom_credit_card_widget.dart' show CustomCreditCardWidget; -export 'custom_image_widget.dart' show CustomImageWidget; +export 'get_c_c_n_widget.dart' show GetCCNWidget; +export 'credit_card_icon_widget.dart' show CreditCardIconWidget; diff --git a/lib/dashboard/add_charity/add_charity_model.dart b/lib/dashboard/add_charity/add_charity_model.dart new file mode 100644 index 0000000..12f7aca --- /dev/null +++ b/lib/dashboard/add_charity/add_charity_model.dart @@ -0,0 +1,77 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; +import 'package:provider/provider.dart'; + +class AddCharityModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + final formKey = GlobalKey(); + // State field(s) for TextField_charityLegalName widget. + TextEditingController? textFieldCharityLegalNameController; + String? Function(BuildContext, String?)? + textFieldCharityLegalNameControllerValidator; + // State field(s) for TextField_charityInformalName widget. + TextEditingController? textFieldCharityInformalNameController; + String? Function(BuildContext, String?)? + textFieldCharityInformalNameControllerValidator; + // State field(s) for TextField_address widget. + TextEditingController? textFieldAddressController; + String? Function(BuildContext, String?)? textFieldAddressControllerValidator; + // State field(s) for TextField_unit widget. + TextEditingController? textFieldUnitController; + String? Function(BuildContext, String?)? textFieldUnitControllerValidator; + // State field(s) for TextField_city widget. + TextEditingController? textFieldCityController; + String? Function(BuildContext, String?)? textFieldCityControllerValidator; + // State field(s) for TextField_provinceState widget. + TextEditingController? textFieldProvinceStateController; + String? Function(BuildContext, String?)? + textFieldProvinceStateControllerValidator; + // State field(s) for TextField_country widget. + TextEditingController? textFieldCountryController; + String? Function(BuildContext, String?)? textFieldCountryControllerValidator; + // State field(s) for TextField_postalZipCode widget. + TextEditingController? textFieldPostalZipCodeController; + final textFieldPostalZipCodeMask = MaskTextInputFormatter(mask: 'A#A #A#'); + String? Function(BuildContext, String?)? + textFieldPostalZipCodeControllerValidator; + // State field(s) for TextField_charitableRegistrationNumber widget. + TextEditingController? textFieldCharitableRegistrationNumberController; + final textFieldCharitableRegistrationNumberMask = + MaskTextInputFormatter(mask: '### ### ### RR ####'); + String? Function(BuildContext, String?)? + textFieldCharitableRegistrationNumberControllerValidator; + // Stores action output result for [Backend Call - Create Document] action in Button_save widget. + CharitiesRecord? createCharityRecordResult; + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + textFieldCharityLegalNameController?.dispose(); + textFieldCharityInformalNameController?.dispose(); + textFieldAddressController?.dispose(); + textFieldUnitController?.dispose(); + textFieldCityController?.dispose(); + textFieldProvinceStateController?.dispose(); + textFieldCountryController?.dispose(); + textFieldPostalZipCodeController?.dispose(); + textFieldCharitableRegistrationNumberController?.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/dashboard/add_charity/add_charity_widget.dart b/lib/dashboard/add_charity/add_charity_widget.dart new file mode 100644 index 0000000..9acc441 --- /dev/null +++ b/lib/dashboard/add_charity/add_charity_widget.dart @@ -0,0 +1,1275 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; +import 'package:provider/provider.dart'; +import 'add_charity_model.dart'; +export 'add_charity_model.dart'; + +class AddCharityWidget extends StatefulWidget { + const AddCharityWidget({Key? key}) : super(key: key); + + @override + _AddCharityWidgetState createState() => _AddCharityWidgetState(); +} + +class _AddCharityWidgetState extends State { + late AddCharityModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => AddCharityModel()); + + _model.textFieldCharityLegalNameController ??= TextEditingController(); + _model.textFieldCharityInformalNameController ??= TextEditingController(); + _model.textFieldAddressController ??= TextEditingController(); + _model.textFieldUnitController ??= TextEditingController(); + _model.textFieldCityController ??= TextEditingController(); + _model.textFieldProvinceStateController ??= TextEditingController(); + _model.textFieldCountryController ??= TextEditingController(); + _model.textFieldPostalZipCodeController ??= TextEditingController(); + _model.textFieldCharitableRegistrationNumberController ??= + TextEditingController(); + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Add Charity', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15.0, 0.0, 15.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Form( + key: _model.formKey, + autovalidateMode: AutovalidateMode.disabled, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldCharityLegalNameController, + obscureText: false, + decoration: InputDecoration( + labelText: 'Legal Name of Charity', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldCharityLegalNameControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldCharityInformalNameController, + obscureText: false, + decoration: InputDecoration( + labelText: 'Informal Name(s) of Charity', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldCharityInformalNameControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: + _model.textFieldAddressController, + obscureText: false, + decoration: InputDecoration( + labelText: 'Street Address', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldAddressControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model.textFieldUnitController, + obscureText: false, + decoration: InputDecoration( + labelText: 'Unit, Suite', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldUnitControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model.textFieldCityController, + obscureText: false, + decoration: InputDecoration( + labelText: 'City', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldCityControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: + _model.textFieldProvinceStateController, + obscureText: false, + decoration: InputDecoration( + labelText: 'Province', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldProvinceStateControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: + _model.textFieldCountryController, + obscureText: false, + decoration: InputDecoration( + labelText: 'Country', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldCountryControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: + _model.textFieldPostalZipCodeController, + textCapitalization: + TextCapitalization.characters, + obscureText: false, + decoration: InputDecoration( + labelText: 'Postal Code', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + validator: _model + .textFieldPostalZipCodeControllerValidator + .asValidator(context), + inputFormatters: [ + _model.textFieldPostalZipCodeMask + ], + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldCharitableRegistrationNumberController, + obscureText: false, + decoration: InputDecoration( + labelText: + 'Charitable Registration Number', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + keyboardType: TextInputType.number, + validator: _model + .textFieldCharitableRegistrationNumberControllerValidator + .asValidator(context), + inputFormatters: [ + _model + .textFieldCharitableRegistrationNumberMask + ], + ), + ), + Align( + alignment: AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 20.0, 0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + FFButtonWidget( + onPressed: () async { + context.safePop(); + }, + text: 'Cancel', + options: FFButtonOptions( + width: 100.0, + height: 40.0, + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .primary, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + FFButtonWidget( + onPressed: () async { + if (_model.formKey.currentState == + null || + !_model.formKey.currentState! + .validate()) { + return; + } + + var charitiesRecordReference = + CharitiesRecord.collection + .doc(); + await charitiesRecordReference + .set(createCharitiesRecordData( + charityLegalName: _model + .textFieldCharityLegalNameController + .text, + address: createAddressStruct( + address: _model + .textFieldAddressController + .text, + unit: _model + .textFieldUnitController + .text, + city: _model + .textFieldCityController + .text, + provinceState: _model + .textFieldProvinceStateController + .text, + country: _model + .textFieldCountryController + .text, + postalZipCode: _model + .textFieldPostalZipCodeController + .text, + clearUnsetFields: false, + create: true, + ), + charityRegistrationNumber: _model + .textFieldCharitableRegistrationNumberController + .text, + charityInformalName: _model + .textFieldCharityInformalNameController + .text, + )); + _model.createCharityRecordResult = + CharitiesRecord.getDocumentFromData( + createCharitiesRecordData( + charityLegalName: _model + .textFieldCharityLegalNameController + .text, + address: + createAddressStruct( + address: _model + .textFieldAddressController + .text, + unit: _model + .textFieldUnitController + .text, + city: _model + .textFieldCityController + .text, + provinceState: _model + .textFieldProvinceStateController + .text, + country: _model + .textFieldCountryController + .text, + postalZipCode: _model + .textFieldPostalZipCodeController + .text, + clearUnsetFields: false, + create: true, + ), + charityRegistrationNumber: + _model + .textFieldCharitableRegistrationNumberController + .text, + charityInformalName: _model + .textFieldCharityInformalNameController + .text, + ), + charitiesRecordReference); + context.safePop(); + + setState(() {}); + }, + text: 'Add', + options: FFButtonOptions( + width: 100.0, + height: 40.0, + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .tertiary, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/dashboard/charities_list/charities_list_model.dart b/lib/dashboard/charities_list/charities_list_model.dart new file mode 100644 index 0000000..38e9cce --- /dev/null +++ b/lib/dashboard/charities_list/charities_list_model.dart @@ -0,0 +1,27 @@ +import '/backend/backend.dart'; +import '/components/text_list_empty/text_list_empty_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class CharitiesListModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/dashboard/charities_list/charities_list_widget.dart b/lib/dashboard/charities_list/charities_list_widget.dart new file mode 100644 index 0000000..f6f1abb --- /dev/null +++ b/lib/dashboard/charities_list/charities_list_widget.dart @@ -0,0 +1,359 @@ +import '/backend/backend.dart'; +import '/components/text_list_empty/text_list_empty_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'charities_list_model.dart'; +export 'charities_list_model.dart'; + +class CharitiesListWidget extends StatefulWidget { + const CharitiesListWidget({Key? key}) : super(key: key); + + @override + _CharitiesListWidgetState createState() => _CharitiesListWidgetState(); +} + +class _CharitiesListWidgetState extends State { + late CharitiesListModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => CharitiesListModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + floatingActionButton: FloatingActionButton.extended( + onPressed: () async { + context.pushNamed('AddCharity'); + }, + backgroundColor: FlutterFlowTheme.of(context).tertiary, + icon: Icon( + Icons.add, + ), + elevation: 8.0, + label: Text( + 'Add Charity', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryBackground, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ), + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Charities', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Align( + alignment: AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15.0, 0.0, 15.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: StreamBuilder>( + stream: queryCharitiesRecord( + queryBuilder: (charitiesRecord) => + charitiesRecord.orderBy('charityLegalName'), + ), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitPumpingHeart( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ); + } + List + listViewCharitiesCharitiesRecordList = + snapshot.data!; + if (listViewCharitiesCharitiesRecordList.isEmpty) { + return Center( + child: TextListEmptyWidget( + listEmptyMessage: 'No Charities', + ), + ); + } + return ListView.separated( + padding: EdgeInsets.symmetric(vertical: 15.0), + primary: false, + shrinkWrap: true, + scrollDirection: Axis.vertical, + itemCount: + listViewCharitiesCharitiesRecordList.length, + separatorBuilder: (_, __) => + SizedBox(height: 15.0), + itemBuilder: (context, listViewCharitiesIndex) { + final listViewCharitiesCharitiesRecord = + listViewCharitiesCharitiesRecordList[ + listViewCharitiesIndex]; + return InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed( + 'CharityDetails', + queryParameters: { + 'charityRecordID': serializeParam( + listViewCharitiesCharitiesRecord + .reference, + ParamType.DocumentReference, + ), + }.withoutNulls, + ); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + borderRadius: + BorderRadius.circular(8.0), + border: Border.all( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + width: 2.0, + ), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 10.0, 10.0, 10.0, 10.0), + child: Card( + clipBehavior: + Clip.antiAliasWithSaveLayer, + color: FlutterFlowTheme.of(context) + .primaryBackground, + elevation: 0.0, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(8.0), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + listViewCharitiesCharitiesRecord + .charityLegalName, + style: + FlutterFlowTheme.of(context) + .labelLarge, + ), + if (listViewCharitiesCharitiesRecord + .charityInformalName != + null && + listViewCharitiesCharitiesRecord + .charityInformalName != + '') + Text( + 'a.k.a. ${listViewCharitiesCharitiesRecord.charityInformalName}', + style: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .labelLargeFamily, + color: + FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 10.0, + fontStyle: + FontStyle.italic, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelLargeFamily), + ), + ), + Padding( + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 10.0, 0.0, 0.0), + child: Text( + listViewCharitiesCharitiesRecord + .address.address, + style: FlutterFlowTheme.of( + context) + .bodySmall, + ), + ), + if (listViewCharitiesCharitiesRecord + .address.unit != + null && + listViewCharitiesCharitiesRecord + .address.unit != + '') + Text( + listViewCharitiesCharitiesRecord + .address.unit, + style: FlutterFlowTheme.of( + context) + .bodySmall, + ), + Text( + '${listViewCharitiesCharitiesRecord.address.city}, ${listViewCharitiesCharitiesRecord.address.provinceState}, ${listViewCharitiesCharitiesRecord.address.country}', + style: + FlutterFlowTheme.of(context) + .bodySmall, + ), + Padding( + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 10.0), + child: Text( + listViewCharitiesCharitiesRecord + .address.postalZipCode, + style: FlutterFlowTheme.of( + context) + .bodySmall, + ), + ), + Text( + 'Charitable Registration Number:', + style: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .labelMediumFamily, + color: FlutterFlowTheme + .of(context) + .primary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + Text( + listViewCharitiesCharitiesRecord + .charityRegistrationNumber, + style: + FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodySmallFamily, + color: FlutterFlowTheme + .of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + ), + ], + ), + ), + ), + ), + ), + ); + }, + ); + }, + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/dashboard/charity_details/charity_details_model.dart b/lib/dashboard/charity_details/charity_details_model.dart new file mode 100644 index 0000000..b3dad9c --- /dev/null +++ b/lib/dashboard/charity_details/charity_details_model.dart @@ -0,0 +1,33 @@ +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class CharityDetailsModel extends FlutterFlowModel { + /// Local state fields for this page. + + bool isEditMode = false; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + final formKey = GlobalKey(); + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/dashboard/charity_details/charity_details_widget.dart b/lib/dashboard/charity_details/charity_details_widget.dart new file mode 100644 index 0000000..3f0aad6 --- /dev/null +++ b/lib/dashboard/charity_details/charity_details_widget.dart @@ -0,0 +1,353 @@ +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'charity_details_model.dart'; +export 'charity_details_model.dart'; + +class CharityDetailsWidget extends StatefulWidget { + const CharityDetailsWidget({ + Key? key, + required this.charityRecordID, + }) : super(key: key); + + final DocumentReference? charityRecordID; + + @override + _CharityDetailsWidgetState createState() => _CharityDetailsWidgetState(); +} + +class _CharityDetailsWidgetState extends State { + late CharityDetailsModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => CharityDetailsModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return StreamBuilder( + stream: CharitiesRecord.getDocument(widget.charityRecordID!), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Scaffold( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitPumpingHeart( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ), + ); + } + final charityDetailsCharitiesRecord = snapshot.data!; + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Charity Details', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: + FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15.0, 0.0, 15.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 15.0, 0.0, 0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Form( + key: _model.formKey, + autovalidateMode: AutovalidateMode.disabled, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + if (charityDetailsCharitiesRecord + .hasCharityInformalName()) + Padding( + padding: + EdgeInsetsDirectional + .fromSTEB( + 0.0, + 10.0, + 0.0, + 0.0), + child: Text( + charityDetailsCharitiesRecord + .charityLegalName, + style: + FlutterFlowTheme.of( + context) + .labelLarge, + ), + ), + if (charityDetailsCharitiesRecord + .charityInformalName != + null && + charityDetailsCharitiesRecord + .charityInformalName != + '') + AutoSizeText( + 'a.k.a. ${charityDetailsCharitiesRecord.charityInformalName}', + style: + FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: FlutterFlowTheme.of( + context) + .labelLargeFamily, + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 10.0, + fontStyle: + FontStyle + .italic, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelLargeFamily), + ), + ), + ], + ), + ), + ], + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 10.0, 0.0, 0.0), + child: Text( + charityDetailsCharitiesRecord + .address.address, + style: FlutterFlowTheme.of(context) + .bodySmall, + ), + ), + if (charityDetailsCharitiesRecord + .address.unit != + null && + charityDetailsCharitiesRecord + .address.unit != + '') + Text( + charityDetailsCharitiesRecord + .address.unit, + style: FlutterFlowTheme.of(context) + .bodySmall, + ), + Text( + '${charityDetailsCharitiesRecord.address.city}, ${charityDetailsCharitiesRecord.address.provinceState}, ${charityDetailsCharitiesRecord.address.country}', + style: FlutterFlowTheme.of(context) + .bodySmall, + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 10.0), + child: Text( + charityDetailsCharitiesRecord + .address.postalZipCode, + style: FlutterFlowTheme.of(context) + .bodySmall, + ), + ), + Text( + 'Charitable Registration Number:', + style: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await launchURL( + 'https://apps.cra-arc.gc.ca/ebci/hacc/srch/pub/chrtydtls?selectedCharityBn=${(String charityRegistrationNumber) { + return charityRegistrationNumber + .replaceAll(' ', ''); + }(charityDetailsCharitiesRecord.charityRegistrationNumber)}'); + }, + child: Text( + charityDetailsCharitiesRecord + .charityRegistrationNumber, + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodySmallFamily, + color: FlutterFlowTheme.of( + context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + ), + ), + ], + ), + ), + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + FlutterFlowIconButton( + borderColor: FlutterFlowTheme.of(context) + .primaryBackground, + borderRadius: 20.0, + buttonSize: 40.0, + fillColor: FlutterFlowTheme.of(context) + .primaryBackground, + icon: Icon( + Icons.edit, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + size: 24.0, + ), + onPressed: () async { + context.pushNamed( + 'CharityUpdate', + queryParameters: { + 'charityRecordID': serializeParam( + widget.charityRecordID, + ParamType.DocumentReference, + ), + }.withoutNulls, + extra: { + kTransitionInfoKey: TransitionInfo( + hasTransition: true, + transitionType: + PageTransitionType.fade, + ), + }, + ); + }, + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + }, + ); + } +} diff --git a/lib/dashboard/charity_update/charity_update_model.dart b/lib/dashboard/charity_update/charity_update_model.dart new file mode 100644 index 0000000..e2c57ae --- /dev/null +++ b/lib/dashboard/charity_update/charity_update_model.dart @@ -0,0 +1,78 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; +import 'package:provider/provider.dart'; + +class CharityUpdateModel extends FlutterFlowModel { + /// Local state fields for this page. + + bool isEditMode = false; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + final formKey = GlobalKey(); + // State field(s) for TextField_charityLegaName widget. + TextEditingController? textFieldCharityLegaNameController; + String? Function(BuildContext, String?)? + textFieldCharityLegaNameControllerValidator; + // State field(s) for TextField_charityInformalName widget. + TextEditingController? textFieldCharityInformalNameController; + String? Function(BuildContext, String?)? + textFieldCharityInformalNameControllerValidator; + // State field(s) for TextField_unit widget. + TextEditingController? textFieldUnitController1; + String? Function(BuildContext, String?)? textFieldUnitController1Validator; + // State field(s) for TextField_unit widget. + TextEditingController? textFieldUnitController2; + String? Function(BuildContext, String?)? textFieldUnitController2Validator; + // State field(s) for TextField_city widget. + TextEditingController? textFieldCityController; + String? Function(BuildContext, String?)? textFieldCityControllerValidator; + // State field(s) for TextField_provinceState widget. + TextEditingController? textFieldProvinceStateController; + String? Function(BuildContext, String?)? + textFieldProvinceStateControllerValidator; + // State field(s) for TextField_country widget. + TextEditingController? textFieldCountryController; + String? Function(BuildContext, String?)? textFieldCountryControllerValidator; + // State field(s) for TextField_postalZipCode widget. + TextEditingController? textFieldPostalZipCodeController; + String? Function(BuildContext, String?)? + textFieldPostalZipCodeControllerValidator; + // State field(s) for TextField_charityRegistrationNumber widget. + TextEditingController? textFieldCharityRegistrationNumberController; + final textFieldCharityRegistrationNumberMask = + MaskTextInputFormatter(mask: '### ### ### RR ####'); + String? Function(BuildContext, String?)? + textFieldCharityRegistrationNumberControllerValidator; + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + textFieldCharityLegaNameController?.dispose(); + textFieldCharityInformalNameController?.dispose(); + textFieldUnitController1?.dispose(); + textFieldUnitController2?.dispose(); + textFieldCityController?.dispose(); + textFieldProvinceStateController?.dispose(); + textFieldCountryController?.dispose(); + textFieldPostalZipCodeController?.dispose(); + textFieldCharityRegistrationNumberController?.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/dashboard/charity_update/charity_update_widget.dart b/lib/dashboard/charity_update/charity_update_widget.dart new file mode 100644 index 0000000..d827166 --- /dev/null +++ b/lib/dashboard/charity_update/charity_update_widget.dart @@ -0,0 +1,1462 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; +import 'package:provider/provider.dart'; +import 'charity_update_model.dart'; +export 'charity_update_model.dart'; + +class CharityUpdateWidget extends StatefulWidget { + const CharityUpdateWidget({ + Key? key, + required this.charityRecordID, + }) : super(key: key); + + final DocumentReference? charityRecordID; + + @override + _CharityUpdateWidgetState createState() => _CharityUpdateWidgetState(); +} + +class _CharityUpdateWidgetState extends State { + late CharityUpdateModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => CharityUpdateModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return StreamBuilder( + stream: CharitiesRecord.getDocument(widget.charityRecordID!), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Scaffold( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitPumpingHeart( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ), + ); + } + final charityUpdateCharitiesRecord = snapshot.data!; + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Update Charity', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: + FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15.0, 0.0, 15.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Form( + key: _model.formKey, + autovalidateMode: AutovalidateMode.disabled, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldCharityLegaNameController ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .charityLegalName, + ), + obscureText: false, + decoration: InputDecoration( + labelText: 'Legal Name of Charity', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldCharityLegaNameControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldCharityInformalNameController ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .charityInformalName, + ), + obscureText: false, + decoration: InputDecoration( + labelText: + 'Informal Name(s) of Charity', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldCharityInformalNameControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: + _model.textFieldUnitController1 ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .address.address, + ), + obscureText: false, + decoration: InputDecoration( + labelText: 'Street Address', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldUnitController1Validator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: + _model.textFieldUnitController2 ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .address.unit, + ), + obscureText: false, + decoration: InputDecoration( + labelText: 'Unit/Suite', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldUnitController2Validator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: + _model.textFieldCityController ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .address.city, + ), + obscureText: false, + decoration: InputDecoration( + labelText: 'City', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldCityControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldProvinceStateController ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .address.provinceState, + ), + obscureText: false, + decoration: InputDecoration( + labelText: 'Province', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldProvinceStateControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldCountryController ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .address.country, + ), + obscureText: false, + decoration: InputDecoration( + labelText: 'Country', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldCountryControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldPostalZipCodeController ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .address.postalZipCode, + ), + obscureText: false, + decoration: InputDecoration( + labelText: 'Postal Code', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + validator: _model + .textFieldPostalZipCodeControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 5.0), + child: TextFormField( + controller: _model + .textFieldCharityRegistrationNumberController ??= + TextEditingController( + text: charityUpdateCharitiesRecord + .charityRegistrationNumber, + ), + obscureText: false, + decoration: InputDecoration( + labelText: + 'Charitable Registration Number', + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 0.0, 0.0), + ), + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + keyboardType: TextInputType.number, + validator: _model + .textFieldCharityRegistrationNumberControllerValidator + .asValidator(context), + inputFormatters: [ + _model + .textFieldCharityRegistrationNumberMask + ], + ), + ), + Align( + alignment: + AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 20.0, 0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + FFButtonWidget( + onPressed: () async { + context.safePop(); + }, + text: 'Cancel', + options: FFButtonOptions( + width: 100.0, + height: 40.0, + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: + FlutterFlowTheme.of(context) + .primary, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + FFButtonWidget( + onPressed: () async { + await widget.charityRecordID! + .update( + createCharitiesRecordData( + charityLegalName: _model + .textFieldCharityLegaNameController + .text, + charityRegistrationNumber: _model + .textFieldCharityRegistrationNumberController + .text, + address: createAddressStruct( + address: _model + .textFieldUnitController1 + .text, + unit: _model + .textFieldUnitController2 + .text, + city: _model + .textFieldCityController + .text, + provinceState: _model + .textFieldProvinceStateController + .text, + country: _model + .textFieldCountryController + .text, + postalZipCode: _model + .textFieldPostalZipCodeController + .text, + clearUnsetFields: false, + ), + charityInformalName: _model + .textFieldCharityInformalNameController + .text, + )); + context.safePop(); + }, + text: 'Save', + options: FFButtonOptions( + width: 100.0, + height: 40.0, + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: + FlutterFlowTheme.of(context) + .tertiary, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ); + }, + ); + } +} diff --git a/lib/dashboard/dashboard/dashboard_model.dart b/lib/dashboard/dashboard/dashboard_model.dart new file mode 100644 index 0000000..76cbbb3 --- /dev/null +++ b/lib/dashboard/dashboard/dashboard_model.dart @@ -0,0 +1,33 @@ +import '/components/navi_btn_grey/navi_btn_grey_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class DashboardModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for NaviBtnGrey_listCharities. + late NaviBtnGreyModel naviBtnGreyListCharitiesModel; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + naviBtnGreyListCharitiesModel = + createModel(context, () => NaviBtnGreyModel()); + } + + void dispose() { + unfocusNode.dispose(); + naviBtnGreyListCharitiesModel.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/dashboard/dashboard/dashboard_widget.dart b/lib/dashboard/dashboard/dashboard_widget.dart new file mode 100644 index 0000000..5748614 --- /dev/null +++ b/lib/dashboard/dashboard/dashboard_widget.dart @@ -0,0 +1,152 @@ +import '/components/navi_btn_grey/navi_btn_grey_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'dashboard_model.dart'; +export 'dashboard_model.dart'; + +class DashboardWidget extends StatefulWidget { + const DashboardWidget({Key? key}) : super(key: key); + + @override + _DashboardWidgetState createState() => _DashboardWidgetState(); +} + +class _DashboardWidgetState extends State { + late DashboardModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => DashboardModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Dashboard', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(20.0, 0.0, 20.0, 0.0), + child: Wrap( + spacing: 20.0, + runSpacing: 20.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: [ + Container( + width: 375.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 20.0), + child: Text( + 'Charities Dashboard', + style: FlutterFlowTheme.of(context).titleLarge, + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed('CharitiesList'); + }, + child: wrapWithModel( + model: _model.naviBtnGreyListCharitiesModel, + updateCallback: () => setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Charities List', + buttonIcon: FaIcon( + FontAwesomeIcons.list, + color: FlutterFlowTheme.of(context) + .secondaryText, + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/donation/donation_wizard/donation_wizard_model.dart b/lib/donation/donation_wizard/donation_wizard_model.dart new file mode 100644 index 0000000..5466d94 --- /dev/null +++ b/lib/donation/donation_wizard/donation_wizard_model.dart @@ -0,0 +1,67 @@ +import '/components/get_donation_amount/get_donation_amount_widget.dart'; +import '/components/heading2/heading2_widget.dart'; +import '/components/navi_btn_grey/navi_btn_grey_widget.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; +import 'package:smooth_page_indicator/smooth_page_indicator.dart' + as smooth_page_indicator; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class DonationWizardModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for Row_LogoAndName component. + late RowLogoAndNameModel rowLogoAndNameModel; + // State field(s) for PageView_Donation_LoggedOut widget. + PageController? pageViewDonationLoggedOutController; + + int get pageViewDonationLoggedOutCurrentIndex => + pageViewDonationLoggedOutController != null && + pageViewDonationLoggedOutController!.hasClients && + pageViewDonationLoggedOutController!.page != null + ? pageViewDonationLoggedOutController!.page!.round() + : 0; + // Model for getDonationAmount component. + late GetDonationAmountModel getDonationAmountModel; + // Model for NaviBtnGrey component. + late NaviBtnGreyModel naviBtnGreyModel1; + // Model for NaviBtnGrey component. + late NaviBtnGreyModel naviBtnGreyModel2; + // Model for Heading2 component. + late Heading2Model heading2Model; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + rowLogoAndNameModel = createModel(context, () => RowLogoAndNameModel()); + getDonationAmountModel = + createModel(context, () => GetDonationAmountModel()); + naviBtnGreyModel1 = createModel(context, () => NaviBtnGreyModel()); + naviBtnGreyModel2 = createModel(context, () => NaviBtnGreyModel()); + heading2Model = createModel(context, () => Heading2Model()); + } + + void dispose() { + unfocusNode.dispose(); + rowLogoAndNameModel.dispose(); + getDonationAmountModel.dispose(); + naviBtnGreyModel1.dispose(); + naviBtnGreyModel2.dispose(); + heading2Model.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/donation/donation_wizard/donation_wizard_widget.dart b/lib/donation/donation_wizard/donation_wizard_widget.dart new file mode 100644 index 0000000..f96fe99 --- /dev/null +++ b/lib/donation/donation_wizard/donation_wizard_widget.dart @@ -0,0 +1,622 @@ +import '/components/get_donation_amount/get_donation_amount_widget.dart'; +import '/components/heading2/heading2_widget.dart'; +import '/components/navi_btn_grey/navi_btn_grey_widget.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; +import 'package:smooth_page_indicator/smooth_page_indicator.dart' + as smooth_page_indicator; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'donation_wizard_model.dart'; +export 'donation_wizard_model.dart'; + +class DonationWizardWidget extends StatefulWidget { + const DonationWizardWidget({ + Key? key, + int? wizardPage, + }) : this.wizardPage = wizardPage ?? 0, + super(key: key); + + final int wizardPage; + + @override + _DonationWizardWidgetState createState() => _DonationWizardWidgetState(); +} + +class _DonationWizardWidgetState extends State { + late DonationWizardModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => DonationWizardModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Donation', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: false, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 20.0), + child: wrapWithModel( + model: _model.rowLogoAndNameModel, + updateCallback: () => setState(() {}), + child: RowLogoAndNameWidget(), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + height: 500.0, + child: Stack( + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 40.0), + child: PageView( + controller: + _model.pageViewDonationLoggedOutController ??= + PageController( + initialPage: min( + valueOrDefault( + FFAppState().wizardPage, + 0, + ), + 3)), + onPageChanged: (_) async { + context.pushNamed( + 'DonationWizard', + queryParameters: { + 'wizardPage': serializeParam( + 0, + ParamType.int, + ), + }.withoutNulls, + ); + }, + scrollDirection: Axis.horizontal, + children: [ + Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: + MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + wrapWithModel( + model: _model.getDonationAmountModel, + updateCallback: () => setState(() {}), + child: GetDonationAmountWidget(), + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 20.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + await showDialog( + context: context, + builder: + (alertDialogContext) { + return AlertDialog( + title: Text( + 'URL of Scanned Image'), + content: Text( + 'penniesfromheaven://penniesfromheaven.app${GoRouter.of(context).location}'), + actions: [ + TextButton( + onPressed: () => + Navigator.pop( + alertDialogContext), + child: Text('OK!'), + ), + ], + ); + }, + ); + + context.pushNamed('Payment'); + }, + text: 'Payment >', + options: FFButtonOptions( + width: 130.0, + height: 40.0, + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: + FlutterFlowTheme.of(context) + .primary, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + ), + ], + ), + Expanded( + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 20.0, 20.0, 20.0, 20.0), + child: SelectionArea( + child: AutoSizeText( + 'penniesfromheaven://penniesfromheaven.app${GoRouter.of(context).location}', + maxLines: 2, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + fontSize: 8.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + )), + ), + ), + ], + ), + ), + ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.network( + 'https://picsum.photos/seed/607/600', + width: 300.0, + height: 200.0, + fit: BoxFit.cover, + ), + ), + Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 30.0, 30.0, 30.0, 30.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Create a', + style: + FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontWeight: + FontWeight + .w300, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + TextSpan( + text: + ' pennies from heaven', + style: TextStyle( + color: FlutterFlowTheme + .of(context) + .primary, + fontWeight: + FontWeight.bold, + ), + ), + TextSpan( + text: + ' account so you can download ', + style: TextStyle(), + ), + TextSpan( + text: 'tax receipts', + style: TextStyle( + color: FlutterFlowTheme + .of(context) + .tertiary, + ), + ), + TextSpan( + text: + ' and see how your generous donation is helping ', + style: TextStyle(), + ) + ], + style: FlutterFlowTheme.of( + context) + .bodySmall, + ), + textAlign: TextAlign.center, + maxLines: 5, + ), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 15.0, 15.0, 15.0, 15.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed('Login'); + }, + child: wrapWithModel( + model: _model.naviBtnGreyModel1, + updateCallback: () => + setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Sign In', + buttonIcon: FaIcon( + FontAwesomeIcons.signInAlt, + color: + FlutterFlowTheme.of(context) + .secondaryText, + ), + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 15.0, 15.0, 15.0, 15.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed('CreateAccount'); + }, + child: wrapWithModel( + model: _model.naviBtnGreyModel2, + updateCallback: () => + setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Create Account', + buttonIcon: FaIcon( + FontAwesomeIcons.userPlus, + color: + FlutterFlowTheme.of(context) + .secondaryText, + ), + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 100.0, 0.0, 0.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed('DonationWizard'); + }, + child: Text( + 'Continue without an account', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme.of( + context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ], + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 10.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 20.0, 0.0), + child: wrapWithModel( + model: _model.heading2Model, + updateCallback: () => + setState(() {}), + child: Heading2Widget( + headingText: 'Card Details', + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Container( + width: + MediaQuery.sizeOf(context) + .width * + 1.0, + height: + MediaQuery.sizeOf(context) + .height * + 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of( + context) + .primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB(20.0, 20.0, + 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf( + context) + .width * + 1.0, + height: MediaQuery.sizeOf( + context) + .height * + 1.0, + child: custom_widgets + .GetCCNWidget( + width: MediaQuery.sizeOf( + context) + .width * + 1.0, + height: MediaQuery.sizeOf( + context) + .height * + 1.0, + saveOnly: true, + refreshPageUI: () async { + // Rebuild Current Page + setState(() {}); + }, + goToNextPage: () async { + context.pushNamed( + 'ThankYou'); + }, + ), + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + ClipRRect( + borderRadius: + BorderRadius.circular(8.0), + child: Image.asset( + 'assets/images/Pay_with_Apple_Pay_button-pay-with@2x.png', + width: 300.0, + height: 107.0, + fit: BoxFit.contain, + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 16.0, 16.0, 16.0), + child: smooth_page_indicator.SmoothPageIndicator( + controller: _model + .pageViewDonationLoggedOutController ??= + PageController( + initialPage: min( + valueOrDefault( + FFAppState().wizardPage, + 0, + ), + 3)), + count: 4, + axisDirection: Axis.horizontal, + onDotClicked: (i) async { + await _model + .pageViewDonationLoggedOutController! + .animateToPage( + i, + duration: Duration(milliseconds: 500), + curve: Curves.ease, + ); + }, + effect: + smooth_page_indicator.ExpandingDotsEffect( + expansionFactor: 3.0, + spacing: 8.0, + radius: 16.0, + dotWidth: 16.0, + dotHeight: 16.0, + dotColor: FlutterFlowTheme.of(context) + .secondaryBackground, + activeDotColor: + FlutterFlowTheme.of(context).tertiary, + paintStyle: PaintingStyle.fill, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/donations_list/donations_list_model.dart b/lib/donations_list/donations_list_model.dart new file mode 100644 index 0000000..316ff77 --- /dev/null +++ b/lib/donations_list/donations_list_model.dart @@ -0,0 +1,26 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class DonationsListModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/donations_list/donations_list_widget.dart b/lib/donations_list/donations_list_widget.dart new file mode 100644 index 0000000..f9b393e --- /dev/null +++ b/lib/donations_list/donations_list_widget.dart @@ -0,0 +1,968 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'donations_list_model.dart'; +export 'donations_list_model.dart'; + +class DonationsListWidget extends StatefulWidget { + const DonationsListWidget({Key? key}) : super(key: key); + + @override + _DonationsListWidgetState createState() => _DonationsListWidgetState(); +} + +class _DonationsListWidgetState extends State { + late DonationsListModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => DonationsListModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: Color(0xFF606A85), + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 0.0, 0.0), + child: Text( + 'Donation History', + style: FlutterFlowTheme.of(context).titleLarge, + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB(24.0, 4.0, 0.0, 0.0), + child: Text( + 'Below are your most recent orders', + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Outfit', + color: Color(0xFF606A85), + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 12.0, 0.0, 24.0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 0.0, 16.0, 0.0), + child: Container( + width: double.infinity, + constraints: BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 12.0, 16.0, 12.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 12.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Donation #: ', + style: TextStyle(), + ), + TextSpan( + text: '429242424', + style: TextStyle( + color: Color(0xFF6F61EF), + fontWeight: FontWeight.bold, + ), + ) + ], + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: 'Poppins', + color: Color(0xFF15161E), + fontSize: 16.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyLargeFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 4.0, 0.0, 0.0), + child: Text( + 'Mon. July 3rd', + style: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Outfit', + color: Color(0xFF606A85), + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + decoration: BoxDecoration( + color: Color(0xFFF1F4F8), + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB(7.0, 0.0, 7.0, 0.0), + child: Text( + '2.5 lbs', + style: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Outfit', + color: + Color(0xFF606A85), + fontSize: 14.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 12.0), + child: Text( + '\$10.00', + textAlign: TextAlign.end, + style: FlutterFlowTheme.of(context) + .headlineSmall + .override( + fontFamily: 'Outfit', + color: Color(0xFF15161E), + fontSize: 22.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .headlineSmallFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + decoration: BoxDecoration( + color: Color(0x4D9489F5), + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: Color(0xFF6F61EF), + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 12.0, 0.0, 12.0, 0.0), + child: Text( + 'Draft', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: Color(0xFF6F61EF), + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 0.0, 16.0, 0.0), + child: Container( + width: double.infinity, + constraints: BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 12.0, 16.0, 12.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 12.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Donation #: ', + style: TextStyle(), + ), + TextSpan( + text: '429242424', + style: TextStyle( + color: + FlutterFlowTheme.of(context) + .tertiary, + fontWeight: FontWeight.bold, + ), + ) + ], + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: 'Plus Jakarta Sans', + color: Color(0xFF15161E), + fontSize: 16.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyLargeFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 4.0, 0.0, 0.0), + child: Text( + 'Mon. July 3rd', + style: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Outfit', + color: Color(0xFF606A85), + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + constraints: BoxConstraints( + maxWidth: 200.0, + ), + decoration: BoxDecoration( + color: Color(0xFFF1F4F8), + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB(7.0, 0.0, 7.0, 0.0), + child: Text( + 'Boyle Street Community Services', + textAlign: TextAlign.start, + maxLines: 1, + style: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Roboto', + color: + Color(0xFF606A85), + fontSize: 14.0, + fontWeight: + FontWeight.w500, + fontStyle: + FontStyle.italic, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 12.0), + child: Text( + '(\$15.00)', + textAlign: TextAlign.end, + style: FlutterFlowTheme.of(context) + .headlineSmall + .override( + fontFamily: 'Outfit', + color: + FlutterFlowTheme.of(context) + .error, + fontSize: 22.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .headlineSmallFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .accent4, + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 12.0, 0.0, 12.0, 0.0), + child: Text( + 'Refund', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .error, + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 0.0, 16.0, 0.0), + child: Container( + width: double.infinity, + constraints: BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 12.0, 16.0, 12.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 12.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Order #: ', + style: TextStyle(), + ), + TextSpan( + text: '429242424', + style: TextStyle( + color: Color(0xFF6F61EF), + fontWeight: FontWeight.bold, + ), + ) + ], + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: 'Plus Jakarta Sans', + color: Color(0xFF15161E), + fontSize: 16.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyLargeFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 4.0, 0.0, 0.0), + child: Text( + 'Mon. July 3rd', + style: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Outfit', + color: Color(0xFF606A85), + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + decoration: BoxDecoration( + color: Color(0xFFF1F4F8), + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB(7.0, 0.0, 7.0, 0.0), + child: Text( + '2.5 lbs', + style: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Outfit', + color: + Color(0xFF606A85), + fontSize: 14.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 12.0), + child: Text( + '\$1.50', + textAlign: TextAlign.end, + style: FlutterFlowTheme.of(context) + .headlineSmall + .override( + fontFamily: 'Outfit', + color: Color(0xFF15161E), + fontSize: 22.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .headlineSmallFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .accent4, + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: FlutterFlowTheme.of(context) + .success, + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 12.0, 0.0, 12.0, 0.0), + child: Text( + 'Payment', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .success, + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 0.0, 16.0, 0.0), + child: Container( + width: double.infinity, + constraints: BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 12.0, 16.0, 12.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 12.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Order #: ', + style: TextStyle(), + ), + TextSpan( + text: '429242424', + style: TextStyle( + color: Color(0xFF6F61EF), + fontWeight: FontWeight.bold, + ), + ) + ], + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: 'Plus Jakarta Sans', + color: Color(0xFF15161E), + fontSize: 16.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyLargeFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 4.0, 0.0, 0.0), + child: Text( + 'Mon. July 3rd', + style: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Outfit', + color: Color(0xFF606A85), + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + decoration: BoxDecoration( + color: Color(0xFFF1F4F8), + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: Color(0xFFE5E7EB), + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB(7.0, 0.0, 7.0, 0.0), + child: Text( + '2.5 lbs', + style: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Outfit', + color: + Color(0xFF606A85), + fontSize: 14.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 12.0), + child: Text( + '\$1.50', + textAlign: TextAlign.end, + style: FlutterFlowTheme.of(context) + .headlineSmall + .override( + fontFamily: 'Outfit', + color: Color(0xFF15161E), + fontSize: 22.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .headlineSmallFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 0.0), + child: Container( + height: 32.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .accent4, + borderRadius: + BorderRadius.circular(12.0), + border: Border.all( + color: FlutterFlowTheme.of(context) + .success, + width: 2.0, + ), + ), + child: Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 12.0, 0.0, 12.0, 0.0), + child: Text( + 'Accepted', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .success, + fontSize: 14.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ].divide(SizedBox(height: 12.0)), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/flutter_flow/custom_functions.dart b/lib/flutter_flow/custom_functions.dart index 56c6095..d2eb4ce 100644 --- a/lib/flutter_flow/custom_functions.dart +++ b/lib/flutter_flow/custom_functions.dart @@ -7,9 +7,11 @@ import 'package:intl/intl.dart'; import 'package:timeago/timeago.dart' as timeago; import 'lat_lng.dart'; import 'place.dart'; -import '../backend/backend.dart'; +import 'uploaded_file.dart'; +import '/backend/backend.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; -import '../../auth/firebase_auth/auth_util.dart'; +import '/backend/schema/structs/index.dart'; +import '/auth/firebase_auth/auth_util.dart'; double getDoubleValueFromString(String? testString) { // returns non-negative double parse of string, otherwise returns 0.0 diff --git a/lib/flutter_flow/flutter_flow_animations.dart b/lib/flutter_flow/flutter_flow_animations.dart index e267591..710f007 100644 --- a/lib/flutter_flow/flutter_flow_animations.dart +++ b/lib/flutter_flow/flutter_flow_animations.dart @@ -19,14 +19,12 @@ class AnimationInfo { final bool applyInitialState; final bool loop; final bool reverse; - late Adapter adapter; late AnimationController controller; } void createAnimation(AnimationInfo animation, TickerProvider vsync) { final newController = AnimationController(vsync: vsync); animation.controller = newController; - animation.adapter = ValueAdapter(newController.value); } void setupAnimations(Iterable animations, TickerProvider vsync) { @@ -35,9 +33,6 @@ void setupAnimations(Iterable animations, TickerProvider vsync) { extension AnimatedWidgetExtension on Widget { Widget animateOnPageLoad(AnimationInfo animationInfo) => Animate( - controller: - animationInfo.applyInitialState ? null : animationInfo.controller, - adapter: animationInfo.applyInitialState ? null : animationInfo.adapter, effects: animationInfo.effects, child: this, onPlay: (controller) => animationInfo.loop @@ -54,7 +49,7 @@ extension AnimatedWidgetExtension on Widget { hasBeenTriggered || animationInfo.applyInitialState ? Animate( controller: animationInfo.controller, - adapter: animationInfo.adapter, + autoPlay: false, effects: animationInfo.effects, child: this) : this; diff --git a/lib/flutter_flow/flutter_flow_drop_down.dart b/lib/flutter_flow/flutter_flow_drop_down.dart new file mode 100644 index 0000000..753d84a --- /dev/null +++ b/lib/flutter_flow/flutter_flow_drop_down.dart @@ -0,0 +1,234 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; + +import 'form_field_controller.dart'; +import 'package:flutter/material.dart'; + +class FlutterFlowDropDown extends StatefulWidget { + const FlutterFlowDropDown({ + required this.controller, + this.hintText, + this.searchHintText, + required this.options, + this.optionLabels, + required this.onChanged, + this.icon, + this.width, + this.height, + this.fillColor, + this.searchHintTextStyle, + this.searchCursorColor, + required this.textStyle, + required this.elevation, + required this.borderWidth, + required this.borderRadius, + required this.borderColor, + required this.margin, + this.hidesUnderline = false, + this.disabled = false, + this.isSearchable = false, + }); + + final FormFieldController controller; + final String? hintText; + final String? searchHintText; + final List options; + final List? optionLabels; + final Function(T?) onChanged; + final Widget? icon; + final double? width; + final double? height; + final Color? fillColor; + final TextStyle? searchHintTextStyle; + final Color? searchCursorColor; + final TextStyle textStyle; + final double elevation; + final double borderWidth; + final double borderRadius; + final Color borderColor; + final EdgeInsetsGeometry margin; + final bool hidesUnderline; + final bool disabled; + final bool isSearchable; + + @override + State> createState() => _FlutterFlowDropDownState(); +} + +class _FlutterFlowDropDownState extends State> { + final TextEditingController _textEditingController = TextEditingController(); + + void Function() get listener => + () => widget.onChanged(widget.controller.value); + + @override + void initState() { + widget.controller.addListener(listener); + super.initState(); + } + + @override + void dispose() { + widget.controller.removeListener(listener); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final optionToDisplayValue = Map.fromEntries( + widget.options.asMap().entries.map((option) => MapEntry( + option.value, + widget.optionLabels == null || + widget.optionLabels!.length < option.key + 1 + ? option.value.toString() + : widget.optionLabels![option.key])), + ); + final value = widget.options.contains(widget.controller.value) + ? widget.controller.value + : null; + final items = widget.options + .map( + (option) => DropdownMenuItem( + value: option, + child: Text( + optionToDisplayValue[option] ?? '', + style: widget.textStyle, + ), + ), + ) + .toList(); + final hintText = widget.hintText != null + ? Text(widget.hintText!, style: widget.textStyle) + : null; + void Function(T?)? onChanged = + !widget.disabled ? (value) => widget.controller.value = value : null; + final dropdownWidget = widget.isSearchable + ? _buildSearchableDropdown( + value, + items, + onChanged, + hintText, + optionToDisplayValue, + ) + : _buildNonSearchableDropdown(value, items, onChanged, hintText); + final childWidget = DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(widget.borderRadius), + border: Border.all( + color: widget.borderColor, + width: widget.borderWidth, + ), + color: widget.fillColor, + ), + child: Padding( + padding: widget.margin, + child: widget.hidesUnderline + ? DropdownButtonHideUnderline(child: dropdownWidget) + : dropdownWidget, + ), + ); + if (widget.height != null || widget.width != null) { + return Container( + width: widget.width, + height: widget.height, + child: childWidget, + ); + } + return childWidget; + } + + Widget _buildNonSearchableDropdown( + T? value, + List>? items, + void Function(T?)? onChanged, + Text? hintText, + ) { + return DropdownButton( + value: value, + hint: hintText, + items: items, + elevation: widget.elevation.toInt(), + onChanged: onChanged, + icon: widget.icon, + isExpanded: true, + dropdownColor: widget.fillColor, + focusColor: Colors.transparent, + ); + } + + Widget _buildSearchableDropdown( + T? value, + List>? items, + void Function(T?)? onChanged, + Text? hintText, + Map optionLabels, + ) { + final overlayColor = MaterialStateProperty.resolveWith((states) => + states.contains(MaterialState.focused) ? Colors.transparent : null); + final iconStyleData = widget.icon != null + ? IconStyleData(icon: widget.icon!) + : const IconStyleData(); + return DropdownButton2( + value: value, + hint: hintText, + items: items, + iconStyleData: iconStyleData, + buttonStyleData: ButtonStyleData( + elevation: widget.elevation.toInt(), + overlayColor: overlayColor, + ), + menuItemStyleData: MenuItemStyleData(overlayColor: overlayColor), + dropdownStyleData: DropdownStyleData( + elevation: widget.elevation.toInt(), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: widget.fillColor, + ), + ), + onChanged: onChanged, + isExpanded: true, + dropdownSearchData: DropdownSearchData( + searchController: _textEditingController, + searchInnerWidgetHeight: 50, + searchInnerWidget: Container( + height: 50, + padding: const EdgeInsets.only( + top: 8, + bottom: 4, + right: 8, + left: 8, + ), + child: TextFormField( + expands: true, + maxLines: null, + controller: _textEditingController, + cursorColor: widget.searchCursorColor, + decoration: InputDecoration( + isDense: true, + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), + hintText: widget.searchHintText, + hintStyle: widget.searchHintTextStyle, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ), + searchMatchFn: (item, searchValue) { + return (optionLabels[item.value] ?? '') + .toLowerCase() + .contains(searchValue.toLowerCase()); + }, + ), + + // This to clear the search value when you close the menu + onMenuStateChange: (isOpen) { + if (!isOpen) { + _textEditingController.clear(); + } + }, + ); + } +} diff --git a/lib/flutter_flow/flutter_flow_icon_button.dart b/lib/flutter_flow/flutter_flow_icon_button.dart index 7e829a3..ae964c2 100644 --- a/lib/flutter_flow/flutter_flow_icon_button.dart +++ b/lib/flutter_flow/flutter_flow_icon_button.dart @@ -120,44 +120,42 @@ class _FlutterFlowIconButtonState extends State { return SizedBox( width: widget.buttonSize, height: widget.buttonSize, - child: (widget.showLoadingIndicator && loading) - ? Center( - child: Container( - width: iconSize, - height: iconSize, - color: widget.onPressed != null - ? widget.fillColor - : widget.disabledColor, - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - iconColor ?? Colors.white, - ), - ), - ), - ) - : Theme( - data: Theme.of(context).copyWith(useMaterial3: true), - child: IconButton( - icon: effectiveIcon, - onPressed: widget.onPressed == null - ? null - : () async { - if (loading) { - return; - } - setState(() => loading = true); - try { - await widget.onPressed!(); - } finally { - if (mounted) { - setState(() => loading = false); - } - } - }, - splashRadius: widget.buttonSize, - style: style, - ), - ), + child: Theme( + data: Theme.of(context).copyWith(useMaterial3: true), + child: IgnorePointer( + ignoring: (widget.showLoadingIndicator && loading), + child: IconButton( + icon: (widget.showLoadingIndicator && loading) + ? Container( + width: iconSize, + height: iconSize, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + iconColor ?? Colors.white, + ), + ), + ) + : effectiveIcon, + onPressed: widget.onPressed == null + ? null + : () async { + if (loading) { + return; + } + setState(() => loading = true); + try { + await widget.onPressed!(); + } finally { + if (mounted) { + setState(() => loading = false); + } + } + }, + splashRadius: widget.buttonSize, + style: style, + ), + ), + ), ); } } diff --git a/lib/flutter_flow/flutter_flow_model.dart b/lib/flutter_flow/flutter_flow_model.dart index 2727bfa..7188e02 100644 --- a/lib/flutter_flow/flutter_flow_model.dart +++ b/lib/flutter_flow/flutter_flow_model.dart @@ -102,13 +102,13 @@ class FlutterFlowDynamicModels { .toList(); } - S? getValueAtIndex(int index, S Function(T) getValue) { + S? getValueAtIndex(int index, S? Function(T) getValue) { final uniqueKey = _childrenIndexes.entries.firstWhereOrNull((e) => e.value == index)?.key; return getValueForKey(uniqueKey, getValue); } - S? getValueForKey(String? uniqueKey, S Function(T) getValue) { + S? getValueForKey(String? uniqueKey, S? Function(T) getValue) { final model = _childrenModels[uniqueKey]; return model != null ? getValue(model) : null; } diff --git a/lib/flutter_flow/flutter_flow_radio_button.dart b/lib/flutter_flow/flutter_flow_radio_button.dart new file mode 100644 index 0000000..496316c --- /dev/null +++ b/lib/flutter_flow/flutter_flow_radio_button.dart @@ -0,0 +1,264 @@ +/* + * Copyright 2020 https://github.com/TercyoStorck + * + * Source code has been modified by FlutterFlow, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import 'form_field_controller.dart'; +import 'package:flutter/material.dart'; + +class FlutterFlowRadioButton extends StatefulWidget { + const FlutterFlowRadioButton({ + required this.options, + required this.onChanged, + required this.controller, + required this.optionHeight, + required this.textStyle, + this.optionWidth, + this.selectedTextStyle, + this.textPadding = EdgeInsets.zero, + this.buttonPosition = RadioButtonPosition.left, + this.direction = Axis.vertical, + required this.radioButtonColor, + this.inactiveRadioButtonColor, + this.toggleable = false, + this.horizontalAlignment = WrapAlignment.start, + this.verticalAlignment = WrapCrossAlignment.start, + }); + + final List options; + final Function(String?)? onChanged; + final FormFieldController controller; + final double optionHeight; + final double? optionWidth; + final TextStyle textStyle; + final TextStyle? selectedTextStyle; + final EdgeInsetsGeometry textPadding; + final RadioButtonPosition buttonPosition; + final Axis direction; + final Color radioButtonColor; + final Color? inactiveRadioButtonColor; + final bool toggleable; + final WrapAlignment horizontalAlignment; + final WrapCrossAlignment verticalAlignment; + + @override + State createState() => _FlutterFlowRadioButtonState(); +} + +class _FlutterFlowRadioButtonState extends State { + void Function()? get listener => widget.onChanged != null + ? () => widget.onChanged!(widget.controller.value) + : null; + + @override + void initState() { + if (listener != null) { + widget.controller.addListener(listener!); + } + super.initState(); + } + + @override + void dispose() { + if (listener != null) { + widget.controller.removeListener(listener!); + } + super.dispose(); + } + + List get effectiveOptions => + widget.options.isEmpty ? ['[Option]'] : widget.options; + + @override + Widget build(BuildContext context) { + return Theme( + data: Theme.of(context) + .copyWith(unselectedWidgetColor: widget.inactiveRadioButtonColor), + child: RadioGroup.builder( + direction: widget.direction, + groupValue: widget.controller.value, + onChanged: (value) => widget.controller.value = value, + activeColor: widget.radioButtonColor, + toggleable: widget.toggleable, + textStyle: widget.textStyle, + selectedTextStyle: widget.selectedTextStyle ?? widget.textStyle, + textPadding: widget.textPadding, + optionHeight: widget.optionHeight, + optionWidth: widget.optionWidth, + horizontalAlignment: widget.horizontalAlignment, + verticalAlignment: widget.verticalAlignment, + items: effectiveOptions, + itemBuilder: (item) => + RadioButtonBuilder(item, buttonPosition: widget.buttonPosition), + ), + ); + } +} + +enum RadioButtonPosition { + right, + left, +} + +class RadioButtonBuilder { + RadioButtonBuilder( + this.description, { + this.buttonPosition = RadioButtonPosition.left, + }); + + final String description; + final RadioButtonPosition buttonPosition; +} + +class RadioButton extends StatelessWidget { + const RadioButton({ + required this.description, + required this.value, + required this.groupValue, + required this.onChanged, + required this.buttonPosition, + required this.activeColor, + required this.toggleable, + required this.textStyle, + required this.selectedTextStyle, + required this.textPadding, + this.shouldFlex = false, + }); + + final String description; + final T value; + final T? groupValue; + final void Function(T?)? onChanged; + final RadioButtonPosition buttonPosition; + final Color activeColor; + final bool toggleable; + final TextStyle textStyle; + final TextStyle selectedTextStyle; + final EdgeInsetsGeometry textPadding; + final bool shouldFlex; + + @override + Widget build(BuildContext context) { + final selectedStyle = selectedTextStyle; + final isSelected = value == groupValue; + Widget radioButtonText = Padding( + padding: textPadding, + child: Text( + description, + style: isSelected ? selectedStyle : textStyle, + ), + ); + if (shouldFlex) { + radioButtonText = Flexible(child: radioButtonText); + } + return InkWell( + onTap: () => onChanged!(value), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (buttonPosition == RadioButtonPosition.right) radioButtonText, + Radio( + groupValue: groupValue, + onChanged: onChanged, + value: value, + activeColor: activeColor, + toggleable: toggleable, + ), + if (buttonPosition == RadioButtonPosition.left) radioButtonText, + ], + ), + ); + } +} + +class RadioGroup extends StatelessWidget { + const RadioGroup.builder({ + required this.groupValue, + required this.onChanged, + required this.items, + required this.itemBuilder, + required this.direction, + required this.optionHeight, + required this.horizontalAlignment, + required this.activeColor, + required this.toggleable, + required this.textStyle, + required this.selectedTextStyle, + required this.textPadding, + this.optionWidth, + this.verticalAlignment = WrapCrossAlignment.center, + }); + + final T? groupValue; + final List items; + final RadioButtonBuilder Function(T value) itemBuilder; + final void Function(T?)? onChanged; + final Axis direction; + final double optionHeight; + final double? optionWidth; + final WrapAlignment horizontalAlignment; + final WrapCrossAlignment verticalAlignment; + final Color activeColor; + final bool toggleable; + final TextStyle textStyle; + final TextStyle selectedTextStyle; + final EdgeInsetsGeometry textPadding; + + List get _group => items.map( + (item) { + final radioButtonBuilder = itemBuilder(item); + return Container( + height: optionHeight, + width: optionWidth, + child: RadioButton( + description: radioButtonBuilder.description, + value: item, + groupValue: groupValue, + onChanged: onChanged, + buttonPosition: radioButtonBuilder.buttonPosition, + activeColor: activeColor, + toggleable: toggleable, + textStyle: textStyle, + selectedTextStyle: selectedTextStyle, + textPadding: textPadding, + shouldFlex: optionWidth != null, + ), + ); + }, + ).toList(); + + @override + Widget build(BuildContext context) => direction == Axis.horizontal + ? Wrap( + direction: direction, + alignment: horizontalAlignment, + children: _group, + ) + : Wrap( + direction: direction, + crossAxisAlignment: verticalAlignment, + children: _group, + ); +} diff --git a/lib/flutter_flow/flutter_flow_theme.dart b/lib/flutter_flow/flutter_flow_theme.dart index f98b277..e036834 100644 --- a/lib/flutter_flow/flutter_flow_theme.dart +++ b/lib/flutter_flow/flutter_flow_theme.dart @@ -3,8 +3,17 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +enum DeviceSize { + mobile, + tablet, + desktop, +} + abstract class FlutterFlowTheme { + static DeviceSize deviceSize = DeviceSize.mobile; + static FlutterFlowTheme of(BuildContext context) { + deviceSize = getDeviceSize(context); return LightModeTheme(); } @@ -34,6 +43,7 @@ abstract class FlutterFlowTheme { late Color primaryBtnText; late Color lineColor; + late Color customColor1; @Deprecated('Use displaySmallFamily instead') String get title1Family => displaySmallFamily; @@ -95,7 +105,22 @@ abstract class FlutterFlowTheme { String get bodySmallFamily => typography.bodySmallFamily; TextStyle get bodySmall => typography.bodySmall; - Typography get typography => ThemeTypography(this); + Typography get typography => { + DeviceSize.mobile: MobileTypography(this), + DeviceSize.tablet: TabletTypography(this), + DeviceSize.desktop: DesktopTypography(this), + }[deviceSize]!; +} + +DeviceSize getDeviceSize(BuildContext context) { + final width = MediaQuery.sizeOf(context).width; + if (width < 479) { + return DeviceSize.mobile; + } else if (width < 991) { + return DeviceSize.tablet; + } else { + return DeviceSize.desktop; + } } class LightModeTheme extends FlutterFlowTheme { @@ -125,6 +150,7 @@ class LightModeTheme extends FlutterFlowTheme { late Color primaryBtnText = Color(0xFFFFFFFF); late Color lineColor = Color(0xFFE0E3E7); + late Color customColor1 = Color(0xFF2FB73C); } abstract class Typography { @@ -160,8 +186,119 @@ abstract class Typography { TextStyle get bodySmall; } -class ThemeTypography extends Typography { - ThemeTypography(this.theme); +class MobileTypography extends Typography { + MobileTypography(this.theme); + + final FlutterFlowTheme theme; + + String get displayLargeFamily => 'Poppins'; + TextStyle get displayLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.tertiary, + fontWeight: FontWeight.normal, + fontSize: 57.0, + ); + String get displayMediumFamily => 'Poppins'; + TextStyle get displayMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primary, + fontWeight: FontWeight.normal, + fontSize: 45.0, + ); + String get displaySmallFamily => 'Poppins'; + TextStyle get displaySmall => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 45.0, + ); + String get headlineLargeFamily => 'Poppins'; + TextStyle get headlineLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.tertiary, + fontWeight: FontWeight.normal, + fontSize: 32.0, + ); + String get headlineMediumFamily => 'Poppins'; + TextStyle get headlineMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primary, + fontWeight: FontWeight.normal, + fontSize: 32.0, + ); + String get headlineSmallFamily => 'Poppins'; + TextStyle get headlineSmall => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 24.0, + ); + String get titleLargeFamily => 'Poppins'; + TextStyle get titleLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.tertiary, + fontWeight: FontWeight.w500, + fontSize: 22.0, + ); + String get titleMediumFamily => 'Poppins'; + TextStyle get titleMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primary, + fontWeight: FontWeight.w500, + fontSize: 22.0, + ); + String get titleSmallFamily => 'Poppins'; + TextStyle get titleSmall => GoogleFonts.getFont( + 'Poppins', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelLargeFamily => 'Poppins'; + TextStyle get labelLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 14.0, + ); + String get labelMediumFamily => 'Poppins'; + TextStyle get labelMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 12.0, + ); + String get labelSmallFamily => 'Poppins'; + TextStyle get labelSmall => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.w200, + fontSize: 11.0, + ); + String get bodyLargeFamily => 'Poppins'; + TextStyle get bodyLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontSize: 20.0, + ); + String get bodyMediumFamily => 'Poppins'; + TextStyle get bodyMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get bodySmallFamily => 'Poppins'; + TextStyle get bodySmall => GoogleFonts.getFont( + 'Poppins', + color: theme.secondaryText, + fontWeight: FontWeight.normal, + fontSize: 14.0, + ); +} + +class TabletTypography extends Typography { + TabletTypography(this.theme); final FlutterFlowTheme theme; @@ -182,7 +319,7 @@ class ThemeTypography extends Typography { String get displaySmallFamily => 'Poppins'; TextStyle get displaySmall => GoogleFonts.getFont( 'Poppins', - color: theme.primaryText, + color: theme.tertiary, fontWeight: FontWeight.normal, fontSize: 45.0, ); @@ -210,14 +347,125 @@ class ThemeTypography extends Typography { String get titleLargeFamily => 'Poppins'; TextStyle get titleLarge => GoogleFonts.getFont( 'Poppins', - color: theme.primaryText, + color: theme.tertiary, fontWeight: FontWeight.w500, fontSize: 22.0, ); String get titleMediumFamily => 'Poppins'; TextStyle get titleMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primary, + fontWeight: FontWeight.w500, + fontSize: 22.0, + ); + String get titleSmallFamily => 'Poppins'; + TextStyle get titleSmall => GoogleFonts.getFont( + 'Poppins', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelLargeFamily => 'Poppins'; + TextStyle get labelLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 14.0, + ); + String get labelMediumFamily => 'Poppins'; + TextStyle get labelMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 12.0, + ); + String get labelSmallFamily => 'Poppins'; + TextStyle get labelSmall => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 11.0, + ); + String get bodyLargeFamily => 'Poppins'; + TextStyle get bodyLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontSize: 20.0, + ); + String get bodyMediumFamily => 'Poppins'; + TextStyle get bodyMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 16.0, + ); + String get bodySmallFamily => 'Poppins'; + TextStyle get bodySmall => GoogleFonts.getFont( + 'Poppins', + color: theme.secondaryText, + fontWeight: FontWeight.normal, + fontSize: 14.0, + ); +} + +class DesktopTypography extends Typography { + DesktopTypography(this.theme); + + final FlutterFlowTheme theme; + + String get displayLargeFamily => 'Poppins'; + TextStyle get displayLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 57.0, + ); + String get displayMediumFamily => 'Poppins'; + TextStyle get displayMedium => GoogleFonts.getFont( 'Poppins', color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 45.0, + ); + String get displaySmallFamily => 'Poppins'; + TextStyle get displaySmall => GoogleFonts.getFont( + 'Poppins', + color: theme.tertiary, + fontWeight: FontWeight.normal, + fontSize: 45.0, + ); + String get headlineLargeFamily => 'Poppins'; + TextStyle get headlineLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 32.0, + ); + String get headlineMediumFamily => 'Poppins'; + TextStyle get headlineMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.secondaryText, + fontWeight: FontWeight.normal, + fontSize: 32.0, + ); + String get headlineSmallFamily => 'Poppins'; + TextStyle get headlineSmall => GoogleFonts.getFont( + 'Poppins', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 24.0, + ); + String get titleLargeFamily => 'Poppins'; + TextStyle get titleLarge => GoogleFonts.getFont( + 'Poppins', + color: theme.tertiary, + fontWeight: FontWeight.w500, + fontSize: 22.0, + ); + String get titleMediumFamily => 'Poppins'; + TextStyle get titleMedium => GoogleFonts.getFont( + 'Poppins', + color: theme.primary, fontWeight: FontWeight.w500, fontSize: 22.0, ); @@ -249,9 +497,11 @@ class ThemeTypography extends Typography { fontWeight: FontWeight.w500, fontSize: 11.0, ); - String get bodyLargeFamily => ''; + String get bodyLargeFamily => 'Poppins'; TextStyle get bodyLarge => GoogleFonts.getFont( - 'Roboto', + 'Poppins', + color: theme.primaryText, + fontSize: 20.0, ); String get bodyMediumFamily => 'Poppins'; TextStyle get bodyMedium => GoogleFonts.getFont( diff --git a/lib/flutter_flow/flutter_flow_util.dart b/lib/flutter_flow/flutter_flow_util.dart index 0e99f6d..26b9256 100644 --- a/lib/flutter_flow/flutter_flow_util.dart +++ b/lib/flutter_flow/flutter_flow_util.dart @@ -42,7 +42,7 @@ String dateTimeFormat(String format, DateTime? dateTime, {String? locale}) { } if (format == 'relative') { _setTimeagoLocales(); - return timeago.format(dateTime, locale: locale); + return timeago.format(dateTime, locale: locale, allowFromNow: true); } return DateFormat(format, locale).format(dateTime); } @@ -185,9 +185,11 @@ bool get isAndroid => !kIsWeb && Platform.isAndroid; bool get isiOS => !kIsWeb && Platform.isIOS; bool get isWeb => kIsWeb; -const kMobileWidthCutoff = 479.0; +const kBreakpointSmall = 479.0; +const kBreakpointMedium = 767.0; +const kBreakpointLarge = 991.0; bool isMobileWidth(BuildContext context) => - MediaQuery.of(context).size.width < kMobileWidthCutoff; + MediaQuery.sizeOf(context).width < kBreakpointSmall; bool responsiveVisibility({ required BuildContext context, bool phone = true, @@ -195,12 +197,12 @@ bool responsiveVisibility({ bool tabletLandscape = true, bool desktop = true, }) { - final width = MediaQuery.of(context).size.width; - if (width < kMobileWidthCutoff) { + final width = MediaQuery.sizeOf(context).width; + if (width < kBreakpointSmall) { return phone; - } else if (width < 767) { + } else if (width < kBreakpointMedium) { return tablet; - } else if (width < 991) { + } else if (width < kBreakpointLarge) { return tabletLandscape; } else { return desktop; @@ -276,3 +278,20 @@ extension FFStringExt on String { extension ListFilterExt on Iterable { List get withoutNulls => where((s) => s != null).map((e) => e!).toList(); } + +extension ListDivideExt on Iterable { + Iterable> get enumerate => toList().asMap().entries; + + List divide(Widget t) => isEmpty + ? [] + : (enumerate.map((e) => [e.value, t]).expand((i) => i).toList() + ..removeLast()); + + List around(Widget t) => addToStart(t).addToEnd(t); + + List addToStart(Widget t) => + enumerate.map((e) => e.value).toList()..insert(0, t); + + List addToEnd(Widget t) => + enumerate.map((e) => e.value).toList()..add(t); +} diff --git a/lib/flutter_flow/flutter_flow_widgets.dart b/lib/flutter_flow/flutter_flow_widgets.dart index f268efe..1d7fd67 100644 --- a/lib/flutter_flow/flutter_flow_widgets.dart +++ b/lib/flutter_flow/flutter_flow_widgets.dart @@ -22,6 +22,7 @@ class FFButtonOptions { this.hoverBorderSide, this.hoverTextColor, this.hoverElevation, + this.maxLines, }); final TextStyle? textStyle; @@ -32,6 +33,7 @@ class FFButtonOptions { final Color? color; final Color? disabledColor; final Color? disabledTextColor; + final int? maxLines; final Color? splashColor; final double? iconSize; final Color? iconColor; @@ -69,6 +71,8 @@ class FFButtonWidget extends StatefulWidget { class _FFButtonWidgetState extends State { bool loading = false; + int get maxLines => widget.options.maxLines ?? 1; + @override Widget build(BuildContext context) { Widget textWidget = loading @@ -86,7 +90,7 @@ class _FFButtonWidgetState extends State { : AutoSizeText( widget.text, style: widget.options.textStyle?.withoutColor(), - maxLines: 1, + maxLines: maxLines, overflow: TextOverflow.ellipsis, ); @@ -171,7 +175,7 @@ class _FFButtonWidgetState extends State { ), ); - if (widget.icon != null || widget.iconData != null) { + if ((widget.icon != null || widget.iconData != null) && !loading) { return Container( height: widget.options.height, width: widget.options.width, diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index b78b276..452f22e 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -1,15 +1,15 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:go_router/go_router.dart'; import 'package:page_transition/page_transition.dart'; import '../flutter_flow_theme.dart'; -import '../../backend/backend.dart'; +import '/backend/backend.dart'; +import '/backend/schema/structs/index.dart'; import '../../auth/base_auth_user_provider.dart'; -import '../../backend/firebase_dynamic_links/firebase_dynamic_links.dart' - show DynamicLinksHandler; import '../../index.dart'; import '../../main.dart'; import '../lat_lng.dart'; @@ -18,12 +18,15 @@ import 'serialization_util.dart'; export 'package:go_router/go_router.dart'; export 'serialization_util.dart'; -export '../../backend/firebase_dynamic_links/firebase_dynamic_links.dart' - show generateCurrentPageLink; const kTransitionInfoKey = '__transition_info__'; class AppStateNotifier extends ChangeNotifier { + AppStateNotifier._(); + + static AppStateNotifier? _instance; + static AppStateNotifier get instance => _instance ??= AppStateNotifier._(); + BaseAuthUser? initialUser; BaseAuthUser? user; bool showSplashImage = true; @@ -51,10 +54,13 @@ class AppStateNotifier extends ChangeNotifier { void updateNotifyOnAuthChange(bool notify) => notifyOnAuthChange = notify; void update(BaseAuthUser newUser) { + final shouldUpdate = + user?.uid == null || newUser.uid == null || user?.uid != newUser.uid; initialUser ??= newUser; user = newUser; // Refresh the app on auth change unless explicitly marked otherwise. - if (notifyOnAuthChange) { + // No need to update unless the user has changed. + if (notifyOnAuthChange && shouldUpdate) { notifyListeners(); } // Once again mark the notifier as needing to update on auth change @@ -72,32 +78,36 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter( initialLocation: '/', debugLogDiagnostics: true, refreshListenable: appStateNotifier, - errorBuilder: (context, _) => - appStateNotifier.loggedIn ? NavBarPage() : DonationWidget(), - navigatorBuilder: (_, __, child) => DynamicLinksHandler(child: child), + errorBuilder: (context, state) => + appStateNotifier.loggedIn ? NavBarPage() : LoginWidget(), routes: [ FFRoute( name: '_initialize', path: '/', builder: (context, _) => - appStateNotifier.loggedIn ? NavBarPage() : DonationWidget(), + appStateNotifier.loggedIn ? NavBarPage() : LoginWidget(), routes: [ FFRoute( name: 'Donation', - path: 'home', + path: 'donation', builder: (context, params) => params.isEmpty ? NavBarPage(initialPage: 'Donation') - : DonationWidget(), + : DonationWidget( + donationAmount: + params.getParam('donationAmount', ParamType.double), + ), ), FFRoute( name: 'Payment', path: 'payment', + builder: (context, params) => PaymentWidget(), + ), + FFRoute( + name: 'ThankYou', + path: 'thankYou', builder: (context, params) => params.isEmpty - ? NavBarPage(initialPage: 'Payment') - : PaymentWidget( - donationAmount: - params.getParam('donationAmount', ParamType.double), - ), + ? NavBarPage(initialPage: 'ThankYou') + : ThankYouWidget(), ), FFRoute( name: 'Account', @@ -107,19 +117,116 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter( : AccountWidget(), ), FFRoute( - name: 'TestPage', - path: 'testPage', - builder: (context, params) => TestPageWidget(), + name: 'PaymentOptions', + path: 'paymentOptions', + builder: (context, params) => PaymentOptionsWidget(), + ), + FFRoute( + name: 'Country', + path: 'country', + builder: (context, params) => CountryWidget(), + ), + FFRoute( + name: 'Profile', + path: 'profile', + builder: (context, params) => ProfileWidget(), ), FFRoute( - name: 'GhostImagePage', - path: 'ghostImagePage', - builder: (context, params) => GhostImagePageWidget(), + name: 'Notifications', + path: 'notifications', + builder: (context, params) => NotificationsWidget(), + ), + FFRoute( + name: 'Support', + path: 'support', + builder: (context, params) => SupportWidget(), + ), + FFRoute( + name: 'TermOfService', + path: 'termOfService', + builder: (context, params) => TermOfServiceWidget(), + ), + FFRoute( + name: 'DonationsList', + path: 'donationsList', + builder: (context, params) => params.isEmpty + ? NavBarPage(initialPage: 'DonationsList') + : DonationsListWidget(), + ), + FFRoute( + name: 'TempLoginPage', + path: 'tempLoginPage', + builder: (context, params) => params.isEmpty + ? NavBarPage(initialPage: 'TempLoginPage') + : TempLoginPageWidget(), + ), + FFRoute( + name: 'Login', + path: 'login', + builder: (context, params) => LoginWidget(), + ), + FFRoute( + name: 'CreateAccount', + path: 'createAccount', + builder: (context, params) => CreateAccountWidget(), + ), + FFRoute( + name: 'PasswordRules', + path: 'passwordRules', + builder: (context, params) => PasswordRulesWidget(), + ), + FFRoute( + name: 'DonationWizard', + path: 'donationWizard', + builder: (context, params) => params.isEmpty + ? NavBarPage(initialPage: 'DonationWizard') + : DonationWizardWidget( + wizardPage: params.getParam('wizardPage', ParamType.int), + ), + ), + FFRoute( + name: 'ClientDonation', + path: 'clientDonation', + builder: (context, params) => params.isEmpty + ? NavBarPage(initialPage: 'ClientDonation') + : ClientDonationWidget(), + ), + FFRoute( + name: 'Dashboard', + path: 'dashboard', + builder: (context, params) => params.isEmpty + ? NavBarPage(initialPage: 'Dashboard') + : DashboardWidget(), + ), + FFRoute( + name: 'CharitiesList', + path: 'CharitiesList', + builder: (context, params) => CharitiesListWidget(), + ), + FFRoute( + name: 'CharityDetails', + path: 'charityDetails', + builder: (context, params) => CharityDetailsWidget( + charityRecordID: params.getParam('charityRecordID', + ParamType.DocumentReference, false, ['charities']), + ), + ), + FFRoute( + name: 'AddCharity', + path: 'addCharity', + builder: (context, params) => AddCharityWidget(), + ), + FFRoute( + name: 'CharityUpdate', + path: 'charityUpdate', + builder: (context, params) => CharityUpdateWidget( + charityRecordID: params.getParam('charityRecordID', + ParamType.DocumentReference, false, ['charities']), + ), ) ].map((r) => r.toRoute(appStateNotifier)).toList(), ), ].map((r) => r.toRoute(appStateNotifier)).toList(), - urlPathStrategy: UrlPathStrategy.path, ); extension NavParamExtensions on Map { @@ -134,8 +241,8 @@ extension NavigationExtensions on BuildContext { void goNamedAuth( String name, bool mounted, { - Map params = const {}, - Map queryParams = const {}, + Map pathParameters = const {}, + Map queryParameters = const {}, Object? extra, bool ignoreRedirect = false, }) => @@ -143,16 +250,16 @@ extension NavigationExtensions on BuildContext { ? null : goNamed( name, - params: params, - queryParams: queryParams, + pathParameters: pathParameters, + queryParameters: queryParameters, extra: extra, ); void pushNamedAuth( String name, bool mounted, { - Map params = const {}, - Map queryParams = const {}, + Map pathParameters = const {}, + Map queryParameters = const {}, Object? extra, bool ignoreRedirect = false, }) => @@ -160,25 +267,24 @@ extension NavigationExtensions on BuildContext { ? null : pushNamed( name, - params: params, - queryParams: queryParams, + pathParameters: pathParameters, + queryParameters: queryParameters, extra: extra, ); void safePop() { // If there is only one route on the stack, navigate to the initial // page instead of popping. - if (GoRouter.of(this).routerDelegate.matches.length <= 1) { - go('/'); - } else { + if (canPop()) { pop(); + } else { + go('/'); } } } extension GoRouterExtensions on GoRouter { - AppStateNotifier get appState => - (routerDelegate.refreshListenable as AppStateNotifier); + AppStateNotifier get appState => AppStateNotifier.instance; void prepareAuthEvent([bool ignoreRedirect = false]) => appState.hasRedirect() && !ignoreRedirect ? null @@ -187,16 +293,15 @@ extension GoRouterExtensions on GoRouter { !ignoreRedirect && appState.hasRedirect(); void clearRedirectLocation() => appState.clearRedirectLocation(); void setRedirectLocationIfUnset(String location) => - (routerDelegate.refreshListenable as AppStateNotifier) - .updateNotifyOnAuthChange(false); + appState.updateNotifyOnAuthChange(false); } extension _GoRouterStateExtensions on GoRouterState { Map get extraMap => extra != null ? extra as Map : {}; Map get allParams => {} - ..addAll(params) - ..addAll(queryParams) + ..addAll(pathParameters) + ..addAll(queryParameters) ..addAll(extraMap); TransitionInfo get transitionInfo => extraMap.containsKey(kTransitionInfoKey) ? extraMap[kTransitionInfoKey] as TransitionInfo @@ -252,7 +357,8 @@ class FFParameters { return param; } // Return serialized value. - return deserializeParam(param, type, isList, collectionNamePath); + return deserializeParam(param, type, isList, + collectionNamePath: collectionNamePath); } } @@ -276,7 +382,7 @@ class FFRoute { GoRoute toRoute(AppStateNotifier appStateNotifier) => GoRoute( name: name, path: path, - redirect: (state) { + redirect: (context, state) { if (appStateNotifier.shouldRedirect) { final redirectLocation = appStateNotifier.getRedirectLocation(); appStateNotifier.clearRedirectLocation(); @@ -285,7 +391,7 @@ class FFRoute { if (requireAuth && !appStateNotifier.loggedIn) { appStateNotifier.setRedirectLocationIfUnset(state.location); - return '/home'; + return '/login'; } return null; }, @@ -298,12 +404,13 @@ class FFRoute { ) : builder(context, ffParams); final child = appStateNotifier.loading - ? Center( - child: SizedBox( - width: 50.0, - height: 50.0, - child: CircularProgressIndicator( - color: FlutterFlowTheme.of(context).tertiary, + ? Container( + color: Colors.transparent, + child: Center( + child: Image.asset( + 'assets/images/Logo_-_Two_Heart_and_Hand.png', + width: double.infinity, + fit: BoxFit.cover, ), ), ) @@ -342,5 +449,9 @@ class TransitionInfo { final Duration duration; final Alignment? alignment; - static TransitionInfo appDefault() => TransitionInfo(hasTransition: false); + static TransitionInfo appDefault() => TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.rightToLeft, + duration: Duration(milliseconds: 400), + ); } diff --git a/lib/flutter_flow/nav/serialization_util.dart b/lib/flutter_flow/nav/serialization_util.dart index 6f0190f..c87fc50 100644 --- a/lib/flutter_flow/nav/serialization_util.dart +++ b/lib/flutter_flow/nav/serialization_util.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:from_css_color/from_css_color.dart'; import '/backend/backend.dart'; +import '/backend/schema/structs/index.dart'; import '../../flutter_flow/lat_lng.dart'; import '../../flutter_flow/place.dart'; @@ -86,9 +87,12 @@ String? serializeParam( case ParamType.DocumentReference: return _serializeDocumentReference(param as DocumentReference); case ParamType.Document: - final reference = (param as dynamic).reference as DocumentReference; + final reference = (param as FirestoreRecord).reference; return _serializeDocumentReference(reference); + case ParamType.DataStruct: + return param is BaseStruct ? param.serialize() : null; + default: return null; } @@ -177,14 +181,16 @@ enum ParamType { JSON, Document, DocumentReference, + DataStruct, } dynamic deserializeParam( String? param, ParamType paramType, - bool isList, [ + bool isList, { List? collectionNamePath, -]) { + StructBuilder? structBuilder, +}) { try { if (param == null) { return null; @@ -197,8 +203,13 @@ dynamic deserializeParam( return paramValues .where((p) => p is String) .map((p) => p as String) - .map((p) => - deserializeParam(p, paramType, false, collectionNamePath)) + .map((p) => deserializeParam( + p, + paramType, + false, + collectionNamePath: collectionNamePath, + structBuilder: structBuilder, + )) .where((p) => p != null) .map((p) => p! as T) .toList(); @@ -232,6 +243,10 @@ dynamic deserializeParam( case ParamType.DocumentReference: return _deserializeDocumentReference(param, collectionNamePath ?? []); + case ParamType.DataStruct: + final data = json.decode(param) as Map? ?? {}; + return structBuilder != null ? structBuilder(data) : null; + default: return null; } @@ -243,16 +258,16 @@ dynamic deserializeParam( Future Function(String) getDoc( List collectionNamePath, - Serializer serializer, + RecordBuilder recordBuilder, ) { return (String ids) => _deserializeDocumentReference(ids, collectionNamePath) .get() - .then((s) => serializers.deserializeWith(serializer, serializedData(s))); + .then((s) => recordBuilder(s)); } Future> Function(String) getDocList( List collectionNamePath, - Serializer serializer, + RecordBuilder recordBuilder, ) { return (String idsList) { List docIds = []; @@ -264,9 +279,7 @@ Future> Function(String) getDocList( docIds.map( (ids) => _deserializeDocumentReference(ids, collectionNamePath) .get() - .then( - (s) => serializers.deserializeWith(serializer, serializedData(s)), - ), + .then((s) => recordBuilder(s)), ), ).then((docs) => docs.where((d) => d != null).map((d) => d!).toList()); }; diff --git a/lib/flutter_flow/uploaded_file.dart b/lib/flutter_flow/uploaded_file.dart index 42b0fef..221dfed 100644 --- a/lib/flutter_flow/uploaded_file.dart +++ b/lib/flutter_flow/uploaded_file.dart @@ -18,7 +18,7 @@ class FFUploadedFile { @override String toString() => - 'FFUploadedFile(name: $name, bytes: ${bytes?.length ?? 0}, height: $height, width: $width, blurHash: $blurHash)'; + 'FFUploadedFile(name: $name, bytes: ${bytes?.length ?? 0}, height: $height, width: $width, blurHash: $blurHash,)'; String serialize() => jsonEncode( { @@ -49,7 +49,13 @@ class FFUploadedFile { } @override - int get hashCode => Object.hash(name, bytes, height, width, blurHash); + int get hashCode => Object.hash( + name, + bytes, + height, + width, + blurHash, + ); @override bool operator ==(other) => diff --git a/lib/index.dart b/lib/index.dart index 1f88b29..684f7c5 100644 --- a/lib/index.dart +++ b/lib/index.dart @@ -1,7 +1,34 @@ // Export pages export '/pages/donation/donation_widget.dart' show DonationWidget; export '/pages/payment/payment_widget.dart' show PaymentWidget; -export '/pages/account/account_widget.dart' show AccountWidget; -export '/pages/test_page/test_page_widget.dart' show TestPageWidget; -export '/pages/ghost_image_page/ghost_image_page_widget.dart' - show GhostImagePageWidget; +export '/pages/thank_you/thank_you_widget.dart' show ThankYouWidget; +export '/pages/account_pages/account/account_widget.dart' show AccountWidget; +export '/pages/account_pages/payment_options/payment_options_widget.dart' + show PaymentOptionsWidget; +export '/pages/account_pages/country/country_widget.dart' show CountryWidget; +export '/pages/account_pages/profile/profile_widget.dart' show ProfileWidget; +export '/pages/account_pages/notifications/notifications_widget.dart' + show NotificationsWidget; +export '/pages/account_pages/support/support_widget.dart' show SupportWidget; +export '/pages/account_pages/term_of_service/term_of_service_widget.dart' + show TermOfServiceWidget; +export '/donations_list/donations_list_widget.dart' show DonationsListWidget; +export '/pages/temp_login_page/temp_login_page_widget.dart' + show TempLoginPageWidget; +export '/pages/authentication_pages/login/login_widget.dart' show LoginWidget; +export '/pages/authentication_pages/create_account/create_account_widget.dart' + show CreateAccountWidget; +export '/pages/authentication_pages/password_rules/password_rules_widget.dart' + show PasswordRulesWidget; +export '/donation/donation_wizard/donation_wizard_widget.dart' + show DonationWizardWidget; +export '/client_pages/client_donation/client_donation_widget.dart' + show ClientDonationWidget; +export '/dashboard/dashboard/dashboard_widget.dart' show DashboardWidget; +export '/dashboard/charities_list/charities_list_widget.dart' + show CharitiesListWidget; +export '/dashboard/charity_details/charity_details_widget.dart' + show CharityDetailsWidget; +export '/dashboard/add_charity/add_charity_widget.dart' show AddCharityWidget; +export '/dashboard/charity_update/charity_update_widget.dart' + show CharityUpdateWidget; diff --git a/lib/main.dart b/lib/main.dart index e84e5db..b9efe59 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_web_plugins/url_strategy.dart'; import 'package:firebase_core/firebase_core.dart'; import 'auth/firebase_auth/firebase_user_provider.dart'; import 'auth/firebase_auth/auth_util.dart'; @@ -11,15 +12,19 @@ import 'backend/firebase/firebase_config.dart'; import 'flutter_flow/flutter_flow_theme.dart'; import 'flutter_flow/flutter_flow_util.dart'; import 'flutter_flow/internationalization.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:google_fonts/google_fonts.dart'; import 'flutter_flow/nav/nav.dart'; import 'index.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); + usePathUrlStrategy(); await initFirebase(); final appState = FFAppState(); // Initialize FFAppState + await appState.initializePersistedState(); runApp(ChangeNotifierProvider( create: (context) => appState, @@ -50,7 +55,7 @@ class _MyAppState extends State { @override void initState() { super.initState(); - _appStateNotifier = AppStateNotifier(); + _appStateNotifier = AppStateNotifier.instance; _router = createRouter(_appStateNotifier); userStream = penniesFromHeavenFirebaseUserStream() ..listen((user) => _appStateNotifier.update(user)); @@ -92,8 +97,7 @@ class _MyAppState extends State { ], theme: ThemeData(brightness: Brightness.light), themeMode: _themeMode, - routeInformationParser: _router.routeInformationParser, - routerDelegate: _router.routerDelegate, + routerConfig: _router, ); } } @@ -110,7 +114,7 @@ class NavBarPage extends StatefulWidget { /// This is the private State class that goes with NavBarPage. class _NavBarPageState extends State { - String _currentPageName = 'Payment'; + String _currentPageName = 'Dashboard'; late Widget? _currentPage; @override @@ -124,10 +128,16 @@ class _NavBarPageState extends State { Widget build(BuildContext context) { final tabs = { 'Donation': DonationWidget(), - 'Payment': PaymentWidget(), + 'ThankYou': ThankYouWidget(), 'Account': AccountWidget(), + 'DonationsList': DonationsListWidget(), + 'TempLoginPage': TempLoginPageWidget(), + 'DonationWizard': DonationWizardWidget(), + 'ClientDonation': ClientDonationWidget(), + 'Dashboard': DashboardWidget(), }; final currentIndex = tabs.keys.toList().indexOf(_currentPageName); + return Scaffold( body: _currentPage ?? tabs[_currentPageName], bottomNavigationBar: BottomNavigationBar( @@ -136,16 +146,16 @@ class _NavBarPageState extends State { _currentPage = null; _currentPageName = tabs.keys.toList()[i]; }), - backgroundColor: Colors.white, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, selectedItemColor: FlutterFlowTheme.of(context).primary, - unselectedItemColor: Color(0x8A000000), - showSelectedLabels: false, - showUnselectedLabels: false, + unselectedItemColor: FlutterFlowTheme.of(context).secondaryText, + showSelectedLabels: true, + showUnselectedLabels: true, type: BottomNavigationBarType.fixed, items: [ BottomNavigationBarItem( icon: Icon( - Icons.home_outlined, + Icons.attach_money_outlined, size: 24.0, ), label: 'Home', @@ -153,7 +163,7 @@ class _NavBarPageState extends State { ), BottomNavigationBarItem( icon: Icon( - Icons.attach_money_outlined, + Icons.home_outlined, size: 24.0, ), label: 'Home', @@ -164,8 +174,48 @@ class _NavBarPageState extends State { Icons.account_circle, size: 24.0, ), + label: 'Account', + tooltip: '', + ), + BottomNavigationBarItem( + icon: Icon( + Icons.attach_money, + size: 24.0, + ), + label: 'Donations', + tooltip: '', + ), + BottomNavigationBarItem( + icon: Icon( + Icons.home_outlined, + size: 24.0, + ), label: 'Home', tooltip: '', + ), + BottomNavigationBarItem( + icon: FaIcon( + FontAwesomeIcons.donate, + size: 24.0, + ), + label: 'Donation', + tooltip: '', + ), + BottomNavigationBarItem( + icon: Icon( + Icons.create_new_folder, + size: 24.0, + ), + label: 'Create', + tooltip: '', + ), + BottomNavigationBarItem( + icon: Icon( + Icons.home_outlined, + size: 24.0, + ), + label: 'Dashboard', + tooltip: '', ) ], ), diff --git a/lib/pages/account/account_widget.dart b/lib/pages/account/account_widget.dart deleted file mode 100644 index c5c24a2..0000000 --- a/lib/pages/account/account_widget.dart +++ /dev/null @@ -1,86 +0,0 @@ -import '/flutter_flow/flutter_flow_icon_button.dart'; -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:provider/provider.dart'; -import 'account_model.dart'; -export 'account_model.dart'; - -class AccountWidget extends StatefulWidget { - const AccountWidget({Key? key}) : super(key: key); - - @override - _AccountWidgetState createState() => _AccountWidgetState(); -} - -class _AccountWidgetState extends State { - late AccountModel _model; - - final scaffoldKey = GlobalKey(); - final _unfocusNode = FocusNode(); - - @override - void initState() { - super.initState(); - _model = createModel(context, () => AccountModel()); - - WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); - } - - @override - void dispose() { - _model.dispose(); - - _unfocusNode.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - context.watch(); - - return GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), - child: Scaffold( - key: scaffoldKey, - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: AppBar( - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - leading: FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: Icon( - Icons.arrow_back_rounded, - color: FlutterFlowTheme.of(context).secondaryBackground, - size: 30.0, - ), - onPressed: () async { - context.pop(); - }, - ), - title: Text( - 'Account', - style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', - color: FlutterFlowTheme.of(context).secondaryBackground, - fontSize: 22.0, - ), - ), - actions: [], - centerTitle: true, - elevation: 0.0, - ), - body: SafeArea( - child: Column( - mainAxisSize: MainAxisSize.max, - children: [], - ), - ), - ), - ); - } -} diff --git a/lib/pages/account_pages/account/account_model.dart b/lib/pages/account_pages/account/account_model.dart new file mode 100644 index 0000000..d5d1658 --- /dev/null +++ b/lib/pages/account_pages/account/account_model.dart @@ -0,0 +1,94 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/components/heading2/heading2_widget.dart'; +import '/components/navi_btn_grey/navi_btn_grey_widget.dart'; +import '/components/user_photo/user_photo_widget.dart'; +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class AccountModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for UserPhoto component. + late UserPhotoModel userPhotoModel; + // Model for Heading2_account. + late Heading2Model heading2AccountModel1; + // Model for NaviBtnGrey_notificationSettings. + late NaviBtnGreyModel naviBtnGreyNotificationSettingsModel1; + // Model for NaviBtnGrey_paymentOptions. + late NaviBtnGreyModel naviBtnGreyPaymentOptionsModel; + // Model for NaviBtnGrey_notificationSettings. + late NaviBtnGreyModel naviBtnGreyNotificationSettingsModel2; + // Model for Heading2_account. + late Heading2Model heading2AccountModel2; + // Model for NaviBtnGrey_country. + late NaviBtnGreyModel naviBtnGreyCountryModel; + // Model for NaviBtnGrey_editProfile. + late NaviBtnGreyModel naviBtnGreyEditProfileModel; + // Model for NaviBtnGrey_notificationSettings. + late NaviBtnGreyModel naviBtnGreyNotificationSettingsModel3; + // Model for Heading2_general. + late Heading2Model heading2GeneralModel; + // Model for NaviBtnGrey_support. + late NaviBtnGreyModel naviBtnGreySupportModel; + // Model for NaviBtnGrey_TOS. + late NaviBtnGreyModel naviBtnGreyTOSModel; + // Model for NaviBtnGrey_InviteFriends. + late NaviBtnGreyModel naviBtnGreyInviteFriendsModel; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + userPhotoModel = createModel(context, () => UserPhotoModel()); + heading2AccountModel1 = createModel(context, () => Heading2Model()); + naviBtnGreyNotificationSettingsModel1 = + createModel(context, () => NaviBtnGreyModel()); + naviBtnGreyPaymentOptionsModel = + createModel(context, () => NaviBtnGreyModel()); + naviBtnGreyNotificationSettingsModel2 = + createModel(context, () => NaviBtnGreyModel()); + heading2AccountModel2 = createModel(context, () => Heading2Model()); + naviBtnGreyCountryModel = createModel(context, () => NaviBtnGreyModel()); + naviBtnGreyEditProfileModel = + createModel(context, () => NaviBtnGreyModel()); + naviBtnGreyNotificationSettingsModel3 = + createModel(context, () => NaviBtnGreyModel()); + heading2GeneralModel = createModel(context, () => Heading2Model()); + naviBtnGreySupportModel = createModel(context, () => NaviBtnGreyModel()); + naviBtnGreyTOSModel = createModel(context, () => NaviBtnGreyModel()); + naviBtnGreyInviteFriendsModel = + createModel(context, () => NaviBtnGreyModel()); + } + + void dispose() { + unfocusNode.dispose(); + userPhotoModel.dispose(); + heading2AccountModel1.dispose(); + naviBtnGreyNotificationSettingsModel1.dispose(); + naviBtnGreyPaymentOptionsModel.dispose(); + naviBtnGreyNotificationSettingsModel2.dispose(); + heading2AccountModel2.dispose(); + naviBtnGreyCountryModel.dispose(); + naviBtnGreyEditProfileModel.dispose(); + naviBtnGreyNotificationSettingsModel3.dispose(); + heading2GeneralModel.dispose(); + naviBtnGreySupportModel.dispose(); + naviBtnGreyTOSModel.dispose(); + naviBtnGreyInviteFriendsModel.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/account_pages/account/account_widget.dart b/lib/pages/account_pages/account/account_widget.dart new file mode 100644 index 0000000..5242612 --- /dev/null +++ b/lib/pages/account_pages/account/account_widget.dart @@ -0,0 +1,698 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/components/heading2/heading2_widget.dart'; +import '/components/navi_btn_grey/navi_btn_grey_widget.dart'; +import '/components/user_photo/user_photo_widget.dart'; +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'account_model.dart'; +export 'account_model.dart'; + +class AccountWidget extends StatefulWidget { + const AccountWidget({Key? key}) : super(key: key); + + @override + _AccountWidgetState createState() => _AccountWidgetState(); +} + +class _AccountWidgetState extends State + with TickerProviderStateMixin { + late AccountModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + FadeEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + ], + ), + 'textOnPageLoadAnimation1': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + FadeEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + 'textOnPageLoadAnimation2': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + FadeEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => AccountModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () { + print('IconButton pressed ...'); + }, + ), + title: Text( + 'Account Settings', + style: FlutterFlowTheme.of(context).bodyLarge.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).secondaryBackground, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyLargeFamily), + ), + ), + actions: [], + centerTitle: false, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Wrap( + spacing: 0.0, + runSpacing: 0.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 1.0, 0.0, 0.0), + child: StreamBuilder( + stream: UsersRecord.getDocument( + currentUserReference!), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitPumpingHeart( + color: FlutterFlowTheme.of(context) + .primary, + size: 50.0, + ), + ), + ); + } + final containerPictureNameUsersRecord = + snapshot.data!; + return Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 16.0, 16.0, 16.0, 16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Container( + width: 90.0, + height: 90.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primary, + shape: BoxShape.circle, + border: Border.all( + width: 2.0, + ), + ), + child: wrapWithModel( + model: _model.userPhotoModel, + updateCallback: () => + setState(() {}), + child: UserPhotoWidget( + parameter1: false, + ), + ), + ).animateOnPageLoad(animationsMap[ + 'containerOnPageLoadAnimation']!), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 16.0, 0.0, 0.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Text( + containerPictureNameUsersRecord + .displayName, + style: + FlutterFlowTheme.of(context) + .headlineSmall + .override( + fontFamily: 'Poppins', + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .headlineSmallFamily), + ), + ).animateOnPageLoad(animationsMap[ + 'textOnPageLoadAnimation1']!), + Padding( + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 4.0, 0.0, 0.0), + child: Text( + containerPictureNameUsersRecord + .email, + style: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: 'Poppins', + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ).animateOnPageLoad(animationsMap[ + 'textOnPageLoadAnimation2']!), + ), + Padding( + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 20.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + // Log Out + GoRouter.of(context) + .prepareAuthEvent(); + await authManager.signOut(); + GoRouter.of(context) + .clearRedirectLocation(); + + context.goNamedAuth('Login', + context.mounted); + }, + text: 'Log Out', + options: FFButtonOptions( + height: 40.0, + padding: + EdgeInsetsDirectional + .fromSTEB(24.0, 0.0, + 24.0, 0.0), + iconPadding: + EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + color: FlutterFlowTheme.of( + context) + .primary, + textStyle: FlutterFlowTheme + .of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 8.0), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ); + }, + ), + ), + Visibility( + visible: + currentUserDocument?.permissions?.donor ?? true, + child: AuthUserStreamWidget( + builder: (context) => Container( + width: valueOrDefault( + MediaQuery.sizeOf(context).width >= 1280.0 + ? valueOrDefault( + MediaQuery.sizeOf(context).width * + 0.5, + 640.0, + ) + : MediaQuery.sizeOf(context).width, + 640.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + ), + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 25.0, 0.0, 25.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + wrapWithModel( + model: _model.heading2AccountModel1, + updateCallback: () => + setState(() {}), + child: Heading2Widget( + headingText: 'Client', + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context + .pushNamed('ClientDonation'); + }, + child: wrapWithModel( + model: _model + .naviBtnGreyNotificationSettingsModel1, + updateCallback: () => + setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Client Donation', + buttonIcon: FaIcon( + FontAwesomeIcons.bell, + color: FlutterFlowTheme.of( + context) + .secondaryText, + size: 24.0, + ), + ), + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context + .pushNamed('PaymentOptions'); + }, + child: wrapWithModel( + model: _model + .naviBtnGreyPaymentOptionsModel, + updateCallback: () => + setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Payment Options', + buttonIcon: FaIcon( + FontAwesomeIcons.dollarSign, + color: FlutterFlowTheme.of( + context) + .secondaryText, + size: 24.0, + ), + ), + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context + .pushNamed('Notifications'); + }, + child: wrapWithModel( + model: _model + .naviBtnGreyNotificationSettingsModel2, + updateCallback: () => + setState(() {}), + child: NaviBtnGreyWidget( + buttonText: + 'Notification Settings', + buttonIcon: FaIcon( + FontAwesomeIcons.bell, + color: FlutterFlowTheme.of( + context) + .secondaryText, + size: 24.0, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + Container( + width: valueOrDefault( + MediaQuery.sizeOf(context).width >= 1280.0 + ? valueOrDefault( + MediaQuery.sizeOf(context).width * 0.5, + 640.0, + ) + : MediaQuery.sizeOf(context).width, + 640.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + ), + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 25.0, 0.0, 25.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + wrapWithModel( + model: _model.heading2AccountModel2, + updateCallback: () => setState(() {}), + child: Heading2Widget( + headingText: 'Account', + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed( + 'Country', + extra: { + kTransitionInfoKey: + TransitionInfo( + hasTransition: true, + transitionType: + PageTransitionType.fade, + duration: + Duration(milliseconds: 0), + ), + }, + ); + }, + child: wrapWithModel( + model: _model.naviBtnGreyCountryModel, + updateCallback: () => setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Country', + buttonIcon: FaIcon( + FontAwesomeIcons.globe, + color: + FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + ), + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed('Profile'); + }, + child: wrapWithModel( + model: _model + .naviBtnGreyEditProfileModel, + updateCallback: () => setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Edit Profile', + buttonIcon: FaIcon( + FontAwesomeIcons.userCircle, + color: + FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + ), + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed('Notifications'); + }, + child: wrapWithModel( + model: _model + .naviBtnGreyNotificationSettingsModel3, + updateCallback: () => setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Notification Settings', + buttonIcon: FaIcon( + FontAwesomeIcons.bell, + color: + FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + Container( + width: valueOrDefault( + MediaQuery.sizeOf(context).width >= 1280.0 + ? (MediaQuery.sizeOf(context).width * 0.5) + : MediaQuery.sizeOf(context).width, + 640.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + ), + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 25.0, 0.0, 25.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + wrapWithModel( + model: _model.heading2GeneralModel, + updateCallback: () => setState(() {}), + child: Heading2Widget( + headingText: 'General', + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed( + 'Support', + extra: { + kTransitionInfoKey: + TransitionInfo( + hasTransition: true, + transitionType: + PageTransitionType.fade, + duration: + Duration(milliseconds: 0), + ), + }, + ); + }, + child: wrapWithModel( + model: _model.naviBtnGreySupportModel, + updateCallback: () => setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Support', + buttonIcon: Icon( + Icons.help_outline, + color: + FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + ), + ), + ), + wrapWithModel( + model: _model.naviBtnGreyTOSModel, + updateCallback: () => setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Terms of Service', + buttonIcon: Icon( + Icons.help_outline, + color: FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + ), + ), + wrapWithModel( + model: _model + .naviBtnGreyInviteFriendsModel, + updateCallback: () => setState(() {}), + child: NaviBtnGreyWidget( + buttonText: 'Invite Friends', + buttonIcon: FaIcon( + FontAwesomeIcons.userFriends, + color: FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/account_pages/country/country_model.dart b/lib/pages/account_pages/country/country_model.dart new file mode 100644 index 0000000..c9ec8aa --- /dev/null +++ b/lib/pages/account_pages/country/country_model.dart @@ -0,0 +1,41 @@ +import '/components/heading2/heading2_widget.dart'; +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_radio_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/form_field_controller.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class CountryModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + final formKey = GlobalKey(); + // Model for Heading2 component. + late Heading2Model heading2Model; + // State field(s) for RadioButton widget. + FormFieldController? radioButtonValueController; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + heading2Model = createModel(context, () => Heading2Model()); + } + + void dispose() { + unfocusNode.dispose(); + heading2Model.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. + + String? get radioButtonValue => radioButtonValueController?.value; +} diff --git a/lib/pages/account_pages/country/country_widget.dart b/lib/pages/account_pages/country/country_widget.dart new file mode 100644 index 0000000..d20b2f7 --- /dev/null +++ b/lib/pages/account_pages/country/country_widget.dart @@ -0,0 +1,193 @@ +import '/components/heading2/heading2_widget.dart'; +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_radio_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/form_field_controller.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'country_model.dart'; +export 'country_model.dart'; + +class CountryWidget extends StatefulWidget { + const CountryWidget({Key? key}) : super(key: key); + + @override + _CountryWidgetState createState() => _CountryWidgetState(); +} + +class _CountryWidgetState extends State + with TickerProviderStateMixin { + late CountryModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'formOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => CountryModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Country', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(20.0, 20.0, 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + wrapWithModel( + model: _model.heading2Model, + updateCallback: () => setState(() {}), + child: Heading2Widget( + headingText: 'Your Country', + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Form( + key: _model.formKey, + autovalidateMode: AutovalidateMode.disabled, + child: Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).accent4, + borderRadius: BorderRadius.circular(8.0), + ), + child: FlutterFlowRadioButton( + options: ['Canada', 'United States', 'Mexico'] + .toList(), + onChanged: (val) => setState(() {}), + controller: + _model.radioButtonValueController ??= + FormFieldController(null), + optionHeight: 32.0, + textStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + fontSize: 16.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + selectedTextStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: + FlutterFlowTheme.of(context).tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + buttonPosition: RadioButtonPosition.left, + direction: Axis.vertical, + radioButtonColor: + FlutterFlowTheme.of(context).tertiary, + inactiveRadioButtonColor: + FlutterFlowTheme.of(context).secondaryText, + toggleable: false, + horizontalAlignment: WrapAlignment.start, + verticalAlignment: WrapCrossAlignment.start, + ), + ), + ).animateOnPageLoad( + animationsMap['formOnPageLoadAnimation']!), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/account_pages/notifications/notifications_model.dart b/lib/pages/account_pages/notifications/notifications_model.dart new file mode 100644 index 0000000..ecdaa69 --- /dev/null +++ b/lib/pages/account_pages/notifications/notifications_model.dart @@ -0,0 +1,40 @@ +import '/components/heading2/heading2_widget.dart'; +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class NotificationsModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for Heading2 component. + late Heading2Model heading2Model; + // State field(s) for Switch widget. + bool? switchValue1; + // State field(s) for Switch widget. + bool? switchValue2; + // State field(s) for Switch widget. + bool? switchValue3; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + heading2Model = createModel(context, () => Heading2Model()); + } + + void dispose() { + unfocusNode.dispose(); + heading2Model.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/account_pages/notifications/notifications_widget.dart b/lib/pages/account_pages/notifications/notifications_widget.dart new file mode 100644 index 0000000..abfbb06 --- /dev/null +++ b/lib/pages/account_pages/notifications/notifications_widget.dart @@ -0,0 +1,202 @@ +import '/components/heading2/heading2_widget.dart'; +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'notifications_model.dart'; +export 'notifications_model.dart'; + +class NotificationsWidget extends StatefulWidget { + const NotificationsWidget({Key? key}) : super(key: key); + + @override + _NotificationsWidgetState createState() => _NotificationsWidgetState(); +} + +class _NotificationsWidgetState extends State + with TickerProviderStateMixin { + late NotificationsModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'columnOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => NotificationsModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Notifications', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(20.0, 20.0, 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: wrapWithModel( + model: _model.heading2Model, + updateCallback: () => setState(() {}), + child: Heading2Widget( + headingText: 'Notification Preferences', + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Donation upcoming in 5 days', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + Switch.adaptive( + value: _model.switchValue1 ??= true, + onChanged: (newValue) async { + setState(() => _model.switchValue1 = newValue!); + }, + activeColor: FlutterFlowTheme.of(context).tertiary, + activeTrackColor: + FlutterFlowTheme.of(context).accent1, + inactiveTrackColor: + FlutterFlowTheme.of(context).alternate, + inactiveThumbColor: + FlutterFlowTheme.of(context).secondaryText, + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Donation Payment Status', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + Switch.adaptive( + value: _model.switchValue2 ??= true, + onChanged: (newValue) async { + setState(() => _model.switchValue2 = newValue!); + }, + activeColor: FlutterFlowTheme.of(context).tertiary, + activeTrackColor: + FlutterFlowTheme.of(context).accent1, + inactiveTrackColor: + FlutterFlowTheme.of(context).alternate, + inactiveThumbColor: + FlutterFlowTheme.of(context).secondaryText, + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Tax Receipt Status', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + Switch.adaptive( + value: _model.switchValue3 ??= true, + onChanged: (newValue) async { + setState(() => _model.switchValue3 = newValue!); + }, + activeColor: FlutterFlowTheme.of(context).tertiary, + activeTrackColor: + FlutterFlowTheme.of(context).accent1, + inactiveTrackColor: + FlutterFlowTheme.of(context).alternate, + inactiveThumbColor: + FlutterFlowTheme.of(context).secondaryText, + ), + ], + ), + ], + ).animateOnPageLoad( + animationsMap['columnOnPageLoadAnimation']!), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/account_pages/payment_options/payment_options_model.dart b/lib/pages/account_pages/payment_options/payment_options_model.dart new file mode 100644 index 0000000..ac45fa9 --- /dev/null +++ b/lib/pages/account_pages/payment_options/payment_options_model.dart @@ -0,0 +1,29 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class PaymentOptionsModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/account_pages/payment_options/payment_options_widget.dart b/lib/pages/account_pages/payment_options/payment_options_widget.dart new file mode 100644 index 0000000..332ac85 --- /dev/null +++ b/lib/pages/account_pages/payment_options/payment_options_widget.dart @@ -0,0 +1,180 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'payment_options_model.dart'; +export 'payment_options_model.dart'; + +class PaymentOptionsWidget extends StatefulWidget { + const PaymentOptionsWidget({Key? key}) : super(key: key); + + @override + _PaymentOptionsWidgetState createState() => _PaymentOptionsWidgetState(); +} + +class _PaymentOptionsWidgetState extends State + with TickerProviderStateMixin { + late PaymentOptionsModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(0.0, 50.0), + end: Offset(0.0, 0.0), + ), + ], + ), + 'textOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + FadeEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => PaymentOptionsModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'My Payment Options', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(20.0, 20.0, 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: 400.0, + child: custom_widgets.GetCCNWidget( + width: MediaQuery.sizeOf(context).width * 1.0, + height: 400.0, + saveOnly: true, + refreshPageUI: () async {}, + goToNextPage: () async {}, + ), + ).animateOnPageLoad( + animationsMap['containerOnPageLoadAnimation']!), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: Text( + 'Your credit card information is stored only on your device and not on our servers.', + textAlign: TextAlign.center, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + fontSize: 14.0, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ).animateOnPageLoad( + animationsMap['textOnPageLoadAnimation']!), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/account_pages/profile/profile_model.dart b/lib/pages/account_pages/profile/profile_model.dart new file mode 100644 index 0000000..4275277 --- /dev/null +++ b/lib/pages/account_pages/profile/profile_model.dart @@ -0,0 +1,49 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class ProfileModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + final formKey = GlobalKey(); + // State field(s) for TextField widget. + TextEditingController? textController1; + late bool passwordVisibility1; + String? Function(BuildContext, String?)? textController1Validator; + // State field(s) for TextField widget. + TextEditingController? textController2; + late bool passwordVisibility2; + String? Function(BuildContext, String?)? textController2Validator; + // State field(s) for TextField widget. + TextEditingController? textController3; + late bool passwordVisibility3; + String? Function(BuildContext, String?)? textController3Validator; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + passwordVisibility1 = false; + passwordVisibility2 = false; + passwordVisibility3 = false; + } + + void dispose() { + unfocusNode.dispose(); + textController1?.dispose(); + textController2?.dispose(); + textController3?.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/account_pages/profile/profile_widget.dart b/lib/pages/account_pages/profile/profile_widget.dart new file mode 100644 index 0000000..6f7595e --- /dev/null +++ b/lib/pages/account_pages/profile/profile_widget.dart @@ -0,0 +1,463 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'profile_model.dart'; +export 'profile_model.dart'; + +class ProfileWidget extends StatefulWidget { + const ProfileWidget({Key? key}) : super(key: key); + + @override + _ProfileWidgetState createState() => _ProfileWidgetState(); +} + +class _ProfileWidgetState extends State + with TickerProviderStateMixin { + late ProfileModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'formOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ProfileModel()); + + _model.textController1 ??= TextEditingController(); + _model.textController2 ??= TextEditingController(); + _model.textController3 ??= TextEditingController(); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Profile', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(20.0, 20.0, 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 20.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Change Password', + style: FlutterFlowTheme.of(context).titleLarge, + ), + ], + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Form( + key: _model.formKey, + autovalidateMode: AutovalidateMode.disabled, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 10.0), + child: TextFormField( + controller: _model.textController1, + autofocus: true, + obscureText: !_model.passwordVisibility1, + decoration: InputDecoration( + labelText: 'Old Password', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium, + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent2, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + suffixIcon: InkWell( + onTap: () => setState( + () => _model.passwordVisibility1 = + !_model.passwordVisibility1, + ), + focusNode: + FocusNode(skipTraversal: true), + child: Icon( + _model.passwordVisibility1 + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + size: 22, + ), + ), + ), + style: + FlutterFlowTheme.of(context).bodyMedium, + validator: _model.textController1Validator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 10.0), + child: TextFormField( + controller: _model.textController2, + autofocus: true, + obscureText: !_model.passwordVisibility2, + decoration: InputDecoration( + labelText: 'New Password', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium, + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent2, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + suffixIcon: InkWell( + onTap: () => setState( + () => _model.passwordVisibility2 = + !_model.passwordVisibility2, + ), + focusNode: + FocusNode(skipTraversal: true), + child: Icon( + _model.passwordVisibility2 + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + size: 22, + ), + ), + ), + style: + FlutterFlowTheme.of(context).bodyMedium, + validator: _model.textController2Validator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 10.0), + child: TextFormField( + controller: _model.textController3, + autofocus: true, + obscureText: !_model.passwordVisibility3, + decoration: InputDecoration( + labelText: 'News Password (Confirm)', + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium, + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent2, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + suffixIcon: InkWell( + onTap: () => setState( + () => _model.passwordVisibility3 = + !_model.passwordVisibility3, + ), + focusNode: + FocusNode(skipTraversal: true), + child: Icon( + _model.passwordVisibility3 + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + size: 22, + ), + ), + ), + style: + FlutterFlowTheme.of(context).bodyMedium, + validator: _model.textController3Validator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 10.0, 0.0, 10.0), + child: FFButtonWidget( + onPressed: () { + print('Button pressed ...'); + }, + text: 'Change Password', + options: FFButtonOptions( + height: 40.0, + padding: EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: + FlutterFlowTheme.of(context).primary, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + elevation: 0.0, + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + ], + ), + ).animateOnPageLoad( + animationsMap['formOnPageLoadAnimation']!), + ), + ], + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 20.0, 0.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Text( + 'At least 1 uppercase, 1 lowercase, 1 numeric, 1 non-alphanumeric', + style: FlutterFlowTheme.of(context).labelSmall, + ), + Text( + 'Length - Min 6 / Max 4096 characters', + style: FlutterFlowTheme.of(context).labelSmall, + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/account_pages/support/support_model.dart b/lib/pages/account_pages/support/support_model.dart new file mode 100644 index 0000000..e83e03c --- /dev/null +++ b/lib/pages/account_pages/support/support_model.dart @@ -0,0 +1,39 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_drop_down.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/flutter_flow/form_field_controller.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class SupportModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + final formKey = GlobalKey(); + // State field(s) for DropDown widget. + String? dropDownValue; + FormFieldController? dropDownValueController; + // State field(s) for TextField widget. + TextEditingController? textController; + String? Function(BuildContext, String?)? textControllerValidator; + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + textController?.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/account_pages/support/support_widget.dart b/lib/pages/account_pages/support/support_widget.dart new file mode 100644 index 0000000..4d116bd --- /dev/null +++ b/lib/pages/account_pages/support/support_widget.dart @@ -0,0 +1,459 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_drop_down.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/flutter_flow/form_field_controller.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'support_model.dart'; +export 'support_model.dart'; + +class SupportWidget extends StatefulWidget { + const SupportWidget({Key? key}) : super(key: key); + + @override + _SupportWidgetState createState() => _SupportWidgetState(); +} + +class _SupportWidgetState extends State + with TickerProviderStateMixin { + late SupportModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'columnOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + 'rowOnPageLoadAnimation1': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + FadeEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: 0.0, + end: 1.0, + ), + ], + ), + 'rowOnPageLoadAnimation2': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => SupportModel()); + + _model.textController ??= TextEditingController(); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Support', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(20.0, 20.0, 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 20.0, 0.0, 20.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'By Email', + style: FlutterFlowTheme.of(context).titleLarge, + ), + ], + ).animateOnPageLoad( + animationsMap['rowOnPageLoadAnimation1']!), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 20.0, 0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Form( + key: _model.formKey, + autovalidateMode: AutovalidateMode.disabled, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 20.0), + child: FlutterFlowDropDown( + controller: _model + .dropDownValueController ??= + FormFieldController( + null), + options: [ + 'Payment / Tax Receipt', + 'Feature suggestion', + 'Technical issue', + 'Other' + ], + onChanged: (val) => setState(() => + _model.dropDownValue = val), + width: MediaQuery.sizeOf(context) + .width * + 1.0, + height: 50.0, + textStyle: + FlutterFlowTheme.of(context) + .bodySmall, + hintText: 'How we can help ...', + icon: Icon( + Icons + .keyboard_arrow_down_rounded, + color: + FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + fillColor: + FlutterFlowTheme.of(context) + .primaryBackground, + elevation: 2.0, + borderColor: + FlutterFlowTheme.of(context) + .secondaryBackground, + borderWidth: 2.0, + borderRadius: 8.0, + margin: EdgeInsetsDirectional + .fromSTEB( + 16.0, 4.0, 16.0, 4.0), + hidesUnderline: true, + isSearchable: false, + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context) + .width * + 1.0, + child: TextFormField( + controller: + _model.textController, + autofocus: true, + obscureText: false, + decoration: InputDecoration( + labelStyle: + FlutterFlowTheme.of( + context) + .labelMedium, + hintText: 'Details ...', + hintStyle: FlutterFlowTheme + .of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .labelMediumFamily, + color: + FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 14.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme + .of(context) + .secondaryBackground, + width: 2.0, + ), + borderRadius: + BorderRadius.circular( + 8.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular( + 8.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular( + 8.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular( + 8.0), + ), + ), + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme + .of(context) + .secondaryText, + fontSize: 14.0, + fontWeight: + FontWeight.normal, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + textAlign: TextAlign.start, + maxLines: 50, + minLines: 5, + validator: _model + .textControllerValidator + .asValidator(context), + ), + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + FFButtonWidget( + onPressed: () async { + ScaffoldMessenger.of(context) + .showSnackBar( + SnackBar( + content: Text( + 'Your message has been received. Check your email.', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: + FlutterFlowTheme.of( + context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + duration: Duration( + milliseconds: 4000), + backgroundColor: + FlutterFlowTheme.of(context) + .secondaryBackground, + ), + ); + }, + text: 'Send', + icon: Icon( + Icons.send, + size: 20.0, + ), + options: FFButtonOptions( + height: 40.0, + padding: + EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .tertiary, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + elevation: 0.0, + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ).animateOnPageLoad( + animationsMap['rowOnPageLoadAnimation2']!), + ), + ], + ), + ).animateOnPageLoad( + animationsMap['columnOnPageLoadAnimation']!), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/account_pages/term_of_service/term_of_service_model.dart b/lib/pages/account_pages/term_of_service/term_of_service_model.dart new file mode 100644 index 0000000..8cf322d --- /dev/null +++ b/lib/pages/account_pages/term_of_service/term_of_service_model.dart @@ -0,0 +1,28 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class TermOfServiceModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/account_pages/term_of_service/term_of_service_widget.dart b/lib/pages/account_pages/term_of_service/term_of_service_widget.dart new file mode 100644 index 0000000..1cc70e5 --- /dev/null +++ b/lib/pages/account_pages/term_of_service/term_of_service_widget.dart @@ -0,0 +1,161 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'term_of_service_model.dart'; +export 'term_of_service_model.dart'; + +class TermOfServiceWidget extends StatefulWidget { + const TermOfServiceWidget({Key? key}) : super(key: key); + + @override + _TermOfServiceWidgetState createState() => _TermOfServiceWidgetState(); +} + +class _TermOfServiceWidgetState extends State + with TickerProviderStateMixin { + late TermOfServiceModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'columnOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeInOut, + delay: 0.ms, + duration: 600.ms, + begin: Offset(10.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => TermOfServiceModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Term of Service', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(20.0, 20.0, 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 20.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Terms of Service', + style: FlutterFlowTheme.of(context).titleLarge, + ), + ], + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + 'Lorem ipsum dolor sit amet, mei quidam pertinax an, nec ex oportere omittantur, his et aliquid fabulas scriptorem. Cu munere deleniti ullamcorper sed. Consul fastidii torquatos mei in! Nam no populo tincidunt voluptatum, ea pro noster legendos! An postulant deterruisset mediocritatem usu, et pri alii novum voluptaria. Te duo aeque platonem signiferumque!\n\nAn vis delenit dolorem? Audiam instructior sea ut, harum adipisci intellegebat quo no? Dictas hendrerit eos no. Agam graece facilisi sit no. Vitae graeci facilis mei et, tantas complectitur est id, consulatu mnesarchum at nam!\n\nVix porro mollis tamquam an. Mel magna illum constituam ei. An porro erroribus honestatis sit, sed putant inermis eloquentiam ex! Sed et euismod detracto. Ius te noster graeco conceptam, everti legimus sensibus sed at!\n\nIn mel consequuntur definitiones, no probatus mnesarchum definitiones has. Assum copiosae te eam, mei ei rebum error incorrupte. No mea tacimates erroribus reprehendunt! Qui vidit denique voluptatibus ea, ei tota verterem pericula pro. Eos dicat alterum reformidans at, diceret adipisci dignissim at mel, no ius fugit debet vitae? In erat aliquam quo, mea doming maiorum eu?\n\nMei cibo omnis inermis ex. Id usu stet dicat putant. Eius facete mea ea, idque probatus usu ei! Et legimus inimicus vix, errem principes vim an.\n\nNe mei iriure perpetua gloriatur. Nec et cetero labores principes, impedit consulatu eam eu? Vis ne tritani detracto omnesque, ut quo habemus voluptatum? Nonumy delectus eu pri, adipiscing repudiandae nam ad. Porro nullam offendit duo an, an odio delectus mel.\n\nEt vel insolens sadipscing. Autem eripuit volumus ne nam, est fabulas lobortis nominati an. An illud honestatis quo, ea hinc vitae interesset vis! Mel adipisci repudiandae ex, nec mentitum rationibus an, id soleat doctus antiopam cum.\n\nVel eu tantas fabulas veritus, quas reque expetenda mel in. Quando conceptam inciderint pri cu. Vix ut porro omnesque temporibus, esse congue adipisci pri eu? Sumo platonem cum an, at possim definitionem pro, no vim veri nullam aperiam. Ei fabellas quaerendum pri, ei his rationibus adipiscing ullamcorper, eum ut mutat decore suavitate?\n\nCu mei illud nonumy scribentur, eu alia oratio aliquam sed, soleat tibique senserit in mei. Qui elit solet eleifend ne, no sed natum dicam. Est te propriae perfecto disputando, eu simul maiorum molestiae sit. Pro velit nihil molestie te, ut ceteros fastidii verterem per!\n\nReque fuisset elaboraret eos ea. Et epicurei disputando eam? Enim feugait mandamus cu nec, appareat placerat no pri. Per nulla scriptorem ut?\n\nVim clita commune vulputate cu, usu labore melius insolens ei. His et eros choro salutandi. Has quod epicuri evertitur ex, vim tamquam consequat constituam ea! Option virtute te pri. Ei tibique probatus contentiones duo. Vim ei aliquip meliore appareat, quod aperiri incorrupte ex pri.\n\nVel ad exerci labore percipit. Eam ea suas assum eligendi, mel ne persius accusata, duo essent iracundia reformidans an. At vel iisque salutandi, case persius antiopam ei eum? No novum tacimates philosophia qui. Fierent ponderum eleifend ut quo. Pri postea semper id, at ullum ceteros molestie sed.\n\nVerear perfecto singulis vim in, usu ei erat senserit tincidunt! Illum qualisque te eam! Adhuc saepe eleifend eam no, ex case quidam mel, an qui dolore scripserit! No regione consequat sit, an sonet delenit nam?\n\nAgam graeco oportere ex ius, vim voluptua epicurei ocurreret id, in eos vidit recteque. Omnis indoctum mei at, ad sea tollit tacimates, mundi veniam ne est! Per id duis consequuntur, ne velit novum tollit nec, has tale copiosae inciderint id! Sea cu commodo delectus, quo no laudem delenit urbanitas, eu copiosae oporteat sit.\n\nEst an prima reprimique, eum oporteat recteque in! Eu consul sapientem eos, vel ne autem legendos! Ei munere impetus tacimates est, ius ei populo repudiandae? Mel ad partem aperiri diceret. Commodo eripuit electram at cum, appareat consectetuer ne quo.\n\nCu eam dicant ceteros, mundi inermis rationibus et eum. Eam stet vocibus efficiendi id, his voluptua consetetur ea, nec natum deterruisset at! Falli labores te sit, cu veniam postulant erroribus qui. Ne vis altera nostrud, possit conceptam appellantur ex mea, at augue legimus intellegat sea. Everti denique cu eam, eos incorrupte argumentum intellegam et.\n\nEa per graece dictas iriure! Cum soluta dissentiet eu. Lorem recusabo est ad. Ne mollis fastidii oportere cum, periculis adversarium no pri. At has quidam salutatus, cum no dicunt scribentur.\n\nSea in diam ubique phaedrum? Brute movet meliore ut mel! Eu eos stet dictas dolorum, id dicit offendit sea. Duis nostro recteque vix an. Alia reformidans an mei, quem facilisis eos at.\n\nElectram suscipiantur an vim? Rebum laboramus usu cu? Odio exerci moderatius at pri, error deterruisset ex duo. Ei nec qualisque sententiae. Et suas alia evertitur quo, quo partem impetus ut, usu omittam tacimates persequeris at? Eu per brute utroque voluptatibus? Eius persecuti pri at.\n\nAccumsan volutpat patrioque vel ei. Mea no eleifend conclusionemque, vel quaeque docendi mandamus et. At soluta graeco mea! Commodo percipit atomorum ei ius. Fabulas ancillae senserit at vis, ex has oratio suscipiantur!', + style: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodySmallFamily, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + lineHeight: 1.11, + ), + ), + ), + ], + ), + ], + ), + ).animateOnPageLoad( + animationsMap['columnOnPageLoadAnimation']!), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/authentication_pages/create_account/create_account_model.dart b/lib/pages/authentication_pages/create_account/create_account_model.dart new file mode 100644 index 0000000..e4f4a9a --- /dev/null +++ b/lib/pages/authentication_pages/create_account/create_account_model.dart @@ -0,0 +1,125 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class CreateAccountModel extends FlutterFlowModel { + /// Local state fields for this page. + + String? createAccountError; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + final formKey = GlobalKey(); + // Model for Row_LogoAndName component. + late RowLogoAndNameModel rowLogoAndNameModel; + // State field(s) for firstName widget. + TextEditingController? firstNameController; + String? Function(BuildContext, String?)? firstNameControllerValidator; + String? _firstNameControllerValidator(BuildContext context, String? val) { + if (val == null || val.isEmpty) { + return 'First name is required'; + } + + return null; + } + + // State field(s) for surname widget. + TextEditingController? surnameController; + String? Function(BuildContext, String?)? surnameControllerValidator; + String? _surnameControllerValidator(BuildContext context, String? val) { + if (val == null || val.isEmpty) { + return 'Surname is required'; + } + + return null; + } + + // State field(s) for emailAddress widget. + TextEditingController? emailAddressController; + String? Function(BuildContext, String?)? emailAddressControllerValidator; + String? _emailAddressControllerValidator(BuildContext context, String? val) { + if (val == null || val.isEmpty) { + return 'Email address is required'; + } + + if (!RegExp(kTextValidatorEmailRegex).hasMatch(val)) { + return 'Email invalid'; + } + return null; + } + + // State field(s) for password widget. + TextEditingController? passwordController; + late bool passwordVisibility; + String? Function(BuildContext, String?)? passwordControllerValidator; + String? _passwordControllerValidator(BuildContext context, String? val) { + if (val == null || val.isEmpty) { + return 'Password is required'; + } + + if (val.length < 6) { + return 'Password must be at least 6 characters'; + } + if (val.length > 4096) { + return 'Password must be at most 4096 characters'; + } + + return null; + } + + // State field(s) for confirmPassword widget. + TextEditingController? confirmPasswordController; + late bool confirmPasswordVisibility; + String? Function(BuildContext, String?)? confirmPasswordControllerValidator; + String? _confirmPasswordControllerValidator( + BuildContext context, String? val) { + if (val == null || val.isEmpty) { + return 'Field is required'; + } + + if (val.length < 6) { + return 'Password must be at least 6 characters'; + } + if (val.length > 4096) { + return 'Password must be at most 4096 characters'; + } + + return null; + } + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + rowLogoAndNameModel = createModel(context, () => RowLogoAndNameModel()); + firstNameControllerValidator = _firstNameControllerValidator; + surnameControllerValidator = _surnameControllerValidator; + emailAddressControllerValidator = _emailAddressControllerValidator; + passwordVisibility = false; + passwordControllerValidator = _passwordControllerValidator; + confirmPasswordVisibility = false; + confirmPasswordControllerValidator = _confirmPasswordControllerValidator; + } + + void dispose() { + unfocusNode.dispose(); + rowLogoAndNameModel.dispose(); + firstNameController?.dispose(); + surnameController?.dispose(); + emailAddressController?.dispose(); + passwordController?.dispose(); + confirmPasswordController?.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/authentication_pages/create_account/create_account_widget.dart b/lib/pages/authentication_pages/create_account/create_account_widget.dart new file mode 100644 index 0000000..b24dc72 --- /dev/null +++ b/lib/pages/authentication_pages/create_account/create_account_widget.dart @@ -0,0 +1,766 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/backend/backend.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'create_account_model.dart'; +export 'create_account_model.dart'; + +class CreateAccountWidget extends StatefulWidget { + const CreateAccountWidget({Key? key}) : super(key: key); + + @override + _CreateAccountWidgetState createState() => _CreateAccountWidgetState(); +} + +class _CreateAccountWidgetState extends State { + late CreateAccountModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => CreateAccountModel()); + + _model.firstNameController ??= TextEditingController(); + _model.surnameController ??= TextEditingController(); + _model.emailAddressController ??= TextEditingController(); + _model.passwordController ??= TextEditingController(); + _model.confirmPasswordController ??= TextEditingController(); + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 8.0), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(12.0, 0.0, 0.0, 0.0), + child: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 50.0, + icon: Icon( + Icons.arrow_back_rounded, + color: + FlutterFlowTheme.of(context).secondaryBackground, + size: 24.0, + ), + onPressed: () async { + context.pop(); + }, + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(4.0, 0.0, 0.0, 0.0), + child: Text( + 'Back', + style: + FlutterFlowTheme.of(context).displaySmall.override( + fontFamily: FlutterFlowTheme.of(context) + .displaySmallFamily, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + fontSize: 16.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .displaySmallFamily), + ), + ), + ), + ], + ), + ), + ], + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: Align( + alignment: AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(25.0, 0.0, 25.0, 0.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + constraints: BoxConstraints( + maxWidth: 400.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + alignment: AlignmentDirectional(0.0, -1.0), + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + wrapWithModel( + model: _model.rowLogoAndNameModel, + updateCallback: () => setState(() {}), + child: RowLogoAndNameWidget(), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 25.0, 0.0, 25.0), + child: Text( + 'Create Account', + style: FlutterFlowTheme.of(context).titleLarge, + ), + ), + Form( + key: _model.formKey, + autovalidateMode: AutovalidateMode.disabled, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Expanded( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 15.0), + child: TextFormField( + controller: _model.firstNameController, + obscureText: false, + decoration: InputDecoration( + labelText: 'First Name', + labelStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Lexend Deca', + color: + FlutterFlowTheme.of(context) + .secondaryText, + fontSize: 14.0, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context) + .primaryBackground, + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 20.0, 24.0), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium, + maxLines: null, + validator: _model + .firstNameControllerValidator + .asValidator(context), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 15.0), + child: TextFormField( + controller: _model.surnameController, + obscureText: false, + decoration: InputDecoration( + labelText: 'Surname', + labelStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodySmallFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodySmallFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Lexend Deca', + color: + FlutterFlowTheme.of(context) + .secondaryText, + fontSize: 14.0, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .tertiary, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context) + .primaryBackground, + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 20.0, 24.0), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium, + maxLines: null, + validator: _model + .surnameControllerValidator + .asValidator(context), + ), + ), + ), + ].divide(SizedBox(width: 20.0)), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 15.0), + child: TextFormField( + controller: _model.emailAddressController, + obscureText: false, + decoration: InputDecoration( + labelStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Lexend Deca', + color: FlutterFlowTheme.of(context) + .secondaryText, + fontSize: 14.0, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context).tertiary, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context) + .primaryBackground, + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 20.0, 24.0), + ), + style: FlutterFlowTheme.of(context).bodyMedium, + maxLines: null, + validator: _model + .emailAddressControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 15.0), + child: TextFormField( + controller: _model.passwordController, + obscureText: !_model.passwordVisibility, + decoration: InputDecoration( + labelText: 'Password', + labelStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Lexend Deca', + color: FlutterFlowTheme.of(context) + .secondaryText, + fontSize: 14.0, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context).tertiary, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context) + .primaryBackground, + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 20.0, 24.0), + suffixIcon: InkWell( + onTap: () => setState( + () => _model.passwordVisibility = + !_model.passwordVisibility, + ), + focusNode: FocusNode(skipTraversal: true), + child: Icon( + _model.passwordVisibility + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + size: 22.0, + ), + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium, + validator: _model.passwordControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 15.0), + child: TextFormField( + controller: _model.confirmPasswordController, + obscureText: !_model.confirmPasswordVisibility, + decoration: InputDecoration( + labelText: 'Confirm Password', + labelStyle: FlutterFlowTheme.of(context) + .bodySmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodySmallFamily, + color: FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodySmallFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Lexend Deca', + color: FlutterFlowTheme.of(context) + .secondaryText, + fontSize: 14.0, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context).tertiary, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context) + .primaryBackground, + contentPadding: + EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 20.0, 24.0), + suffixIcon: InkWell( + onTap: () => setState( + () => _model.confirmPasswordVisibility = + !_model.confirmPasswordVisibility, + ), + focusNode: FocusNode(skipTraversal: true), + child: Icon( + _model.confirmPasswordVisibility + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + size: 22.0, + ), + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium, + validator: _model + .confirmPasswordControllerValidator + .asValidator(context), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 24.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + // Validate individual fields + if (_model.formKey.currentState == null || + !_model.formKey.currentState! + .validate()) { + return; + } + if (_model.passwordController.text != + _model.confirmPasswordController.text) { + // Error Message + setState(() { + _model.createAccountError = + 'Passwords don\'t match'; + }); + return; + } + // Create Donor User Account + GoRouter.of(context).prepareAuthEvent(); + if (_model.passwordController.text != + _model.confirmPasswordController.text) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Passwords don\'t match!', + ), + ), + ); + return; + } + + final user = + await authManager.createAccountWithEmail( + context, + _model.emailAddressController.text, + _model.passwordController.text, + ); + if (user == null) { + return; + } + + await UsersRecord.collection + .doc(user.uid) + .update(createUsersRecordData( + email: + _model.emailAddressController.text, + displayName: + '${_model.firstNameController.text} ${_model.surnameController.text}', + permissions: createPermissionsStruct( + active: true, + donor: true, + clearUnsetFields: false, + create: true, + ), + country: '', + firstName: + _model.firstNameController.text, + surname: _model.surnameController.text, + )); + + context.goNamedAuth( + 'Dashboard', context.mounted); + }, + text: 'Create Account', + options: FFButtonOptions( + width: 270.0, + height: 50.0, + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).tertiary, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .titleSmallFamily, + color: FlutterFlowTheme.of(context) + .primaryBackground, + fontSize: 16.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + elevation: 0.0, + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + ), + ), + ), + ], + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), + child: Text( + _model.createAccountError == null || + _model.createAccountError == '' + ? ' ' + : _model.createAccountError!, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context).error, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 20.0, 0.0, 0.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await showDialog( + context: context, + builder: (alertDialogContext) { + return AlertDialog( + title: Text( + '\rPASSWORD RULES\r\rMinimum:\r\u25AA 1 lowercase\r\u25AA 1 uppercase\r\u25AA 1 numeric\r\u25AA 1 non-alphanumeric:\r\r ^ \$ * . [ ] { } ( ) ? " ! @\r # % & / \u005C , > < \' \u003A \u003B | _ ~ ` \r\rLength:\r\u25AA Minimum = 6\r\u25AA Maximum = 4096\r '), + actions: [ + TextButton( + onPressed: () => + Navigator.pop(alertDialogContext), + child: Text('Ok'), + ), + ], + ); + }, + ); + }, + child: Text( + 'Password Rules', + style: FlutterFlowTheme.of(context).bodySmall, + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/authentication_pages/login/login_model.dart b/lib/pages/authentication_pages/login/login_model.dart new file mode 100644 index 0000000..30faed4 --- /dev/null +++ b/lib/pages/authentication_pages/login/login_model.dart @@ -0,0 +1,46 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class LoginModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for Row_LogoAndName component. + late RowLogoAndNameModel rowLogoAndNameModel; + // State field(s) for emailAddress widget. + TextEditingController? emailAddressController; + String? Function(BuildContext, String?)? emailAddressControllerValidator; + // State field(s) for password widget. + TextEditingController? passwordController; + late bool passwordVisibility; + String? Function(BuildContext, String?)? passwordControllerValidator; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + rowLogoAndNameModel = createModel(context, () => RowLogoAndNameModel()); + passwordVisibility = false; + } + + void dispose() { + unfocusNode.dispose(); + rowLogoAndNameModel.dispose(); + emailAddressController?.dispose(); + passwordController?.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/authentication_pages/login/login_widget.dart b/lib/pages/authentication_pages/login/login_widget.dart new file mode 100644 index 0000000..39b9091 --- /dev/null +++ b/lib/pages/authentication_pages/login/login_widget.dart @@ -0,0 +1,893 @@ +import '/auth/firebase_auth/auth_util.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'login_model.dart'; +export 'login_model.dart'; + +class LoginWidget extends StatefulWidget { + const LoginWidget({Key? key}) : super(key: key); + + @override + _LoginWidgetState createState() => _LoginWidgetState(); +} + +class _LoginWidgetState extends State { + late LoginModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => LoginModel()); + + _model.emailAddressController ??= TextEditingController(); + _model.passwordController ??= TextEditingController(); + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).secondaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Padding( + padding: EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 0.0, 0.0), + child: Text( + 'Log in', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: + FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + flex: 6, + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + alignment: AlignmentDirectional(0.0, -1.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (responsiveVisibility( + context: context, + phone: false, + tablet: false, + )) + Container( + width: double.infinity, + height: 140.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(16.0), + bottomRight: Radius.circular(16.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + ), + if (responsiveVisibility( + context: context, + tabletLandscape: false, + desktop: false, + )) + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.0, 30.0, 30.0, 30.0), + child: Container( + width: double.infinity, + height: 140.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(16.0), + bottomRight: Radius.circular(16.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + alignment: AlignmentDirectional(-1.0, 0.0), + child: wrapWithModel( + model: _model.rowLogoAndNameModel, + updateCallback: () => setState(() {}), + child: RowLogoAndNameWidget(), + ), + ), + ), + Container( + width: double.infinity, + constraints: BoxConstraints( + maxWidth: 430.0, + ), + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context).primaryBackground, + ), + child: Align( + alignment: AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 24.0, 24.0), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 25.0), + child: Text( + 'Welcome Back', + style: FlutterFlowTheme.of(context) + .titleLarge, + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: Container( + width: double.infinity, + child: TextFormField( + controller: + _model.emailAddressController, + autofocus: true, + autofillHints: [AutofillHints.email], + obscureText: false, + decoration: InputDecoration( + labelText: 'Email', + labelStyle: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelLargeFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelLargeFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryBackground, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of(context) + .primaryBackground, + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyLargeFamily, + color: + FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyLargeFamily), + ), + keyboardType: + TextInputType.emailAddress, + validator: _model + .emailAddressControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 25.0), + child: Container( + width: double.infinity, + child: TextFormField( + controller: _model.passwordController, + autofocus: true, + obscureText: !_model.passwordVisibility, + decoration: InputDecoration( + labelText: 'Password', + labelStyle: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelLargeFamily, + color: + FlutterFlowTheme.of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelLargeFamily), + ), + errorStyle: FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyLargeFamily, + color: + FlutterFlowTheme.of(context) + .error, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyLargeFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .secondaryBackground, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .tertiary, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .error, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of(context) + .primaryBackground, + suffixIcon: InkWell( + onTap: () => setState( + () => _model.passwordVisibility = + !_model.passwordVisibility, + ), + focusNode: + FocusNode(skipTraversal: true), + child: Icon( + _model.passwordVisibility + ? Icons.visibility_outlined + : Icons + .visibility_off_outlined, + color: + FlutterFlowTheme.of(context) + .secondaryText, + size: 24.0, + ), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyLarge, + validator: _model + .passwordControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + // Login with email + GoRouter.of(context).prepareAuthEvent(); + + final user = + await authManager.signInWithEmail( + context, + _model.emailAddressController.text, + _model.passwordController.text, + ); + if (user == null) { + return; + } + + context.goNamedAuth( + 'Dashboard', context.mounted); + }, + text: 'Sign In', + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .primary, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .titleSmallFamily, + color: Colors.white, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + elevation: 0.0, + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 24.0), + child: Container( + width: 370.0, + child: Stack( + alignment: + AlignmentDirectional(0.0, 0.0), + children: [ + Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: Container( + width: double.infinity, + height: 2.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of( + context) + .primaryBackground, + ), + ), + ), + ), + Align( + alignment: + AlignmentDirectional(0.0, 0.0), + child: Container( + width: 70.0, + height: 32.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context) + .primaryBackground, + ), + alignment: AlignmentDirectional( + 0.0, 0.0), + child: Text( + 'OR', + style: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .labelMediumFamily, + color: FlutterFlowTheme + .of(context) + .tertiary, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + ), + ), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + GoRouter.of(context).prepareAuthEvent(); + final user = await authManager + .signInWithGoogle(context); + if (user == null) { + return; + } + + context.goNamedAuth( + 'Dashboard', context.mounted); + }, + text: 'Continue with Google', + icon: FaIcon( + FontAwesomeIcons.google, + size: 20.0, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .primaryText, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .titleSmallFamily, + color: + FlutterFlowTheme.of(context) + .primaryBackground, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + elevation: 0.0, + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .alternate, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + hoverColor: FlutterFlowTheme.of(context) + .secondaryText, + ), + ), + ), + isAndroid + ? Container() + : Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + GoRouter.of(context) + .prepareAuthEvent(); + final user = await authManager + .signInWithApple(context); + if (user == null) { + return; + } + + context.goNamedAuth( + 'Dashboard', context.mounted); + }, + text: 'Continue with Apple', + icon: FaIcon( + FontAwesomeIcons.apple, + size: 20.0, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, 0.0, 0.0), + color: + FlutterFlowTheme.of(context) + .primaryText, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: FlutterFlowTheme + .of(context) + .primaryBackground, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + elevation: 0.0, + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context) + .alternate, + width: 2.0, + ), + borderRadius: + BorderRadius.circular(12.0), + hoverColor: + FlutterFlowTheme.of(context) + .primaryBackground, + ), + ), + ), + + // You will have to add an action on this rich text to go to your login page. + Align( + alignment: AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.pushNamed('CreateAccount'); + }, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: + 'Don\'t have an account? ', + style: TextStyle( + color: FlutterFlowTheme.of( + context) + .secondaryText, + ), + ), + TextSpan( + text: 'Sign Up here', + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme + .of(context) + .tertiary, + fontWeight: + FontWeight.normal, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ) + ], + style: FlutterFlowTheme.of(context) + .bodyMedium, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ), + if (responsiveVisibility( + context: context, + phone: false, + tablet: false, + )) + Expanded( + flex: 8, + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB(16.0, 16.0, 16.0, 16.0), + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + FlutterFlowTheme.of(context).primary, + FlutterFlowTheme.of(context).secondary + ], + stops: [0.0, 1.0], + begin: AlignmentDirectional(1.0, -1.0), + end: AlignmentDirectional(-1.0, 1.0), + ), + borderRadius: BorderRadius.circular(16.0), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 24.0, 24.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: double.infinity, + constraints: BoxConstraints( + maxWidth: 400.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 3.0, + color: Color(0x2E000000), + offset: Offset(0.0, 2.0), + ) + ], + borderRadius: BorderRadius.circular(8.0), + border: Border.all( + color: FlutterFlowTheme.of(context) + .primaryBackground, + width: 2.0, + ), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 4.0, 4.0, 4.0, 4.0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 12.0, 12.0, 12.0, 8.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 8.0, 0.0), + child: Container( + width: 40.0, + height: 40.0, + decoration: BoxDecoration( + color: Color(0xFFEEEEEE), + shape: BoxShape.circle, + ), + child: Icon( + Icons.person, + color: FlutterFlowTheme.of( + context) + .primary, + size: 24.0, + ), + ), + ), + Text( + 'UserName', + style: + FlutterFlowTheme.of(context) + .titleMedium, + ), + ], + ), + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + Text( + 'Overall', + style: + FlutterFlowTheme.of(context) + .bodySmall, + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 4.0, 0.0), + child: Text( + '5', + style: + FlutterFlowTheme.of( + context) + .headlineMedium, + ), + ), + Icon( + Icons.star_rounded, + color: FlutterFlowTheme.of( + context) + .primary, + size: 20.0, + ), + ], + ), + ], + ), + ], + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 12.0, 0.0, 12.0, 8.0), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: AutoSizeText( + 'Nice outdoor courts, solid concrete and good hoops for the neighborhood.', + style: + FlutterFlowTheme.of(context) + .bodyMedium, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/authentication_pages/password_rules/password_rules_model.dart b/lib/pages/authentication_pages/password_rules/password_rules_model.dart new file mode 100644 index 0000000..d32598b --- /dev/null +++ b/lib/pages/authentication_pages/password_rules/password_rules_model.dart @@ -0,0 +1,31 @@ +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class PasswordRulesModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for Row_LogoAndName component. + late RowLogoAndNameModel rowLogoAndNameModel; + + /// Initialization and disposal methods. + + void initState(BuildContext context) { + rowLogoAndNameModel = createModel(context, () => RowLogoAndNameModel()); + } + + void dispose() { + unfocusNode.dispose(); + rowLogoAndNameModel.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/authentication_pages/password_rules/password_rules_widget.dart b/lib/pages/authentication_pages/password_rules/password_rules_widget.dart new file mode 100644 index 0000000..8176238 --- /dev/null +++ b/lib/pages/authentication_pages/password_rules/password_rules_widget.dart @@ -0,0 +1,229 @@ +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'password_rules_model.dart'; +export 'password_rules_model.dart'; + +class PasswordRulesWidget extends StatefulWidget { + const PasswordRulesWidget({Key? key}) : super(key: key); + + @override + _PasswordRulesWidgetState createState() => _PasswordRulesWidgetState(); +} + +class _PasswordRulesWidgetState extends State { + late PasswordRulesModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => PasswordRulesModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 8.0), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(12.0, 0.0, 0.0, 0.0), + child: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 50.0, + icon: Icon( + Icons.arrow_back_rounded, + color: + FlutterFlowTheme.of(context).secondaryBackground, + size: 24.0, + ), + onPressed: () async { + context.pop(); + }, + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(4.0, 0.0, 0.0, 0.0), + child: Text( + 'Back', + style: + FlutterFlowTheme.of(context).displaySmall.override( + fontFamily: FlutterFlowTheme.of(context) + .displaySmallFamily, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + fontSize: 16.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .displaySmallFamily), + ), + ), + ), + ], + ), + ), + ], + ), + actions: [], + centerTitle: true, + elevation: 0.0, + ), + body: SafeArea( + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Container( + width: double.infinity, + height: double.infinity, + constraints: BoxConstraints( + maxWidth: 400.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15.0, 0.0, 15.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 65.0), + child: wrapWithModel( + model: _model.rowLogoAndNameModel, + updateCallback: () => setState(() {}), + child: RowLogoAndNameWidget(), + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 25.0), + child: Text( + 'Password Rules', + style: FlutterFlowTheme.of(context).titleLarge, + ), + ), + Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 15.0, 0.0, 15.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '▪ Minimum 1 lowercase (a-z)', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + Text( + '▪ Minimum 1 uppercase (A-Z)', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + Text( + '▪ Minimum 1 numeric (0-9)', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + Text( + '▪ Minimum 1 non-alphanumeric:', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Text( + '^ \$ * . [ ] { } ( ) ? \" ! @ # ', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Text( + ' % & / \\ , > < \' : ; | _ ~ `', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 15.0, 0.0, 0.0), + child: Text( + '▪ Minimum length = 6 characters', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + ), + Text( + '▪ Maximum length = 4096 characters', + style: FlutterFlowTheme.of(context).bodyMedium, + ), + ].divide(SizedBox(height: 15.0)), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/donation/donation_model.dart b/lib/pages/donation/donation_model.dart index 10f5147..d5c24c1 100644 --- a/lib/pages/donation/donation_model.dart +++ b/lib/pages/donation/donation_model.dart @@ -1,11 +1,10 @@ -import '/components/get_donation_amount_widget.dart'; -import '/components/row_logo_and_name_widget.dart'; -import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/components/get_donation_amount/get_donation_amount_widget.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_widgets.dart'; import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; @@ -16,24 +15,27 @@ class DonationModel extends FlutterFlowModel { /// State fields for stateful widgets in this page. + final unfocusNode = FocusNode(); // Model for Row_LogoAndName component. late RowLogoAndNameModel rowLogoAndNameModel; - // Model for DonationLoggedIn. - late GetDonationAmountModel donationLoggedInModel; + // Model for getDonationAmount component. + late GetDonationAmountModel getDonationAmountModel; /// Initialization and disposal methods. void initState(BuildContext context) { rowLogoAndNameModel = createModel(context, () => RowLogoAndNameModel()); - donationLoggedInModel = + getDonationAmountModel = createModel(context, () => GetDonationAmountModel()); } void dispose() { + unfocusNode.dispose(); rowLogoAndNameModel.dispose(); - donationLoggedInModel.dispose(); + getDonationAmountModel.dispose(); } - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/pages/donation/donation_widget.dart b/lib/pages/donation/donation_widget.dart index b58c7d9..71d66e7 100644 --- a/lib/pages/donation/donation_widget.dart +++ b/lib/pages/donation/donation_widget.dart @@ -1,18 +1,23 @@ -import '/components/get_donation_amount_widget.dart'; -import '/components/row_logo_and_name_widget.dart'; -import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/components/get_donation_amount/get_donation_amount_widget.dart'; +import '/components/row_logo_and_name/row_logo_and_name_widget.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_widgets.dart'; import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'donation_model.dart'; export 'donation_model.dart'; class DonationWidget extends StatefulWidget { - const DonationWidget({Key? key}) : super(key: key); + const DonationWidget({ + Key? key, + double? donationAmount, + }) : this.donationAmount = donationAmount ?? 0.0, + super(key: key); + + final double donationAmount; @override _DonationWidgetState createState() => _DonationWidgetState(); @@ -22,7 +27,6 @@ class _DonationWidgetState extends State { late DonationModel _model; final scaffoldKey = GlobalKey(); - final _unfocusNode = FocusNode(); @override void initState() { @@ -36,7 +40,6 @@ class _DonationWidgetState extends State { void dispose() { _model.dispose(); - _unfocusNode.dispose(); super.dispose(); } @@ -45,7 +48,7 @@ class _DonationWidgetState extends State { context.watch(); return GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), child: Scaffold( key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, @@ -53,11 +56,13 @@ class _DonationWidgetState extends State { backgroundColor: FlutterFlowTheme.of(context).primaryBackground, automaticallyImplyLeading: false, title: Text( - 'Donation', + 'Payment', style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, color: FlutterFlowTheme.of(context).secondaryBackground, fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), ), ), actions: [], @@ -65,121 +70,46 @@ class _DonationWidgetState extends State { elevation: 0.0, ), body: SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - InkWell( - splashColor: Colors.transparent, - focusColor: Colors.transparent, - hoverColor: Colors.transparent, - highlightColor: Colors.transparent, - onTap: () async { - context.pushNamed('TestPage'); - }, - child: wrapWithModel( - model: _model.rowLogoAndNameModel, - updateCallback: () => setState(() {}), - child: RowLogoAndNameWidget(), - ), - ), - wrapWithModel( - model: _model.donationLoggedInModel, - updateCallback: () => setState(() {}), - child: GetDonationAmountWidget(), - ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, + top: true, + child: Align( + alignment: AlignmentDirectional(0.0, -1.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, children: [ - Padding( - padding: - EdgeInsetsDirectional.fromSTEB(10.0, 10.0, 10.0, 10.0), - child: FFButtonWidget( - onPressed: () async { - context.pushNamed('TestPage'); - }, - text: 'Test Page ', - options: FFButtonOptions( - width: 130.0, - height: 40.0, - padding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - iconPadding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - color: FlutterFlowTheme.of(context).primary, - textStyle: - FlutterFlowTheme.of(context).titleSmall.override( - fontFamily: 'Poppins', - color: Colors.white, - ), - borderSide: BorderSide( - color: Colors.transparent, - width: 1.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + wrapWithModel( + model: _model.rowLogoAndNameModel, + updateCallback: () => setState(() {}), + child: RowLogoAndNameWidget(), ), - Padding( - padding: - EdgeInsetsDirectional.fromSTEB(10.0, 10.0, 10.0, 10.0), - child: FFButtonWidget( - onPressed: () async { - context.pushNamed('GhostImagePage'); - }, - text: 'Ghosts', - options: FFButtonOptions( - width: 130.0, - height: 40.0, - padding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - iconPadding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - color: FlutterFlowTheme.of(context).primary, - textStyle: - FlutterFlowTheme.of(context).titleSmall.override( - fontFamily: 'Poppins', - color: Colors.white, - ), - borderSide: BorderSide( - color: Colors.transparent, - width: 1.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), + Container( + width: 600.0, + height: 600.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).secondaryBackground, + ), + child: wrapWithModel( + model: _model.getDonationAmountModel, + updateCallback: () => setState(() {}), + child: GetDonationAmountWidget(), ), ), - ], - ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( + Row( mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, children: [ - Padding( - padding: - EdgeInsetsDirectional.fromSTEB(0.0, 30.0, 0.0, 0.0), - child: Text( - 'Continue as', - style: - FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: 'Poppins', - fontSize: 20.0, - fontWeight: FontWeight.w600, - ), - ), - ), Padding( padding: EdgeInsetsDirectional.fromSTEB(0.0, 20.0, 0.0, 0.0), child: FFButtonWidget( - onPressed: () { - print('Button pressed ...'); + onPressed: () async { + context.pushNamed('Payment'); }, - text: 'Guest', + text: 'Payment >', options: FFButtonOptions( width: 130.0, height: 40.0, @@ -191,10 +121,13 @@ class _DonationWidgetState extends State { textStyle: FlutterFlowTheme.of(context) .titleSmall .override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context) + .titleSmallFamily, color: Colors.white, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .titleSmallFamily), ), - elevation: 2.0, borderSide: BorderSide( color: Colors.transparent, width: 1.0, @@ -203,77 +136,11 @@ class _DonationWidgetState extends State { ), ), ), - Padding( - padding: - EdgeInsetsDirectional.fromSTEB(0.0, 20.0, 0.0, 0.0), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: FaIcon( - FontAwesomeIcons.google, - color: Colors.black, - size: 30.0, - ), - onPressed: () { - print('IconButton pressed ...'); - }, - ), - FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: FaIcon( - FontAwesomeIcons.apple, - color: FlutterFlowTheme.of(context).primaryText, - size: 30.0, - ), - onPressed: () { - print('IconButton pressed ...'); - }, - ), - FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: FaIcon( - FontAwesomeIcons.facebook, - color: Colors.black, - size: 30.0, - ), - onPressed: () { - print('IconButton pressed ...'); - }, - ), - FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: Icon( - Icons.email_outlined, - color: Colors.black, - size: 30.0, - ), - onPressed: () { - print('IconButton pressed ...'); - }, - ), - ], - ), - ), ], ), ], ), - ], + ), ), ), ), diff --git a/lib/pages/ghost_image_page/ghost_image_page_widget.dart b/lib/pages/ghost_image_page/ghost_image_page_widget.dart deleted file mode 100644 index da39e5a..0000000 --- a/lib/pages/ghost_image_page/ghost_image_page_widget.dart +++ /dev/null @@ -1,126 +0,0 @@ -import '/flutter_flow/flutter_flow_icon_button.dart'; -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:provider/provider.dart'; -import 'ghost_image_page_model.dart'; -export 'ghost_image_page_model.dart'; - -class GhostImagePageWidget extends StatefulWidget { - const GhostImagePageWidget({Key? key}) : super(key: key); - - @override - _GhostImagePageWidgetState createState() => _GhostImagePageWidgetState(); -} - -class _GhostImagePageWidgetState extends State { - late GhostImagePageModel _model; - - final scaffoldKey = GlobalKey(); - final _unfocusNode = FocusNode(); - - @override - void initState() { - super.initState(); - _model = createModel(context, () => GhostImagePageModel()); - - WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); - } - - @override - void dispose() { - _model.dispose(); - - _unfocusNode.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - context.watch(); - - return GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), - child: Scaffold( - key: scaffoldKey, - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: AppBar( - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - leading: FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: Icon( - Icons.arrow_back_rounded, - color: FlutterFlowTheme.of(context).secondaryBackground, - size: 30.0, - ), - onPressed: () async { - context.pop(); - }, - ), - title: Text( - 'Page Title', - style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', - color: FlutterFlowTheme.of(context).secondaryBackground, - fontSize: 22.0, - ), - ), - actions: [], - centerTitle: true, - elevation: 2.0, - ), - body: SafeArea( - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: EdgeInsetsDirectional.fromSTEB(0.0, 50.0, 0.0, 0.0), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: - EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), - child: Image.asset( - 'assets/images/Logo_-_Two_Heart_and_Hand.png', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, - ), - ), - Padding( - padding: - EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), - child: Image.asset( - 'assets/images/Logo_-_Two_Heart_and_Hand.png', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, - ), - ), - Padding( - padding: - EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), - child: Image.asset( - 'assets/images/Logo_-_Two_Heart_and_Hand.png', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, - ), - ), - ], - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/payment/payment_model.dart b/lib/pages/payment/payment_model.dart index 94bd7c0..9a4ab2b 100644 --- a/lib/pages/payment/payment_model.dart +++ b/lib/pages/payment/payment_model.dart @@ -1,37 +1,32 @@ -import '/components/get_donation_amount_widget.dart'; -import '/components/row_logo_and_name_widget.dart'; +import '/components/heading2/heading2_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; -import '/flutter_flow/flutter_flow_widgets.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; class PaymentModel extends FlutterFlowModel { - /// Local state fields for this page. - - double? donationAmount = 0.0; - /// State fields for stateful widgets in this page. - // Model for Row_LogoAndName component. - late RowLogoAndNameModel rowLogoAndNameModel; - // Model for getDonationAmount component. - late GetDonationAmountModel getDonationAmountModel; + final unfocusNode = FocusNode(); + // Model for Heading2 component. + late Heading2Model heading2Model; /// Initialization and disposal methods. void initState(BuildContext context) { - rowLogoAndNameModel = createModel(context, () => RowLogoAndNameModel()); - getDonationAmountModel = - createModel(context, () => GetDonationAmountModel()); + heading2Model = createModel(context, () => Heading2Model()); } void dispose() { - rowLogoAndNameModel.dispose(); - getDonationAmountModel.dispose(); + unfocusNode.dispose(); + heading2Model.dispose(); } - /// Additional helper methods are added here. + /// Action blocks are added here. + /// Additional helper methods are added here. } diff --git a/lib/pages/payment/payment_widget.dart b/lib/pages/payment/payment_widget.dart index 7544811..e953f41 100644 --- a/lib/pages/payment/payment_widget.dart +++ b/lib/pages/payment/payment_widget.dart @@ -1,22 +1,17 @@ -import '/components/get_donation_amount_widget.dart'; -import '/components/row_logo_and_name_widget.dart'; +import '/components/heading2/heading2_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; -import '/flutter_flow/flutter_flow_widgets.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'payment_model.dart'; export 'payment_model.dart'; class PaymentWidget extends StatefulWidget { - const PaymentWidget({ - Key? key, - double? donationAmount, - }) : this.donationAmount = donationAmount ?? 0.0, - super(key: key); - - final double donationAmount; + const PaymentWidget({Key? key}) : super(key: key); @override _PaymentWidgetState createState() => _PaymentWidgetState(); @@ -26,7 +21,6 @@ class _PaymentWidgetState extends State { late PaymentModel _model; final scaffoldKey = GlobalKey(); - final _unfocusNode = FocusNode(); @override void initState() { @@ -40,7 +34,6 @@ class _PaymentWidgetState extends State { void dispose() { _model.dispose(); - _unfocusNode.dispose(); super.dispose(); } @@ -49,72 +42,112 @@ class _PaymentWidgetState extends State { context.watch(); return GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), child: Scaffold( key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, appBar: AppBar( backgroundColor: FlutterFlowTheme.of(context).primaryBackground, automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), title: Text( 'Payment', style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Poppins', + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, color: FlutterFlowTheme.of(context).secondaryBackground, fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), ), ), actions: [], centerTitle: true, - elevation: 0.0, + elevation: 2.0, ), body: SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - wrapWithModel( - model: _model.rowLogoAndNameModel, - updateCallback: () => setState(() {}), - child: RowLogoAndNameWidget(), - ), - wrapWithModel( - model: _model.getDonationAmountModel, - updateCallback: () => setState(() {}), - child: GetDonationAmountWidget(), - ), - Row( + top: true, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: SingleChildScrollView( + child: Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ - FFButtonWidget( - onPressed: () async { - context.pushNamed('TestPage'); - }, - text: 'Test Page ', - options: FFButtonOptions( - width: 130.0, - height: 40.0, - padding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - iconPadding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - color: FlutterFlowTheme.of(context).primary, - textStyle: - FlutterFlowTheme.of(context).titleSmall.override( - fontFamily: 'Poppins', - color: Colors.white, - ), - borderSide: BorderSide( - color: Colors.transparent, - width: 1.0, - ), - borderRadius: BorderRadius.circular(8.0), + wrapWithModel( + model: _model.heading2Model, + updateCallback: () => setState(() {}), + child: Heading2Widget( + headingText: 'Card Details', ), ), + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 20.0, 20.0, 20.0, 20.0), + child: Container( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + child: custom_widgets.GetCCNWidget( + width: MediaQuery.sizeOf(context).width * 1.0, + height: MediaQuery.sizeOf(context).height * 1.0, + saveOnly: true, + refreshPageUI: () async { + // Rebuild Current Page + setState(() {}); + }, + goToNextPage: () async { + context.pushNamed('ThankYou'); + }, + ), + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.asset( + 'assets/images/Pay_with_Apple_Pay_button-pay-with@2x.png', + width: 300.0, + height: 107.0, + fit: BoxFit.contain, + ), + ), + ], + ), ], ), - ], + ), ), ), ), diff --git a/lib/pages/temp_login_page/temp_login_page_model.dart b/lib/pages/temp_login_page/temp_login_page_model.dart new file mode 100644 index 0000000..3bf1f94 --- /dev/null +++ b/lib/pages/temp_login_page/temp_login_page_model.dart @@ -0,0 +1,24 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class TempLoginPageModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/temp_login_page/temp_login_page_widget.dart b/lib/pages/temp_login_page/temp_login_page_widget.dart new file mode 100644 index 0000000..cda16d6 --- /dev/null +++ b/lib/pages/temp_login_page/temp_login_page_widget.dart @@ -0,0 +1,56 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'temp_login_page_model.dart'; +export 'temp_login_page_model.dart'; + +class TempLoginPageWidget extends StatefulWidget { + const TempLoginPageWidget({Key? key}) : super(key: key); + + @override + _TempLoginPageWidgetState createState() => _TempLoginPageWidgetState(); +} + +class _TempLoginPageWidgetState extends State { + late TempLoginPageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => TempLoginPageModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: SafeArea( + top: true, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [], + ), + ), + ), + ); + } +} diff --git a/lib/pages/thank_you/thank_you_model.dart b/lib/pages/thank_you/thank_you_model.dart new file mode 100644 index 0000000..2d6d124 --- /dev/null +++ b/lib/pages/thank_you/thank_you_model.dart @@ -0,0 +1,30 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:lottie/lottie.dart'; +import 'package:provider/provider.dart'; + +class ThankYouModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() { + unfocusNode.dispose(); + } + + /// Action blocks are added here. + + /// Additional helper methods are added here. +} diff --git a/lib/pages/thank_you/thank_you_widget.dart b/lib/pages/thank_you/thank_you_widget.dart new file mode 100644 index 0000000..366bcf2 --- /dev/null +++ b/lib/pages/thank_you/thank_you_widget.dart @@ -0,0 +1,156 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:lottie/lottie.dart'; +import 'package:provider/provider.dart'; +import 'thank_you_model.dart'; +export 'thank_you_model.dart'; + +class ThankYouWidget extends StatefulWidget { + const ThankYouWidget({Key? key}) : super(key: key); + + @override + _ThankYouWidgetState createState() => _ThankYouWidgetState(); +} + +class _ThankYouWidgetState extends State + with TickerProviderStateMixin { + late ThankYouModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = { + 'textOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effects: [ + MoveEffect( + curve: Curves.easeIn, + delay: 0.ms, + duration: 600.ms, + begin: Offset(150.0, 0.0), + end: Offset(0.0, 0.0), + ), + ], + ), + }; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ThankYouModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_model.unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Thank You', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + top: true, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 50.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + HapticFeedback.vibrate(); + }, + child: Lottie.network( + 'https://lottie.host/9333a63a-d962-4912-ab14-e31626963161/Z1WTXYMOzg.json', + width: 300.0, + height: 260.0, + fit: BoxFit.cover, + repeat: false, + animate: true, + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Thank you!', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).tertiary, + fontSize: 40.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ).animateOnPageLoad( + animationsMap['textOnPageLoadAnimation']!), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index dc524ee..bf20b4d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=3.0.0 <4.0.0" dependencies: flutter: @@ -26,53 +26,62 @@ dependencies: flutter_localizations: sdk: flutter auto_size_text: 3.0.0 - built_collection: 5.1.1 - built_value: 8.4.3 cached_network_image: 3.2.1 - cloud_firestore: 4.2.0 - cloud_firestore_platform_interface: 5.9.1 - cloud_firestore_web: 3.1.1 + cloud_firestore: 4.8.0 + cloud_firestore_platform_interface: 5.15.0 + cloud_firestore_web: 3.6.0 csv: 5.0.1 + dropdown_button2: 2.0.0 easy_debounce: 2.0.1 - firebase_auth: 4.2.0 - firebase_auth_platform_interface: 6.11.4 - firebase_auth_web: 5.2.0 - firebase_core: 2.4.0 - firebase_core_platform_interface: 4.5.2 - firebase_core_web: 2.0.2 - firebase_dynamic_links: 5.0.8 - firebase_dynamic_links_platform_interface: 0.2.3+24 + firebase_auth: 4.6.2 + firebase_auth_platform_interface: 6.15.2 + firebase_auth_web: 5.5.2 + firebase_core: 2.13.1 + firebase_core_platform_interface: 4.8.0 + firebase_core_web: 2.5.0 flutter_animate: 4.1.1+1 flutter_cache_manager: 3.3.0 - flutter_credit_card: ^3.0.6 + flutter_multi_formatter: ^2.10.2 flutter_secure_storage: 8.0.0 + flutter_spinkit: 5.1.0 font_awesome_flutter: 10.1.0 from_css_color: 2.0.0 - go_router: 3.1.0 + go_router: 7.1.1 google_fonts: 4.0.3 - google_sign_in: 5.4.0 + google_sign_in: 6.0.2 google_sign_in_android: 6.1.8 - google_sign_in_ios: 5.4.0 - google_sign_in_platform_interface: 2.2.0 - google_sign_in_web: 0.10.2 - intl: 0.17.0 + google_sign_in_ios: 5.6.1 + google_sign_in_platform_interface: 2.4.0 + google_sign_in_web: 0.11.0+2 + intl: 0.18.0 json_path: 0.4.1 - json_serializable: 6.6.1 + lottie: 1.2.1 + mask_text_input_formatter: 2.4.0 page_transition: 2.0.4 + path_provider: 2.0.14 + path_provider_android: 2.0.25 + path_provider_foundation: 2.2.2 + path_provider_platform_interface: 2.0.6 plugin_platform_interface: 2.1.3 provider: 6.0.4 - rxdart: 0.27.5 + rxdart: 0.27.7 shared_preferences: 2.0.15 shared_preferences_android: 2.1.0 shared_preferences_ios: 2.1.1 shared_preferences_platform_interface: 2.2.0 shared_preferences_web: 2.1.0 - sign_in_with_apple: 4.1.0 + sign_in_with_apple: 4.3.0 sign_in_with_apple_platform_interface: 1.0.0 sign_in_with_apple_web: 1.0.1 + smooth_page_indicator: 1.0.1 sqflite: 2.2.6 + stream_transform: 2.1.0 + synchronized: 3.1.0 timeago: 3.2.2 url_launcher: 6.1.10 + url_launcher_android: 6.0.27 + url_launcher_ios: 6.1.4 + url_launcher_platform_interface: 2.1.2 # The following adds the Cupertino Icons font to your application. @@ -80,8 +89,6 @@ dependencies: cupertino_icons: ^1.0.0 dev_dependencies: - build_runner: 2.3.3 - built_value_generator: 8.4.3 flutter_test: sdk: flutter

A7BQqf9K80=Rt|6##onQxm4}!`cUHxU~WS(`? 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 literal 0 HcmV?d00001 diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index 095facb..b78b276 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -110,6 +110,11 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter( name: 'TestPage', path: 'testPage', builder: (context, params) => TestPageWidget(), + ), + FFRoute( + name: 'GhostImagePage', + path: 'ghostImagePage', + builder: (context, params) => GhostImagePageWidget(), ) ].map((r) => r.toRoute(appStateNotifier)).toList(), ), diff --git a/lib/index.dart b/lib/index.dart index 9ac71b4..1f88b29 100644 --- a/lib/index.dart +++ b/lib/index.dart @@ -3,3 +3,5 @@ export '/pages/donation/donation_widget.dart' show DonationWidget; export '/pages/payment/payment_widget.dart' show PaymentWidget; export '/pages/account/account_widget.dart' show AccountWidget; export '/pages/test_page/test_page_widget.dart' show TestPageWidget; +export '/pages/ghost_image_page/ghost_image_page_widget.dart' + show GhostImagePageWidget; diff --git a/lib/pages/ghost_image_page/ghost_image_page_model.dart b/lib/pages/ghost_image_page/ghost_image_page_model.dart new file mode 100644 index 0000000..115fe1b --- /dev/null +++ b/lib/pages/ghost_image_page/ghost_image_page_model.dart @@ -0,0 +1,17 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; + +class GhostImagePageModel extends FlutterFlowModel { + /// Initialization and disposal methods. + + void initState(BuildContext context) {} + + void dispose() {} + + /// Additional helper methods are added here. + +} diff --git a/lib/pages/ghost_image_page/ghost_image_page_widget.dart b/lib/pages/ghost_image_page/ghost_image_page_widget.dart new file mode 100644 index 0000000..a1fa703 --- /dev/null +++ b/lib/pages/ghost_image_page/ghost_image_page_widget.dart @@ -0,0 +1,105 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'ghost_image_page_model.dart'; +export 'ghost_image_page_model.dart'; + +class GhostImagePageWidget extends StatefulWidget { + const GhostImagePageWidget({Key? key}) : super(key: key); + + @override + _GhostImagePageWidgetState createState() => _GhostImagePageWidgetState(); +} + +class _GhostImagePageWidgetState extends State { + late GhostImagePageModel _model; + + final scaffoldKey = GlobalKey(); + final _unfocusNode = FocusNode(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => GhostImagePageModel()); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); + } + + @override + void dispose() { + _model.dispose(); + + _unfocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => FocusScope.of(context).requestFocus(_unfocusNode), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).secondaryBackground, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + 'Page Title', + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Poppins', + color: FlutterFlowTheme.of(context).secondaryBackground, + fontSize: 22.0, + ), + ), + actions: [], + centerTitle: true, + elevation: 2.0, + ), + body: SafeArea( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Image.asset( + 'assets/images/mastercard.png', + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + Image.asset( + 'assets/images/card_bg.png', + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + Image.asset( + 'assets/images/bg.png', + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + ], + ), + ), + ), + ); + } +} From e95acf77521da34962c97fbff5620dd5fa1f6e85 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 20:11:06 +0000 Subject: [PATCH 12/15] Updating to latest FlutterFlow output. Assets format: images/bg.jpg --- .../firebase_auth/firebase_user_provider.dart | 6 +- .../firebase_dynamic_links.dart | 12 ++- .../get_donation_amount_widget.dart | 4 + .../widgets/custom_credit_card_widget.dart | 2 +- .../widgets/custom_image_widget.dart | 39 +++++++++ lib/custom_code/widgets/index.dart | 1 + lib/flutter_flow/flutter_flow_animations.dart | 2 +- lib/flutter_flow/uploaded_file.dart | 19 ++++- lib/pages/donation/donation_widget.dart | 81 ++++++++++++++----- .../ghost_image_page_widget.dart | 55 +++++++++---- pubspec.yaml | 14 ++-- 11 files changed, 179 insertions(+), 56 deletions(-) create mode 100644 lib/custom_code/widgets/custom_image_widget.dart diff --git a/lib/auth/firebase_auth/firebase_user_provider.dart b/lib/auth/firebase_auth/firebase_user_provider.dart index fdd8a07..0a02f99 100644 --- a/lib/auth/firebase_auth/firebase_user_provider.dart +++ b/lib/auth/firebase_auth/firebase_user_provider.dart @@ -29,8 +29,10 @@ class PenniesFromHeavenFirebaseUser extends BaseAuthUser { bool get emailVerified { // Reloads the user when checking in order to get the most up to date // email verified status. - if (loggedIn && user!.emailVerified) { - user!.reload().then((_) => user = FirebaseAuth.instance.currentUser); + if (loggedIn && !user!.emailVerified) { + FirebaseAuth.instance.currentUser + ?.reload() + .then((_) => user = FirebaseAuth.instance.currentUser); } return user?.emailVerified ?? false; } diff --git a/lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart b/lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart index d0c7ad3..ac89284 100644 --- a/lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart +++ b/lib/backend/firebase_dynamic_links/firebase_dynamic_links.dart @@ -5,7 +5,7 @@ import '../../flutter_flow/flutter_flow_util.dart'; import 'package:flutter/material.dart'; const _kDynamicLinksUrl = 'https://penniesfromheaven.app'; -const _kAppId = 'com.mycompany.penniesfromheaven'; +const _kAppBundleId = 'com.mycompany.penniesfromheaven'; Future generateCurrentPageLink( BuildContext context, { @@ -13,17 +13,23 @@ Future generateCurrentPageLink( String? description, String? imageUrl, bool isShortLink = true, + bool forceRedirect = false, }) async { final dynamicLinkParams = DynamicLinkParameters( link: Uri.parse('$_kDynamicLinksUrl${GoRouter.of(context).location}'), uriPrefix: _kDynamicLinksUrl, - androidParameters: const AndroidParameters(packageName: _kAppId), - iosParameters: const IOSParameters(bundleId: _kAppId), + androidParameters: const AndroidParameters(packageName: _kAppBundleId), + iosParameters: const IOSParameters( + bundleId: _kAppBundleId, + ), socialMetaTagParameters: SocialMetaTagParameters( title: title, description: description, imageUrl: imageUrl != null ? Uri.tryParse(imageUrl) : null, ), + navigationInfoParameters: forceRedirect + ? NavigationInfoParameters(forcedRedirectEnabled: true) + : null, ); return isShortLink ? FirebaseDynamicLinks.instance diff --git a/lib/components/get_donation_amount_widget.dart b/lib/components/get_donation_amount_widget.dart index 72ca1ca..fbc110d 100644 --- a/lib/components/get_donation_amount_widget.dart +++ b/lib/components/get_donation_amount_widget.dart @@ -241,6 +241,10 @@ class _GetDonationAmountWidgetState extends State scrollDirection: Axis.vertical, children: [ InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, onTap: () async { _model.updatePage(() {}); }, diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart index 72234c9..7f59bd6 100644 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -68,7 +68,7 @@ class _CustomCreditCardWidgetState extends State { height: widget.height, decoration: const BoxDecoration( image: DecorationImage( - image: ExactAssetImage('assets/bg.png'), + image: ExactAssetImage('images/bg.png'), fit: BoxFit.fill, ), color: Colors.black, diff --git a/lib/custom_code/widgets/custom_image_widget.dart b/lib/custom_code/widgets/custom_image_widget.dart new file mode 100644 index 0000000..0b940dd --- /dev/null +++ b/lib/custom_code/widgets/custom_image_widget.dart @@ -0,0 +1,39 @@ +// Automatic FlutterFlow imports +import '/backend/backend.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom widgets +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom widget code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +class CustomImageWidget extends StatefulWidget { + const CustomImageWidget({ + Key? key, + this.width, + this.height, + }) : super(key: key); + + final double? width; + final double? height; + + @override + _CustomImageWidgetState createState() => _CustomImageWidgetState(); +} + +class _CustomImageWidgetState extends State { + @override + Widget build(BuildContext context) { + return Container( + width: 100, + height: 100, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage("images/mastercard.png"), + fit: BoxFit.cover, + ), + ), + ); + } +} diff --git a/lib/custom_code/widgets/index.dart b/lib/custom_code/widgets/index.dart index f148a7e..5d97b04 100644 --- a/lib/custom_code/widgets/index.dart +++ b/lib/custom_code/widgets/index.dart @@ -1 +1,2 @@ export 'custom_credit_card_widget.dart' show CustomCreditCardWidget; +export 'custom_image_widget.dart' show CustomImageWidget; diff --git a/lib/flutter_flow/flutter_flow_animations.dart b/lib/flutter_flow/flutter_flow_animations.dart index ecd42ae..e267591 100644 --- a/lib/flutter_flow/flutter_flow_animations.dart +++ b/lib/flutter_flow/flutter_flow_animations.dart @@ -26,7 +26,7 @@ class AnimationInfo { void createAnimation(AnimationInfo animation, TickerProvider vsync) { final newController = AnimationController(vsync: vsync); animation.controller = newController; - animation.adapter = Adapter()..init(newController); + animation.adapter = ValueAdapter(newController.value); } void setupAnimations(Iterable animations, TickerProvider vsync) { diff --git a/lib/flutter_flow/uploaded_file.dart b/lib/flutter_flow/uploaded_file.dart index 7fd15f9..42b0fef 100644 --- a/lib/flutter_flow/uploaded_file.dart +++ b/lib/flutter_flow/uploaded_file.dart @@ -7,19 +7,27 @@ class FFUploadedFile { this.bytes, this.height, this.width, + this.blurHash, }); final String? name; final Uint8List? bytes; final double? height; final double? width; + final String? blurHash; @override String toString() => - 'FFUploadedFile(name: $name, bytes: ${bytes?.length ?? 0}, height: $height, width: $width)'; + 'FFUploadedFile(name: $name, bytes: ${bytes?.length ?? 0}, height: $height, width: $width, blurHash: $blurHash)'; String serialize() => jsonEncode( - {'name': name, 'bytes': bytes, 'height': height, 'width': width}, + { + 'name': name, + 'bytes': bytes, + 'height': height, + 'width': width, + 'blurHash': blurHash, + }, ); static FFUploadedFile deserialize(String val) { @@ -29,17 +37,19 @@ class FFUploadedFile { 'bytes': serializedData['bytes'] ?? Uint8List.fromList([]), 'height': serializedData['height'], 'width': serializedData['width'], + 'blurHash': serializedData['blurHash'], }; return FFUploadedFile( name: data['name'] as String, bytes: data['bytes'] as Uint8List, height: data['height'] as double?, width: data['width'] as double?, + blurHash: data['blurHash'] as String?, ); } @override - int get hashCode => Object.hash(name, bytes, height, width); + int get hashCode => Object.hash(name, bytes, height, width, blurHash); @override bool operator ==(other) => @@ -47,5 +57,6 @@ class FFUploadedFile { name == other.name && bytes == other.bytes && height == other.height && - width == other.width; + width == other.width && + blurHash == other.blurHash; } diff --git a/lib/pages/donation/donation_widget.dart b/lib/pages/donation/donation_widget.dart index d4b89bb..b58c7d9 100644 --- a/lib/pages/donation/donation_widget.dart +++ b/lib/pages/donation/donation_widget.dart @@ -70,6 +70,10 @@ class _DonationWidgetState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, onTap: () async { context.pushNamed('TestPage'); }, @@ -88,29 +92,62 @@ class _DonationWidgetState extends State { mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ - FFButtonWidget( - onPressed: () async { - context.pushNamed('TestPage'); - }, - text: 'Test Page ', - options: FFButtonOptions( - width: 130.0, - height: 40.0, - padding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - iconPadding: - EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), - color: FlutterFlowTheme.of(context).primary, - textStyle: - FlutterFlowTheme.of(context).titleSmall.override( - fontFamily: 'Poppins', - color: Colors.white, - ), - borderSide: BorderSide( - color: Colors.transparent, - width: 1.0, + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(10.0, 10.0, 10.0, 10.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed('TestPage'); + }, + text: 'Test Page ', + options: FFButtonOptions( + width: 130.0, + height: 40.0, + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: + FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: 'Poppins', + color: Colors.white, + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(10.0, 10.0, 10.0, 10.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed('GhostImagePage'); + }, + text: 'Ghosts', + options: FFButtonOptions( + width: 130.0, + height: 40.0, + padding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: + EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: + FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: 'Poppins', + color: Colors.white, + ), + borderSide: BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), ), - borderRadius: BorderRadius.circular(8.0), ), ), ], diff --git a/lib/pages/ghost_image_page/ghost_image_page_widget.dart b/lib/pages/ghost_image_page/ghost_image_page_widget.dart index a1fa703..292c919 100644 --- a/lib/pages/ghost_image_page/ghost_image_page_widget.dart +++ b/lib/pages/ghost_image_page/ghost_image_page_widget.dart @@ -78,23 +78,44 @@ class _GhostImagePageWidgetState extends State { child: Column( mainAxisSize: MainAxisSize.max, children: [ - Image.asset( - 'assets/images/mastercard.png', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, - ), - Image.asset( - 'assets/images/card_bg.png', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, - ), - Image.asset( - 'assets/images/bg.png', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, + Padding( + padding: EdgeInsetsDirectional.fromSTEB(0.0, 50.0, 0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), + child: Image.asset( + 'assets/images/bg.png', + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), + child: Image.asset( + 'assets/images/mastercard.png', + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + ), + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(5.0, 5.0, 5.0, 5.0), + child: Image.asset( + 'assets/images/card_bg.png', + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + ), + ], + ), ), ], ), diff --git a/pubspec.yaml b/pubspec.yaml index c7d2bdd..dc524ee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,15 +42,16 @@ dependencies: firebase_core_web: 2.0.2 firebase_dynamic_links: 5.0.8 firebase_dynamic_links_platform_interface: 0.2.3+24 - flutter_animate: 1.0.0 + flutter_animate: 4.1.1+1 flutter_cache_manager: 3.3.0 flutter_credit_card: ^3.0.6 - flutter_secure_storage: 6.0.0 + flutter_secure_storage: 8.0.0 font_awesome_flutter: 10.1.0 from_css_color: 2.0.0 go_router: 3.1.0 - google_fonts: 3.0.1 + google_fonts: 4.0.3 google_sign_in: 5.4.0 + google_sign_in_android: 6.1.8 google_sign_in_ios: 5.4.0 google_sign_in_platform_interface: 2.2.0 google_sign_in_web: 0.10.2 @@ -60,7 +61,7 @@ dependencies: page_transition: 2.0.4 plugin_platform_interface: 2.1.3 provider: 6.0.4 - rxdart: 0.27.4 + rxdart: 0.27.5 shared_preferences: 2.0.15 shared_preferences_android: 2.1.0 shared_preferences_ios: 2.1.1 @@ -69,9 +70,9 @@ dependencies: sign_in_with_apple: 4.1.0 sign_in_with_apple_platform_interface: 1.0.0 sign_in_with_apple_web: 1.0.1 - sqflite: 2.2.0+2 + sqflite: 2.2.6 timeago: 3.2.2 - url_launcher: 6.1.5 + url_launcher: 6.1.10 # The following adds the Cupertino Icons font to your application. @@ -107,6 +108,7 @@ flutter: - assets/pdfs/ + # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. From 1295bd85c133b458bba6692ce3ed4e7a19f9cd31 Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 20:28:40 +0000 Subject: [PATCH 13/15] Updating to latest FlutterFlow output. assets/images/bg.png + ghost widget --- lib/custom_code/widgets/custom_credit_card_widget.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/custom_code/widgets/custom_credit_card_widget.dart b/lib/custom_code/widgets/custom_credit_card_widget.dart index 7f59bd6..364d935 100644 --- a/lib/custom_code/widgets/custom_credit_card_widget.dart +++ b/lib/custom_code/widgets/custom_credit_card_widget.dart @@ -68,7 +68,7 @@ class _CustomCreditCardWidgetState extends State { height: widget.height, decoration: const BoxDecoration( image: DecorationImage( - image: ExactAssetImage('images/bg.png'), + image: ExactAssetImage('assets/images/bg.png'), fit: BoxFit.fill, ), color: Colors.black, @@ -96,14 +96,15 @@ class _CustomCreditCardWidgetState extends State { obscureCardCvv: false, isHolderNameVisible: true, cardBgColor: AppColors.cardBgColor, - backgroundImage: useBackgroundImage ? 'images/card_bg.png' : null, + backgroundImage: + useBackgroundImage ? 'assets/images/card_bg.png' : null, isSwipeGestureEnabled: true, onCreditCardWidgetChange: (CreditCardBrand creditCardBrand) {}, customCardTypeIcons: [ CustomCardTypeIcon( cardType: CardType.mastercard, cardImage: Image.asset( - 'images/mastercard.png', + 'assets/images/mastercard.png', height: 48, width: 48, ), From 4d381db1708a20323fbb86a046ad3433d3fc05ff Mon Sep 17 00:00:00 2001 From: "flutterflow-github-app[bot]" <79809161+flutterflow-github-app[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 20:50:52 +0000 Subject: [PATCH 14/15] Updating to latest FlutterFlow output. no ghost images --- assets/images/bg.png | Bin 159876 -> 0 bytes assets/images/card_bg.png | Bin 20431 -> 0 bytes assets/images/mastercard.png | Bin 1036 -> 0 bytes .../ghost_image_page_widget.dart | 6 +++--- 4 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 assets/images/bg.png delete mode 100644 assets/images/card_bg.png delete mode 100644 assets/images/mastercard.png diff --git a/assets/images/bg.png b/assets/images/bg.png deleted file mode 100644 index 053e4e09ca38fa0d84553fe2b66ef39a9ea9bd45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159876 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