From 8b93978fa15b5417e3cf5d69bb281d2598232ca5 Mon Sep 17 00:00:00 2001 From: kleponijo <158453666+kleponijo@users.noreply.github.com> Date: Tue, 10 Feb 2026 17:28:07 +0700 Subject: [PATCH] ganti tema anjay --- .../auth/blocs/sign_up_bloc/sign_up_bloc.dart | 2 +- lib/screens/auth/views/sign_in_screen.dart | 1 - lib/screens/auth/views/sign_up_screen.dart | 463 ++++++++---------- lib/screens/auth/views/welcome_screen.dart | 31 +- pubspec.yaml | 9 - 5 files changed, 218 insertions(+), 288 deletions(-) diff --git a/lib/screens/auth/blocs/sign_up_bloc/sign_up_bloc.dart b/lib/screens/auth/blocs/sign_up_bloc/sign_up_bloc.dart index 1d1c874..a61bf58 100644 --- a/lib/screens/auth/blocs/sign_up_bloc/sign_up_bloc.dart +++ b/lib/screens/auth/blocs/sign_up_bloc/sign_up_bloc.dart @@ -14,7 +14,7 @@ class SignUpBloc extends Bloc { try { MyUser myUser = await _userRepository.signUp(event.user, event.password); await _userRepository.setUserData(myUser); - emit(SignUpProcess()); + emit(SignUpSuccess()); } catch (e) { emit(SignUpFailure()); } diff --git a/lib/screens/auth/views/sign_in_screen.dart b/lib/screens/auth/views/sign_in_screen.dart index 3e7de9e..7659aa9 100644 --- a/lib/screens/auth/views/sign_in_screen.dart +++ b/lib/screens/auth/views/sign_in_screen.dart @@ -4,7 +4,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../components/my_text_field.dart'; import '../blocs/sign_in_bloc/sign_in_bloc.dart'; -// import '../blocs/sing_in_bloc/sign_in_bloc.dart'; class SignInScreen extends StatefulWidget { const SignInScreen({super.key}); diff --git a/lib/screens/auth/views/sign_up_screen.dart b/lib/screens/auth/views/sign_up_screen.dart index daa3c7d..8eb7f61 100644 --- a/lib/screens/auth/views/sign_up_screen.dart +++ b/lib/screens/auth/views/sign_up_screen.dart @@ -13,264 +13,231 @@ class SignUpScreen extends StatefulWidget { } class _SignUpScreenState extends State { - final passwordController = TextEditingController(); + final passwordController = TextEditingController(); final emailController = TextEditingController(); - final nameController = TextEditingController(); + final nameController = TextEditingController(); + final confirmPasswordController = TextEditingController(); final _formKey = GlobalKey(); - IconData iconPassword = CupertinoIcons.eye_fill; - bool obscurePassword = true; - bool signUpRequired = false; - - bool containsUpperCase = false; - bool containsLowerCase = false; - bool containsNumber = false; - bool containsSpecialChar = false; - bool contains8Length = false; + IconData iconPassword = CupertinoIcons.eye_fill; + bool obscurePassword = true; + bool signUpRequired = false; @override Widget build(BuildContext context) { return BlocListener( - listener: (context, state) { - if(state is SignUpSuccess) { - setState(() { - signUpRequired = false; - }); - } else if(state is SignUpProcess) { - setState(() { - signUpRequired = true; - }); - } else if(state is SignUpFailure) { - return; - } - }, - child: Form( - key: _formKey, - child: Center( - child: Column( - children: [ - const SizedBox(height: 20), - SizedBox( - width: MediaQuery.of(context).size.width * 0.9, - child: MyTextField( - controller: emailController, - hintText: 'Email', - obscureText: false, - keyboardType: TextInputType.emailAddress, - prefixIcon: const Icon(CupertinoIcons.mail_solid), - validator: (val) { - if(val!.isEmpty) { - return 'Please fill in this field'; - } else if(!RegExp(r'^[\w-\.]+@([\w-]+.)+[\w-]{2,4}$').hasMatch(val)) { - return 'Please enter a valid email'; - } - return null; - } - ), - ), - const SizedBox(height: 10), - SizedBox( - width: MediaQuery.of(context).size.width * 0.9, - child: MyTextField( - controller: passwordController, - hintText: 'Password', - obscureText: obscurePassword, - keyboardType: TextInputType.visiblePassword, - prefixIcon: const Icon(CupertinoIcons.lock_fill), - onChanged: (val) { - if(val!.contains(RegExp(r'[A-Z]'))) { - setState(() { - containsUpperCase = true; - }); - } else { - setState(() { - containsUpperCase = false; - }); - } - if(val.contains(RegExp(r'[a-z]'))) { - setState(() { - containsLowerCase = true; - }); - } else { - setState(() { - containsLowerCase = false; - }); - } - if(val.contains(RegExp(r'[0-9]'))) { - setState(() { - containsNumber = true; - }); - } else { - setState(() { - containsNumber = false; - }); - } - if(val.contains(RegExp(r'^(?=.*?[!@#$&*~`)\%\-(_+=;:,.<>/?"[{\]}\|^])'))) { - setState(() { - containsSpecialChar = true; - }); - } else { - setState(() { - containsSpecialChar = false; - }); - } - if(val.length >= 8) { - setState(() { - contains8Length = true; - }); - } else { - setState(() { - contains8Length = false; - }); - } - return null; - }, - suffixIcon: IconButton( - onPressed: () { - setState(() { - obscurePassword = !obscurePassword; - if(obscurePassword) { - iconPassword = CupertinoIcons.eye_fill; - } else { - iconPassword = CupertinoIcons.eye_slash_fill; - } - }); - }, - icon: Icon(iconPassword), - ), - validator: (val) { - if(val!.isEmpty) { - return 'Please fill in this field'; - } else if(!RegExp(r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~`)\%\-(_+=;:,.<>/?"[{\]}\|^]).{8,}$').hasMatch(val)) { - return 'Please enter a valid password'; - } - return null; - } - ), - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "⚈ 1 uppercase", - style: TextStyle( - color: containsUpperCase - ? Colors.green - : Theme.of(context).colorScheme.onBackground - ), + listener: (context, state) { + if (state is SignUpSuccess) { + setState(() { + signUpRequired = false; + }); + } else if (state is SignUpProcess) { + setState(() { + signUpRequired = true; + }); + } else if (state is SignUpFailure) { + return; + } + }, + child: Form( + key: _formKey, + child: Scaffold( + backgroundColor: Colors.white, + body: Center( + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 30), + Container( + width: MediaQuery.of(context).size.width * 0.92, + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 22), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.04), + blurRadius: 10, + offset: const Offset(0, 4), + ) + ], ), - Text( - "⚈ 1 lowercase", - style: TextStyle( - color: containsLowerCase - ? Colors.green - : Theme.of(context).colorScheme.onBackground - ), - ), - Text( - "⚈ 1 number", - style: TextStyle( - color: containsNumber - ? Colors.green - : Theme.of(context).colorScheme.onBackground - ), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "⚈ 1 special character", - style: TextStyle( - color: containsSpecialChar - ? Colors.green - : Theme.of(context).colorScheme.onBackground - ), - ), - Text( - "⚈ 8 minimum character", - style: TextStyle( - color: contains8Length - ? Colors.green - : Theme.of(context).colorScheme.onBackground - ), - ), - ], - ), - ], - ), - const SizedBox(height: 10), - SizedBox( - width: MediaQuery.of(context).size.width * 0.9, - child: MyTextField( - controller: nameController, - hintText: 'Name', - obscureText: false, - keyboardType: TextInputType.name, - prefixIcon: const Icon(CupertinoIcons.person_fill), - validator: (val) { - if(val!.isEmpty) { - return 'Please fill in this field'; - } else if(val.length > 30) { - return 'Name too long'; - } - return null; - } - ), - ), - SizedBox(height: MediaQuery.of(context).size.height * 0.02), - !signUpRequired - ? SizedBox( - width: MediaQuery.of(context).size.width * 0.5, - child: TextButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - MyUser myUser = MyUser.empty; - myUser.email = emailController.text; - myUser.name = nameController.text; - - setState(() { - context.read().add( - SignUpRequired( - myUser, - passwordController.text - ) - ); - }); - } - }, - style: TextButton.styleFrom( - elevation: 3.0, - backgroundColor: Theme.of(context).colorScheme.primary, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(60) - ) - ), - child: const Padding( - padding: EdgeInsets.symmetric(horizontal: 25, vertical: 5), - child: Text( - 'Sign Up', - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600 + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 6), + const Center( + child: Text( + 'Buat Akun', + style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700), + ), ), - ), - ) + const SizedBox(height: 6), + const Center( + child: Text( + 'Daftar untuk mulai monitoring', + style: TextStyle(fontSize: 13, color: Colors.black54), + ), + ), + const SizedBox(height: 14), + + // Name + SizedBox( + width: MediaQuery.of(context).size.width * 0.9, + child: MyTextField( + controller: nameController, + hintText: 'Masukkan nama lengkap', + obscureText: false, + keyboardType: TextInputType.name, + prefixIcon: const Icon(CupertinoIcons.person_fill), + validator: (val) { + if (val == null || val.isEmpty) { + return 'Please fill in this field'; + } else if (val.length > 50) { + return 'Name too long'; + } + return null; + }, + ), + ), + const SizedBox(height: 10), + + // Email + SizedBox( + width: MediaQuery.of(context).size.width * 0.9, + child: MyTextField( + controller: emailController, + hintText: 'nama@email.com', + obscureText: false, + keyboardType: TextInputType.emailAddress, + prefixIcon: const Icon(CupertinoIcons.mail_solid), + validator: (val) { + if (val == null || val.isEmpty) { + return 'Please fill in this field'; + } else if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(val)) { + return 'Please enter a valid email'; + } + return null; + }, + ), + ), + const SizedBox(height: 10), + + // Password + SizedBox( + width: MediaQuery.of(context).size.width * 0.9, + child: MyTextField( + controller: passwordController, + hintText: 'Minimal 6 karakter', + obscureText: obscurePassword, + keyboardType: TextInputType.visiblePassword, + prefixIcon: const Icon(CupertinoIcons.lock_fill), + suffixIcon: IconButton( + onPressed: () { + setState(() { + obscurePassword = !obscurePassword; + iconPassword = obscurePassword + ? CupertinoIcons.eye_fill + : CupertinoIcons.eye_slash_fill; + }); + }, + icon: Icon(iconPassword), + ), + validator: (val) { + if (val == null || val.isEmpty) { + return 'Please fill in this field'; + } else if (val.length < 6) { + return 'Password minimal 6 karakter'; + } + return null; + }, + ), + ), + const SizedBox(height: 10), + + // Confirm Password + SizedBox( + width: MediaQuery.of(context).size.width * 0.9, + child: MyTextField( + controller: confirmPasswordController, + hintText: 'Ulangi password', + obscureText: obscurePassword, + keyboardType: TextInputType.visiblePassword, + prefixIcon: const Icon(CupertinoIcons.lock_fill), + validator: (val) { + if (val == null || val.isEmpty) { + return 'Please fill in this field'; + } else if (val != passwordController.text) { + return 'Password tidak cocok'; + } + return null; + }, + ), + ), + + const SizedBox(height: 18), + + // Button + !signUpRequired + ? SizedBox( + width: MediaQuery.of(context).size.width * 0.92, + child: ElevatedButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + MyUser myUser = MyUser.empty; + myUser.email = emailController.text; + myUser.name = nameController.text; + + setState(() { + context.read().add( + SignUpRequired( + myUser, + passwordController.text, + ), + ); + }); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.black87, + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: const Text( + 'Daftar', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + ), + ), + ) + : const CircularProgressIndicator(), + + const SizedBox(height: 12), + Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Sudah punya akun? '), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Login di sini'), + ) + ], + ), + ), + ], + ), ), - ) - : const CircularProgressIndicator() - ], + const SizedBox(height: 30), + ], + ), + ), + ), ), ), - ), - ); + ); } } \ No newline at end of file diff --git a/lib/screens/auth/views/welcome_screen.dart b/lib/screens/auth/views/welcome_screen.dart index 79ea53c..4ec3d63 100644 --- a/lib/screens/auth/views/welcome_screen.dart +++ b/lib/screens/auth/views/welcome_screen.dart @@ -1,4 +1,3 @@ -import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../blocs/authentication_bloc/authentication_bloc.dart'; @@ -30,39 +29,13 @@ class _WelcomeScreenState extends State with TickerProviderStateM @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Theme.of(context).colorScheme.background, + return Scaffold( + backgroundColor: Colors.white, body: SingleChildScrollView( child: SizedBox( height: MediaQuery.of(context).size.height, child: Stack( children: [ - Align( - alignment: const AlignmentDirectional(20, -1.2), - child: Container( - height: MediaQuery.of(context).size.width, - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).colorScheme.tertiary - ), - ), - ), - Align( - alignment: const AlignmentDirectional(2.7, -1.2), - child: Container( - height: MediaQuery.of(context).size.width / 1.3, - width: MediaQuery.of(context).size.width / 1.3, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).colorScheme.primary - ), - ), - ), - BackdropFilter( - filter: ImageFilter.blur(sigmaX: 100.0, sigmaY: 100.0), - child: Container(), - ), Align( alignment: Alignment.center, child: SizedBox( diff --git a/pubspec.yaml b/pubspec.yaml index c70e8e3..81e0163 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,35 +2,26 @@ name: klimatologiot description: "A new Flutter project." publish_to: 'none' version: 1.0.0+1 - environment: sdk: ^3.1.0 - dependencies: flutter: sdk: flutter - firebase_core: ^4.3.0 firebase_auth: ^6.1.3 cloud_firestore: ^6.1.1 rxdart: ^0.27.7 google_sign_in: ^7.2.0 - bloc: ^8.1.0 flutter_bloc: ^8.1.0 equatable: ^2.0.5 - user_repository: path: packages/user_repository - cupertino_icons: ^1.0.8 - dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^3.0.0 - flutter: uses-material-design: true