diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 5609eba..0f7e262 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.2/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.1.2/","native_build":true,"dependencies":[]},{"name":"url_launcher_ios","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_ios-6.2.5/","native_build":true,"dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.2/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_android-2.0.27/","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_android-2.0.15/","native_build":true,"dependencies":[]},{"name":"url_launcher_android","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.3/","native_build":true,"dependencies":[]}],"macos":[{"name":"flutter_secure_storage_macos","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.2/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.1.2/","native_build":true,"dependencies":[]},{"name":"url_launcher_macos","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_macos-3.1.0/","native_build":true,"dependencies":[]}],"linux":[{"name":"flutter_secure_storage_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.1/","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.7/","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.1.3/","native_build":false,"dependencies":["path_provider_linux"]},{"name":"url_launcher_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_linux-3.1.1/","native_build":true,"dependencies":[]}],"windows":[{"name":"flutter_secure_storage_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.7/","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.1.3/","native_build":false,"dependencies":["path_provider_windows"]},{"name":"url_launcher_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.1/","native_build":true,"dependencies":[]}],"web":[{"name":"flutter_secure_storage_web","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[]},{"name":"shared_preferences_web","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_web-2.0.4/","dependencies":[]},{"name":"url_launcher_web","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_web-2.3.1/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2024-07-06 23:15:23.666343","version":"3.22.2"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.2/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.1.2/","native_build":true,"dependencies":[]},{"name":"url_launcher_ios","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_ios-6.2.5/","native_build":true,"dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.2/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_android-2.0.27/","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_android-2.0.15/","native_build":true,"dependencies":[]},{"name":"url_launcher_android","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.3/","native_build":true,"dependencies":[]}],"macos":[{"name":"flutter_secure_storage_macos","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.2/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.1.2/","native_build":true,"dependencies":[]},{"name":"url_launcher_macos","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_macos-3.1.0/","native_build":true,"dependencies":[]}],"linux":[{"name":"flutter_secure_storage_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.1/","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.7/","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.1.3/","native_build":false,"dependencies":["path_provider_linux"]},{"name":"url_launcher_linux","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_linux-3.1.1/","native_build":true,"dependencies":[]}],"windows":[{"name":"flutter_secure_storage_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.7/","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.1.3/","native_build":false,"dependencies":["path_provider_windows"]},{"name":"url_launcher_windows","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.1/","native_build":true,"dependencies":[]}],"web":[{"name":"flutter_secure_storage_web","path":"/Users/anthony/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[]},{"name":"shared_preferences_web","path":"/Users/anthony/.pub-cache/hosted/pub.dev/shared_preferences_web-2.0.4/","dependencies":[]},{"name":"url_launcher_web","path":"/Users/anthony/.pub-cache/hosted/pub.dev/url_launcher_web-2.3.1/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2024-07-08 03:40:32.576485","version":"3.22.2"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2281721..eb4f1af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [1.0.0] - 2024-07-08 + +* Update stubs + * New Login Page + * New Landing Page + * New Register Page + * Remove Widgets +* Update pubspec.yaml + ## [0.5.2] - 2024-06-06 * Update pubspec.yaml diff --git a/README.md b/README.md index 5f6d012..c1ffa30 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ In your flutter project add the dependency: ``` dart dependencies: ... - ny_auth_slate: ^0.5.2 + ny_auth_slate: ^1.0.0 ``` ``` bash @@ -25,7 +25,7 @@ dart run ny_auth_slate:main publish:all With Nylo ``` bash -metro publish:slate ny_auth_slate +metro slate:publish ny_auth_slate ``` ## Requirements @@ -36,9 +36,7 @@ metro publish:slate ny_auth_slate - Pages - Login - Register -- Widgets - - Buttons - - Text Fields + - Landing ## Licence diff --git a/images/sonoran_desert_1.jpg b/images/sonoran_desert_1.jpg new file mode 100644 index 0000000..4c1fcbd Binary files /dev/null and b/images/sonoran_desert_1.jpg differ diff --git a/images/sonoran_desert_2.png b/images/sonoran_desert_2.png new file mode 100644 index 0000000..aeefb27 Binary files /dev/null and b/images/sonoran_desert_2.png differ diff --git a/images/sonoran_desert_3.jpg b/images/sonoran_desert_3.jpg new file mode 100644 index 0000000..f0449f4 Binary files /dev/null and b/images/sonoran_desert_3.jpg differ diff --git a/lib/ny_auth_slate.dart b/lib/ny_auth_slate.dart index 8c9936c..c2c9a9b 100644 --- a/lib/ny_auth_slate.dart +++ b/lib/ny_auth_slate.dart @@ -1,9 +1,10 @@ library ny_auth_slate; -import '/stubs/buttons.dart'; +import '/stubs/landing_page.dart'; +import '/stubs/login_form.dart'; +import '/stubs/register_form.dart'; import '/stubs/login_page.dart'; import '/stubs/register_page.dart'; -import '/stubs/text_fields.dart'; import 'package:nylo_support/metro/constants/strings.dart'; import 'package:nylo_support/metro/models/ny_template.dart'; @@ -18,6 +19,12 @@ import 'package:nylo_support/metro/models/ny_template.dart'; |-------------------------------------------------------------------------- */ List run() => [ + NyTemplate( + name: "landing", + saveTo: pagesFolder, + pluginsRequired: [], + stub: stubLandingPage(), + ), NyTemplate( name: "login", saveTo: pagesFolder, @@ -31,16 +38,16 @@ List run() => [ stub: stubRegisterPage(), ), NyTemplate( - name: "buttons", - saveTo: widgetsFolder, + name: "register_form", + saveTo: formsFolder, pluginsRequired: [], - stub: stubButtons(), + stub: stubRegisterForm(), ), NyTemplate( - name: "text_fields", - saveTo: widgetsFolder, + name: "login_form", + saveTo: formsFolder, pluginsRequired: [], - stub: stubTextFields(), + stub: stubLoginForm(), ), ]; diff --git a/lib/stubs/buttons.dart b/lib/stubs/buttons.dart deleted file mode 100644 index acca0fd..0000000 --- a/lib/stubs/buttons.dart +++ /dev/null @@ -1,158 +0,0 @@ -String stubButtons() => ''' -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_app/bootstrap/extensions.dart'; -import 'package:flutter_app/bootstrap/helpers.dart'; - -class AccentButton extends StatelessWidget { - const AccentButton({ - Key? key, - required this.title, - this.action, - }) : super(key: key); - - final String title; - final void Function()? action; - - @override - Widget build(BuildContext context) => DefaultButton( - key: key, - title: title, - action: action, - textStyle: Theme.of(context).textTheme.bodyLarge, - bgColor: ThemeColor.get(context).primaryAccent, - ); -} - -class SecondaryButton extends StatelessWidget { - const SecondaryButton({ - Key? key, - required this.title, - this.action, - }) : super(key: key); - - final String title; - final void Function()? action; - - @override - Widget build(BuildContext context) => DefaultButton( - key: key, - title: title, - action: action, - textStyle: Theme.of(context) - .textTheme - .bodyLarge! - .copyWith(color: Colors.white), - bgColor: ThemeColor.get(context).buttonBackground, - ); -} - -class DefaultButton extends StatelessWidget { - const DefaultButton({ - Key? key, - required this.title, - this.action, - this.textStyle, - this.bgColor, - }) : super(key: key); - - final String title; - final void Function()? action; - final TextStyle? textStyle; - final Color? bgColor; - - @override - Widget build(BuildContext context) { - final double screenWidth = MediaQuery.of(context).size.width; - return Container( - height: (screenWidth >= 385 ? 55 : 49), - width: double.infinity, - decoration: BoxDecoration( - color: Colors.transparent, - ), - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - ), - padding: EdgeInsets.all(8), - elevation: 0, - backgroundColor: bgColor, - shadowColor: Colors.transparent), - child: Text( - title, - style: textStyle, - maxLines: (screenWidth >= 385 ? 2 : 1), - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - ), - onPressed: action, - ), - ); - } -} - -class PrimaryButtonWidget extends StatefulWidget { - final Function() action; - final String text; - final bool isSelected; - final bool? isLoading; - final Color? color; - - PrimaryButtonWidget( - {Key? key, - required this.action, - required this.text, - this.isLoading, - this.isSelected = false, - this.color}) - : super(key: key); - - @override - _PrimaryButtonWidgetState createState() => _PrimaryButtonWidgetState(); -} - -class _PrimaryButtonWidgetState extends State { - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Container( - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - boxShadow: [ - BoxShadow( - color: Colors.black26, - spreadRadius: 1, - blurRadius: 5, - offset: Offset(0, 1), - ) - ], - ), - child: MaterialButton( - shape: - RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)), - padding: EdgeInsets.all(12), - color: widget.color ?? ThemeColor.get(context).buttonBackground, - disabledColor: Colors.grey, - onPressed: (widget.isLoading ?? false) ? null : widget.action, - elevation: 0, - child: (widget.isLoading ?? false) - ? CupertinoActivityIndicator() - : Text( - widget.text, - style: Theme.of(context) - .textTheme - .titleMedium! - .setColor(context, (color) => color.buttonPrimaryContent), - textAlign: TextAlign.center, - ), - ), - ); - } -} -'''; diff --git a/lib/stubs/landing_page.dart b/lib/stubs/landing_page.dart new file mode 100644 index 0000000..6e5afcf --- /dev/null +++ b/lib/stubs/landing_page.dart @@ -0,0 +1,190 @@ +String stubLandingPage() => ''' +import 'dart:async'; +import 'dart:ui'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '/bootstrap/extensions.dart'; +import '/resources/pages/login_page.dart'; +import '/resources/pages/register_page.dart'; +import 'package:nylo_framework/nylo_framework.dart'; + +class LandingPage extends NyStatefulWidget { + static const path = '/landing'; + + LandingPage() : super(path, child: _LandingPageState()); +} + +class _LandingPageState extends NyState { + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBody: true, + extendBodyBehindAppBar: true, + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.black26, + Colors.black87 + ], + ), + ), + width: double.infinity, + child: Stack( + children: [ + Positioned.fill( + child: Opacity(opacity: 0.3, + child: ImageCarousel(images: [ + "sonoran_desert_1.jpg", + "sonoran_desert_2.png", + "sonoran_desert_3.jpg", + ], duration: Duration(seconds: 5)) + ), + ), + + Positioned.fill( + child: SafeArea( + minimum: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Sonoran") + .fontWeightBold() + .alignCenter() + .setColor(context, (color) => Colors.white) + .setFontSize(40) + .paddingOnly(bottom: 25), + + ClipRect( + child: BackdropFilter( + filter: new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), + child: Container( + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 30), + decoration: new BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: BorderRadius.circular(32), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text("Start your journey", style: TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold), textAlign: TextAlign.center).paddingOnly(bottom: 5), + Text("Built to help you create amazing things! Join our community.", style: TextStyle(fontSize: 16, color: Colors.white), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis).paddingOnly(bottom: 25), + + MaterialButton( + padding: EdgeInsets.symmetric(vertical: 10), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + color: Colors.white.withOpacity(0.3), + elevation: 0, + onPressed: () { + routeTo(RegisterPage.path); + }, child: Text("Get Started", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18)), + ), + + NyRichText( + textAlign: TextAlign.center, + style: TextStyle(fontSize: 16), + children: [ + Text("Already have an account? ", style: TextStyle(color: Colors.white)), + Text("Login", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), + ],).onTap(() { + routeTo(LoginPage.path); + }).paddingOnly(top: 20), + ], + ), + ), + ), + ) + ], + ), + ), + ), + ], + ), + ) + ); + } +} + +/// Image Carousel +class ImageCarousel extends StatefulWidget { + final List images; + final Duration duration; + + ImageCarousel({ + required this.images, + this.duration = const Duration(seconds: 5), + }); + + @override + _ImageCarouselState createState() => _ImageCarouselState(); +} + +class _ImageCarouselState extends State { + late int _currentIndex; + late Timer _timer; + + @override + void initState() { + super.initState(); + _currentIndex = 0; + _timer = Timer.periodic(widget.duration + Duration(seconds: 1), (timer) { + setState(() { + _currentIndex = (_currentIndex + 1) % widget.images.length; + }); + }); + } + + @override + void dispose() { + _timer.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (listEquals([ + "sonoran_desert_1.jpg", + "sonoran_desert_2.png", + "sonoran_desert_3.jpg", + ], widget.images)) { + return AnimatedSwitcher( + duration: Duration(seconds: 1), + child: Image.asset( + 'packages/ny_auth_slate/images/\${widget.images[_currentIndex]}', + key: ValueKey(widget.images[_currentIndex]), + fit: BoxFit.cover, + width: double.infinity, + height: double.infinity, + ), + transitionBuilder: (child, animation) { + return FadeTransition( + opacity: animation, + child: child, + ); + }, + ); + } + + return AnimatedSwitcher( + duration: Duration(seconds: 1), + child: Image.asset( + 'public/assets/images/\${widget.images[_currentIndex]}', + key: ValueKey(widget.images[_currentIndex]), + fit: BoxFit.cover, + width: double.infinity, + height: double.infinity, + ), + transitionBuilder: (child, animation) { + return FadeTransition( + opacity: animation, + child: child, + ); + }, + ); + } +} +'''; diff --git a/lib/stubs/login_form.dart b/lib/stubs/login_form.dart new file mode 100644 index 0000000..93d9d1b --- /dev/null +++ b/lib/stubs/login_form.dart @@ -0,0 +1,30 @@ +String stubLoginForm() => ''' +import 'package:nylo_framework/nylo_framework.dart'; + +/* Login Form +|-------------------------------------------------------------------------- +| Usage: https://nylo.dev/docs/5.20.0/forms#how-it-works +| Casts: https://nylo.dev/docs/5.20.0/forms#form-casts +| Validation Rules: https://nylo.dev/docs/5.20.0/validation#validation-rules +|-------------------------------------------------------------------------- */ + +class LoginForm extends NyFormData { + + LoginForm({String? name}) : super(name ?? "login"); + + @override + fields() => [ + Field("Email", + autofocus: true, + cast: FormCast.email(), + validate: FormValidator.rule("email"), + style: "compact" + ), + Field("Password", + cast: FormCast.password(), + validate: FormValidator.password(strength: 1), + style: "compact" + ), + ]; +} +'''; diff --git a/lib/stubs/login_page.dart b/lib/stubs/login_page.dart index 9ac9530..5563192 100644 --- a/lib/stubs/login_page.dart +++ b/lib/stubs/login_page.dart @@ -1,115 +1,55 @@ String stubLoginPage() => ''' -import 'package:flutter/material.dart'; import '/resources/widgets/logo_widget.dart'; -import '/resources/widgets/buttons_widget.dart'; -import '/resources/widgets/text_fields_widget.dart'; +import '/bootstrap/extensions.dart'; +import 'package:flutter/material.dart'; import 'package:nylo_framework/nylo_framework.dart'; class LoginPage extends NyStatefulWidget { - static String path = '/login'; + static const path = '/login'; - LoginPage({Key? key}) : super(path, key: key, child: _LoginPageState()); + LoginPage() : super(path, child: () => _LoginPageState()); } class _LoginPageState extends NyState { - TextEditingController _txtEmailController = TextEditingController(), - _txtPasswordController = TextEditingController(); - - @override - init() async { - whenEnv('developing', perform: () { - _txtEmailController.text = 'fake@gmail.com'; - _txtPasswordController.text = 'password'; - }); - } - - loginUser() async { - String email = _txtEmailController.text; - String password = _txtPasswordController.text; - - await lockRelease('login', perform: () async { - /// handle login - await Future.delayed(Duration(seconds: 2)); - }); - } - @override Widget build(BuildContext context) { - return new Scaffold( - resizeToAvoidBottomInset: false, + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + iconTheme: IconThemeData(color: Colors.black), + title: Logo(height: 40), + ), body: SafeArea( minimum: EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child: ListView( children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Logo( - height: 50, - width: 50, - ), - Container( - height: 60, - padding: EdgeInsets.only(top: 10), - child: Text( - 'Welcome back', - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(fontSize: 20), - ), - ), - ], - ), - Container( - margin: EdgeInsets.symmetric(vertical: 40), - child: Column(children: [ - PrimaryTextFieldWidget( - controller: _txtEmailController, - labelText: "EMAIL", - enableSuggestions: false, - textInputType: TextInputType.emailAddress, - obscureText: false, - ), - PrimaryTextFieldWidget( - controller: _txtPasswordController, - labelText: "PASSWORD", - obscureText: true, - ), - SizedBox( - height: 15, - ), - PrimaryButtonWidget( - action: loginUser, - text: "Log in", - isLoading: isLocked('login'), - ), - ]), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - alignment: AlignmentDirectional.center, - child: InkWell( - child: Text( - 'Forgot your password?', - ), - onTap: () => - Navigator.pushNamed(context, "/forgot-password"), - ), - ), - ], - ) - ], + Text("Login".tr()).headingSmall(context).fontWeightBold().paddingOnly(bottom: 25), + NyForm.login(name: "login", crossAxisSpacing: 20), + Container( + height: 45, + margin: EdgeInsets.only(top: 20, bottom: 20), + width: double.infinity, + child: MaterialButton( + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: EdgeInsets.symmetric(vertical: 8), + color: Colors.black87, + child: Text((isLocked('login') ? "Processing".tr() : "Login".tr())) + .bodyMedium(context) + .fontWeightBold() + .setColor(context, (color) => Colors.white), + onPressed: () { + NyForm.submit("login", onSuccess: (data) { + // add your code here + // data = {"email": "email", "password": "password"} + }); + } + ), ), + Text("Forgot your password?".tr(), textAlign: TextAlign.center).onTap(() { + // add your code here + }) ], ), ), diff --git a/lib/stubs/register_form.dart b/lib/stubs/register_form.dart new file mode 100644 index 0000000..05fd769 --- /dev/null +++ b/lib/stubs/register_form.dart @@ -0,0 +1,35 @@ +String stubRegisterForm() => ''' +import 'package:nylo_framework/nylo_framework.dart'; + +/* Register Form +|-------------------------------------------------------------------------- +| Usage: https://nylo.dev/docs/5.20.0/forms#how-it-works +| Casts: https://nylo.dev/docs/5.20.0/forms#form-casts +| Validation Rules: https://nylo.dev/docs/5.20.0/validation#validation-rules +|-------------------------------------------------------------------------- */ + +class RegisterForm extends NyFormData { + + RegisterForm({String? name}) : super(name ?? "register"); + + @override + fields() => [ + Field("Name", + autofocus: true, + cast: FormCast.text(), + validate: FormValidator.rule("not_empty"), + style: "compact" + ), + Field("Email", + cast: FormCast.email(), + validate: FormValidator.rule("email"), + style: "compact" + ), + Field("Password", + cast: FormCast.password(), + validate: FormValidator.password(strength: 1), + style: "compact" + ), + ]; +} +'''; diff --git a/lib/stubs/register_page.dart b/lib/stubs/register_page.dart index bde32c2..4657c02 100644 --- a/lib/stubs/register_page.dart +++ b/lib/stubs/register_page.dart @@ -1,185 +1,95 @@ String stubRegisterPage() => ''' import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import '/resources/widgets/buttons_widget.dart'; +import '/app/forms/register_form.dart'; +import 'package:url_launcher/url_launcher.dart'; import '/resources/widgets/logo_widget.dart'; -import '/resources/widgets/text_fields_widget.dart'; +import '/bootstrap/extensions.dart'; +import 'package:flutter/material.dart'; import 'package:nylo_framework/nylo_framework.dart'; -import 'package:url_launcher/url_launcher.dart'; class RegisterPage extends NyStatefulWidget { - static String path = '/register'; + static const path = '/register'; - RegisterPage({Key? key}) : super(path, key: key, child: _RegisterPageState()); + RegisterPage() : super(path, child: () => _RegisterPageState()); } class _RegisterPageState extends NyState { - TextEditingController _txtNameController = TextEditingController(), - _txtEmailController = TextEditingController(), - _txtPasswordController = TextEditingController(); - @override - init() async { - whenEnv('developing', perform: () { - _txtEmailController.text = "Anthony@mail.com"; - _txtNameController.text = "Anthony"; - _txtPasswordController.text = "Password"; - }); - } - - @override - void dispose() { - super.dispose(); - } - - bool _isProcessing = false; - String? dateOfBirth; - - registerUser() async { - String name = _txtNameController.text; - String email = _txtEmailController.text; - String password = _txtPasswordController.text; - - await lockRelease('register', perform: () async { - /// handle the registration - }); - } - - @override - void initState() { - super.initState(); - _isProcessing = false; - } + RegisterForm form = RegisterForm(); @override Widget build(BuildContext context) { - DateTime dateTime = DateTime.now(); - return new Scaffold( - resizeToAvoidBottomInset: false, + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + iconTheme: IconThemeData(color: Colors.black), + title: Logo(height: 40), + ), body: SafeArea( minimum: EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) => Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - child: Logo( - height: 30, - width: 50, - ), - padding: EdgeInsets.all(8), - margin: EdgeInsets.symmetric(vertical: 16), - ), - ], - ), - Container( - margin: EdgeInsets.symmetric(vertical: 10), - child: Column(children: [ - ListView( - shrinkWrap: true, - children: [ - Row( - children: [ - Flexible( - child: PrimaryTextFieldWidget( - controller: _txtNameController, - labelText: "Name", - autoFocus: true, - obscureText: false, - ), - ), - ], - ), - PrimaryTextFieldWidget( - controller: _txtEmailController, - labelText: "Email", - textInputType: TextInputType.emailAddress, - autoFocus: false, - enableSuggestions: false, - obscureText: false, - ), - Row( - children: [ - Flexible( - child: PrimaryTextFieldWidget( - controller: _txtPasswordController, - labelText: "Password", - obscureText: true, - ), - ), - ], - ), - SizedBox( - height: 15, - ), - PrimaryButtonWidget( - action: registerUser, - text: "Create account", - isLoading: isLocked('register'), - ), - ], - ), - ]), - ), - RichText( - textAlign: TextAlign.center, - text: new TextSpan( - style: new TextStyle( - fontSize: 14.0, - color: Colors.black54, - ), - children: [ - new TextSpan( - text: 'By tapping "Create account", you agree to our ', - ), - new TextSpan( - text: 'terms and conditions', - style: new TextStyle(fontWeight: FontWeight.bold), - recognizer: new TapGestureRecognizer() - ..onTap = () => launchUrl(termsUrl()), - ), - new TextSpan(text: '. You can also view our '), - new TextSpan( - text: 'privacy policy', - style: new TextStyle(fontWeight: FontWeight.bold), - recognizer: new TapGestureRecognizer() - ..onTap = () => launchUrl(privacyUrl()), - ), - new TextSpan(text: ' here.'), - ], - ), - ), - ]), - Container( - height: 40.0, - color: Colors.transparent, - child: Container( - child: MaterialButton( - onPressed: () => - _isProcessing == true ? () {} : Navigator.pop(context), - child: Text( - "Back", - ), - ), + child: ListView( + children: [ + Text("Register".tr()).headingSmall(context).fontWeightBold().paddingOnly(bottom: 25), + NyForm(form: form, crossAxisSpacing: 20), + Container( + height: 45, + margin: EdgeInsets.only(top: 20, bottom: 20), + width: double.infinity, + child: MaterialButton( + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: EdgeInsets.symmetric(vertical: 8), + color: Colors.black87, + child: Text((isLocked('register') ? "Processing".tr() : "Register".tr())) + .bodyMedium(context) + .fontWeightBold() + .setColor(context, (color) => Colors.white), + onPressed: () { + form.submit(onSuccess: (data) { + // add your code here + // data = {"name": name, "email": "email", "password": "password"} + }); + } + ), + ), + RichText( + textAlign: TextAlign.center, + text: new TextSpan( + style: new TextStyle( + fontSize: 14.0, + color: Colors.black54, ), - ) - ], - ), + children: [ + new TextSpan( + text: 'By tapping "Register", you agree to our ', + ), + new TextSpan( + text: 'terms and conditions', + style: new TextStyle(fontWeight: FontWeight.bold), + recognizer: new TapGestureRecognizer() + ..onTap = () => launchUrl(termsUrl()), + ), + new TextSpan(text: '. You can also view our '), + new TextSpan( + text: 'privacy policy', + style: new TextStyle(fontWeight: FontWeight.bold), + recognizer: new TapGestureRecognizer() + ..onTap = () => launchUrl(privacyUrl()), + ), + new TextSpan(text: ' here.'), + ], + ), + ), + ], ), ), ); } - Uri privacyUrl() => Uri.parse("\${getEnv('APP_URL')}/${Uri.parse("privacy-policy")}"); + // Your privacy policy URL + Uri privacyUrl() => Uri.parse("\${getEnv('APP_URL')}/privacy-policy"); - Uri termsUrl() => Uri.parse("\${getEnv('APP_URL')}/${Uri.parse("terms-and-conditions")}"); + // Your terms and conditions URL + Uri termsUrl() => Uri.parse("\${getEnv('APP_URL')}/terms-and-conditions"); } '''; diff --git a/lib/stubs/text_fields.dart b/lib/stubs/text_fields.dart deleted file mode 100644 index 24786e7..0000000 --- a/lib/stubs/text_fields.dart +++ /dev/null @@ -1,58 +0,0 @@ -String stubTextFields() => ''' -import 'package:flutter/material.dart'; - -class PrimaryTextFieldWidget extends StatelessWidget { - final String? labelText; - final TextEditingController controller; - final bool obscureText; - final int maxLines; - final TextInputType textInputType; - final bool autoFocus; - final TextAlign? textAlign; - final bool enableSuggestions; - final FocusNode? focusNode; - final String? hintText; - final TextStyle? hintStyle; - - PrimaryTextFieldWidget( - {Key? key, - required this.controller, - this.labelText, - this.obscureText = false, - this.autoFocus = false, - this.textInputType = TextInputType.text, - this.textAlign, - this.maxLines = 1, - this.enableSuggestions = true, - this.hintText, - this.hintStyle, - this.focusNode}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return TextField( - decoration: InputDecoration( - labelText: labelText, - hintText: hintText, - hintStyle: hintStyle, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.black54), - ), - ), - controller: controller, - keyboardAppearance: Brightness.light, - autofocus: autoFocus, - textAlign: textAlign ?? TextAlign.left, - maxLines: maxLines, - keyboardType: textInputType, - textCapitalization: (textInputType == TextInputType.emailAddress - ? TextCapitalization.none - : TextCapitalization.sentences), - obscureText: obscureText, - focusNode: focusNode, - enableSuggestions: enableSuggestions, - ); - } -} -'''; diff --git a/pubspec.yaml b/pubspec.yaml index 9c8ed51..a699104 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: ny_auth_slate description: Slate package to quickly scaffold a login + register system. -version: 0.5.2 +version: 1.0.0 repository: https://github.com/nylo-core/ny_auth_slate homepage: https://nylo.dev @@ -9,7 +9,7 @@ environment: flutter: ">=1.17.0" dependencies: - nylo_support: ^5.79.1 + nylo_support: ^5.81.0 flutter: sdk: flutter args: ^2.5.0 @@ -18,8 +18,9 @@ dependencies: dev_dependencies: flutter_lints: ^3.0.2 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - # The following section is specific to Flutter packages. -flutter: \ No newline at end of file +flutter: + assets: + - images/sonoran_desert_1.jpg + - images/sonoran_desert_2.png + - images/sonoran_desert_3.jpg \ No newline at end of file