pin code screen, forgot pin code screen
This commit is contained in:
@@ -34,4 +34,8 @@ class RouteName {
|
||||
|
||||
//Biometric
|
||||
static const String otpScreen = 'otpScreen';
|
||||
|
||||
//Pin Screen
|
||||
static const String pinScreen = 'pinScreen';
|
||||
static const String confirmPinScreen = 'confirmPinScreen';
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import 'package:tanami_app/features/countrySelection/presentation/pages/choose_c
|
||||
import 'package:tanami_app/features/otpVerification/presentation/pages/otp_screen.dart';
|
||||
import 'package:tanami_app/features/register/presentation/pages/register_screen.dart';
|
||||
import 'package:tanami_app/features/register/presentation/pages/register_step_screen.dart';
|
||||
import 'package:tanami_app/features/securePin/presentation/pages/pin_screen.dart';
|
||||
import 'package:tanami_app/features/welcome/presentation/pages/weclome_screen.dart';
|
||||
|
||||
import '../../features/login/presentation/pages/login_screen.dart';
|
||||
import '../../features/register/presentation/pages/register_user_details_screen.dart';
|
||||
import '../../features/securePin/presentation/pages/confirm_pin_screen.dart';
|
||||
import '../../features/splash/presentation/pages/splash_screen.dart';
|
||||
|
||||
/* CREATED BY - JAYESH JAIN
|
||||
@@ -108,6 +110,22 @@ final goRouter = GoRouter(
|
||||
return const RegisterUserDetailsScreen();
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: RouteName.pinScreen,
|
||||
path: "${RouteName.pinScreen}/:fromScreen",
|
||||
builder: (context, state) {
|
||||
return PinScreen(
|
||||
fromScreen: state.pathParameters["fromScreen"]!,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: RouteName.confirmPinScreen,
|
||||
path: RouteName.confirmPinScreen,
|
||||
builder: (context, state) {
|
||||
return const ConfirmPinScreen();
|
||||
},
|
||||
),
|
||||
]),
|
||||
|
||||
// GoRoute(
|
||||
|
||||
@@ -44,4 +44,12 @@ class AppColor {
|
||||
|
||||
//CheckBox Color
|
||||
static const Color checkBoxActiveColor = Color(0xFF09622E);
|
||||
|
||||
//Selectable Text Color
|
||||
static const Color selectableTextColor = Color(0xFF015BA2);
|
||||
|
||||
//Pin Code Color
|
||||
static const Color pinFillColor = Color(0xFFC9D9CB);
|
||||
static const Color pinFillBorderColor = Color(0xFF648774);
|
||||
static const Color pinInActiveBorderColor = Color(0xFFDFDFE3);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,10 @@ class AppText {
|
||||
static const String enterEmail = "Enter Email";
|
||||
static const String cantBeEmptyText = "Can't Be Empty";
|
||||
static const String passwordMismatch = "Password Mismatch";
|
||||
static const String iAgreeToThe = "I agree to the ";
|
||||
static const String termsAndCondition = "Terms & Conditions";
|
||||
static const String andThe = " and the";
|
||||
static const String privacyPolicy = "Privacy Policy";
|
||||
|
||||
//Country Name
|
||||
static const String bahrainCountryText = "Bahrain";
|
||||
@@ -92,4 +96,20 @@ class AppText {
|
||||
static const String resendSms = "Resend SMS";
|
||||
static const String otpVerifiedSucessfully = "OTP Verified Successfully!";
|
||||
static const String otpVerifiedFailed = "OTP Verification Failed:";
|
||||
|
||||
//Pin Code
|
||||
static const String pinCode = "Pin Code";
|
||||
static const String createPinCode = "Create Pin Code";
|
||||
static const String confirmPinCode = "Confirm Pin Code";
|
||||
static const String incorrectPinCode = "Incorrect PIN. Please try again.";
|
||||
static const String welcomeBackText = "Welcome back";
|
||||
static const String userYourAppPinToLoginEnterTanami =
|
||||
"Use your app PIN to login to enter Tanami";
|
||||
static const String forgotPinCode = "Forgot Pin Code";
|
||||
|
||||
static const String notificationText = "Notification";
|
||||
static const String toRestorePinYouWillBeLoggedOut =
|
||||
"To restore PIN you will be Logged out";
|
||||
static const String allowText = "Allow";
|
||||
static const String declineText = "Decline";
|
||||
}
|
||||
|
||||
21
lib/core/utils/secure/secure_storage_service.dart
Normal file
21
lib/core/utils/secure/secure_storage_service.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
class SecureStorageService {
|
||||
final FlutterSecureStorage _storage = const FlutterSecureStorage(
|
||||
aOptions: AndroidOptions(
|
||||
encryptedSharedPreferences: true,
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> write(String key, String value) async {
|
||||
await _storage.write(key: key, value: value);
|
||||
}
|
||||
|
||||
Future<String?> read(String key) async {
|
||||
return await _storage.read(key: key);
|
||||
}
|
||||
|
||||
Future<void> delete(String key) async {
|
||||
await _storage.delete(key: key);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
@@ -91,7 +88,7 @@ class _AcademyScreenState extends State<AcademyScreen> {
|
||||
title: Text(
|
||||
'Academy',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF272727),
|
||||
color: const Color(0xFF272727),
|
||||
fontSize: 22.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -109,13 +106,13 @@ class _AcademyScreenState extends State<AcademyScreen> {
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 3), // changes position of shadow
|
||||
offset: const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -170,7 +167,7 @@ class _AcademyScreenState extends State<AcademyScreen> {
|
||||
Text(
|
||||
'${data[index]['videos']} videos',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFFD8D8D8),
|
||||
color: const Color(0xFFD8D8D8),
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -190,7 +187,7 @@ class _AcademyScreenState extends State<AcademyScreen> {
|
||||
Text(
|
||||
data[index]['date'],
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF8D8D8D),
|
||||
color: const Color(0xFF8D8D8D),
|
||||
fontSize: 11.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -216,7 +213,7 @@ class _AcademyScreenState extends State<AcademyScreen> {
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF8D8D8D),
|
||||
color: const Color(0xFF8D8D8D),
|
||||
fontSize: 11.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
|
||||
@@ -10,6 +10,8 @@ class InvestScreen extends StatefulWidget {
|
||||
class _InvestScreenState extends State<InvestScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(body: Text('Invest'),);
|
||||
return const Scaffold(
|
||||
body: Text('Invest'),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:tanami_app/features/MainScreens/Settings/presentation/pages/sett
|
||||
import 'package:tanami_app/features/MainScreens/Wallet/presentation/pages/walletScreen.dart';
|
||||
import 'package:tanami_app/shared/components/common_bottom_navigation.dart';
|
||||
|
||||
import '../../shared/components/exit_app_dialog.dart';
|
||||
|
||||
var currentTab = [
|
||||
const WalletScreen(),
|
||||
const PortfolioScreen(),
|
||||
@@ -24,10 +26,16 @@ class MainScreen extends StatelessWidget {
|
||||
const MainScreen({super.key});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: currentTab[selectedIndex],
|
||||
bottomNavigationBar: bottomnavigationbar(selectedIndex),
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
exitAppDialog(context);
|
||||
return false;
|
||||
},
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: currentTab[selectedIndex],
|
||||
bottomNavigationBar: bottomnavigationbar(selectedIndex),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,13 +37,13 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 3), // changes position of shadow
|
||||
offset: const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -230,7 +230,7 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
child: Text(
|
||||
AppText.investmentamount,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF535353),
|
||||
color: const Color(0xFF535353),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -271,7 +271,7 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
child: Text(
|
||||
AppText.currentval,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF535353),
|
||||
color: const Color(0xFF535353),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -312,7 +312,7 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
child: Text(
|
||||
AppText.disttodate,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF535353),
|
||||
color: const Color(0xFF535353),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -338,7 +338,7 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
Text(
|
||||
AppText.totalreturn,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF535353),
|
||||
color: const Color(0xFF535353),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -346,7 +346,7 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
Text(
|
||||
'+ 20.0%',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF066123),
|
||||
color: const Color(0xFF066123),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -373,7 +373,7 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
color: Colors.black.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 3), // changes position of shadow
|
||||
offset: const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -404,12 +404,12 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
(index) {
|
||||
return Center(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFFF4F4F4),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(10.0)),
|
||||
),
|
||||
padding: EdgeInsets.all(20.0),
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
@@ -443,7 +443,7 @@ class _DetailsScreenState extends State<DetailsScreen> {
|
||||
Text(
|
||||
"512 Mb",
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF535353),
|
||||
color: const Color(0xFF535353),
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
|
||||
@@ -36,7 +36,8 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
var opacity = (1 - percentage).clamp(0.0, 1.0);
|
||||
return FlexibleSpaceBar(
|
||||
// centerTitle: true,
|
||||
titlePadding: EdgeInsets.only(left: 30, top: 0, bottom: 15),
|
||||
titlePadding:
|
||||
const EdgeInsets.only(left: 30, top: 0, bottom: 15),
|
||||
title: Opacity(
|
||||
opacity: opacity,
|
||||
child: Row(
|
||||
@@ -44,7 +45,7 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
Text(
|
||||
AppText.portfolio,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF888888),
|
||||
color: const Color(0xFF888888),
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -78,7 +79,7 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
Text(
|
||||
AppText.portfolio,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFFC9D9CB),
|
||||
color: const Color(0xFFC9D9CB),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -115,13 +116,15 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(20.0)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 3), // changes position of shadow
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -152,7 +155,7 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
Text(
|
||||
'Mar 01 2024',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: Color(0xFF004717),
|
||||
color: const Color(0xFF004717),
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -163,8 +166,8 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
(index == 2) ? 'Exited' : 'Pending',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
: Color(0xFF0FA4A4),
|
||||
? const Color(0xFF8D8D8D)
|
||||
: const Color(0xFF0FA4A4),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -209,8 +212,8 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
AppText.investmentamount,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
: Color(0xFF535353),
|
||||
? const Color(0xFF8D8D8D)
|
||||
: const Color(0xFF535353),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -223,7 +226,7 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
'SAR 100,000',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
? const Color(0xFF8D8D8D)
|
||||
: Colors.black,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -233,7 +236,7 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
' \$ 26,700',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
? const Color(0xFF8D8D8D)
|
||||
: Colors.black,
|
||||
fontSize: 11.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
@@ -255,8 +258,8 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
AppText.currentval,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
: Color(0xFF535353),
|
||||
? const Color(0xFF8D8D8D)
|
||||
: const Color(0xFF535353),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -269,7 +272,7 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
'SAR 100,000',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
? const Color(0xFF8D8D8D)
|
||||
: Colors.black,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -279,7 +282,7 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
' \$ 26,700',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
? const Color(0xFF8D8D8D)
|
||||
: Colors.black,
|
||||
fontSize: 11.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
@@ -301,8 +304,8 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
AppText.totalreturn,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFF8D8D8D)
|
||||
: Color(0xFF535353),
|
||||
? const Color(0xFF8D8D8D)
|
||||
: const Color(0xFF535353),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -311,8 +314,8 @@ class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
(index == 2) ? '- 20.0%' : '+ 20.0%',
|
||||
style: GoogleFonts.dmSans(
|
||||
color: (index == 2)
|
||||
? Color(0xFFde9595)
|
||||
: Color(0xFF066123),
|
||||
? const Color(0xFFde9595)
|
||||
: const Color(0xFF066123),
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
|
||||
@@ -10,7 +10,7 @@ class SettingsScreen extends StatefulWidget {
|
||||
class _SettingsScreenState extends State<SettingsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
return const Scaffold(
|
||||
body: Text('Settings'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ class WalletScreen extends StatefulWidget {
|
||||
class _WalletScreenState extends State<WalletScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(body: Text('Wallet'),);
|
||||
return const Scaffold(
|
||||
body: Text('Wallet'),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,9 @@ class BottomSection extends StatelessWidget {
|
||||
successToastMessage(context, "login successful !");
|
||||
goRouter.pop();
|
||||
|
||||
// goRouter.goNamed(RouteName.biometricScreen);
|
||||
goRouter.goNamed(RouteName.mainScreen);
|
||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
||||
"fromScreen": "login",
|
||||
});
|
||||
} else if (state is LoginFailure) {
|
||||
goRouter.pop();
|
||||
errorToastMessage(
|
||||
|
||||
@@ -20,7 +20,7 @@ class TimerInitial extends TimerState {
|
||||
}
|
||||
|
||||
class TimerRunInProgress extends TimerState {
|
||||
const TimerRunInProgress(int duration) : super(duration);
|
||||
const TimerRunInProgress(super.duration);
|
||||
}
|
||||
|
||||
class TimerRunComplete extends TimerState {
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:tanami_app/core/styles/app_images.dart';
|
||||
import 'package:tanami_app/shared/components/checkbox_widget.dart';
|
||||
import 'package:tanami_app/shared/components/loader.dart';
|
||||
@@ -12,6 +17,8 @@ import '../../../../core/routes/route_name.dart';
|
||||
import '../../../../core/routes/routes.dart';
|
||||
import '../../../../core/styles/app_color.dart';
|
||||
import '../../../../core/styles/app_text.dart';
|
||||
import '../../../../shared/components/bloc/checkbox/checkbox_bloc.dart';
|
||||
import '../../../../shared/components/bloc/checkbox/checkbox_state.dart';
|
||||
import '../../../../shared/components/button_widget.dart';
|
||||
import '../../../../shared/components/text_widget.dart';
|
||||
import '../bloc/register_user_bloc.dart';
|
||||
@@ -27,41 +34,52 @@ class RegisterUserBottomSection extends StatelessWidget {
|
||||
children: [
|
||||
const Gap(40),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
const CheckBoxWidget(),
|
||||
Container(
|
||||
width: 0.8.sw,
|
||||
child: Row(
|
||||
children: [
|
||||
const Text("I agree to the "),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// Handle Terms & Conditions tap
|
||||
},
|
||||
child: const Text(
|
||||
"Terms & Conditions",
|
||||
style: TextStyle(
|
||||
color: Colors.blue,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
Expanded(
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
text: AppText.iAgreeToThe,
|
||||
style: GoogleFonts.dmSans(
|
||||
color: AppColor.charcoalColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const Text(" and the "),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// Handle Privacy Policy tap
|
||||
},
|
||||
child: const Text(
|
||||
"Privacy Policy",
|
||||
style: TextStyle(
|
||||
color: Colors.blue,
|
||||
decoration: TextDecoration.underline,
|
||||
children: [
|
||||
TextSpan(
|
||||
style: GoogleFonts.dmSans(
|
||||
color: AppColor.selectableTextColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
text: AppText.termsAndCondition,
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => log('Tap Here onTap'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
const TextSpan(
|
||||
text: AppText.andThe,
|
||||
style: TextStyle(
|
||||
color: AppColor.charcoalColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: AppText.privacyPolicy,
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => log('Tap Here onTap'),
|
||||
style: const TextStyle(
|
||||
color: AppColor.selectableTextColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
const Gap(10),
|
||||
@@ -79,7 +97,9 @@ class RegisterUserBottomSection extends StatelessWidget {
|
||||
successToastMessage(context, "successful !");
|
||||
goRouter.pop();
|
||||
|
||||
goRouter.pushNamed(RouteName.otpScreen);
|
||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
||||
"fromScreen": "register",
|
||||
});
|
||||
} else if (state is RegisterUserFailure) {
|
||||
goRouter.pop();
|
||||
errorToastMessage(
|
||||
@@ -90,10 +110,13 @@ class RegisterUserBottomSection extends StatelessWidget {
|
||||
},
|
||||
builder: (context, state) {
|
||||
bool isButtonEnabled = false;
|
||||
if (state is RegisterUserFieldsState) {
|
||||
final checkboxState = context.watch<CheckboxBloc>().state;
|
||||
if (state is RegisterUserFieldsState &&
|
||||
checkboxState is CheckboxChecked) {
|
||||
isButtonEnabled = state.areFieldsFilled;
|
||||
} else if (state is RegisterUserSuccess ||
|
||||
state is RegisterUserFailure) {
|
||||
} else if ((state is RegisterUserSuccess ||
|
||||
state is RegisterUserFailure) &&
|
||||
checkboxState is CheckboxChecked) {
|
||||
isButtonEnabled = true;
|
||||
}
|
||||
return Container(
|
||||
|
||||
54
lib/features/securePin/presentation/bloc/pin_bloc.dart
Normal file
54
lib/features/securePin/presentation/bloc/pin_bloc.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
|
||||
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||
|
||||
part 'pin_event.dart';
|
||||
part 'pin_state.dart';
|
||||
|
||||
class PinBloc extends Bloc<PinEvent, PinState> {
|
||||
final SecureStorageService secureStorageService;
|
||||
|
||||
PinBloc({required this.secureStorageService})
|
||||
: super(const PinState(
|
||||
pin: '', pinComplete: false, isVerified: false, error: '')) {
|
||||
on<NumberPressed>((event, emit) {
|
||||
final newPin = state.pin + event.number;
|
||||
|
||||
if (newPin.length <= 6) {
|
||||
emit(state.copyWith(
|
||||
pin: newPin, pinComplete: newPin.length == 6, error: ''));
|
||||
|
||||
if (newPin.length == 6) {
|
||||
add(VerifyPinPressed(newPin));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
on<BackspacePressed>((event, emit) {
|
||||
if (state.pin.isNotEmpty) {
|
||||
final newPin = state.pin.substring(0, state.pin.length - 1);
|
||||
emit(state.copyWith(
|
||||
pin: newPin, pinComplete: newPin.length == 6, error: ''));
|
||||
}
|
||||
});
|
||||
|
||||
on<SavePinPressed>((event, emit) async {
|
||||
await secureStorageService.write('pin_code', state.pin);
|
||||
});
|
||||
|
||||
on<VerifyPinPressed>((event, emit) async {
|
||||
final storedPin = await secureStorageService.read('pin_code');
|
||||
|
||||
if (storedPin == event.pin) {
|
||||
emit(state.copyWith(isVerified: true, error: ''));
|
||||
} else {
|
||||
emit(state.copyWith(
|
||||
isVerified: false,
|
||||
error: AppText.incorrectPinCode,
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
30
lib/features/securePin/presentation/bloc/pin_event.dart
Normal file
30
lib/features/securePin/presentation/bloc/pin_event.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
part of 'pin_bloc.dart';
|
||||
|
||||
abstract class PinEvent extends Equatable {
|
||||
const PinEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class NumberPressed extends PinEvent {
|
||||
final String number;
|
||||
|
||||
const NumberPressed(this.number);
|
||||
|
||||
@override
|
||||
List<Object> get props => [number];
|
||||
}
|
||||
|
||||
class BackspacePressed extends PinEvent {}
|
||||
|
||||
class SavePinPressed extends PinEvent {}
|
||||
|
||||
class VerifyPinPressed extends PinEvent {
|
||||
final String pin;
|
||||
|
||||
const VerifyPinPressed(this.pin);
|
||||
|
||||
@override
|
||||
List<Object> get props => [pin];
|
||||
}
|
||||
32
lib/features/securePin/presentation/bloc/pin_state.dart
Normal file
32
lib/features/securePin/presentation/bloc/pin_state.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
part of 'pin_bloc.dart';
|
||||
|
||||
class PinState extends Equatable {
|
||||
final String pin;
|
||||
final bool pinComplete;
|
||||
final bool isVerified;
|
||||
final String error;
|
||||
|
||||
const PinState({
|
||||
required this.pin,
|
||||
required this.pinComplete,
|
||||
required this.isVerified,
|
||||
required this.error,
|
||||
});
|
||||
|
||||
PinState copyWith({
|
||||
String? pin,
|
||||
bool? pinComplete,
|
||||
bool? isVerified,
|
||||
String? error,
|
||||
}) {
|
||||
return PinState(
|
||||
pin: pin ?? this.pin,
|
||||
pinComplete: pinComplete ?? this.pinComplete,
|
||||
isVerified: isVerified ?? this.isVerified,
|
||||
error: error ?? this.error,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => [pin, pinComplete, isVerified, error];
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../widgets/confirm_pin_keypad_section.dart';
|
||||
import '../widgets/confirm_pin_top_section.dart';
|
||||
|
||||
class ConfirmPinLayout extends StatelessWidget {
|
||||
const ConfirmPinLayout({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ListView(
|
||||
children: const [
|
||||
ConfirmPinTopSection(),
|
||||
ConfirmPinKey(),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../../../core/styles/app_text.dart';
|
||||
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||
import '../../../../shared/components/appbar_widget.dart';
|
||||
import '../bloc/pin_bloc.dart';
|
||||
import 'confirm_pin_layout.dart';
|
||||
|
||||
class ConfirmPinScreen extends StatelessWidget {
|
||||
const ConfirmPinScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final secureStorageService = SecureStorageService();
|
||||
return Scaffold(
|
||||
appBar: const AppBarWidget(
|
||||
height: 75,
|
||||
titleTxt: AppText.createPinCode,
|
||||
showLeading: true,
|
||||
),
|
||||
resizeToAvoidBottomInset: true,
|
||||
body: MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
// Create an instance of the OnboardingBloc
|
||||
create: (context) =>
|
||||
PinBloc(secureStorageService: secureStorageService),
|
||||
),
|
||||
],
|
||||
child: const ConfirmPinLayout(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
21
lib/features/securePin/presentation/pages/pin_layout.dart
Normal file
21
lib/features/securePin/presentation/pages/pin_layout.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tanami_app/features/securePin/presentation/widgets/pin_keypad_section.dart';
|
||||
import 'package:tanami_app/features/securePin/presentation/widgets/pin_top_section.dart';
|
||||
|
||||
class PinLayout extends StatelessWidget {
|
||||
final String fromScreen;
|
||||
const PinLayout({super.key, required this.fromScreen});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ListView(
|
||||
children: [
|
||||
PinTopSection(fromScreen: fromScreen),
|
||||
PinKey(
|
||||
fromScreen: fromScreen,
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
40
lib/features/securePin/presentation/pages/pin_screen.dart
Normal file
40
lib/features/securePin/presentation/pages/pin_screen.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../../../core/styles/app_text.dart';
|
||||
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||
import '../../../../shared/components/appbar_widget.dart';
|
||||
import '../bloc/pin_bloc.dart';
|
||||
import 'pin_layout.dart';
|
||||
|
||||
class PinScreen extends StatelessWidget {
|
||||
final String fromScreen;
|
||||
const PinScreen({super.key, required this.fromScreen});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final secureStorageService = SecureStorageService();
|
||||
return Scaffold(
|
||||
appBar: fromScreen == "register"
|
||||
? const AppBarWidget(
|
||||
height: 75,
|
||||
titleTxt: AppText.createPinCode,
|
||||
showLeading: false,
|
||||
)
|
||||
: null,
|
||||
resizeToAvoidBottomInset: true,
|
||||
body: MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
// Create an instance of the OnboardingBloc
|
||||
create: (context) =>
|
||||
PinBloc(secureStorageService: secureStorageService),
|
||||
),
|
||||
],
|
||||
child: PinLayout(
|
||||
fromScreen: fromScreen,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/routes/route_name.dart';
|
||||
import 'package:tanami_app/core/routes/routes.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
import '../bloc/pin_bloc.dart';
|
||||
|
||||
class ConfirmPinKey extends StatelessWidget {
|
||||
const ConfirmPinKey({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
const Gap(20),
|
||||
BlocConsumer<PinBloc, PinState>(
|
||||
listener: (context, state) {
|
||||
if (state.pinComplete && state.isVerified) {
|
||||
// successToastMessage(context, "Pin verified successfully");
|
||||
goRouter.goNamed(RouteName.mainScreen);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(6, (index) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 10),
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: state.error.isNotEmpty
|
||||
? AppColor.txtErrorColor
|
||||
: index < state.pin.length
|
||||
? AppColor.pinFillBorderColor
|
||||
: AppColor.pinInActiveBorderColor),
|
||||
color: index < state.pin.length
|
||||
? AppColor.pinFillColor
|
||||
: Colors.transparent,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocBuilder<PinBloc, PinState>(
|
||||
builder: (context, state) {
|
||||
if (state.error.isNotEmpty) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 5),
|
||||
child: TextWidget()
|
||||
.text14W500(state.error, clr: AppColor.txtErrorColor),
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
const Gap(50),
|
||||
GridView.builder(
|
||||
shrinkWrap: true,
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
childAspectRatio: 1.3,
|
||||
),
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == 9) {
|
||||
return const SizedBox.shrink();
|
||||
} else if (index == 11) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.read<PinBloc>().add(BackspacePressed());
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.black12),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.arrow_back_rounded,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final number = index == 10 ? '0' : '${index + 1}';
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.read<PinBloc>().add(NumberPressed(number));
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.black12),
|
||||
),
|
||||
child: Center(
|
||||
child: TextWidget().text20W700(
|
||||
number,
|
||||
clr: AppColor.plainBlack,
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
import '../../../../core/styles/app_images.dart';
|
||||
import '../../../../core/styles/app_text.dart';
|
||||
|
||||
class ConfirmPinTopSection extends StatelessWidget {
|
||||
const ConfirmPinTopSection({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
const Gap(85),
|
||||
Center(
|
||||
child: SvgPicture.asset(
|
||||
AppImages.weclomeLogo,
|
||||
),
|
||||
),
|
||||
const Gap(60),
|
||||
TextWidget().text14W500(
|
||||
AppText.confirmPinCode,
|
||||
clr: AppColor.textLabelColor,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/routes/routes.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/shared/components/button_widget.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
void forgotPinDialog(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return Dialog(
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(22),
|
||||
color: AppColor.plainWhite,
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextWidget().text17W700(AppText.notificationText,
|
||||
clr: AppColor.plainBlack),
|
||||
const Gap(25),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 25,
|
||||
),
|
||||
child: TextWidget().text15W500(
|
||||
AppText.toRestorePinYouWillBeLoggedOut,
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
),
|
||||
const Gap(40),
|
||||
SizedBox(
|
||||
width: 0.9.sw,
|
||||
height: 55.h,
|
||||
child: ButtonWidget().elevatedBtn(
|
||||
txtClr: AppColor.plainWhite,
|
||||
text: AppText.allowText,
|
||||
clr: AppColor.primaryColor2,
|
||||
function: () {
|
||||
goRouter.pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
const Gap(10),
|
||||
ButtonWidget().textBtn(
|
||||
text: TextWidget().text14W700(
|
||||
AppText.declineText,
|
||||
textDecoration: TextDecoration.underline,
|
||||
clr: AppColor.textLabelColor,
|
||||
),
|
||||
function: () {
|
||||
goRouter.pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/routes/route_name.dart';
|
||||
import 'package:tanami_app/core/routes/routes.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/features/securePin/presentation/widgets/forgot_pin_dialog.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
import '../bloc/pin_bloc.dart';
|
||||
|
||||
class PinKey extends StatelessWidget {
|
||||
final String fromScreen;
|
||||
const PinKey({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
const Gap(20),
|
||||
BlocConsumer<PinBloc, PinState>(
|
||||
listener: (context, state) {
|
||||
if (state.pinComplete) {
|
||||
if (fromScreen == "login") {
|
||||
goRouter.pushNamed(RouteName.mainScreen);
|
||||
} else {
|
||||
context.read<PinBloc>().add(SavePinPressed());
|
||||
goRouter.pushNamed(RouteName.confirmPinScreen);
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(6, (index) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 10),
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: index < state.pin.length
|
||||
? AppColor.pinFillBorderColor
|
||||
: AppColor.pinInActiveBorderColor,
|
||||
),
|
||||
color: index < state.pin.length
|
||||
? AppColor.pinFillColor
|
||||
: Colors.transparent,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
fromScreen == "login" ? const Gap(20) : const Gap(0),
|
||||
fromScreen == "login"
|
||||
? InkWell(
|
||||
onTap: () {
|
||||
forgotPinDialog(context);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
right: 50,
|
||||
),
|
||||
child: TextWidget().text15W500(
|
||||
AppText.forgotPinCode,
|
||||
clr: AppColor.hintTextColor,
|
||||
textDecoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox(),
|
||||
const Gap(50),
|
||||
GridView.builder(
|
||||
shrinkWrap: true,
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
childAspectRatio: 1.3,
|
||||
),
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == 9) {
|
||||
return const SizedBox.shrink();
|
||||
} else if (index == 11) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.read<PinBloc>().add(BackspacePressed());
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.black12),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.arrow_back_rounded,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final number = index == 10 ? '0' : '${index + 1}';
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.read<PinBloc>().add(NumberPressed(number));
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.black12),
|
||||
),
|
||||
child: Center(
|
||||
child: TextWidget().text20W700(
|
||||
number,
|
||||
clr: AppColor.plainBlack,
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
import '../../../../core/styles/app_images.dart';
|
||||
|
||||
class PinTopSection extends StatelessWidget {
|
||||
final String fromScreen;
|
||||
const PinTopSection({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
const Gap(85),
|
||||
Center(
|
||||
child: SvgPicture.asset(
|
||||
AppImages.weclomeLogo,
|
||||
),
|
||||
),
|
||||
const Gap(60),
|
||||
fromScreen == "login"
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
TextWidget().text14W500(AppText.welcomeBackText,
|
||||
clr: AppColor.smokeGrayColor),
|
||||
TextWidget()
|
||||
.text14W700(", Jayesh", clr: AppColor.plainBlack),
|
||||
],
|
||||
),
|
||||
TextWidget().text14W500(
|
||||
AppText.userYourAppPinToLoginEnterTanami,
|
||||
clr: AppColor.smokeGrayColor),
|
||||
const Gap(25),
|
||||
TextWidget().text14W400(
|
||||
AppText.pinCode,
|
||||
clr: AppColor.textLabelColor,
|
||||
)
|
||||
],
|
||||
)
|
||||
: TextWidget().text14W500(
|
||||
AppText.createPinCode,
|
||||
clr: AppColor.textLabelColor,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -41,21 +41,23 @@ class AppBarWidget extends StatelessWidget implements PreferredSizeWidget {
|
||||
padding: EdgeInsets.only(
|
||||
left: 16.w,
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
customBack ?? false
|
||||
? goRouter.goNamed(backPageName!)
|
||||
: goRouter.pop();
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 8.w),
|
||||
child: Icon(
|
||||
Icons.arrow_back_rounded,
|
||||
color: AppColor.appBarIconColor,
|
||||
size: 25.r,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: !showLeading!
|
||||
? null
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
customBack ?? false
|
||||
? goRouter.goNamed(backPageName!)
|
||||
: goRouter.pop();
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 8.w),
|
||||
child: Icon(
|
||||
Icons.arrow_back_rounded,
|
||||
color: AppColor.appBarIconColor,
|
||||
size: 25.r,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (customActionWidget != null)
|
||||
|
||||
@@ -29,7 +29,7 @@ class CheckBoxWidget extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6), // Custom radius
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
value: state is CheckboxChecked,
|
||||
onChanged: (value) {
|
||||
|
||||
@@ -14,6 +14,21 @@ class TextWidget {
|
||||
|
||||
//Text Size 14
|
||||
|
||||
Widget text14W400(
|
||||
String text, {
|
||||
Color? clr,
|
||||
TextDecoration? textDecoration,
|
||||
TextAlign? txtAlign,
|
||||
}) {
|
||||
return Text(text,
|
||||
textAlign: txtAlign ?? TextAlign.center,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
decoration: textDecoration ?? TextDecoration.none,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
|
||||
Widget text14W500(
|
||||
String text, {
|
||||
Color? clr,
|
||||
@@ -44,11 +59,14 @@ class TextWidget {
|
||||
Widget text15W500(
|
||||
String text, {
|
||||
Color? clr,
|
||||
TextDecoration? textDecoration,
|
||||
}) {
|
||||
return Text(text,
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 15,
|
||||
decorationColor: AppColor.hintTextColor,
|
||||
decoration: textDecoration ?? TextDecoration.none,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
@@ -69,6 +87,22 @@ class TextWidget {
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
|
||||
//Text Size 17
|
||||
Widget text17W700(
|
||||
String text, {
|
||||
Color? clr,
|
||||
TextDecoration? textDecoration,
|
||||
}) {
|
||||
return Text(text,
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 17,
|
||||
decorationColor: AppColor.hintTextColor,
|
||||
decoration: textDecoration ?? TextDecoration.none,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
|
||||
//Text Size 22
|
||||
Widget text22W700(String text, {Color? clr}) {
|
||||
return Text(text,
|
||||
|
||||
Reference in New Issue
Block a user