@@ -29,7 +29,7 @@ class RouteName {
|
||||
//Portfolio details
|
||||
static const String porfolioDetails = 'porfolioDetails';
|
||||
|
||||
//Portfolio details
|
||||
//Portfolio details
|
||||
static const String academyDetails = 'academyDetails';
|
||||
|
||||
//Biometric
|
||||
@@ -41,4 +41,10 @@ class RouteName {
|
||||
//Pin Screen
|
||||
static const String pinScreen = 'pinScreen';
|
||||
static const String confirmPinScreen = 'confirmPinScreen';
|
||||
|
||||
//Forgot Password
|
||||
|
||||
static const String forgotPasswordPhoneVerificationScreen =
|
||||
'forgotPasswordPhoneVerificationScreen';
|
||||
static const String forgotPasswordScreen = 'forgotPasswordScreen';
|
||||
}
|
||||
|
||||
@@ -5,17 +5,19 @@ import 'package:tanami_app/core/routes/route_name.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/detailsScreen.dart';
|
||||
import 'package:tanami_app/features/MainScreens/MainScreen.dart';
|
||||
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/detailsScreen.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolio_details_screen.dart';
|
||||
|
||||
import 'package:tanami_app/features/biometric/presentation/pages/biometric_screen.dart';
|
||||
|
||||
import 'package:tanami_app/features/countrySelection/presentation/pages/choose_country_screen.dart';
|
||||
import 'package:tanami_app/features/forgotPassword/presentation/pages/restore_password_screen.dart';
|
||||
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/forgotPassword/presentation/pages/restore_password_phone_verification_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';
|
||||
@@ -99,9 +101,11 @@ final goRouter = GoRouter(
|
||||
),
|
||||
GoRoute(
|
||||
name: RouteName.otpScreen,
|
||||
path: RouteName.otpScreen,
|
||||
path: "${RouteName.otpScreen}/:fromScreen",
|
||||
builder: (context, state) {
|
||||
return const OtpScreen();
|
||||
return OtpScreen(
|
||||
fromScreen: state.pathParameters["fromScreen"]!,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
@@ -134,6 +138,20 @@ final goRouter = GoRouter(
|
||||
return const ConfirmPinScreen();
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: RouteName.forgotPasswordPhoneVerificationScreen,
|
||||
path: RouteName.forgotPasswordPhoneVerificationScreen,
|
||||
builder: (context, state) {
|
||||
return const RestorePasswordPhoneVerificationScreen();
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: RouteName.forgotPasswordScreen,
|
||||
path: RouteName.forgotPasswordScreen,
|
||||
builder: (context, state) {
|
||||
return const RestorePasswordScreen();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
// GoRoute(
|
||||
|
||||
@@ -52,4 +52,10 @@ class AppColor {
|
||||
static const Color pinFillColor = Color(0xFFC9D9CB);
|
||||
static const Color pinFillBorderColor = Color(0xFF648774);
|
||||
static const Color pinInActiveBorderColor = Color(0xFFDFDFE3);
|
||||
|
||||
//Portfolio Color
|
||||
static const Color portfolioCardBgColor = Color(0xFFF8F8F8);
|
||||
static const Color negativePercentageColor = Color(0xFFde9595);
|
||||
static const Color statusTextColor = Color(0xFF0FA4A4);
|
||||
static const Color portoflioCardTextColor = Color(0xFF535353);
|
||||
}
|
||||
|
||||
@@ -56,4 +56,11 @@ class AppImages {
|
||||
|
||||
//Dialog
|
||||
static const String exitAppIcon = "assets/images/dialog/svg/exit_icon.svg";
|
||||
|
||||
//Portfolio
|
||||
static const String portfolioBg = 'assets/images/portfolio_screen/bg.png';
|
||||
static const String portfolioClock =
|
||||
'assets/images/portfolio_screen/clock.png';
|
||||
static const String portfolioClockOff =
|
||||
'assets/images/portfolio_screen/clock_off.png';
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ class AppText {
|
||||
static const String welcomeText = "Welcome back!";
|
||||
static const String pleaseEnterLoginDetails =
|
||||
"Please enter your login details to get started";
|
||||
static const String toGetYourAccountPleaseSetYourInfo =
|
||||
"To get your account please set your info";
|
||||
static const String countryOfResidence = "Country of residence";
|
||||
static const String chooseCountry = "Choose country";
|
||||
static const String phoneNumber = "Phone Number";
|
||||
@@ -86,9 +88,6 @@ class AppText {
|
||||
//Academy
|
||||
static const String videosTitle = "Videos";
|
||||
|
||||
//Wallet
|
||||
static const String walletTitle = "Wallet balance";
|
||||
|
||||
//Dialog
|
||||
static const String exitText = "Exit";
|
||||
static const String cancelText = "Cancel";
|
||||
@@ -106,6 +105,7 @@ class AppText {
|
||||
//Pin Code
|
||||
static const String pinCode = "Pin Code";
|
||||
static const String createPinCode = "Create Pin Code";
|
||||
static const String changePinCode = "Change Pin Code";
|
||||
static const String confirmPinCode = "Confirm Pin Code";
|
||||
static const String incorrectPinCode = "Incorrect PIN. Please try again.";
|
||||
static const String welcomeBackText = "Welcome back";
|
||||
@@ -118,4 +118,15 @@ class AppText {
|
||||
"To restore PIN you will be Logged out";
|
||||
static const String allowText = "Allow";
|
||||
static const String declineText = "Decline";
|
||||
|
||||
//Forgot Password
|
||||
|
||||
static const String restorePasswordText = "Restore password";
|
||||
static const String toRestorePasswordPleaseEnterPhoneNumber =
|
||||
"To restore password please enter phone number";
|
||||
static const String createNewPasswordText = "Create new password";
|
||||
static const String submitText = "Submit";
|
||||
|
||||
//Wallet
|
||||
static const String walletTitle = "Wallet balance";
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academyScreen.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Invest/presentation/pages/investScreen.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolioScreen.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolio_screen.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Settings/presentation/pages/settingsScreen.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Wallet/presentation/pages/walletScreen.dart';
|
||||
import 'package:tanami_app/shared/components/common_bottom_navigation.dart';
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'portfolio_model.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class PortfolioModel {
|
||||
final String date;
|
||||
final String title;
|
||||
final String status;
|
||||
final String investmentAmountSAR;
|
||||
final String investmentAmountUSD;
|
||||
final String currentValuationSAR;
|
||||
final String currentValuationUSD;
|
||||
final String totalReturnPercentage;
|
||||
|
||||
PortfolioModel({
|
||||
required this.date,
|
||||
required this.title,
|
||||
required this.status,
|
||||
required this.investmentAmountSAR,
|
||||
required this.investmentAmountUSD,
|
||||
required this.currentValuationSAR,
|
||||
required this.currentValuationUSD,
|
||||
required this.totalReturnPercentage,
|
||||
});
|
||||
|
||||
factory PortfolioModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$PortfolioModelFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$PortfolioModelToJson(this);
|
||||
}
|
||||
|
||||
List<PortfolioModel> portfolioModelList = [
|
||||
PortfolioModel(
|
||||
date: "Mar 01 2024",
|
||||
title: "Private equity portfolio I",
|
||||
status: "Pending",
|
||||
investmentAmountSAR: "SAR 100,000",
|
||||
investmentAmountUSD: "26,700",
|
||||
currentValuationSAR: "SAR 100,000",
|
||||
currentValuationUSD: "26,700",
|
||||
totalReturnPercentage: "20.0%",
|
||||
),
|
||||
PortfolioModel(
|
||||
date: "Sept 1 2023",
|
||||
title: "Real estate portfolio IV",
|
||||
status: "Pending",
|
||||
investmentAmountSAR: "SAR 50,000",
|
||||
investmentAmountUSD: "13,350",
|
||||
currentValuationSAR: "SAR 55,000",
|
||||
currentValuationUSD: "14,685",
|
||||
totalReturnPercentage: "10.0%",
|
||||
),
|
||||
PortfolioModel(
|
||||
date: "Jul 10 2025",
|
||||
title: "Real estate III",
|
||||
status: "Exited",
|
||||
investmentAmountSAR: "SAR 10,000",
|
||||
investmentAmountUSD: "2,670",
|
||||
currentValuationSAR: "SAR 8,000",
|
||||
currentValuationUSD: "2,136",
|
||||
totalReturnPercentage: "20.0%",
|
||||
)
|
||||
];
|
||||
@@ -0,0 +1,31 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'portfolio_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PortfolioModel _$PortfolioModelFromJson(Map<String, dynamic> json) =>
|
||||
PortfolioModel(
|
||||
date: json['date'] as String,
|
||||
title: json['title'] as String,
|
||||
status: json['status'] as String,
|
||||
investmentAmountSAR: json['investmentAmountSAR'] as String,
|
||||
investmentAmountUSD: json['investmentAmountUSD'] as String,
|
||||
currentValuationSAR: json['currentValuationSAR'] as String,
|
||||
currentValuationUSD: json['currentValuationUSD'] as String,
|
||||
totalReturnPercentage: json['totalReturnPercentage'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PortfolioModelToJson(PortfolioModel instance) =>
|
||||
<String, dynamic>{
|
||||
'date': instance.date,
|
||||
'title': instance.title,
|
||||
'status': instance.status,
|
||||
'investmentAmountSAR': instance.investmentAmountSAR,
|
||||
'investmentAmountUSD': instance.investmentAmountUSD,
|
||||
'currentValuationSAR': instance.currentValuationSAR,
|
||||
'currentValuationUSD': instance.currentValuationUSD,
|
||||
'totalReturnPercentage': instance.totalReturnPercentage,
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
import 'package:tanami_app/core/styles/app_images.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/domain/model/portfolio_model.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/presentation/widgets/exited_card.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/presentation/widgets/pending_card.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
import '../../../../../core/styles/app_text.dart';
|
||||
|
||||
class PortfolioLayout extends StatelessWidget {
|
||||
const PortfolioLayout({super.key});
|
||||
//2339.712 - 2326.866
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
expandedHeight: 230.0,
|
||||
automaticallyImplyLeading: false,
|
||||
snap: false,
|
||||
pinned: true,
|
||||
floating: false,
|
||||
flexibleSpace: LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
var top = constraints.biggest.height;
|
||||
var percentage =
|
||||
((top - kToolbarHeight) / (200.0 - kToolbarHeight))
|
||||
.clamp(0.0, 1.0);
|
||||
var opacity = (1 - percentage).clamp(0.0, 1.0);
|
||||
return FlexibleSpaceBar(
|
||||
// centerTitle: true,
|
||||
titlePadding:
|
||||
const EdgeInsets.only(left: 30, top: 0, bottom: 15),
|
||||
title: Opacity(
|
||||
opacity: opacity,
|
||||
child: Row(
|
||||
children: [
|
||||
TextWidget().text12W700(
|
||||
AppText.portfolio,
|
||||
clr: const Color(0xFF888888),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'SAR 178,000',
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
background: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Image.asset(
|
||||
AppImages.portfolioBg,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 40.0),
|
||||
child: Opacity(
|
||||
opacity: percentage,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextWidget().text14W700(
|
||||
AppText.portfolio,
|
||||
clr: const Color(0xFFC9D9CB),
|
||||
),
|
||||
Gap(
|
||||
8.h,
|
||||
),
|
||||
TextWidget().text28W700(
|
||||
'SAR 178,000',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => portfolioModelList[index].status == "Exited"
|
||||
? ExitedCard(
|
||||
portfolioModel: portfolioModelList[index],
|
||||
)
|
||||
: PendingCard(
|
||||
portfolioModel: portfolioModelList[index],
|
||||
),
|
||||
childCount: 3,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolio_layout.dart';
|
||||
|
||||
class PortfolioScreen extends StatefulWidget {
|
||||
const PortfolioScreen({super.key});
|
||||
|
||||
@override
|
||||
State<PortfolioScreen> createState() => _PortfolioScreenState();
|
||||
}
|
||||
|
||||
class _PortfolioScreenState extends State<PortfolioScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold(body: PortfolioLayout());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/domain/model/portfolio_model.dart';
|
||||
|
||||
import '../../../../../core/routes/route_name.dart';
|
||||
import '../../../../../core/routes/routes.dart';
|
||||
import '../../../../../core/styles/app_color.dart';
|
||||
import '../../../../../core/styles/app_images.dart';
|
||||
import '../../../../../core/styles/app_text.dart';
|
||||
import '../../../../../shared/components/text_widget.dart';
|
||||
|
||||
class ExitedCard extends StatelessWidget {
|
||||
final PortfolioModel portfolioModel;
|
||||
const ExitedCard({
|
||||
super.key,
|
||||
required this.portfolioModel,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pushNamed(RouteName.porfolioDetails);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.plainWhite,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColor.plainBlack.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20.0, vertical: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(
|
||||
AppImages.portfolioClockOff,
|
||||
height: 25.sp,
|
||||
),
|
||||
Gap(
|
||||
5.w,
|
||||
),
|
||||
TextWidget().text12W500(
|
||||
portfolioModel.date,
|
||||
clr: AppColor.primaryColor2,
|
||||
),
|
||||
],
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
portfolioModel.status,
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
Gap(
|
||||
8.h,
|
||||
),
|
||||
TextWidget().text17W700(
|
||||
portfolioModel.title,
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColor.portfolioCardBgColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(20.0),
|
||||
bottomRight: Radius.circular(20.0),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20.0, vertical: 16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextWidget().text14W500(
|
||||
AppText.investmentamount,
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
TextWidget().text14W700(
|
||||
portfolioModel.investmentAmountSAR,
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
TextWidget().text11W400(
|
||||
'\$ ${portfolioModel.investmentAmountUSD}',
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
Gap(
|
||||
8.h,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextWidget().text14W500(
|
||||
AppText.currentval,
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
TextWidget().text14W700(
|
||||
portfolioModel.currentValuationSAR,
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
TextWidget().text11W400(
|
||||
'\$ ${portfolioModel.currentValuationUSD}',
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 8.h,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextWidget().text14W500(
|
||||
AppText.totalreturn,
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'- ${portfolioModel.totalReturnPercentage}',
|
||||
clr: AppColor.negativePercentageColor,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Portfolio/domain/model/portfolio_model.dart';
|
||||
|
||||
import '../../../../../core/routes/route_name.dart';
|
||||
import '../../../../../core/routes/routes.dart';
|
||||
import '../../../../../core/styles/app_color.dart';
|
||||
import '../../../../../core/styles/app_images.dart';
|
||||
import '../../../../../core/styles/app_text.dart';
|
||||
import '../../../../../shared/components/text_widget.dart';
|
||||
|
||||
class PendingCard extends StatelessWidget {
|
||||
final PortfolioModel portfolioModel;
|
||||
const PendingCard({
|
||||
super.key,
|
||||
required this.portfolioModel,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pushNamed(RouteName.porfolioDetails);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.plainWhite,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColor.plainBlack.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20.0, vertical: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(
|
||||
AppImages.portfolioClock,
|
||||
height: 25.sp,
|
||||
),
|
||||
Gap(
|
||||
5.w,
|
||||
),
|
||||
TextWidget().text12W500(
|
||||
portfolioModel.date,
|
||||
clr: AppColor.primaryColor2,
|
||||
),
|
||||
],
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
portfolioModel.status,
|
||||
clr: AppColor.statusTextColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
Gap(
|
||||
8.h,
|
||||
),
|
||||
TextWidget().text17W700(
|
||||
portfolioModel.title,
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColor.portfolioCardBgColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(20.0),
|
||||
bottomRight: Radius.circular(20.0),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20.0, vertical: 16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextWidget().text14W500(
|
||||
AppText.investmentamount,
|
||||
clr: AppColor.portoflioCardTextColor,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
TextWidget().text14W700(
|
||||
portfolioModel.investmentAmountSAR,
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
TextWidget().text11W400(
|
||||
' \$ ${portfolioModel.investmentAmountUSD}',
|
||||
clr: Colors.black,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
Gap(
|
||||
8.h,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextWidget().text14W500(
|
||||
AppText.currentval,
|
||||
clr: AppColor.portoflioCardTextColor,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
TextWidget().text14W700(
|
||||
portfolioModel.currentValuationSAR,
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
TextWidget().text11W400(
|
||||
' \$ ${portfolioModel.currentValuationUSD}',
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 8.h,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextWidget().text14W500(
|
||||
AppText.totalreturn,
|
||||
clr: const Color(0xFF535353),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'+ ${portfolioModel.totalReturnPercentage}',
|
||||
clr: const Color(0xFF066123),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'restore_password_event.dart';
|
||||
import 'restore_password_state.dart';
|
||||
|
||||
class RestorePasswordBloc
|
||||
extends Bloc<RestorePasswordEvent, RestorePasswordState> {
|
||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
final TextEditingController passwordTextField = TextEditingController();
|
||||
final TextEditingController repeatPasswordTextField = TextEditingController();
|
||||
|
||||
GlobalKey<FormState> getFormKey() {
|
||||
return formKey;
|
||||
}
|
||||
|
||||
RestorePasswordBloc() : super(RestorePasswordInitial()) {
|
||||
passwordTextField.addListener(_onFormFieldChanged);
|
||||
repeatPasswordTextField.addListener(_onFormFieldChanged);
|
||||
on<RestorePasswordFormChanged>(_onLoginFormChanged);
|
||||
on<RestorePasswordSubmitted>((event, emit) async {
|
||||
if (!formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
emit(RestorePasswordLoading());
|
||||
try {
|
||||
// Simulate API call
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
// Replace the next line with actual API call
|
||||
final isSuccess = await _mockLoginApi(event.password);
|
||||
if (isSuccess) {
|
||||
emit(RestorePasswordSuccess());
|
||||
} else {
|
||||
emit(const RestorePasswordFailure(
|
||||
"Failed. Please check your credentials."));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(RestorePasswordFailure(e.toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
void _onFormFieldChanged() {
|
||||
add(RestorePasswordFormChanged(
|
||||
passwordTextField.text,
|
||||
repeatPasswordTextField.text,
|
||||
));
|
||||
}
|
||||
|
||||
void _onLoginFormChanged(
|
||||
RestorePasswordFormChanged event, Emitter<RestorePasswordState> emit) {
|
||||
final areFieldsFilled =
|
||||
event.password.isNotEmpty && event.repeatPassword.isNotEmpty;
|
||||
emit(RestorePasswordFieldsState(areFieldsFilled));
|
||||
}
|
||||
|
||||
// Method to reset text fields
|
||||
void resetFields() {
|
||||
passwordTextField.clear();
|
||||
repeatPasswordTextField.clear();
|
||||
}
|
||||
|
||||
// Mock API function, replace with actual API call
|
||||
Future<bool> _mockLoginApi(
|
||||
String phoneNumber,
|
||||
) async {
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
passwordTextField.dispose();
|
||||
repeatPasswordTextField.dispose();
|
||||
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class RestorePasswordEvent extends Equatable {
|
||||
const RestorePasswordEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class RestorePasswordSubmitted extends RestorePasswordEvent {
|
||||
final String password;
|
||||
final String repeatPassword;
|
||||
|
||||
const RestorePasswordSubmitted(
|
||||
this.password,
|
||||
this.repeatPassword,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [password, repeatPassword];
|
||||
}
|
||||
|
||||
class RestorePasswordFormChanged extends RestorePasswordEvent {
|
||||
final String password;
|
||||
final String repeatPassword;
|
||||
|
||||
const RestorePasswordFormChanged(this.password, this.repeatPassword);
|
||||
|
||||
@override
|
||||
List<Object> get props => [password, repeatPassword];
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'restore_password_phone_verification_event.dart';
|
||||
import 'restore_password_phone_verification_state.dart';
|
||||
|
||||
class RestorePasswordPhoneVerificationBloc extends Bloc<
|
||||
RestorePasswordPhoneVerificationEvent,
|
||||
RestorePasswordPhoneVerificationState> {
|
||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
final TextEditingController phoneNumberTextField = TextEditingController();
|
||||
final TextEditingController countrySelectionTextField =
|
||||
TextEditingController();
|
||||
|
||||
GlobalKey<FormState> getFormKey() {
|
||||
return formKey;
|
||||
}
|
||||
|
||||
RestorePasswordPhoneVerificationBloc()
|
||||
: super(RestorePasswordPhoneVerificationInitial()) {
|
||||
phoneNumberTextField.addListener(_onFormFieldChanged);
|
||||
countrySelectionTextField.addListener(_onFormFieldChanged);
|
||||
on<RestorePasswordPhoneVerificationFormChanged>(_onLoginFormChanged);
|
||||
on<RestorePasswordPhoneVerificationSubmitted>((event, emit) async {
|
||||
if (!formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
emit(RestorePasswordPhoneVerificationLoading());
|
||||
try {
|
||||
// Simulate API call
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
// Replace the next line with actual API call
|
||||
final isSuccess = await _mockLoginApi(event.phoneNumber);
|
||||
if (isSuccess) {
|
||||
emit(RestorePasswordPhoneVerificationSuccess());
|
||||
} else {
|
||||
emit(const RestorePasswordPhoneVerificationFailure(
|
||||
"Failed. Please check your credentials."));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(RestorePasswordPhoneVerificationFailure(e.toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
void _onFormFieldChanged() {
|
||||
add(RestorePasswordPhoneVerificationFormChanged(
|
||||
phoneNumberTextField.text,
|
||||
countrySelectionTextField.text,
|
||||
));
|
||||
}
|
||||
|
||||
void _onLoginFormChanged(RestorePasswordPhoneVerificationFormChanged event,
|
||||
Emitter<RestorePasswordPhoneVerificationState> emit) {
|
||||
final areFieldsFilled =
|
||||
event.phoneNumber.isNotEmpty && event.country.isNotEmpty;
|
||||
emit(RestorePasswordPhoneVerificationFieldsState(areFieldsFilled));
|
||||
}
|
||||
|
||||
// Method to reset text fields
|
||||
void resetFields() {
|
||||
phoneNumberTextField.clear();
|
||||
countrySelectionTextField.clear();
|
||||
}
|
||||
|
||||
// Mock API function, replace with actual API call
|
||||
Future<bool> _mockLoginApi(
|
||||
String phoneNumber,
|
||||
) async {
|
||||
return phoneNumber == "1234567891";
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
phoneNumberTextField.dispose();
|
||||
countrySelectionTextField.dispose();
|
||||
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class RestorePasswordPhoneVerificationEvent extends Equatable {
|
||||
const RestorePasswordPhoneVerificationEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class RestorePasswordPhoneVerificationSubmitted
|
||||
extends RestorePasswordPhoneVerificationEvent {
|
||||
final String phoneNumber;
|
||||
final String countryResidence;
|
||||
|
||||
const RestorePasswordPhoneVerificationSubmitted(
|
||||
this.phoneNumber,
|
||||
this.countryResidence,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [phoneNumber, countryResidence];
|
||||
}
|
||||
|
||||
class RestorePasswordPhoneVerificationFormChanged
|
||||
extends RestorePasswordPhoneVerificationEvent {
|
||||
final String phoneNumber;
|
||||
final String country;
|
||||
|
||||
const RestorePasswordPhoneVerificationFormChanged(
|
||||
this.phoneNumber, this.country);
|
||||
|
||||
@override
|
||||
List<Object> get props => [phoneNumber, country];
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class RestorePasswordPhoneVerificationState extends Equatable {
|
||||
const RestorePasswordPhoneVerificationState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class RestorePasswordPhoneVerificationInitial
|
||||
extends RestorePasswordPhoneVerificationState {}
|
||||
|
||||
class RestorePasswordPhoneVerificationLoading
|
||||
extends RestorePasswordPhoneVerificationState {}
|
||||
|
||||
class RestorePasswordPhoneVerificationSuccess
|
||||
extends RestorePasswordPhoneVerificationState {}
|
||||
|
||||
class RestorePasswordPhoneVerificationFailure
|
||||
extends RestorePasswordPhoneVerificationState {
|
||||
final String error;
|
||||
|
||||
const RestorePasswordPhoneVerificationFailure(this.error);
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class RestorePasswordPhoneVerificationFieldsState
|
||||
extends RestorePasswordPhoneVerificationState {
|
||||
final bool areFieldsFilled;
|
||||
|
||||
const RestorePasswordPhoneVerificationFieldsState(this.areFieldsFilled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [areFieldsFilled];
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class RestorePasswordState extends Equatable {
|
||||
const RestorePasswordState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class RestorePasswordInitial extends RestorePasswordState {}
|
||||
|
||||
class RestorePasswordLoading extends RestorePasswordState {}
|
||||
|
||||
class RestorePasswordSuccess extends RestorePasswordState {}
|
||||
|
||||
class RestorePasswordFailure extends RestorePasswordState {
|
||||
final String error;
|
||||
|
||||
const RestorePasswordFailure(this.error);
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class RestorePasswordFieldsState extends RestorePasswordState {
|
||||
final bool areFieldsFilled;
|
||||
|
||||
const RestorePasswordFieldsState(this.areFieldsFilled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [areFieldsFilled];
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
|
||||
import '../widgets/restore_password_bottom_section.dart';
|
||||
import '../widgets/restore_password_form.dart';
|
||||
import '../widgets/restore_password_top_section.dart';
|
||||
|
||||
class RestorePasswordLayout extends StatelessWidget {
|
||||
const RestorePasswordLayout({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ListView(
|
||||
children: const [
|
||||
RestorePasswordTopSection(),
|
||||
RestorePasswordForm(),
|
||||
Gap(150),
|
||||
RestorePasswordBottomSection(),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/features/forgotPassword/presentation/widgets/restore_password_phone_verification_bottom_section.dart';
|
||||
import 'package:tanami_app/features/forgotPassword/presentation/widgets/restore_password_phone_verification_top_section.dart';
|
||||
|
||||
import '../widgets/restore_password_phone_verification_form.dart';
|
||||
|
||||
class RestorePasswordPhoneVerificationLayout extends StatelessWidget {
|
||||
const RestorePasswordPhoneVerificationLayout({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ListView(
|
||||
children: const [
|
||||
RestorePasswordPhoneVerificationTopSection(),
|
||||
RestorePasswordPhoneVerificationForm(),
|
||||
Gap(150),
|
||||
RestorePasswordPhoneVerificationBottomSection(),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tanami_app/features/forgotPassword/presentation/pages/restore_password_phone_verification_layout.dart';
|
||||
|
||||
import '../bloc/restore_password_phone_verification_bloc.dart';
|
||||
|
||||
class RestorePasswordPhoneVerificationScreen extends StatelessWidget {
|
||||
const RestorePasswordPhoneVerificationScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
body: MultiBlocProvider(
|
||||
// Define the providers for the OnboardingBloc and other blocs
|
||||
providers: [
|
||||
BlocProvider(
|
||||
// Create an instance of the OnboardingBloc
|
||||
create: (context) => RestorePasswordPhoneVerificationBloc(),
|
||||
),
|
||||
],
|
||||
child: const RestorePasswordPhoneVerificationLayout(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../bloc/restore_password_bloc.dart';
|
||||
import 'restore_password_layout.dart';
|
||||
|
||||
class RestorePasswordScreen extends StatelessWidget {
|
||||
const RestorePasswordScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
body: MultiBlocProvider(
|
||||
// Define the providers for the OnboardingBloc and other blocs
|
||||
providers: [
|
||||
BlocProvider(
|
||||
// Create an instance of the OnboardingBloc
|
||||
create: (context) => RestorePasswordBloc(),
|
||||
),
|
||||
],
|
||||
child: const RestorePasswordLayout(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/shared/components/loader.dart';
|
||||
import 'package:tanami_app/shared/components/toast_message.dart';
|
||||
|
||||
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/button_widget.dart';
|
||||
import '../../../../shared/components/text_widget.dart';
|
||||
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
|
||||
import '../bloc/restore_password_bloc.dart';
|
||||
import '../bloc/restore_password_event.dart';
|
||||
import '../bloc/restore_password_state.dart';
|
||||
|
||||
class RestorePasswordBottomSection extends StatelessWidget {
|
||||
const RestorePasswordBottomSection({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final radioBloc = context.read<RadioBloc>();
|
||||
return Column(
|
||||
children: [
|
||||
BlocConsumer<RestorePasswordBloc, RestorePasswordState>(
|
||||
listener: (context, state) {
|
||||
if (state is RestorePasswordLoading) {
|
||||
Loader.loader(context);
|
||||
} else if (state is RestorePasswordSuccess) {
|
||||
successToastMessage(context, "Password resetted successful !");
|
||||
goRouter.pop();
|
||||
radioBloc.resetSelection();
|
||||
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
|
||||
"fromScreen": "registerStep",
|
||||
});
|
||||
} else if (state is RestorePasswordFailure) {
|
||||
goRouter.pop();
|
||||
errorToastMessage(
|
||||
context,
|
||||
state.error,
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
bool isButtonEnabled = false;
|
||||
if (state is RestorePasswordFieldsState) {
|
||||
isButtonEnabled = state.areFieldsFilled;
|
||||
} else if (state is RestorePasswordSuccess ||
|
||||
state is RestorePasswordFailure) {
|
||||
isButtonEnabled = true;
|
||||
}
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
width: 1.sw,
|
||||
height: 56.h,
|
||||
child: ButtonWidget().elevatedBtn(
|
||||
txtClr: isButtonEnabled
|
||||
? AppColor.plainWhite
|
||||
: AppColor.inactiveBtnTxtColor,
|
||||
function: () {
|
||||
isButtonEnabled
|
||||
? context.read<RestorePasswordBloc>().add(
|
||||
RestorePasswordSubmitted(
|
||||
context
|
||||
.read<RestorePasswordBloc>()
|
||||
.passwordTextField
|
||||
.text,
|
||||
""),
|
||||
)
|
||||
: null;
|
||||
},
|
||||
text: AppText.submitText,
|
||||
clr: isButtonEnabled
|
||||
? AppColor.primaryColor2
|
||||
: AppColor.inactiveBtnColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Gap(5),
|
||||
ButtonWidget().textBtn(
|
||||
function: () {
|
||||
goRouter.pop();
|
||||
},
|
||||
text: TextWidget().text14W700(AppText.backText,
|
||||
clr: AppColor.textLabelColor,
|
||||
textDecoration: TextDecoration.underline)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/features/forgotPassword/presentation/bloc/restore_password_bloc.dart';
|
||||
|
||||
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
|
||||
import '../../../../shared/components/form_label_textfield.dart';
|
||||
|
||||
class RestorePasswordForm extends StatelessWidget {
|
||||
const RestorePasswordForm({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final restorePasswordBloc = context.read<RestorePasswordBloc>();
|
||||
|
||||
// Reset fields when the screen is built
|
||||
restorePasswordBloc.resetFields();
|
||||
|
||||
return Form(
|
||||
key: restorePasswordBloc.formKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 14,
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Gap(50),
|
||||
BlocProvider(
|
||||
create: (_) => PasswordVisibilityBloc(),
|
||||
child: FormLabelTextField(
|
||||
hintText: AppText.enterPassword,
|
||||
title: AppText.password,
|
||||
type: AppText.password.toLowerCase(),
|
||||
textEditingController: restorePasswordBloc.passwordTextField,
|
||||
),
|
||||
),
|
||||
const Gap(12),
|
||||
BlocProvider(
|
||||
create: (_) => PasswordVisibilityBloc(),
|
||||
child: FormLabelTextField(
|
||||
hintText: AppText.repeatPasswordText,
|
||||
title: AppText.repeatPasswordText,
|
||||
type: AppText.password.toLowerCase(),
|
||||
textEditingController:
|
||||
restorePasswordBloc.repeatPasswordTextField,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/shared/components/loader.dart';
|
||||
import 'package:tanami_app/shared/components/toast_message.dart';
|
||||
|
||||
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/button_widget.dart';
|
||||
import '../../../../shared/components/text_widget.dart';
|
||||
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
|
||||
import '../bloc/restore_password_phone_verification_bloc.dart';
|
||||
import '../bloc/restore_password_phone_verification_event.dart';
|
||||
import '../bloc/restore_password_phone_verification_state.dart';
|
||||
|
||||
class RestorePasswordPhoneVerificationBottomSection extends StatelessWidget {
|
||||
const RestorePasswordPhoneVerificationBottomSection({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final radioBloc = context.read<RadioBloc>();
|
||||
return Column(
|
||||
children: [
|
||||
BlocConsumer<RestorePasswordPhoneVerificationBloc,
|
||||
RestorePasswordPhoneVerificationState>(
|
||||
listener: (context, state) {
|
||||
if (state is RestorePasswordPhoneVerificationLoading) {
|
||||
Loader.loader(context);
|
||||
} else if (state is RestorePasswordPhoneVerificationSuccess) {
|
||||
successToastMessage(context, "OTP send successful !");
|
||||
goRouter.pop();
|
||||
radioBloc.resetSelection();
|
||||
goRouter.pushNamed(RouteName.otpScreen,
|
||||
pathParameters: {"fromScreen": "forgot-password"});
|
||||
} else if (state is RestorePasswordPhoneVerificationFailure) {
|
||||
goRouter.pop();
|
||||
errorToastMessage(
|
||||
context,
|
||||
state.error,
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
bool isButtonEnabled = false;
|
||||
if (state is RestorePasswordPhoneVerificationFieldsState) {
|
||||
isButtonEnabled = state.areFieldsFilled;
|
||||
} else if (state is RestorePasswordPhoneVerificationSuccess ||
|
||||
state is RestorePasswordPhoneVerificationFailure) {
|
||||
isButtonEnabled = true;
|
||||
}
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
width: 1.sw,
|
||||
height: 56.h,
|
||||
child: ButtonWidget().elevatedBtn(
|
||||
txtClr: isButtonEnabled
|
||||
? AppColor.plainWhite
|
||||
: AppColor.inactiveBtnTxtColor,
|
||||
function: () {
|
||||
isButtonEnabled
|
||||
? context
|
||||
.read<RestorePasswordPhoneVerificationBloc>()
|
||||
.add(
|
||||
RestorePasswordPhoneVerificationSubmitted(
|
||||
context
|
||||
.read<
|
||||
RestorePasswordPhoneVerificationBloc>()
|
||||
.phoneNumberTextField
|
||||
.text,
|
||||
""),
|
||||
)
|
||||
: null;
|
||||
},
|
||||
text: AppText.nextText,
|
||||
clr: isButtonEnabled
|
||||
? AppColor.primaryColor2
|
||||
: AppColor.inactiveBtnColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Gap(5),
|
||||
ButtonWidget().textBtn(
|
||||
function: () {
|
||||
goRouter.pop();
|
||||
},
|
||||
text: TextWidget().text14W700(AppText.backText,
|
||||
clr: AppColor.textLabelColor,
|
||||
textDecoration: TextDecoration.underline)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
|
||||
|
||||
import '../../../../shared/components/form_label_textfield.dart';
|
||||
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
|
||||
import '../../../countrySelection/presentation/bloc/choose_country_state.dart';
|
||||
import '../bloc/restore_password_phone_verification_bloc.dart';
|
||||
|
||||
class RestorePasswordPhoneVerificationForm extends StatelessWidget {
|
||||
const RestorePasswordPhoneVerificationForm({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final restorePasswordBloc =
|
||||
context.read<RestorePasswordPhoneVerificationBloc>();
|
||||
|
||||
// Reset fields when the screen is built
|
||||
restorePasswordBloc.resetFields();
|
||||
|
||||
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
|
||||
int selectedCountry = -1;
|
||||
if (state is RadioSelectionChanged) {
|
||||
selectedCountry = state.selectedIndex;
|
||||
restorePasswordBloc.countrySelectionTextField.text =
|
||||
countryName[selectedCountry];
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
int selectedCountry = -1;
|
||||
if (state is RadioSelectionChanged) {
|
||||
selectedCountry = state.selectedIndex;
|
||||
}
|
||||
return Form(
|
||||
key: restorePasswordBloc.formKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 14,
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Gap(50),
|
||||
FormLabelTextField(
|
||||
prefixWidget: selectedCountry == -1
|
||||
? null
|
||||
: Image.asset(
|
||||
countryFlag[selectedCountry],
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
hintText: AppText.chooseCountry,
|
||||
title: AppText.countryOfResidence,
|
||||
type: "country selection",
|
||||
textEditingController:
|
||||
restorePasswordBloc.countrySelectionTextField,
|
||||
),
|
||||
const Gap(20),
|
||||
FormLabelTextField(
|
||||
prefixWidget: selectedCountry == -1
|
||||
? null
|
||||
: Image.asset(
|
||||
countryFlag[selectedCountry],
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
hintText: "+0 (000) 000 00 00",
|
||||
title: AppText.phoneNumber,
|
||||
type: "phone number",
|
||||
textEditingController:
|
||||
restorePasswordBloc.phoneNumberTextField,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
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_images.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
class RestorePasswordPhoneVerificationTopSection extends StatelessWidget {
|
||||
const RestorePasswordPhoneVerificationTopSection({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Gap(85),
|
||||
Center(
|
||||
child: SvgPicture.asset(
|
||||
AppImages.weclomeLogo,
|
||||
),
|
||||
),
|
||||
const Gap(60),
|
||||
TextWidget().text20W700(
|
||||
AppText.restorePasswordText,
|
||||
clr: AppColor.charcoalColor,
|
||||
),
|
||||
const Gap(10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 75),
|
||||
child: TextWidget().text14W500(
|
||||
AppText.toRestorePasswordPleaseEnterPhoneNumber,
|
||||
clr: AppColor.smokeGrayColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
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_images.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
class RestorePasswordTopSection extends StatelessWidget {
|
||||
const RestorePasswordTopSection({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Gap(85),
|
||||
Center(
|
||||
child: SvgPicture.asset(
|
||||
AppImages.weclomeLogo,
|
||||
),
|
||||
),
|
||||
const Gap(60),
|
||||
TextWidget().text20W700(
|
||||
AppText.restorePasswordText,
|
||||
clr: AppColor.charcoalColor,
|
||||
),
|
||||
const Gap(10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 75),
|
||||
child: TextWidget().text14W500(
|
||||
AppText.createNewPasswordText,
|
||||
clr: AppColor.smokeGrayColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -5,17 +5,25 @@ import '../widgets/bottom_section.dart';
|
||||
import '../widgets/top_section.dart';
|
||||
|
||||
class LoginLayout extends StatelessWidget {
|
||||
const LoginLayout({super.key});
|
||||
final String fromScreen;
|
||||
const LoginLayout({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ListView(
|
||||
//
|
||||
children: const [
|
||||
TopSection(),
|
||||
LoginForm(),
|
||||
BottomSection(),
|
||||
children: [
|
||||
TopSection(
|
||||
fromScreen: fromScreen,
|
||||
),
|
||||
const LoginForm(),
|
||||
BottomSection(
|
||||
fromScreen: fromScreen,
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@ class LoginScreen extends StatelessWidget {
|
||||
final radioBloc = context.read<RadioBloc>();
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
if (fromScreen == "welcome" || fromScreen == "registerStep") {
|
||||
if (fromScreen == "welcome" ||
|
||||
fromScreen == "registerStep" ||
|
||||
fromScreen == "forgot-pin") {
|
||||
exitAppDialog(context);
|
||||
return false;
|
||||
} else {
|
||||
@@ -33,7 +35,9 @@ class LoginScreen extends StatelessWidget {
|
||||
create: (context) => LoginBloc(),
|
||||
),
|
||||
],
|
||||
child: const LoginLayout(),
|
||||
child: LoginLayout(
|
||||
fromScreen: fromScreen,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -17,7 +17,11 @@ import '../bloc/login_event.dart';
|
||||
import '../bloc/login_state.dart';
|
||||
|
||||
class BottomSection extends StatelessWidget {
|
||||
const BottomSection({super.key});
|
||||
final String fromScreen;
|
||||
const BottomSection({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -29,7 +33,8 @@ class BottomSection extends StatelessWidget {
|
||||
alignment: Alignment.topRight,
|
||||
child: ButtonWidget().textBtn(
|
||||
function: () {
|
||||
goRouter.goNamed(RouteName.loginScreen);
|
||||
goRouter
|
||||
.pushNamed(RouteName.forgotPasswordPhoneVerificationScreen);
|
||||
},
|
||||
text: TextWidget().text15W400(AppText.forgorPassword,
|
||||
clr: AppColor.forgotPassButtonColor,
|
||||
@@ -44,10 +49,11 @@ class BottomSection extends StatelessWidget {
|
||||
goRouter.goNamed('mainScreen');
|
||||
successToastMessage(context, "login successful !");
|
||||
goRouter.pop();
|
||||
|
||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
||||
"fromScreen": "login",
|
||||
});
|
||||
radioBloc.resetSelection();
|
||||
goRouter.pushNamed(RouteName.pinScreen, pathParameters: {
|
||||
"fromScreen":
|
||||
fromScreen == "forgot-pin" ? "forgot-pin" : "login",
|
||||
}); //Push Or GO Need to Check
|
||||
} else if (state is LoginFailure) {
|
||||
goRouter.pop();
|
||||
errorToastMessage(
|
||||
@@ -101,11 +107,17 @@ class BottomSection extends StatelessWidget {
|
||||
ButtonWidget().textBtn(
|
||||
function: () {
|
||||
radioBloc.resetSelection();
|
||||
goRouter.pushNamed(RouteName.registerStepScreen, pathParameters: {
|
||||
"fromScreentype": "login",
|
||||
});
|
||||
fromScreen == "forgot-pin"
|
||||
? goRouter.pop()
|
||||
: goRouter
|
||||
.pushNamed(RouteName.registerStepScreen, pathParameters: {
|
||||
"fromScreentype": "login",
|
||||
});
|
||||
},
|
||||
text: TextWidget().text14W700(AppText.signUpText,
|
||||
text: TextWidget().text14W700(
|
||||
fromScreen == "forgot-pin"
|
||||
? AppText.backText
|
||||
: AppText.signUpText,
|
||||
clr: AppColor.textLabelColor,
|
||||
textDecoration: TextDecoration.underline)),
|
||||
],
|
||||
|
||||
@@ -7,7 +7,11 @@ import 'package:tanami_app/core/styles/app_text.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
|
||||
class TopSection extends StatelessWidget {
|
||||
const TopSection({super.key});
|
||||
final String fromScreen;
|
||||
const TopSection({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -29,7 +33,9 @@ class TopSection extends StatelessWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 75),
|
||||
child: TextWidget().text14W500(
|
||||
AppText.pleaseEnterLoginDetails,
|
||||
fromScreen == "forgot-pin"
|
||||
? AppText.toGetYourAccountPleaseSetYourInfo
|
||||
: AppText.pleaseEnterLoginDetails,
|
||||
clr: AppColor.smokeGrayColor,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -5,16 +5,22 @@ import '../widgets/otp_top_section.dart';
|
||||
import '../widgets/resend_otp_section.dart';
|
||||
|
||||
class OtpLayout extends StatelessWidget {
|
||||
const OtpLayout({super.key});
|
||||
final String fromScreen;
|
||||
const OtpLayout({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ListView(
|
||||
children: const [
|
||||
OtpTopSection(),
|
||||
OtpFillSection(),
|
||||
ResendOtpSection(),
|
||||
children: [
|
||||
const OtpTopSection(),
|
||||
OtpFillSection(
|
||||
fromScreen: fromScreen,
|
||||
),
|
||||
const ResendOtpSection(),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
@@ -8,7 +8,11 @@ import '../bloc/timer/timer_bloc.dart';
|
||||
import '../bloc/timer/timer_event.dart';
|
||||
|
||||
class OtpScreen extends StatelessWidget {
|
||||
const OtpScreen({super.key});
|
||||
final String fromScreen;
|
||||
const OtpScreen({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -25,7 +29,7 @@ class OtpScreen extends StatelessWidget {
|
||||
TimerBloc()..add(StartTimer()), // Start the timer here
|
||||
),
|
||||
],
|
||||
child: const OtpLayout(),
|
||||
child: OtpLayout(fromScreen: fromScreen),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,11 @@ import '../bloc/otp_event.dart';
|
||||
import '../bloc/otp_state.dart';
|
||||
|
||||
class OtpFillSection extends StatelessWidget {
|
||||
const OtpFillSection({super.key});
|
||||
final String fromScreen;
|
||||
const OtpFillSection({
|
||||
super.key,
|
||||
required this.fromScreen,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -28,7 +32,10 @@ class OtpFillSection extends StatelessWidget {
|
||||
context,
|
||||
AppText.otpVerifiedSucessfully,
|
||||
);
|
||||
goRouter.pushNamed(RouteName.registerUserDetailsScreen);
|
||||
|
||||
fromScreen == "forgot-password"
|
||||
? goRouter.pushNamed(RouteName.forgotPasswordScreen)
|
||||
: goRouter.pushNamed(RouteName.registerUserDetailsScreen);
|
||||
} else if (state is OtpSubmissionFailure) {
|
||||
goRouter.pop();
|
||||
errorToastMessage(
|
||||
|
||||
@@ -41,7 +41,8 @@ class RegisterBottomSection extends StatelessWidget {
|
||||
successToastMessage(context, "successful !");
|
||||
goRouter.pop();
|
||||
|
||||
goRouter.pushNamed(RouteName.otpScreen);
|
||||
goRouter.pushNamed(RouteName.otpScreen,
|
||||
pathParameters: {"fromScreen": "register"});
|
||||
} else if (state is RegisterFailure) {
|
||||
goRouter.pop();
|
||||
errorToastMessage(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.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';
|
||||
@@ -46,6 +47,9 @@ void forgotPinDialog(BuildContext context) {
|
||||
text: AppText.allowText,
|
||||
clr: AppColor.primaryColor2,
|
||||
function: () {
|
||||
goRouter.pushNamed(RouteName.loginScreen, pathParameters: {
|
||||
"fromScreen": "forgot-pin",
|
||||
});
|
||||
goRouter.pop();
|
||||
},
|
||||
),
|
||||
|
||||
@@ -58,8 +58,10 @@ class PinKey extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
fromScreen == "login" ? const Gap(20) : const Gap(0),
|
||||
fromScreen == "login"
|
||||
(fromScreen == "login" || fromScreen == "forgot-pin")
|
||||
? const Gap(20)
|
||||
: const Gap(0),
|
||||
(fromScreen == "login")
|
||||
? InkWell(
|
||||
onTap: () {
|
||||
forgotPinDialog(context);
|
||||
|
||||
@@ -49,10 +49,15 @@ class PinTopSection extends StatelessWidget {
|
||||
)
|
||||
],
|
||||
)
|
||||
: TextWidget().text14W500(
|
||||
AppText.createPinCode,
|
||||
clr: AppColor.textLabelColor,
|
||||
)
|
||||
: fromScreen == "forgot-pin"
|
||||
? TextWidget().text14W500(
|
||||
AppText.changePinCode,
|
||||
clr: AppColor.textLabelColor,
|
||||
)
|
||||
: TextWidget().text14W500(
|
||||
AppText.createPinCode,
|
||||
clr: AppColor.textLabelColor,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,15 @@ import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
|
||||
class TextWidget {
|
||||
//Text Size 11
|
||||
Widget text11W400(String text, {Color? clr}) {
|
||||
return Text(text,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
|
||||
//Text Size 12
|
||||
Widget text12W400(String text, {Color? clr}) {
|
||||
return Text(text,
|
||||
@@ -12,6 +21,21 @@ class TextWidget {
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
|
||||
Widget text12W500(String text, {Color? clr}) {
|
||||
return Text(text,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
|
||||
Widget text12W700(String text, {Color? clr}) {
|
||||
return Text(text,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
//Text Size 14
|
||||
|
||||
Widget text14W400(
|
||||
@@ -120,4 +144,13 @@ class TextWidget {
|
||||
fontWeight: FontWeight.w700,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
|
||||
//Text Size 28
|
||||
Widget text28W700(String text, {Color? clr}) {
|
||||
return Text(text,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: clr ?? AppColor.plainWhite));
|
||||
}
|
||||
}
|
||||
|
||||
148
pubspec.lock
148
pubspec.lock
@@ -81,6 +81,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.9"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.3.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.2"
|
||||
cached_network_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -137,6 +185,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.10.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -424,6 +480,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
gap:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -456,6 +520,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.1"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -472,6 +544,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -496,6 +576,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -505,7 +593,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
@@ -513,7 +601,7 @@ packages:
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
json_serializable:
|
||||
dependency: "direct main"
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: json_serializable
|
||||
sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
|
||||
@@ -632,6 +720,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -840,6 +936,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -936,6 +1040,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
shimmer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1029,6 +1149,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1061,6 +1189,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
toastification:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1221,6 +1357,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.5"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -69,7 +69,7 @@ dependencies:
|
||||
go_router: ^14.1.3
|
||||
|
||||
# Json Annotation
|
||||
json_serializable: ^6.8.0
|
||||
json_annotation: ^4.9.0
|
||||
|
||||
#Style
|
||||
control_style: ^0.1.0
|
||||
@@ -81,6 +81,8 @@ dependencies:
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
json_serializable:
|
||||
build_runner:
|
||||
|
||||
flutter_lints: ^3.0.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user