io api settings api
This commit is contained in:
@@ -5,5 +5,6 @@ class Globalconst {
|
||||
static String isdcode = "";
|
||||
static String createdpin = "";
|
||||
static String firstName = "";
|
||||
static String lastName = "";
|
||||
static String languageSelected = "en";
|
||||
}
|
||||
|
||||
@@ -81,4 +81,10 @@ class RouteName {
|
||||
|
||||
//Bank Details
|
||||
static const String addBankDetailsScreen = "addBankDetailsScreen";
|
||||
|
||||
//Vimeo
|
||||
static const String vimeoScreen = "vimeoScreen";
|
||||
|
||||
//PDF
|
||||
static const String pdfReaderScreen = "pdfReaderScreen";
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import 'package:tanami_app/features/register/presentation/pages/register_step_sc
|
||||
import 'package:tanami_app/features/securePin/presentation/pages/pin_screen.dart';
|
||||
import 'package:tanami_app/features/welcome/presentation/pages/weclome_screen.dart';
|
||||
import 'package:tanami_app/shared/components/no_internet.dart';
|
||||
import 'package:tanami_app/shared/components/read_pdf.dart';
|
||||
|
||||
import '../../features/MainScreens/Wallet/presentation/pages/deposit/deposit_completed_screen.dart';
|
||||
import '../../features/MainScreens/main_screen.dart';
|
||||
@@ -39,6 +40,7 @@ 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';
|
||||
import '../../shared/components/viemo_screen.dart';
|
||||
|
||||
/* CREATED BY - JAYESH JAIN
|
||||
DATE - 24-05-2024
|
||||
@@ -313,6 +315,25 @@ final goRouter = GoRouter(
|
||||
return const FAQScreen();
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: RouteName.vimeoScreen,
|
||||
path: "${RouteName.vimeoScreen}/:videoUrl",
|
||||
builder: (context, state) {
|
||||
return VimeoScreen(
|
||||
videoUrl: state.pathParameters["videoUrl"]!,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: RouteName.pdfReaderScreen,
|
||||
path: "${RouteName.pdfReaderScreen}/:title/:pdfUrl",
|
||||
builder: (context, state) {
|
||||
return ReadPDF(
|
||||
title: state.pathParameters["title"]!,
|
||||
pdfUrl: state.pathParameters["pdfUrl"]!,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -109,6 +109,58 @@ class AppText {
|
||||
|
||||
//FAQ
|
||||
static const String faqTitle = "faqTitle";
|
||||
static const String gettingStarted = "gettingStarted";
|
||||
static const String knowledgeAndEducation = "knowledgeAndEducation";
|
||||
static const String complianceSecurityAndSupport =
|
||||
"complianceSecurityAndSupport";
|
||||
static const String getStartedTitle1 = "getStartedTitle1";
|
||||
static const String geStartedDesc1 = "geStartedDesc1";
|
||||
static const String getStartedTitle2 = "getStartedTitle2";
|
||||
static const String geStartedDesc2 = "geStartedDesc2";
|
||||
static const String getStartedTitle3 = "getStartedTitle3";
|
||||
static const String geStartedDesc3 = "geStartedDesc3";
|
||||
static const String investmentTitle1 = "investmentTitle1";
|
||||
static const String investmentDesc1 = "investmentDesc1";
|
||||
static const String investmentTitle2 = "investmentTitle2";
|
||||
static const String investmentDesc2 = "investmentDesc2";
|
||||
static const String investmentTitle3 = "investmentTitle3";
|
||||
static const String investmentDesc3 = "investmentDesc3";
|
||||
static const String investmentTitle4 = "investmentTitle4";
|
||||
static const String investmentDesc4 = "investmentDesc4";
|
||||
static const String investmentTitle5 = "investmentTitle5";
|
||||
static const String investmentDesc5 = "investmentDesc5";
|
||||
static const String investmentTitle6 = "investmentTitle6";
|
||||
static const String investmentDesc6 = "investmentDesc6";
|
||||
static const String investmentTitle7 = "investmentTitle7";
|
||||
static const String investmentDesc7 = "investmentDesc7";
|
||||
static const String investmentTitle8 = "investmentTitle8";
|
||||
static const String investmentDesc8 = "investmentDesc8";
|
||||
static const String investmentTitle9 = "investmentTitle9";
|
||||
static const String investmentDesc9 = "investmentDesc9";
|
||||
static const String investmentTitle10 = "investmentTitle10";
|
||||
static const String investmentDesc10 = "investmentDesc10";
|
||||
static const String investmentTitle11 = "investmentTitle11";
|
||||
static const String investmentDesc11 = "investmentDesc11";
|
||||
static const String investmentTitle12 = "investmentTitle12";
|
||||
static const String investmentDesc12 = "investmentDesc12";
|
||||
static const String investmentTitle13 = "investmentTitle13";
|
||||
static const String investmentDesc13 = "investmentDesc13";
|
||||
static const String knowledgeTitle1 = "knowledgeTitle1";
|
||||
static const String knowledgeDesc1 = "knowledgeDesc1";
|
||||
static const String knowledgeTitle2 = "knowledgeTitle2";
|
||||
static const String knowledgeDesc2 = "knowledgeDesc2";
|
||||
static const String knowledgeTitle3 = "knowledgeTitle3";
|
||||
static const String knowledgeDesc3 = "knowledgeDesc3";
|
||||
static const String securityTitle1 = "securityTitle1";
|
||||
static const String securityDesc1 = "securityDesc1";
|
||||
static const String securityTitle2 = "securityTitle2";
|
||||
static const String securityDesc2 = "securityDesc2";
|
||||
static const String securityTitle3 = "securityTitle3";
|
||||
static const String securityDesc3 = "securityDesc3";
|
||||
static const String securityTitle4 = "securityTitle4";
|
||||
static const String securityDesc4 = "securityDesc4";
|
||||
static const String securityTitle5 = "securityTitle5";
|
||||
static const String securityDesc5 = "securityDesc5";
|
||||
|
||||
//Security
|
||||
static const String unlockText = "unlockText";
|
||||
@@ -144,6 +196,9 @@ class AppText {
|
||||
static const String masterPinAddedSucessfullyText =
|
||||
"masterPinAddedSucessfullyText";
|
||||
|
||||
static const String toRestorePasswordYouWillBeLoggedOut =
|
||||
"toRestorePasswordYouWillBeLoggedOut";
|
||||
|
||||
//Forgot Password
|
||||
static const String almostHere = "almostHere";
|
||||
static const String completeAcc = "completeAcc";
|
||||
@@ -270,6 +325,7 @@ class AppText {
|
||||
static const String currentPsswordText = "currentPsswordText";
|
||||
static const String bankDetails = "bankDetails";
|
||||
static const String addBankDetails = "addBankDetails";
|
||||
static const String websiteText = "websiteText";
|
||||
|
||||
//Contact Admin
|
||||
static const String byPhoneText = "byPhoneText";
|
||||
|
||||
16
lib/core/utils/date_time_formatter/date_time_formatter.dart
Normal file
16
lib/core/utils/date_time_formatter/date_time_formatter.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class DateTimeFormatter {
|
||||
String formatDate(String dateString) {
|
||||
// Parse the input date string
|
||||
DateTime dateTime = DateTime.parse(dateString);
|
||||
|
||||
// Define the output format
|
||||
DateFormat formatter = DateFormat('MMM dd yyyy');
|
||||
|
||||
// Format the date
|
||||
String formattedDate = formatter.format(dateTime);
|
||||
|
||||
return formattedDate;
|
||||
}
|
||||
}
|
||||
10
lib/core/utils/device_info/device_info_data.dart
Normal file
10
lib/core/utils/device_info/device_info_data.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
|
||||
class DeviceInfoData {
|
||||
final deviceInfoPlugin = DeviceInfoPlugin();
|
||||
|
||||
Future<String> getDeviceId() async {
|
||||
var dataV = await deviceInfoPlugin.androidInfo;
|
||||
return dataV.id.toString();
|
||||
}
|
||||
}
|
||||
@@ -16,4 +16,15 @@ class CommaTextInputFormatter extends TextInputFormatter {
|
||||
selection: TextSelection.collapsed(offset: newText.length),
|
||||
);
|
||||
}
|
||||
|
||||
String getInitials(String name) {
|
||||
List<String> words = name.split(' ');
|
||||
String initials = '';
|
||||
for (var word in words) {
|
||||
if (word.isNotEmpty) {
|
||||
initials += word[0].toUpperCase();
|
||||
}
|
||||
}
|
||||
return initials;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,3 +17,12 @@ void launchEmail(String email) async {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
}
|
||||
|
||||
void launchWebsiteUrl(String websiteUrl) async {
|
||||
final url = websiteUrl;
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,460 @@
|
||||
class AvailableIOModel {
|
||||
int? statusCode;
|
||||
Data? data;
|
||||
String? message;
|
||||
bool? success;
|
||||
|
||||
AvailableIOModel({this.statusCode, this.data, this.message, this.success});
|
||||
|
||||
AvailableIOModel.fromJson(Map<String, dynamic> json) {
|
||||
statusCode = json['statusCode'];
|
||||
data = json['data'] != null ? Data.fromJson(json['data']) : null;
|
||||
message = json['message'];
|
||||
success = json['success'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['statusCode'] = statusCode;
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.toJson();
|
||||
}
|
||||
data['message'] = message;
|
||||
data['success'] = success;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Data {
|
||||
int? totalItems;
|
||||
List<Rows>? rows;
|
||||
int? totalPages;
|
||||
int? currentPage;
|
||||
|
||||
Data({this.totalItems, this.rows, this.totalPages, this.currentPage});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
totalItems = json['totalItems'];
|
||||
if (json['rows'] != null) {
|
||||
rows = <Rows>[];
|
||||
json['rows'].forEach((v) {
|
||||
rows!.add(Rows.fromJson(v));
|
||||
});
|
||||
}
|
||||
totalPages = json['totalPages'];
|
||||
currentPage = json['currentPage'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['totalItems'] = totalItems;
|
||||
if (rows != null) {
|
||||
data['rows'] = rows!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['totalPages'] = totalPages;
|
||||
data['currentPage'] = currentPage;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Rows {
|
||||
int? id;
|
||||
String? ioId;
|
||||
int? investmentTypeXid;
|
||||
int? sponsorXid;
|
||||
int? ioStatusXid;
|
||||
String? investmentNameEnglish;
|
||||
String? investmentNameArabic;
|
||||
String? descriptionEnglish;
|
||||
String? descriptionArabic;
|
||||
String? goalAmount;
|
||||
String? closingDate;
|
||||
String? holdingPeriod;
|
||||
String? expectedReturn;
|
||||
String? originalValuation;
|
||||
String? currentValuation;
|
||||
String? iSIN;
|
||||
String? investmentDetails;
|
||||
String? comment;
|
||||
bool? isInvestedAmount;
|
||||
String? amountInvested;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
Sponsor? sponsor;
|
||||
IoStatus? ioStatus;
|
||||
InvestmentType? investmentType;
|
||||
List<String>? artifactsImage;
|
||||
List<MinInvestmentAmt>? minInvestmentAmt;
|
||||
|
||||
Rows(
|
||||
{this.id,
|
||||
this.ioId,
|
||||
this.investmentTypeXid,
|
||||
this.sponsorXid,
|
||||
this.ioStatusXid,
|
||||
this.investmentNameEnglish,
|
||||
this.investmentNameArabic,
|
||||
this.descriptionEnglish,
|
||||
this.descriptionArabic,
|
||||
this.goalAmount,
|
||||
this.closingDate,
|
||||
this.holdingPeriod,
|
||||
this.expectedReturn,
|
||||
this.originalValuation,
|
||||
this.currentValuation,
|
||||
this.iSIN,
|
||||
this.investmentDetails,
|
||||
this.comment,
|
||||
this.isInvestedAmount,
|
||||
this.amountInvested,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt,
|
||||
this.sponsor,
|
||||
this.ioStatus,
|
||||
this.investmentType,
|
||||
this.artifactsImage,
|
||||
this.minInvestmentAmt});
|
||||
|
||||
Rows.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
ioId = json['io_id'];
|
||||
investmentTypeXid = json['investmentType_xid'];
|
||||
sponsorXid = json['sponsor_xid'];
|
||||
ioStatusXid = json['ioStatus_xid'];
|
||||
investmentNameEnglish = json['investmentNameEnglish'];
|
||||
investmentNameArabic = json['investmentNameArabic'];
|
||||
descriptionEnglish = json['descriptionEnglish'];
|
||||
descriptionArabic = json['descriptionArabic'];
|
||||
goalAmount = json['goalAmount'];
|
||||
closingDate = json['closingDate'];
|
||||
holdingPeriod = json['holdingPeriod'];
|
||||
expectedReturn = json['expectedReturn'];
|
||||
originalValuation = json['originalValuation'];
|
||||
currentValuation = json['currentValuation'];
|
||||
iSIN = json['ISIN'];
|
||||
investmentDetails = json['InvestmentDetails'];
|
||||
comment = json['comment'];
|
||||
isInvestedAmount = json['isInvestedAmount'];
|
||||
amountInvested = json['amountInvested'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
sponsor =
|
||||
json['sponsor'] != null ? Sponsor.fromJson(json['sponsor']) : null;
|
||||
ioStatus =
|
||||
json['ioStatus'] != null ? IoStatus.fromJson(json['ioStatus']) : null;
|
||||
investmentType = json['investmentType'] != null
|
||||
? InvestmentType.fromJson(json['investmentType'])
|
||||
: null;
|
||||
if (json['artifactsImage'] != null) {
|
||||
artifactsImage = <String>[];
|
||||
json['artifactsImage'].forEach((v) {
|
||||
artifactsImage!.add(v);
|
||||
});
|
||||
}
|
||||
if (json['minInvestmentAmt'] != null) {
|
||||
minInvestmentAmt = <MinInvestmentAmt>[];
|
||||
json['minInvestmentAmt'].forEach((v) {
|
||||
minInvestmentAmt!.add(MinInvestmentAmt.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['io_id'] = ioId;
|
||||
data['investmentType_xid'] = investmentTypeXid;
|
||||
data['sponsor_xid'] = sponsorXid;
|
||||
data['ioStatus_xid'] = ioStatusXid;
|
||||
data['investmentNameEnglish'] = investmentNameEnglish;
|
||||
data['investmentNameArabic'] = investmentNameArabic;
|
||||
data['descriptionEnglish'] = descriptionEnglish;
|
||||
data['descriptionArabic'] = descriptionArabic;
|
||||
data['goalAmount'] = goalAmount;
|
||||
data['closingDate'] = closingDate;
|
||||
data['holdingPeriod'] = holdingPeriod;
|
||||
data['expectedReturn'] = expectedReturn;
|
||||
data['originalValuation'] = originalValuation;
|
||||
data['currentValuation'] = currentValuation;
|
||||
data['ISIN'] = iSIN;
|
||||
data['InvestmentDetails'] = investmentDetails;
|
||||
data['comment'] = comment;
|
||||
data['isInvestedAmount'] = isInvestedAmount;
|
||||
data['amountInvested'] = amountInvested;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
if (sponsor != null) {
|
||||
data['sponsor'] = sponsor!.toJson();
|
||||
}
|
||||
if (ioStatus != null) {
|
||||
data['ioStatus'] = ioStatus!.toJson();
|
||||
}
|
||||
if (investmentType != null) {
|
||||
data['investmentType'] = investmentType!.toJson();
|
||||
}
|
||||
if (artifactsImage != null) {
|
||||
data['artifactsImage'] = artifactsImage!.map((v) => v).toList();
|
||||
}
|
||||
if (minInvestmentAmt != null) {
|
||||
data['minInvestmentAmt'] =
|
||||
minInvestmentAmt!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Sponsor {
|
||||
int? id;
|
||||
String? sponsorName;
|
||||
String? sponsorNameArabic;
|
||||
String? email;
|
||||
Null profile;
|
||||
Null address;
|
||||
Null mobileNo;
|
||||
Null bankName;
|
||||
Null accountNumber;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
Sponsor(
|
||||
{this.id,
|
||||
this.sponsorName,
|
||||
this.sponsorNameArabic,
|
||||
this.email,
|
||||
this.profile,
|
||||
this.address,
|
||||
this.mobileNo,
|
||||
this.bankName,
|
||||
this.accountNumber,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
Sponsor.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
sponsorName = json['sponsorName'];
|
||||
sponsorNameArabic = json['sponsorNameArabic'];
|
||||
email = json['email'];
|
||||
profile = json['profile'];
|
||||
address = json['address'];
|
||||
mobileNo = json['mobileNo'];
|
||||
bankName = json['bankName'];
|
||||
accountNumber = json['accountNumber'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['sponsorName'] = sponsorName;
|
||||
data['sponsorNameArabic'] = sponsorNameArabic;
|
||||
data['email'] = email;
|
||||
data['profile'] = profile;
|
||||
data['address'] = address;
|
||||
data['mobileNo'] = mobileNo;
|
||||
data['bankName'] = bankName;
|
||||
data['accountNumber'] = accountNumber;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class IoStatus {
|
||||
int? id;
|
||||
String? statusAdmin;
|
||||
String? statusInvest;
|
||||
String? statusPortfolio;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
IoStatus(
|
||||
{this.id,
|
||||
this.statusAdmin,
|
||||
this.statusInvest,
|
||||
this.statusPortfolio,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
IoStatus.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
statusAdmin = json['statusAdmin'];
|
||||
statusInvest = json['statusInvest'];
|
||||
statusPortfolio = json['statusPortfolio'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['statusAdmin'] = statusAdmin;
|
||||
data['statusInvest'] = statusInvest;
|
||||
data['statusPortfolio'] = statusPortfolio;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class InvestmentType {
|
||||
int? id;
|
||||
String? investmentTypeName;
|
||||
String? investmentTypeNameArabic;
|
||||
String? note;
|
||||
String? noteArabic;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
InvestmentType(
|
||||
{this.id,
|
||||
this.investmentTypeName,
|
||||
this.investmentTypeNameArabic,
|
||||
this.note,
|
||||
this.noteArabic,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
InvestmentType.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
investmentTypeName = json['investmentTypeName'];
|
||||
investmentTypeNameArabic = json['investmentTypeNameArabic'];
|
||||
note = json['note'];
|
||||
noteArabic = json['noteArabic'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['investmentTypeName'] = investmentTypeName;
|
||||
data['investmentTypeNameArabic'] = investmentTypeNameArabic;
|
||||
data['note'] = note;
|
||||
data['noteArabic'] = noteArabic;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MinInvestmentAmt {
|
||||
int? id;
|
||||
int? ioXid;
|
||||
int? countryXid;
|
||||
String? minInvestmentAmt;
|
||||
String? maxInvestmentAmt;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
MinInvestmentAmt(
|
||||
{this.id,
|
||||
this.ioXid,
|
||||
this.countryXid,
|
||||
this.minInvestmentAmt,
|
||||
this.maxInvestmentAmt,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
MinInvestmentAmt.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
ioXid = json['io_xid'];
|
||||
countryXid = json['country_xid'];
|
||||
minInvestmentAmt = json['minInvestmentAmt'];
|
||||
maxInvestmentAmt = json['maxInvestmentAmt'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['io_xid'] = ioXid;
|
||||
data['country_xid'] = countryXid;
|
||||
data['minInvestmentAmt'] = minInvestmentAmt;
|
||||
data['maxInvestmentAmt'] = maxInvestmentAmt;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
class ClosedIOModel {
|
||||
int? statusCode;
|
||||
Data? data;
|
||||
String? message;
|
||||
bool? success;
|
||||
|
||||
ClosedIOModel({this.statusCode, this.data, this.message, this.success});
|
||||
|
||||
ClosedIOModel.fromJson(Map<String, dynamic> json) {
|
||||
statusCode = json['statusCode'];
|
||||
data = json['data'] != null ? Data.fromJson(json['data']) : null;
|
||||
message = json['message'];
|
||||
success = json['success'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['statusCode'] = statusCode;
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.toJson();
|
||||
}
|
||||
data['message'] = message;
|
||||
data['success'] = success;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Data {
|
||||
int? totalItems;
|
||||
List<Rows>? rows;
|
||||
int? totalPages;
|
||||
int? currentPage;
|
||||
|
||||
Data({this.totalItems, this.rows, this.totalPages, this.currentPage});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
totalItems = json['totalItems'];
|
||||
if (json['rows'] != null) {
|
||||
rows = <Rows>[];
|
||||
json['rows'].forEach((v) {
|
||||
rows!.add(Rows.fromJson(v));
|
||||
});
|
||||
}
|
||||
totalPages = json['totalPages'];
|
||||
currentPage = json['currentPage'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['totalItems'] = totalItems;
|
||||
if (rows != null) {
|
||||
data['rows'] = rows!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['totalPages'] = totalPages;
|
||||
data['currentPage'] = currentPage;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Rows {
|
||||
int? id;
|
||||
String? ioId;
|
||||
int? investmentTypeXid;
|
||||
int? sponsorXid;
|
||||
int? ioStatusXid;
|
||||
String? investmentNameEnglish;
|
||||
String? investmentNameArabic;
|
||||
String? descriptionEnglish;
|
||||
String? descriptionArabic;
|
||||
String? goalAmount;
|
||||
String? closingDate;
|
||||
String? holdingPeriod;
|
||||
String? expectedReturn;
|
||||
String? originalValuation;
|
||||
String? currentValuation;
|
||||
String? iSIN;
|
||||
String? investmentDetails;
|
||||
String? comment;
|
||||
bool? isInvestedAmount;
|
||||
String? amountInvested;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
Sponsor? sponsor;
|
||||
IoStatus? ioStatus;
|
||||
InvestmentType? investmentType;
|
||||
List<String>? artifactsImage;
|
||||
List<MinInvestmentAmt>? minInvestmentAmt;
|
||||
|
||||
Rows(
|
||||
{this.id,
|
||||
this.ioId,
|
||||
this.investmentTypeXid,
|
||||
this.sponsorXid,
|
||||
this.ioStatusXid,
|
||||
this.investmentNameEnglish,
|
||||
this.investmentNameArabic,
|
||||
this.descriptionEnglish,
|
||||
this.descriptionArabic,
|
||||
this.goalAmount,
|
||||
this.closingDate,
|
||||
this.holdingPeriod,
|
||||
this.expectedReturn,
|
||||
this.originalValuation,
|
||||
this.currentValuation,
|
||||
this.iSIN,
|
||||
this.investmentDetails,
|
||||
this.comment,
|
||||
this.isInvestedAmount,
|
||||
this.amountInvested,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt,
|
||||
this.sponsor,
|
||||
this.ioStatus,
|
||||
this.investmentType,
|
||||
this.artifactsImage,
|
||||
this.minInvestmentAmt});
|
||||
|
||||
Rows.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
ioId = json['io_id'];
|
||||
investmentTypeXid = json['investmentType_xid'];
|
||||
sponsorXid = json['sponsor_xid'];
|
||||
ioStatusXid = json['ioStatus_xid'];
|
||||
investmentNameEnglish = json['investmentNameEnglish'];
|
||||
investmentNameArabic = json['investmentNameArabic'];
|
||||
descriptionEnglish = json['descriptionEnglish'];
|
||||
descriptionArabic = json['descriptionArabic'];
|
||||
goalAmount = json['goalAmount'];
|
||||
closingDate = json['closingDate'];
|
||||
holdingPeriod = json['holdingPeriod'];
|
||||
expectedReturn = json['expectedReturn'];
|
||||
originalValuation = json['originalValuation'];
|
||||
currentValuation = json['currentValuation'];
|
||||
iSIN = json['ISIN'];
|
||||
investmentDetails = json['InvestmentDetails'];
|
||||
comment = json['comment'];
|
||||
isInvestedAmount = json['isInvestedAmount'];
|
||||
amountInvested = json['amountInvested'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
sponsor =
|
||||
json['sponsor'] != null ? Sponsor.fromJson(json['sponsor']) : null;
|
||||
ioStatus =
|
||||
json['ioStatus'] != null ? IoStatus.fromJson(json['ioStatus']) : null;
|
||||
investmentType = json['investmentType'] != null
|
||||
? InvestmentType.fromJson(json['investmentType'])
|
||||
: null;
|
||||
if (json['artifactsImage'] != null) {
|
||||
artifactsImage = <String>[];
|
||||
json['artifactsImage'].forEach((v) {
|
||||
artifactsImage!.add(v);
|
||||
});
|
||||
}
|
||||
if (json['minInvestmentAmt'] != null) {
|
||||
minInvestmentAmt = <MinInvestmentAmt>[];
|
||||
json['minInvestmentAmt'].forEach((v) {
|
||||
minInvestmentAmt!.add(MinInvestmentAmt.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['io_id'] = ioId;
|
||||
data['investmentType_xid'] = investmentTypeXid;
|
||||
data['sponsor_xid'] = sponsorXid;
|
||||
data['ioStatus_xid'] = ioStatusXid;
|
||||
data['investmentNameEnglish'] = investmentNameEnglish;
|
||||
data['investmentNameArabic'] = investmentNameArabic;
|
||||
data['descriptionEnglish'] = descriptionEnglish;
|
||||
data['descriptionArabic'] = descriptionArabic;
|
||||
data['goalAmount'] = goalAmount;
|
||||
data['closingDate'] = closingDate;
|
||||
data['holdingPeriod'] = holdingPeriod;
|
||||
data['expectedReturn'] = expectedReturn;
|
||||
data['originalValuation'] = originalValuation;
|
||||
data['currentValuation'] = currentValuation;
|
||||
data['ISIN'] = iSIN;
|
||||
data['InvestmentDetails'] = investmentDetails;
|
||||
data['comment'] = comment;
|
||||
data['isInvestedAmount'] = isInvestedAmount;
|
||||
data['amountInvested'] = amountInvested;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
if (sponsor != null) {
|
||||
data['sponsor'] = sponsor!.toJson();
|
||||
}
|
||||
if (ioStatus != null) {
|
||||
data['ioStatus'] = ioStatus!.toJson();
|
||||
}
|
||||
if (investmentType != null) {
|
||||
data['investmentType'] = investmentType!.toJson();
|
||||
}
|
||||
if (artifactsImage != null) {
|
||||
data['artifactsImage'] = artifactsImage!.map((v) => v).toList();
|
||||
}
|
||||
if (minInvestmentAmt != null) {
|
||||
data['minInvestmentAmt'] =
|
||||
minInvestmentAmt!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Sponsor {
|
||||
int? id;
|
||||
String? sponsorName;
|
||||
String? sponsorNameArabic;
|
||||
String? email;
|
||||
Null profile;
|
||||
Null address;
|
||||
Null mobileNo;
|
||||
Null bankName;
|
||||
Null accountNumber;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
Sponsor(
|
||||
{this.id,
|
||||
this.sponsorName,
|
||||
this.sponsorNameArabic,
|
||||
this.email,
|
||||
this.profile,
|
||||
this.address,
|
||||
this.mobileNo,
|
||||
this.bankName,
|
||||
this.accountNumber,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
Sponsor.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
sponsorName = json['sponsorName'];
|
||||
sponsorNameArabic = json['sponsorNameArabic'];
|
||||
email = json['email'];
|
||||
profile = json['profile'];
|
||||
address = json['address'];
|
||||
mobileNo = json['mobileNo'];
|
||||
bankName = json['bankName'];
|
||||
accountNumber = json['accountNumber'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['sponsorName'] = sponsorName;
|
||||
data['sponsorNameArabic'] = sponsorNameArabic;
|
||||
data['email'] = email;
|
||||
data['profile'] = profile;
|
||||
data['address'] = address;
|
||||
data['mobileNo'] = mobileNo;
|
||||
data['bankName'] = bankName;
|
||||
data['accountNumber'] = accountNumber;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class IoStatus {
|
||||
int? id;
|
||||
String? statusAdmin;
|
||||
String? statusInvest;
|
||||
String? statusPortfolio;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
IoStatus(
|
||||
{this.id,
|
||||
this.statusAdmin,
|
||||
this.statusInvest,
|
||||
this.statusPortfolio,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
IoStatus.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
statusAdmin = json['statusAdmin'];
|
||||
statusInvest = json['statusInvest'];
|
||||
statusPortfolio = json['statusPortfolio'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['statusAdmin'] = statusAdmin;
|
||||
data['statusInvest'] = statusInvest;
|
||||
data['statusPortfolio'] = statusPortfolio;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class InvestmentType {
|
||||
int? id;
|
||||
String? investmentTypeName;
|
||||
String? investmentTypeNameArabic;
|
||||
String? note;
|
||||
String? noteArabic;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
InvestmentType(
|
||||
{this.id,
|
||||
this.investmentTypeName,
|
||||
this.investmentTypeNameArabic,
|
||||
this.note,
|
||||
this.noteArabic,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
InvestmentType.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
investmentTypeName = json['investmentTypeName'];
|
||||
investmentTypeNameArabic = json['investmentTypeNameArabic'];
|
||||
note = json['note'];
|
||||
noteArabic = json['noteArabic'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['investmentTypeName'] = investmentTypeName;
|
||||
data['investmentTypeNameArabic'] = investmentTypeNameArabic;
|
||||
data['note'] = note;
|
||||
data['noteArabic'] = noteArabic;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MinInvestmentAmt {
|
||||
int? id;
|
||||
int? ioXid;
|
||||
int? countryXid;
|
||||
String? minInvestmentAmt;
|
||||
String? maxInvestmentAmt;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
MinInvestmentAmt(
|
||||
{this.id,
|
||||
this.ioXid,
|
||||
this.countryXid,
|
||||
this.minInvestmentAmt,
|
||||
this.maxInvestmentAmt,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
MinInvestmentAmt.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
ioXid = json['io_xid'];
|
||||
countryXid = json['country_xid'];
|
||||
minInvestmentAmt = json['minInvestmentAmt'];
|
||||
maxInvestmentAmt = json['maxInvestmentAmt'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['io_xid'] = ioXid;
|
||||
data['country_xid'] = countryXid;
|
||||
data['minInvestmentAmt'] = minInvestmentAmt;
|
||||
data['maxInvestmentAmt'] = maxInvestmentAmt;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import '../../../../../Api_Helper/base_manager.dart';
|
||||
import '../../../../../shared/api/api_endpoints.dart';
|
||||
import '../../../../../shared/api/network_api_services.dart';
|
||||
|
||||
class IOApi {
|
||||
Future<ResponseData> availableIOAPI() async {
|
||||
String url = ApiEndpoints.availableIOApi;
|
||||
final response = await NetworkApiService().get(url);
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<ResponseData> closedIOAPI() async {
|
||||
String url = ApiEndpoints.closedIOApi;
|
||||
final response = await NetworkApiService().get(url);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,52 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Invest/domain/model/available_io_model.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Invest/domain/model/closed_io_model.dart';
|
||||
|
||||
import '../../../../../Api_Helper/base_manager.dart';
|
||||
import '../../domain/repository/io_api.dart';
|
||||
import 'tab_event.dart';
|
||||
import 'tab_state.dart';
|
||||
|
||||
class TabBloc extends Bloc<TabEvent, TabState> {
|
||||
TabBloc() : super(const TabState()) {
|
||||
TabBloc() : super(TabState(AvailableIOModel(), ClosedIOModel(), false, '')) {
|
||||
on<LoadAvailableItems>(_onLoadAvailableItems);
|
||||
on<LoadClosedItems>(_onLoadClosedItems);
|
||||
}
|
||||
|
||||
void _onLoadAvailableItems(LoadAvailableItems event, Emitter<TabState> emit) {
|
||||
// Simulate fetching available items
|
||||
final availableItems =
|
||||
List<String>.generate(10, (index) => 'Available Item $index');
|
||||
emit(state.copyWith(availableItems: availableItems));
|
||||
void _onLoadAvailableItems(
|
||||
LoadAvailableItems event, Emitter<TabState> emit) async {
|
||||
emit(state.copyWith(loading: true));
|
||||
try {
|
||||
ResponseData response = await IOApi().availableIOAPI();
|
||||
log(response.data.toString());
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
AvailableIOModel availableIOModel =
|
||||
AvailableIOModel.fromJson(response.data);
|
||||
emit(state.copyWith(availableItems: availableIOModel, loading: false));
|
||||
} else {
|
||||
emit(state.copyWith(errorMessage: response.message, loading: false));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
errorMessage: 'Failed to fetch available items: $e', loading: false));
|
||||
}
|
||||
}
|
||||
|
||||
void _onLoadClosedItems(LoadClosedItems event, Emitter<TabState> emit) {
|
||||
// Simulate fetching closed items
|
||||
final closedItems =
|
||||
List<String>.generate(10, (index) => 'Closed Item $index');
|
||||
emit(state.copyWith(closedItems: closedItems));
|
||||
void _onLoadClosedItems(LoadClosedItems event, Emitter<TabState> emit) async {
|
||||
emit(state.copyWith(loading: true));
|
||||
try {
|
||||
ResponseData response = await IOApi().closedIOAPI();
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
ClosedIOModel closedIOModel = ClosedIOModel.fromJson(response.data);
|
||||
emit(state.copyWith(closedItems: closedIOModel, loading: false));
|
||||
} else {
|
||||
emit(state.copyWith(errorMessage: response.message, loading: false));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
errorMessage: 'Failed to fetch available items: $e', loading: false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,36 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class TabState extends Equatable {
|
||||
final List<String> availableItems;
|
||||
final List<String> closedItems;
|
||||
import '../../domain/model/available_io_model.dart';
|
||||
import '../../domain/model/closed_io_model.dart';
|
||||
|
||||
const TabState({
|
||||
this.availableItems = const [],
|
||||
this.closedItems = const [],
|
||||
});
|
||||
class TabState extends Equatable {
|
||||
final AvailableIOModel availableItems;
|
||||
final ClosedIOModel closedItems;
|
||||
final bool loading;
|
||||
final String errorMessage;
|
||||
|
||||
const TabState(
|
||||
this.availableItems,
|
||||
this.closedItems,
|
||||
this.loading,
|
||||
this.errorMessage,
|
||||
);
|
||||
|
||||
TabState copyWith({
|
||||
List<String>? availableItems,
|
||||
List<String>? closedItems,
|
||||
AvailableIOModel? availableItems,
|
||||
ClosedIOModel? closedItems,
|
||||
bool? loading,
|
||||
String? errorMessage,
|
||||
}) {
|
||||
return TabState(
|
||||
availableItems: availableItems ?? this.availableItems,
|
||||
closedItems: closedItems ?? this.closedItems,
|
||||
availableItems ?? this.availableItems,
|
||||
closedItems ?? this.closedItems,
|
||||
loading ?? this.loading,
|
||||
errorMessage ?? this.errorMessage,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => [availableItems, closedItems];
|
||||
List<Object> get props =>
|
||||
[availableItems, closedItems, loading, errorMessage];
|
||||
}
|
||||
|
||||
@@ -72,52 +72,63 @@ class AvailableItemsScreen extends StatelessWidget {
|
||||
|
||||
return BlocBuilder<TabBloc, TabState>(
|
||||
builder: (context, state) {
|
||||
if (state.availableItems.isEmpty) {
|
||||
if (state.loading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: state.availableItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
return index == 0
|
||||
? Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 18,
|
||||
),
|
||||
child: kycCard(context))
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pushNamed(RouteName.investDetailScreen,
|
||||
pathParameters: {"type": "available"});
|
||||
},
|
||||
child: Container(
|
||||
} else if (state.errorMessage.isNotEmpty) {
|
||||
return Center(child: Text(state.errorMessage));
|
||||
} else if (state.availableItems.data!.rows!.isEmpty) {
|
||||
return const Center(child: Text('No available items.'));
|
||||
} else {
|
||||
return ListView.builder(
|
||||
itemCount: state.availableItems.data!.rows!.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
return index == 0
|
||||
? Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 18,
|
||||
),
|
||||
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),
|
||||
),
|
||||
],
|
||||
child: kycCard(context))
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pushNamed(RouteName.investDetailScreen,
|
||||
pathParameters: {"type": "available"});
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 18,
|
||||
),
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
InvestCarouselView(
|
||||
imageList: state.availableItems.data!
|
||||
.rows![index - 1].artifactsImage!,
|
||||
),
|
||||
InvestDetailsSection(
|
||||
availableIOModel:
|
||||
state.availableItems.data!.rows![index - 1],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
InvestCarouselView(),
|
||||
const InvestDetailsSection(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -132,44 +143,53 @@ class ClosedItemsScreen extends StatelessWidget {
|
||||
|
||||
return BlocBuilder<TabBloc, TabState>(
|
||||
builder: (context, state) {
|
||||
if (state.closedItems.isEmpty) {
|
||||
if (state.loading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state.errorMessage.isNotEmpty) {
|
||||
return Center(child: Text(state.errorMessage));
|
||||
} else if (state.closedItems.data!.rows!.isEmpty) {
|
||||
return const Center(child: Text('No available items.'));
|
||||
} else {
|
||||
return ListView.builder(
|
||||
itemCount: state.closedItems.data!.rows!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pushNamed(RouteName.investDetailScreen,
|
||||
pathParameters: {"type": "closed"});
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 18,
|
||||
),
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
InvestCarouselView(
|
||||
imageList: const [],
|
||||
),
|
||||
InvestClosedDetailsSection(
|
||||
closedIoModel: state.closedItems.data!.rows![index],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: state.closedItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pushNamed(RouteName.investDetailScreen,
|
||||
pathParameters: {"type": "closed"});
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 18,
|
||||
),
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
InvestCarouselView(),
|
||||
const InvestClosedDetailsSection(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,11 +5,14 @@ import 'package:tanami_app/core/styles/app_color.dart';
|
||||
|
||||
import '../../../../../core/styles/app_images.dart';
|
||||
import '../../../../../core/styles/app_text.dart';
|
||||
import '../../../../../core/utils/date_time_formatter/date_time_formatter.dart';
|
||||
import '../../../../../core/utils/language/localizations_delegate.dart';
|
||||
import '../../../../../shared/components/text_widget.dart';
|
||||
import '../../domain/model/closed_io_model.dart';
|
||||
|
||||
class InvestClosedDetailsSection extends StatelessWidget {
|
||||
const InvestClosedDetailsSection({super.key});
|
||||
final Rows closedIoModel;
|
||||
const InvestClosedDetailsSection({super.key, required this.closedIoModel});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -32,7 +35,7 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextWidget().text17W700(
|
||||
'Multi Family Residental',
|
||||
closedIoModel.investmentNameEnglish!,
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
Container(
|
||||
@@ -46,7 +49,7 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: TextWidget().text12W700(
|
||||
"Real estate",
|
||||
closedIoModel.investmentType!.investmentTypeName!,
|
||||
clr: AppColor.selectedItemColor,
|
||||
)),
|
||||
)
|
||||
@@ -77,7 +80,8 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
TextWidget().text12W500(
|
||||
'Jul 10 2025',
|
||||
DateTimeFormatter()
|
||||
.formatDate(closedIoModel.closingDate!),
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
],
|
||||
@@ -86,23 +90,8 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
Gap(
|
||||
10.h,
|
||||
),
|
||||
// TextWidget()
|
||||
// .text22W900("SAR 1,478,000", clr: AppColor.investTextColor),
|
||||
// const Gap(8.0),
|
||||
// LinearProgressIndicator(
|
||||
// value: 1,
|
||||
// borderRadius: BorderRadius.circular(2),
|
||||
// minHeight: 8.0,
|
||||
// backgroundColor: AppColor.txtBorderColor,
|
||||
// valueColor: const AlwaysStoppedAnimation<Color>(
|
||||
// AppColor.investTextColor),
|
||||
// ),
|
||||
// const Gap(8.0),
|
||||
// TextWidget().text11W700("100% ${AppText.fundedText}",
|
||||
// clr: AppColor.portoflioCardTextColor),
|
||||
// const Gap(8.0),
|
||||
TextWidget().text14W400(
|
||||
'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.',
|
||||
closedIoModel.descriptionEnglish!,
|
||||
clr: Colors.grey,
|
||||
txtAlign: TextAlign.start,
|
||||
maxLine: 2,
|
||||
@@ -135,7 +124,7 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'Silverlake',
|
||||
closedIoModel.sponsor!.sponsorName!,
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
)
|
||||
@@ -157,7 +146,7 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'22.5%',
|
||||
closedIoModel.expectedReturn!,
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
),
|
||||
@@ -179,7 +168,7 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'24 Months',
|
||||
closedIoModel.holdingPeriod!,
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
),
|
||||
@@ -198,7 +187,8 @@ class InvestClosedDetailsSection extends StatelessWidget {
|
||||
txtAlign: TextAlign.start,
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'August 1, 2027',
|
||||
DateTimeFormatter()
|
||||
.formatDate(closedIoModel.closingDate!),
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
),
|
||||
|
||||
@@ -2,6 +2,8 @@ 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/utils/date_time_formatter/date_time_formatter.dart';
|
||||
import 'package:tanami_app/features/MainScreens/Invest/domain/model/available_io_model.dart';
|
||||
|
||||
import '../../../../../core/styles/app_images.dart';
|
||||
import '../../../../../core/styles/app_text.dart';
|
||||
@@ -9,7 +11,8 @@ import '../../../../../core/utils/language/localizations_delegate.dart';
|
||||
import '../../../../../shared/components/text_widget.dart';
|
||||
|
||||
class InvestDetailsSection extends StatelessWidget {
|
||||
const InvestDetailsSection({super.key});
|
||||
final Rows availableIOModel;
|
||||
const InvestDetailsSection({super.key, required this.availableIOModel});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -32,7 +35,7 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextWidget().text17W700(
|
||||
'Multi Family Residental',
|
||||
availableIOModel.investmentNameEnglish!,
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
Container(
|
||||
@@ -46,7 +49,7 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: TextWidget().text11W700(
|
||||
"Real estate",
|
||||
availableIOModel.investmentType!.investmentTypeName!,
|
||||
clr: AppColor.selectedItemColor,
|
||||
)),
|
||||
)
|
||||
@@ -77,7 +80,8 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
TextWidget().text12W500(
|
||||
'Jul 10 2025',
|
||||
DateTimeFormatter()
|
||||
.formatDate(availableIOModel.closingDate!),
|
||||
clr: AppColor.plainBlack,
|
||||
),
|
||||
],
|
||||
@@ -86,11 +90,12 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
Gap(
|
||||
10.h,
|
||||
),
|
||||
TextWidget()
|
||||
.text22W900("SAR 1,478,000", clr: AppColor.investTextColor),
|
||||
TextWidget().text22W900("USD ${availableIOModel.goalAmount!}",
|
||||
clr: AppColor.investTextColor),
|
||||
const Gap(8.0),
|
||||
LinearProgressIndicator(
|
||||
value: 0.6,
|
||||
value: (double.parse(availableIOModel.amountInvested!) /
|
||||
double.parse(availableIOModel.goalAmount!)),
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
minHeight: 8.0,
|
||||
backgroundColor: AppColor.txtBorderColor,
|
||||
@@ -99,11 +104,11 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
),
|
||||
const Gap(8.0),
|
||||
TextWidget().text11W700(
|
||||
"60% ${localizations.translate(AppText.fundedText)}",
|
||||
"${(double.parse(availableIOModel.amountInvested!) / double.parse(availableIOModel.goalAmount!)) * 100}% ${localizations.translate(AppText.fundedText)}",
|
||||
clr: AppColor.portoflioCardTextColor),
|
||||
const Gap(8.0),
|
||||
TextWidget().text14W400(
|
||||
'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.',
|
||||
availableIOModel.descriptionEnglish!,
|
||||
clr: Colors.grey,
|
||||
txtAlign: TextAlign.start,
|
||||
maxLine: 2,
|
||||
@@ -136,7 +141,7 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'Silverlake',
|
||||
availableIOModel.sponsor!.sponsorName!,
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
)
|
||||
@@ -158,7 +163,7 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'20.0%',
|
||||
availableIOModel.expectedReturn!,
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
),
|
||||
@@ -180,7 +185,7 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'24 Months',
|
||||
availableIOModel.holdingPeriod!,
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
),
|
||||
@@ -199,7 +204,7 @@ class InvestDetailsSection extends StatelessWidget {
|
||||
txtAlign: TextAlign.start,
|
||||
),
|
||||
TextWidget().text14W700(
|
||||
'SAR 1,000',
|
||||
'BHD ${availableIOModel.minInvestmentAmt![0].minInvestmentAmt}',
|
||||
clr: AppColor.plainBlack,
|
||||
txtAlign: TextAlign.end,
|
||||
),
|
||||
|
||||
@@ -19,8 +19,9 @@ final List imgList = [
|
||||
|
||||
class InvestCarouselView extends StatelessWidget {
|
||||
final CarouselController _controller = CarouselController();
|
||||
final List<String> imageList;
|
||||
|
||||
InvestCarouselView({super.key});
|
||||
InvestCarouselView({super.key, required this.imageList});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -37,10 +38,10 @@ class InvestCarouselView extends StatelessWidget {
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: CarouselSlider(
|
||||
items: imgList
|
||||
items: imageList
|
||||
.map(
|
||||
(item) => Image.asset(
|
||||
item['img_path'],
|
||||
item,
|
||||
fit: BoxFit.cover,
|
||||
width: double.infinity,
|
||||
alignment: Alignment.topCenter,
|
||||
@@ -67,7 +68,7 @@ class InvestCarouselView extends StatelessWidget {
|
||||
}
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: imgList.asMap().entries.map((entry) {
|
||||
children: imageList.asMap().entries.map((entry) {
|
||||
return GestureDetector(
|
||||
onTap: () => _controller.animateToPage(entry.key),
|
||||
child: Container(
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
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_images.dart';
|
||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||
@@ -51,48 +53,60 @@ class InvestIncludedDocumentsSection extends StatelessWidget {
|
||||
6,
|
||||
(index) {
|
||||
return Center(
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColor.documentCardBgColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(10.0)),
|
||||
),
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
AppImages.documentIcon,
|
||||
height: 16.sp,
|
||||
),
|
||||
Gap(
|
||||
7.w,
|
||||
),
|
||||
TextWidget().text12W700("Filename.pdf",
|
||||
clr: AppColor.plainBlack),
|
||||
],
|
||||
),
|
||||
Gap(
|
||||
20.h,
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
//https://www.orimi.com/pdf-test.pdf
|
||||
goRouter.pushNamed(RouteName.pdfReaderScreen,
|
||||
pathParameters: {
|
||||
"pdfUrl":
|
||||
"https://dn790007.ca.archive.org/0/items/atomic-habits-pdfdrive/Atomic%20habits%20%28%20PDFDrive%20%29.pdf",
|
||||
"title": "Test"
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColor.documentCardBgColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(10.0)),
|
||||
),
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
TextWidget().text12W700("512 Mb",
|
||||
clr: AppColor.portoflioCardTextColor),
|
||||
Image.asset(
|
||||
AppImages.documentIcon,
|
||||
height: 16.sp,
|
||||
),
|
||||
Gap(
|
||||
7.w,
|
||||
),
|
||||
Image.asset(
|
||||
AppImages.donwloadIcon,
|
||||
height: 20.sp,
|
||||
),
|
||||
TextWidget().text12W700("Filename.pdf",
|
||||
clr: AppColor.plainBlack),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
Gap(
|
||||
20.h,
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextWidget().text12W700("512 Mb",
|
||||
clr: AppColor.portoflioCardTextColor),
|
||||
Gap(
|
||||
7.w,
|
||||
),
|
||||
Image.asset(
|
||||
AppImages.donwloadIcon,
|
||||
height: 20.sp,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.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_images.dart';
|
||||
|
||||
import '../../../../../core/styles/app_text.dart';
|
||||
@@ -46,32 +48,38 @@ class InvestVideoSection extends StatelessWidget {
|
||||
shrinkWrap: true,
|
||||
itemCount: videos.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 18.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(18.0),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Image.asset(
|
||||
videos[index],
|
||||
fit: BoxFit.cover,
|
||||
height: 160.h,
|
||||
width: 1.sw,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0.0,
|
||||
child: Image.asset(
|
||||
AppImages.academyCardOverlay,
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
goRouter.pushNamed(RouteName.vimeoScreen,
|
||||
pathParameters: {"videoUrl": "989972367"});
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 18.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(18.0),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Image.asset(
|
||||
videos[index],
|
||||
fit: BoxFit.cover,
|
||||
height: 160.h,
|
||||
width: 1.sw,
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
AppImages.videoPlayIcon,
|
||||
Positioned(
|
||||
bottom: 0.0,
|
||||
child: Image.asset(
|
||||
AppImages.academyCardOverlay,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
AppImages.videoPlayIcon,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import '../../../../../Api_Helper/base_manager.dart';
|
||||
import '../../../../../shared/api/api_endpoints.dart';
|
||||
import '../../../../../shared/api/network_api_services.dart';
|
||||
|
||||
class SettingsApi {
|
||||
Future<ResponseData> updateNotification() async {
|
||||
String url = ApiEndpoints.updateNotificationApi;
|
||||
final response = await NetworkApiService().post(url, {});
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,17 @@ class UserAccountSection extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String getInitials(String name) {
|
||||
List<String> words = name.split(' ');
|
||||
String initials = '';
|
||||
for (var word in words) {
|
||||
if (word.isNotEmpty) {
|
||||
initials += word[0].toUpperCase();
|
||||
}
|
||||
}
|
||||
return initials;
|
||||
}
|
||||
|
||||
var localizations = AppLocalizations.of(context);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@@ -65,7 +76,8 @@ class UserAccountSection extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
TextWidget().text15W500(
|
||||
'AN',
|
||||
getInitials(
|
||||
"${Globalconst.firstName} ${Globalconst.lastName}"),
|
||||
clr: const Color(0xFF066123),
|
||||
)
|
||||
],
|
||||
@@ -80,7 +92,7 @@ class UserAccountSection extends StatelessWidget {
|
||||
TextWidget().text14W500(
|
||||
Globalconst.firstName.isEmpty
|
||||
? "User"
|
||||
: Globalconst.firstName,
|
||||
: "${Globalconst.firstName} ${Globalconst.lastName}",
|
||||
clr: const Color(0xFF191B1E),
|
||||
),
|
||||
const Gap(4),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||
import 'package:tanami_app/features/biometric/domain/repository/biometric_api.dart';
|
||||
|
||||
import '../../../Api_Helper/base_manager.dart';
|
||||
import '../../../core/utils/device_info/device_info_data.dart';
|
||||
import 'biometric_event.dart';
|
||||
import 'biometric_state.dart';
|
||||
|
||||
@@ -57,16 +58,17 @@ class BiometricBloc extends Bloc<BiometricEvent, BiometricState> {
|
||||
|
||||
if (authenticated) {
|
||||
Map<String, dynamic> biometricLoginData = {
|
||||
"token": await secureStorageService.read("temp_token"),
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"deviceId": await DeviceInfoData().getDeviceId(),
|
||||
};
|
||||
|
||||
ResponseData response =
|
||||
await BiometricAPIServices().biometricLoginApi(biometricLoginData);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write(
|
||||
'accesstoken', response.data["data"]["accessToken"]);
|
||||
'accesstoken', response.data["data"]["access"]["token"]);
|
||||
await secureStorageService.write(
|
||||
'refreshtoken', response.data["data"]["refreshToken"]);
|
||||
'refreshtoken', response.data["data"]["refresh"]["token"]);
|
||||
emit(BiometricAuthenticated());
|
||||
} else {
|
||||
if (Globalconst.languageSelected == "en") {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tanami_app/features/changePassword/domain/repository/change_password_api.dart';
|
||||
|
||||
import '../../../Api_Helper/base_manager.dart';
|
||||
import 'change_password_event.dart';
|
||||
import 'change_password_state.dart';
|
||||
|
||||
@@ -28,15 +30,18 @@ class ChangePasswordBloc
|
||||
}
|
||||
emit(ChangePasswordLoading());
|
||||
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) {
|
||||
Map<String, dynamic> dataForm = {
|
||||
"oldPassword": event.currentPassword,
|
||||
"newPassword": event.password,
|
||||
"confirmNewPassword": event.repeatPassword,
|
||||
};
|
||||
ResponseData response =
|
||||
await ChangePasswordApi().changePassword(dataForm);
|
||||
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
emit(ChangePasswordSuccess());
|
||||
} else {
|
||||
emit(const ChangePasswordFailure(
|
||||
"Failed. Please check your credentials."));
|
||||
emit(ChangePasswordFailure(response.message));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(ChangePasswordFailure(e.toString()));
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import '../../../../../Api_Helper/base_manager.dart';
|
||||
import '../../../../../shared/api/api_endpoints.dart';
|
||||
import '../../../../../shared/api/network_api_services.dart';
|
||||
|
||||
class ChangePasswordApi {
|
||||
Future<ResponseData> changePassword(Map<String, dynamic> data) async {
|
||||
String url = ApiEndpoints.updatePasswordApi;
|
||||
final response = await NetworkApiService().post(url, data);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/core/styles/app_text.dart';
|
||||
|
||||
import '../../../../core/routes/route_name.dart';
|
||||
import '../../../../core/routes/routes.dart';
|
||||
import '../../../../core/styles/app_color.dart';
|
||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
|
||||
import '../../../../shared/components/button_widget.dart';
|
||||
import '../../../../shared/components/forgot_password_log_out_dialog.dart';
|
||||
import '../../../../shared/components/form_label_textfield.dart';
|
||||
import '../../../../shared/components/text_widget.dart';
|
||||
import '../../bloc/change_password_bloc.dart';
|
||||
@@ -41,7 +40,7 @@ class RestorePasswordForm extends StatelessWidget {
|
||||
child: FormLabelTextField(
|
||||
hintText: localizations.translate(AppText.enterPassword),
|
||||
title: localizations.translate(AppText.currentPsswordText),
|
||||
type: AppText.password.toLowerCase(),
|
||||
type: "login-password",
|
||||
textEditingController:
|
||||
restorePasswordBloc.currentPasswordTextField,
|
||||
),
|
||||
@@ -65,6 +64,8 @@ class RestorePasswordForm extends StatelessWidget {
|
||||
type: AppText.password.toLowerCase(),
|
||||
textEditingController:
|
||||
restorePasswordBloc.repeatPasswordTextField,
|
||||
originalPasswordController:
|
||||
restorePasswordBloc.passwordTextField,
|
||||
),
|
||||
),
|
||||
const Gap(12),
|
||||
@@ -72,8 +73,7 @@ class RestorePasswordForm extends StatelessWidget {
|
||||
alignment: Alignment.topRight,
|
||||
child: ButtonWidget().textBtn(
|
||||
function: () {
|
||||
goRouter.pushNamed(
|
||||
RouteName.forgotPasswordPhoneVerificationScreen);
|
||||
forgotPasswordlogoutdialog(context);
|
||||
},
|
||||
text: TextWidget().text15W400(
|
||||
localizations.translate(AppText.forgotPassword),
|
||||
|
||||
34
lib/features/contactAdmin/bloc/contact_admin_bloc.dart
Normal file
34
lib/features/contactAdmin/bloc/contact_admin_bloc.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
// video_bloc.dart
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/bloc/contact_admin_event.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/bloc/contact_admin_state.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/domain/model/contact_admin_model.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/domain/repository/contact_admin_api.dart';
|
||||
|
||||
import '../../../Api_Helper/base_manager.dart';
|
||||
import '../../../Globalconst.dart';
|
||||
|
||||
class ContactAdminBloc extends Bloc<ContactAdminEvent, ContactAdminState> {
|
||||
ContactAdminBloc() : super(ContactAdminInitial()) {
|
||||
on<ContactAdminEvent>(mapEventToState);
|
||||
}
|
||||
|
||||
Future<void> mapEventToState(
|
||||
ContactAdminEvent event, Emitter<ContactAdminState> emit) async {
|
||||
emit(ContactAdminLoading());
|
||||
try {
|
||||
ResponseData response = await ContactAdminApi().contactAdminApi();
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
ContactAdminModel contactAdminModel =
|
||||
ContactAdminModel.fromJson(response.data);
|
||||
emit(ContactAdminLoaded(contactAdminModel));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(ContactAdminError(Globalconst.languageSelected == "en"
|
||||
? 'Oops Something went wrong'
|
||||
: "تبا شيء ما حدث بشكل خاطئ"));
|
||||
}
|
||||
}
|
||||
}
|
||||
16
lib/features/contactAdmin/bloc/contact_admin_event.dart
Normal file
16
lib/features/contactAdmin/bloc/contact_admin_event.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
// video_event.dart
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class ContactAdminEvent extends Equatable {
|
||||
const ContactAdminEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class FetchContactData extends ContactAdminEvent {
|
||||
const FetchContactData();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
32
lib/features/contactAdmin/bloc/contact_admin_state.dart
Normal file
32
lib/features/contactAdmin/bloc/contact_admin_state.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
// video_state.dart
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/domain/model/contact_admin_model.dart';
|
||||
|
||||
abstract class ContactAdminState extends Equatable {
|
||||
const ContactAdminState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ContactAdminInitial extends ContactAdminState {}
|
||||
|
||||
class ContactAdminLoading extends ContactAdminState {}
|
||||
|
||||
class ContactAdminLoaded extends ContactAdminState {
|
||||
final ContactAdminModel contactAdminModel;
|
||||
|
||||
const ContactAdminLoaded(this.contactAdminModel);
|
||||
|
||||
@override
|
||||
List<Object> get props => [contactAdminModel];
|
||||
}
|
||||
|
||||
class ContactAdminError extends ContactAdminState {
|
||||
final String message;
|
||||
|
||||
const ContactAdminError(this.message);
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
class ContactAdminModel {
|
||||
int? statusCode;
|
||||
List<Data>? data;
|
||||
String? message;
|
||||
bool? success;
|
||||
|
||||
ContactAdminModel({this.statusCode, this.data, this.message, this.success});
|
||||
|
||||
ContactAdminModel.fromJson(Map<String, dynamic> json) {
|
||||
statusCode = json['statusCode'];
|
||||
if (json['data'] != null) {
|
||||
data = <Data>[];
|
||||
json['data'].forEach((v) {
|
||||
data!.add(Data.fromJson(v));
|
||||
});
|
||||
}
|
||||
message = json['message'];
|
||||
success = json['success'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['statusCode'] = statusCode;
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['message'] = message;
|
||||
data['success'] = success;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Data {
|
||||
int? id;
|
||||
String? phoneNumber;
|
||||
String? emailAddress;
|
||||
String? websiteUrl;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
Data(
|
||||
{this.id,
|
||||
this.phoneNumber,
|
||||
this.emailAddress,
|
||||
this.websiteUrl,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
phoneNumber = json['phoneNumber'];
|
||||
emailAddress = json['emailAddress'];
|
||||
websiteUrl = json['websiteUrl'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['phoneNumber'] = phoneNumber;
|
||||
data['emailAddress'] = emailAddress;
|
||||
data['websiteUrl'] = websiteUrl;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import '../../../../../Api_Helper/base_manager.dart';
|
||||
import '../../../../../shared/api/api_endpoints.dart';
|
||||
import '../../../../../shared/api/network_api_services.dart';
|
||||
|
||||
class ContactAdminApi {
|
||||
Future<ResponseData> contactAdminApi() async {
|
||||
String url = ApiEndpoints.contactAdminApi;
|
||||
final response = await NetworkApiService().get(url);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/bloc/contact_admin_event.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/presentation/widgets/bottom_section.dart';
|
||||
|
||||
import '../../../../core/styles/app_color.dart';
|
||||
import '../../../../core/styles/app_text.dart';
|
||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||
import '../../../../shared/components/appbar_widget.dart';
|
||||
import '../../bloc/contact_admin_bloc.dart';
|
||||
import '../../bloc/contact_admin_state.dart';
|
||||
import '../widgets/top_section.dart';
|
||||
|
||||
class ContactAdminScreen extends StatelessWidget {
|
||||
@@ -14,17 +18,30 @@ class ContactAdminScreen extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
var localizations = AppLocalizations.of(context);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
appBar: AppBarWidget(
|
||||
height: 75,
|
||||
titleTxt: localizations.translate(AppText.contactAdminText),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
topSection(context),
|
||||
bottomSection(context),
|
||||
],
|
||||
return BlocProvider(
|
||||
create: (context) => ContactAdminBloc()..add(const FetchContactData()),
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
appBar: AppBarWidget(
|
||||
height: 75,
|
||||
titleTxt: localizations.translate(AppText.contactAdminText),
|
||||
),
|
||||
body: BlocBuilder<ContactAdminBloc, ContactAdminState>(
|
||||
builder: (context, state) {
|
||||
if (state is ContactAdminLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is ContactAdminLoaded) {
|
||||
return ListView(
|
||||
children: [
|
||||
topSection(context),
|
||||
bottomSection(context, state.contactAdminModel),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return const Center(child: Text('Something went wrong!'));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ 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/core/utils/url_launcher/url_launcher.dart';
|
||||
import 'package:tanami_app/features/contactAdmin/domain/model/contact_admin_model.dart';
|
||||
|
||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||
import '../../../../shared/components/text_widget.dart';
|
||||
|
||||
Widget bottomSection(BuildContext context) {
|
||||
Widget bottomSection(
|
||||
BuildContext context, ContactAdminModel contactAdminModel) {
|
||||
var localizations = AppLocalizations.of(context);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(22.0),
|
||||
@@ -19,18 +21,27 @@ Widget bottomSection(BuildContext context) {
|
||||
contactOption(
|
||||
icon: AppImages.byPhoneIcon,
|
||||
title: localizations.translate(AppText.byPhoneText),
|
||||
subtitle: '+973 12345678',
|
||||
subtitle: contactAdminModel.data![0].phoneNumber!,
|
||||
onTap: () {
|
||||
launchPhone('+973 12345678');
|
||||
launchPhone(contactAdminModel.data![0].phoneNumber!);
|
||||
},
|
||||
),
|
||||
const Gap(16.0),
|
||||
contactOption(
|
||||
icon: AppImages.byMailIcon,
|
||||
title: localizations.translate(AppText.byEmailText),
|
||||
subtitle: 'info@tanamicapital.com',
|
||||
subtitle: contactAdminModel.data![0].emailAddress!,
|
||||
onTap: () {
|
||||
launchEmail('info@tanamicapital.com');
|
||||
launchEmail(contactAdminModel.data![0].emailAddress!);
|
||||
},
|
||||
),
|
||||
const Gap(16.0),
|
||||
contactOption(
|
||||
icon: AppImages.languageIcon,
|
||||
title: localizations.translate(AppText.websiteText),
|
||||
subtitle: contactAdminModel.data![0].websiteUrl!,
|
||||
onTap: () {
|
||||
launchWebsiteUrl("https://tanamicapital.com/");
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,58 +1,79 @@
|
||||
class GetCountryModel {
|
||||
int? statusCode;
|
||||
List<Data>? data;
|
||||
String? message;
|
||||
bool? success;
|
||||
|
||||
GetCountryModel({this.data});
|
||||
GetCountryModel({this.statusCode, this.data, this.message, this.success});
|
||||
|
||||
GetCountryModel.fromJson(Map<String, dynamic> json) {
|
||||
statusCode = json['statusCode'];
|
||||
if (json['data'] != null) {
|
||||
data = <Data>[];
|
||||
json['data'].forEach((v) {
|
||||
data!.add(Data.fromJson(v));
|
||||
});
|
||||
}
|
||||
message = json['message'];
|
||||
success = json['success'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['statusCode'] = statusCode;
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['message'] = message;
|
||||
data['success'] = success;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Data {
|
||||
String? id;
|
||||
int? id;
|
||||
String? countryName;
|
||||
String? countryCode;
|
||||
String? isdCode;
|
||||
String? iSDcode;
|
||||
String? flagIcon;
|
||||
Null currencyXid;
|
||||
int? maxDigits;
|
||||
int? currencyXid;
|
||||
bool? isActive;
|
||||
Null createdBy;
|
||||
Null modifiedBy;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
Null deletedAt;
|
||||
|
||||
Data(
|
||||
{this.id,
|
||||
this.countryName,
|
||||
this.countryCode,
|
||||
this.isdCode,
|
||||
this.iSDcode,
|
||||
this.flagIcon,
|
||||
this.maxDigits,
|
||||
this.currencyXid,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.modifiedBy});
|
||||
this.modifiedBy,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
countryName = json['countryName'];
|
||||
countryCode = json['countryCode'];
|
||||
isdCode = json['isdCode'];
|
||||
iSDcode = json['ISDcode'];
|
||||
flagIcon = json['flagIcon'];
|
||||
maxDigits = json['maxDigits'];
|
||||
currencyXid = json['currency_xid'];
|
||||
isActive = json['isActive'];
|
||||
createdBy = json['createdBy'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
createdAt = json['createdAt'];
|
||||
updatedAt = json['updatedAt'];
|
||||
deletedAt = json['deletedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@@ -60,12 +81,16 @@ class Data {
|
||||
data['id'] = id;
|
||||
data['countryName'] = countryName;
|
||||
data['countryCode'] = countryCode;
|
||||
data['isdCode'] = isdCode;
|
||||
data['ISDcode'] = iSDcode;
|
||||
data['flagIcon'] = flagIcon;
|
||||
data['maxDigits'] = maxDigits;
|
||||
data['currency_xid'] = currencyXid;
|
||||
data['isActive'] = isActive;
|
||||
data['createdBy'] = createdBy;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['createdAt'] = createdAt;
|
||||
data['updatedAt'] = updatedAt;
|
||||
data['deletedAt'] = deletedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,123 @@ class FAQScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _AccountappState extends State<FAQScreen> {
|
||||
int selectedTile = 0;
|
||||
int gettingStartedselectedTile = 0;
|
||||
int investmentSelectedTile = 0;
|
||||
int knowledgeSelectedTile = 0;
|
||||
int complianceSelectedTile = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var localizations = AppLocalizations.of(context);
|
||||
|
||||
List<Map<String, String>> gettingStartedList = [
|
||||
{
|
||||
"title": localizations.translate(AppText.getStartedTitle1),
|
||||
"answer": localizations.translate(AppText.geStartedDesc1),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.getStartedTitle2),
|
||||
"answer": localizations.translate(AppText.geStartedDesc2),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.getStartedTitle3),
|
||||
"answer": localizations.translate(AppText.geStartedDesc3),
|
||||
}
|
||||
];
|
||||
|
||||
List<Map<String, String>> investmentList = [
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle1),
|
||||
"answer": localizations.translate(AppText.investmentDesc1),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle2),
|
||||
"answer": localizations.translate(AppText.investmentDesc2),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle3),
|
||||
"answer": localizations.translate(AppText.investmentDesc3),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle4),
|
||||
"answer": localizations.translate(AppText.investmentDesc4),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle5),
|
||||
"answer": localizations.translate(AppText.investmentDesc5),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle6),
|
||||
"answer": localizations.translate(AppText.investmentDesc6),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle7),
|
||||
"answer": localizations.translate(AppText.investmentDesc7),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle8),
|
||||
"answer": localizations.translate(AppText.investmentDesc8),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle9),
|
||||
"answer": localizations.translate(AppText.investmentDesc9),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle10),
|
||||
"answer": localizations.translate(AppText.investmentDesc10),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle11),
|
||||
"answer": localizations.translate(AppText.investmentDesc11),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle12),
|
||||
"answer": localizations.translate(AppText.investmentDesc12),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.investmentTitle13),
|
||||
"answer": localizations.translate(AppText.investmentDesc13),
|
||||
}
|
||||
];
|
||||
|
||||
List<Map<String, String>> knowledgeAndEducationList = [
|
||||
{
|
||||
"title": localizations.translate(AppText.knowledgeTitle1),
|
||||
"answer": localizations.translate(AppText.knowledgeDesc1),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.knowledgeTitle2),
|
||||
"answer": localizations.translate(AppText.knowledgeDesc2),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.knowledgeTitle3),
|
||||
"answer": localizations.translate(AppText.knowledgeDesc3),
|
||||
}
|
||||
];
|
||||
|
||||
List<Map<String, String>> complianceSecurityAndSupportList = [
|
||||
{
|
||||
"title": localizations.translate(AppText.securityTitle1),
|
||||
"answer": localizations.translate(AppText.securityDesc1),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.securityTitle2),
|
||||
"answer": localizations.translate(AppText.securityDesc2),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.securityTitle3),
|
||||
"answer": localizations.translate(AppText.securityDesc3),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.securityTitle4),
|
||||
"answer": localizations.translate(AppText.securityDesc4),
|
||||
},
|
||||
{
|
||||
"title": localizations.translate(AppText.securityTitle5),
|
||||
"answer": localizations.translate(AppText.securityDesc5),
|
||||
}
|
||||
];
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
appBar: AppBarWidget(
|
||||
@@ -37,7 +149,7 @@ class _AccountappState extends State<FAQScreen> {
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16.w, top: 23.h),
|
||||
child: Text(
|
||||
localizations.translate(AppText.faqTitle),
|
||||
localizations.translate(AppText.gettingStarted),
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 18.sp,
|
||||
color: AppColor.charcoalColor,
|
||||
@@ -47,17 +159,16 @@ class _AccountappState extends State<FAQScreen> {
|
||||
Gap(17.h),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: 50,
|
||||
bottom: 20,
|
||||
top: 15,
|
||||
),
|
||||
height: 1.sh,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||
child: ExpansionTileGroup(
|
||||
spaceBetweenItem: 23,
|
||||
toggleType: ToggleType.expandOnlyCurrent,
|
||||
children: List.generate(
|
||||
faList.length,
|
||||
gettingStartedList.length,
|
||||
(index) => ExpansionTileItem(
|
||||
isHasBottomBorder: true,
|
||||
isHasLeftBorder: true,
|
||||
@@ -77,21 +188,21 @@ class _AccountappState extends State<FAQScreen> {
|
||||
onExpansionChanged: (bool expanding) {
|
||||
if (expanding) {
|
||||
setState(() {
|
||||
selectedTile = index;
|
||||
gettingStartedselectedTile = index;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
selectedTile = -1;
|
||||
gettingStartedselectedTile = -1;
|
||||
});
|
||||
}
|
||||
},
|
||||
backgroundColor: AppColor.portfolioCardBgColor,
|
||||
childrenPadding: EdgeInsets.only(
|
||||
left: 0.w, right: 0.w, bottom: 8.h, top: 10.h),
|
||||
initiallyExpanded: index == selectedTile,
|
||||
initiallyExpanded: index == gettingStartedselectedTile,
|
||||
isHasTrailing: false,
|
||||
title: Text(
|
||||
faList[index]['title']!,
|
||||
gettingStartedList[index]['title']!,
|
||||
maxLines: 3,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
@@ -111,7 +222,278 @@ class _AccountappState extends State<FAQScreen> {
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 12.w, vertical: 10.h),
|
||||
child: Text(
|
||||
faList[index]['answer']!,
|
||||
gettingStartedList[index]['answer']!,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
color: AppColor.investPaymentTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16.w, top: 23.h),
|
||||
child: Text(
|
||||
localizations.translate(AppText.investment),
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 18.sp,
|
||||
color: AppColor.charcoalColor,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Gap(17.h),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: 20,
|
||||
top: 15,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||
child: ExpansionTileGroup(
|
||||
spaceBetweenItem: 23,
|
||||
toggleType: ToggleType.expandOnlyCurrent,
|
||||
children: List.generate(
|
||||
investmentList.length,
|
||||
(index) => ExpansionTileItem(
|
||||
isHasBottomBorder: true,
|
||||
isHasLeftBorder: true,
|
||||
isHasRightBorder: true,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColor.plainBlack.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
isHasTopBorder: true,
|
||||
collapsedBackgroundColor: AppColor.portfolioCardBgColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
onExpansionChanged: (bool expanding) {
|
||||
if (expanding) {
|
||||
setState(() {
|
||||
investmentSelectedTile = index;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
investmentSelectedTile = -1;
|
||||
});
|
||||
}
|
||||
},
|
||||
backgroundColor: AppColor.portfolioCardBgColor,
|
||||
childrenPadding: EdgeInsets.only(
|
||||
left: 0.w, right: 0.w, bottom: 8.h, top: 10.h),
|
||||
initiallyExpanded: index == investmentSelectedTile,
|
||||
isHasTrailing: false,
|
||||
title: Text(
|
||||
investmentList[index]['title']!,
|
||||
maxLines: 3,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
color: AppColor.otpTextColor,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
children: <Widget>[
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 5),
|
||||
width: 1.sw,
|
||||
// height: 109.h,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.plainWhite,
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 12.w, vertical: 10.h),
|
||||
child: Text(
|
||||
investmentList[index]['answer']!,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
color: AppColor.investPaymentTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16.w, top: 23.h),
|
||||
child: Text(
|
||||
localizations.translate(AppText.knowledgeAndEducation),
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 18.sp,
|
||||
color: AppColor.charcoalColor,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Gap(17.h),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: 20,
|
||||
top: 15,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||
child: ExpansionTileGroup(
|
||||
spaceBetweenItem: 23,
|
||||
toggleType: ToggleType.expandOnlyCurrent,
|
||||
children: List.generate(
|
||||
knowledgeAndEducationList.length,
|
||||
(index) => ExpansionTileItem(
|
||||
isHasBottomBorder: true,
|
||||
isHasLeftBorder: true,
|
||||
isHasRightBorder: true,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColor.plainBlack.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
isHasTopBorder: true,
|
||||
collapsedBackgroundColor: AppColor.portfolioCardBgColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
onExpansionChanged: (bool expanding) {
|
||||
if (expanding) {
|
||||
setState(() {
|
||||
knowledgeSelectedTile = index;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
knowledgeSelectedTile = -1;
|
||||
});
|
||||
}
|
||||
},
|
||||
backgroundColor: AppColor.portfolioCardBgColor,
|
||||
childrenPadding: EdgeInsets.only(
|
||||
left: 0.w, right: 0.w, bottom: 8.h, top: 10.h),
|
||||
initiallyExpanded: index == knowledgeSelectedTile,
|
||||
isHasTrailing: false,
|
||||
title: Text(
|
||||
knowledgeAndEducationList[index]['title']!,
|
||||
maxLines: 3,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
color: AppColor.otpTextColor,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
children: <Widget>[
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 5),
|
||||
width: 1.sw,
|
||||
// height: 109.h,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.plainWhite,
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 12.w, vertical: 10.h),
|
||||
child: Text(
|
||||
knowledgeAndEducationList[index]['answer']!,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
color: AppColor.investPaymentTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16.w, top: 23.h),
|
||||
child: Text(
|
||||
localizations.translate(AppText.complianceSecurityAndSupport),
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 18.sp,
|
||||
color: AppColor.charcoalColor,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Gap(17.h),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: 20,
|
||||
top: 15,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||
child: ExpansionTileGroup(
|
||||
spaceBetweenItem: 23,
|
||||
toggleType: ToggleType.expandOnlyCurrent,
|
||||
children: List.generate(
|
||||
complianceSecurityAndSupportList.length,
|
||||
(index) => ExpansionTileItem(
|
||||
isHasBottomBorder: true,
|
||||
isHasLeftBorder: true,
|
||||
isHasRightBorder: true,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColor.plainBlack.withOpacity(0.15),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 10,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
isHasTopBorder: true,
|
||||
collapsedBackgroundColor: AppColor.portfolioCardBgColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
onExpansionChanged: (bool expanding) {
|
||||
if (expanding) {
|
||||
setState(() {
|
||||
complianceSelectedTile = index;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
complianceSelectedTile = -1;
|
||||
});
|
||||
}
|
||||
},
|
||||
backgroundColor: AppColor.portfolioCardBgColor,
|
||||
childrenPadding: EdgeInsets.only(
|
||||
left: 0.w, right: 0.w, bottom: 8.h, top: 10.h),
|
||||
initiallyExpanded: index == complianceSelectedTile,
|
||||
isHasTrailing: false,
|
||||
title: Text(
|
||||
complianceSecurityAndSupportList[index]['title']!,
|
||||
maxLines: 3,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
color: AppColor.otpTextColor,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
children: <Widget>[
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 5),
|
||||
width: 1.sw,
|
||||
// height: 109.h,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.plainWhite,
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 12.w, vertical: 10.h),
|
||||
child: Text(
|
||||
complianceSecurityAndSupportList[index]
|
||||
['answer']!,
|
||||
style: GoogleFonts.dmSans(
|
||||
fontSize: 16.sp,
|
||||
color: AppColor.investPaymentTextColor,
|
||||
@@ -131,31 +513,3 @@ class _AccountappState extends State<FAQScreen> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, String>> faList = [
|
||||
{
|
||||
"title": "What is fractional property investment?",
|
||||
"answer":
|
||||
"Fractional property investment allows multiple investors to own a fraction of a property. This means you can invest in real estate without needing to purchase an entire property. Instead, you buy a share of the property, and your investment is proportionate to the amount you invest.",
|
||||
},
|
||||
{
|
||||
"title": "How does the app work?",
|
||||
"answer":
|
||||
"Our app simplifies the process of fractional property investment. Users can browse available properties, view detailed information and investment opportunities, and purchase shares in properties directly through the app. The app also provides tools to manage investments, track performance, and receive updates on property management."
|
||||
},
|
||||
{
|
||||
"title": "Is fractional property investment safe?",
|
||||
"answer":
|
||||
"While all investments carry risk, fractional property investment can be a safer option due to diversification. By investing in multiple properties, you can spread risk and reduce the impact of any single property’s performance on your overall investment."
|
||||
},
|
||||
{
|
||||
"title": "What kind of properties can I invest in?",
|
||||
"answer":
|
||||
"The app offers a variety of properties, including residential, commercial, and mixed-use properties. Each listing provides detailed information about the property, including location, projected returns, and investment terms."
|
||||
},
|
||||
{
|
||||
"title": "Is there a minimum investment amount?",
|
||||
"answer":
|
||||
"Yes, each property listing will specify the minimum investment amount required. This amount varies depending on the property and the terms of the investment."
|
||||
}
|
||||
];
|
||||
|
||||
@@ -31,8 +31,8 @@ class RestorePasswordBloc
|
||||
try {
|
||||
log(Globalconst.token);
|
||||
Map<String, dynamic> dataForm = {
|
||||
"token": Globalconst.token,
|
||||
"passwordHash": event.password
|
||||
"code": Globalconst.token,
|
||||
"password_hash": event.password
|
||||
};
|
||||
ResponseData response =
|
||||
await ForgotPasswordApi().resetPasswordApi(dataForm);
|
||||
|
||||
@@ -39,7 +39,7 @@ class RestorePasswordPhoneVerificationForm extends StatelessWidget {
|
||||
selectedCountry = state.selectedIndex;
|
||||
if (countryState is CountryLoaded) {
|
||||
restorePasswordBloc.isdcode =
|
||||
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||
"${countryState.countryModel.data![selectedCountry].iSDcode}";
|
||||
restorePasswordBloc.countrySelectionTextField.text = countryState
|
||||
.countryModel.data![selectedCountry].countryName
|
||||
.toString();
|
||||
@@ -53,7 +53,7 @@ class RestorePasswordPhoneVerificationForm extends StatelessWidget {
|
||||
restorePasswordBloc.isdcode, expectedLength!);
|
||||
}
|
||||
restorePasswordBloc.countryId =
|
||||
countryState.countryModel.data![selectedCountry].id!;
|
||||
countryState.countryModel.data![selectedCountry].id!.toString();
|
||||
flag =
|
||||
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import '../../../../../Api_Helper/base_manager.dart';
|
||||
import '../../../../../shared/api/api_endpoints.dart';
|
||||
import '../../../../../shared/api/network_api_services.dart';
|
||||
|
||||
class LanguageApi {
|
||||
Future<ResponseData> updateLanguage(Map<String, String> data) async {
|
||||
String url = ApiEndpoints.updateLanguageApi;
|
||||
final response = await NetworkApiService().post(url, data);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../../../Api_Helper/base_manager.dart';
|
||||
import '../../domain/repositories/language_api.dart';
|
||||
import 'choose_language_event.dart';
|
||||
import 'choose_language_state.dart';
|
||||
|
||||
@@ -15,6 +17,17 @@ class ChooseLanguageBloc
|
||||
emit(ChooseLanguageSelectionChanged(event.selectedIndex));
|
||||
}
|
||||
|
||||
Future<String> langaugeChangeApiCall(String languageCode) async {
|
||||
Map<String, String> languageData = {"languageCode": languageCode};
|
||||
|
||||
ResponseData response = await LanguageApi().updateLanguage(languageData);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
return "success";
|
||||
} else {
|
||||
return "failed";
|
||||
}
|
||||
}
|
||||
|
||||
void _onResetRadioSelection(
|
||||
ResetRadioSelection event, Emitter<ChooseLanguageState> emit) {
|
||||
emit(ChooseLanguageInitial());
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
@@ -32,18 +34,32 @@ Widget bottomSection(BuildContext context) {
|
||||
child: ButtonWidget().elevatedBtn(
|
||||
txtClr: AppColor.plainWhite,
|
||||
function: () async {
|
||||
var newLocale = radioBloc.selectedCountry == 1
|
||||
? const Locale('ar')
|
||||
: const Locale('en');
|
||||
context.read<LocalizationBloc>().add(ChangeLanguage(newLocale));
|
||||
if (radioBloc.selectedCountry == 1) {
|
||||
await secureStorageService.write('languageSelected', "ar");
|
||||
Globalconst.languageSelected = "ar";
|
||||
} else {
|
||||
await secureStorageService.write('languageSelected', "en");
|
||||
Globalconst.languageSelected = "en";
|
||||
}
|
||||
goRouter.pop();
|
||||
radioBloc
|
||||
.langaugeChangeApiCall(
|
||||
radioBloc.selectedCountry == 1 ? "AR" : "EN")
|
||||
.then(
|
||||
(value) async {
|
||||
if (value == "success") {
|
||||
var newLocale = radioBloc.selectedCountry == 1
|
||||
? const Locale('ar')
|
||||
: const Locale('en');
|
||||
context
|
||||
.read<LocalizationBloc>()
|
||||
.add(ChangeLanguage(newLocale));
|
||||
if (radioBloc.selectedCountry == 1) {
|
||||
await secureStorageService.write('languageSelected', "ar");
|
||||
Globalconst.languageSelected = "ar";
|
||||
} else {
|
||||
await secureStorageService.write('languageSelected', "en");
|
||||
Globalconst.languageSelected = "en";
|
||||
}
|
||||
goRouter.pop();
|
||||
} else {
|
||||
log(value.toString());
|
||||
//goRouter.pop();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
text: localizations.translate(AppText.submitText),
|
||||
clr: AppColor.primaryColor2,
|
||||
|
||||
@@ -37,27 +37,27 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
|
||||
emit(LoginLoading());
|
||||
try {
|
||||
Map<String, dynamic> logindata = {
|
||||
"countryId": event.countryId,
|
||||
"phoneNumber": event.phoneNumber,
|
||||
"passwordHash": event.password
|
||||
"ISDcode": event.isdCode,
|
||||
"mobileNumber": event.phoneNumber,
|
||||
"password": event.password
|
||||
};
|
||||
ResponseData response = await LoginAPI().LoginRequest(logindata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write(
|
||||
'first_name', response.data['data']['firstName']);
|
||||
Globalconst.firstName = response.data['data']['firstName'];
|
||||
Globalconst.lastName = response.data['data']['lastName'];
|
||||
await secureStorageService.write(
|
||||
'temp_token', response.data['data']['token']);
|
||||
|
||||
emit(LoginSuccess());
|
||||
} else if (response.status == ResponseStatus.PRIVATE) {
|
||||
if (response.message.toString() == "Master Pin is not created") {
|
||||
'temp_token', response.data['data']['code']);
|
||||
if (response.data["data"]["isMasterPin"] == false) {
|
||||
await secureStorageService.write(
|
||||
'temp_token', response.data['data']['user']);
|
||||
'temp_token', response.data['data']['code']);
|
||||
emit(LoginMasterPinPending());
|
||||
} else {
|
||||
emit(LoginFailure(response.message.toString()));
|
||||
emit(LoginSuccess());
|
||||
}
|
||||
} else if (response.status == ResponseStatus.PRIVATE) {
|
||||
emit(LoginFailure(response.message.toString()));
|
||||
} else {
|
||||
emit(LoginFailure(response.message.toString()));
|
||||
}
|
||||
|
||||
@@ -12,12 +12,13 @@ class LoginSubmitted extends LoginEvent {
|
||||
final String password;
|
||||
final String countryResidence;
|
||||
final String countryId;
|
||||
final String isdCode;
|
||||
|
||||
const LoginSubmitted(
|
||||
this.phoneNumber, this.password, this.countryResidence, this.countryId);
|
||||
const LoginSubmitted(this.phoneNumber, this.password, this.countryResidence,
|
||||
this.countryId, this.isdCode);
|
||||
|
||||
@override
|
||||
List<Object> get props => [phoneNumber, password, countryResidence];
|
||||
List<Object> get props => [phoneNumber, password, countryResidence, isdCode];
|
||||
}
|
||||
|
||||
class LoginFormChanged extends LoginEvent {
|
||||
|
||||
@@ -103,7 +103,8 @@ class BottomSection extends StatelessWidget {
|
||||
loginbloc.phoneNumberTextField.text,
|
||||
loginbloc.passwordTextField.text,
|
||||
"",
|
||||
loginbloc.countryId),
|
||||
loginbloc.countryId,
|
||||
loginbloc.isdcode),
|
||||
)
|
||||
: null;
|
||||
},
|
||||
|
||||
@@ -46,7 +46,7 @@ class LoginForm extends StatelessWidget {
|
||||
.toString();
|
||||
loginBloc.phoneNumberTextField.text = "";
|
||||
loginBloc.isdcode =
|
||||
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||
"${countryState.countryModel.data![selectedCountry].iSDcode}";
|
||||
if (PhoneNumberHintGenerator().countryPhoneLengths.containsKey(
|
||||
loginBloc.isdcode,
|
||||
)) {
|
||||
@@ -65,7 +65,7 @@ class LoginForm extends StatelessWidget {
|
||||
.countryModel.data![selectedCountry].countryName
|
||||
.toString();
|
||||
Globalconst.isdcode =
|
||||
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||
"${countryState.countryModel.data![selectedCountry].iSDcode}";
|
||||
}
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
|
||||
@@ -34,7 +34,7 @@ class OtpBloc extends Bloc<OtpEvent, OtpState> {
|
||||
emit(OtpSubmitting());
|
||||
try {
|
||||
Map<String, dynamic> otpdata = {
|
||||
"token": await secureStorageService.read("temp_token"),
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"otp": otpController.text
|
||||
};
|
||||
ResponseData response = await OTPAPI().verifyOTP(otpdata);
|
||||
|
||||
@@ -32,13 +32,13 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
|
||||
emit(RegisterLoading());
|
||||
try {
|
||||
Map<String, dynamic> requestdata = {
|
||||
"countryId": event.id,
|
||||
"phoneNumber": event.phoneNumber
|
||||
"ISDcode": event.isdcode,
|
||||
"mobileNumber": event.phoneNumber
|
||||
};
|
||||
ResponseData response = await OTPAPI().requestOTP(requestdata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
var data = response.data["data"];
|
||||
String token = data["token"];
|
||||
var data = response.data;
|
||||
String token = data["data"];
|
||||
await secureStorageService.write('temp_token', token);
|
||||
emit(RegisterSuccess(token)); //emit(OTPLoaded());
|
||||
} else {
|
||||
@@ -53,7 +53,7 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
|
||||
emit(RegisterLoading());
|
||||
try {
|
||||
Map<String, dynamic> requestdata = {
|
||||
"token": await secureStorageService.read('temp_token'),
|
||||
"code": await secureStorageService.read('temp_token'),
|
||||
};
|
||||
ResponseData response = await OTPAPI().resendOTPRequest(requestdata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
|
||||
@@ -36,11 +36,12 @@ class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
|
||||
emit(RegisterUserLoading());
|
||||
try {
|
||||
Map<String, dynamic> registerdata = {
|
||||
"token": event.token,
|
||||
"code": event.token,
|
||||
"firstName": event.firstName,
|
||||
"lastName": event.lastName,
|
||||
"emailAddress": event.email,
|
||||
"passwordHash": event.password
|
||||
"password": event.password,
|
||||
"confirmPassword": event.password,
|
||||
};
|
||||
ResponseData response =
|
||||
await RegisterAPIService().RegisterRequest(registerdata);
|
||||
|
||||
@@ -39,7 +39,7 @@ class RegisterForm extends StatelessWidget {
|
||||
.toString();
|
||||
registerBloc.phoneNumberTextField.text = "";
|
||||
registerBloc.isdcode =
|
||||
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||
"${countryState.countryModel.data![selectedCountry].iSDcode}";
|
||||
if (PhoneNumberHintGenerator().countryPhoneLengths.containsKey(
|
||||
registerBloc.isdcode,
|
||||
)) {
|
||||
@@ -58,7 +58,7 @@ class RegisterForm extends StatelessWidget {
|
||||
.countryModel.data![selectedCountry].countryName
|
||||
.toString();
|
||||
Globalconst.isdcode =
|
||||
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||
"${countryState.countryModel.data![selectedCountry].iSDcode}";
|
||||
}
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
|
||||
@@ -15,4 +15,10 @@ class PinAPIServices {
|
||||
final response = await NetworkApiService().post(url, data);
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<ResponseData> updatePin(Map<String, dynamic> data) async {
|
||||
String url = ApiEndpoints.updatePinApi;
|
||||
final response = await NetworkApiService().post(url, data);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
||||
|
||||
if (newPin.length <= 6) {
|
||||
if ((event.fromscreen == "login" ||
|
||||
event.fromscreen == "LoginedInUser") &&
|
||||
event.fromscreen == "LoginedInUser" ||
|
||||
event.fromscreen == "reset-pin") &&
|
||||
newPin.length < 6) {
|
||||
emit(state.copyWith(
|
||||
pin: newPin,
|
||||
@@ -35,7 +36,8 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
||||
));
|
||||
} else {
|
||||
if ((event.fromscreen != "login" &&
|
||||
event.fromscreen != "LoginedInUser")) {
|
||||
event.fromscreen != "LoginedInUser" &&
|
||||
event.fromscreen != "reset-pin")) {
|
||||
emit(state.copyWith(
|
||||
pin: newPin,
|
||||
pinComplete: newPin.length == 6,
|
||||
@@ -51,6 +53,8 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
||||
} else if (event.fromscreen == "login" ||
|
||||
event.fromscreen == "LoginedInUser") {
|
||||
add(VerifyLoginPinPressed(newPin, event.fromscreen));
|
||||
} else if (event.fromscreen == "reset-pin") {
|
||||
add(UpdateLoginPinPressed(newPin, event.fromscreen));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,12 +79,17 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
||||
emit(const PinLoading());
|
||||
final storedPin = await secureStorageService.read('pin_code');
|
||||
Map<String, dynamic> pindata = {
|
||||
"token": await secureStorageService.read("temp_token"),
|
||||
"masterPin": event.pin
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"masterPin": event.pin,
|
||||
"confirmMasterPin": event.pin,
|
||||
};
|
||||
if (storedPin == event.pin) {
|
||||
ResponseData response = await PinAPIServices().ConfirmPin(pindata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write(
|
||||
'accesstoken', response.data["data"]["access"]["token"]);
|
||||
await secureStorageService.write(
|
||||
'refreshtoken', response.data["data"]["refresh"]["token"]);
|
||||
await secureStorageService.write('userMPIN', storedPin.toString());
|
||||
}
|
||||
|
||||
@@ -101,19 +110,48 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
||||
}
|
||||
});
|
||||
|
||||
on<UpdateLoginPinPressed>((event, emit) async {
|
||||
emit(const PinLoading());
|
||||
Map<String, dynamic> pindata = {
|
||||
"masterPin": event.pin,
|
||||
"confirmMasterPin": event.pin
|
||||
};
|
||||
|
||||
ResponseData response = await PinAPIServices().updatePin(pindata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
emit(state.copyWith(
|
||||
pinComplete: true,
|
||||
pin: state.pin,
|
||||
isVerified: true,
|
||||
error: '',
|
||||
verifiedOnce: false));
|
||||
} else {
|
||||
goRouter.pop();
|
||||
emit(state.copyWith(
|
||||
pinComplete: true,
|
||||
pin: state.pin,
|
||||
isVerified: false,
|
||||
error: Globalconst.languageSelected == "en"
|
||||
? response.message
|
||||
: "رمز التعريف الشخصي غير صحيح",
|
||||
verifiedOnce: true,
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
on<VerifyLoginPinPressed>((event, emit) async {
|
||||
emit(const PinLoading());
|
||||
Map<String, dynamic> pindata = {
|
||||
"token": await secureStorageService.read("temp_token"),
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"masterPin": event.pin
|
||||
};
|
||||
|
||||
ResponseData response = await PinAPIServices().Verifypin(pindata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write(
|
||||
'accesstoken', response.data["user"]["accessToken"]);
|
||||
'accesstoken', response.data["data"]["access"]["token"]);
|
||||
await secureStorageService.write(
|
||||
'refreshtoken', response.data["user"]["refreshToken"]);
|
||||
'refreshtoken', response.data["data"]["refresh"]["token"]);
|
||||
emit(state.copyWith(
|
||||
pinComplete: true,
|
||||
pin: state.pin,
|
||||
|
||||
@@ -38,3 +38,12 @@ class VerifyLoginPinPressed extends PinEvent {
|
||||
@override
|
||||
List<Object> get props => [pin, fromscreen];
|
||||
}
|
||||
|
||||
class UpdateLoginPinPressed extends PinEvent {
|
||||
final String pin;
|
||||
final String fromscreen;
|
||||
const UpdateLoginPinPressed(this.pin, this.fromscreen);
|
||||
|
||||
@override
|
||||
List<Object> get props => [pin, fromscreen];
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ class PinKey extends StatelessWidget {
|
||||
successToastMessage(
|
||||
context, localizations.translate(AppText.pinUpdatedSucess));
|
||||
goRouter.pop();
|
||||
goRouter.pop();
|
||||
} else {
|
||||
goRouter.pop();
|
||||
context.read<PinBloc>().add(SavePinPressed());
|
||||
|
||||
@@ -19,6 +19,7 @@ class SplashScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SecureStorageService secureStorageService = SecureStorageService();
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
body: MultiBlocProvider(
|
||||
|
||||
@@ -1,31 +1,48 @@
|
||||
class ApiEndpoints {
|
||||
static const base = "https://tanami.betadelivery.com/";
|
||||
static const baseurl =
|
||||
"https://tanami.betadelivery.com/api/development/v1/"; //App Base url
|
||||
static const base =
|
||||
"https://admin.tanami.betadelivery.com/"; //"https://tanami.betadelivery.com/";
|
||||
static const baseurl = "https://admin.tanami.betadelivery.com/api/v1/";
|
||||
// "https://tanami.betadelivery.com/api/development/v1/"; //App Base url
|
||||
|
||||
//Country
|
||||
static const getcountryurl = "${baseurl}country/getAllCountry";
|
||||
static const getcountryurl = "${baseurl}country/";
|
||||
|
||||
//Register
|
||||
static const requestotpapi = "${baseurl}auth/public/register";
|
||||
static const registerrequestapi = "${baseurl}auth/public/email-register";
|
||||
static const requestotpapi = "${baseurl}auth/user/register-mobileNumber";
|
||||
static const registerrequestapi = "${baseurl}auth/user/registration";
|
||||
|
||||
//OTP
|
||||
static const requestresendotp = "${baseurl}auth/public/resend-otp";
|
||||
static const verifyotp = "${baseurl}auth/public/verify-otp";
|
||||
static const requestresendotp = "${baseurl}auth/user/resend-otp";
|
||||
static const verifyotp = "${baseurl}auth/user/verified-otp";
|
||||
|
||||
//Biometric
|
||||
static const biometricUpdateapi = "${baseurl}auth/public/biometric-update";
|
||||
static const biometricLoginapi = "${baseurl}auth/public/biometric-login";
|
||||
static const biometricUpdateapi = "${baseurl}auth/user/set-biometric";
|
||||
static const biometricLoginapi = "${baseurl}auth/user/login-biometric";
|
||||
|
||||
//PIN
|
||||
static const confirmpinapi = "${baseurl}auth/public/masterPin";
|
||||
static const verifypinapi = "${baseurl}auth/public/verify-materPin";
|
||||
static const confirmpinapi = "${baseurl}auth/user/set-masterPin";
|
||||
static const verifypinapi = "${baseurl}auth/user/login-masterPin";
|
||||
static const updatePinApi = "${baseurl}auth/user/update-pin";
|
||||
|
||||
//Login
|
||||
static const loginapi = "${baseurl}auth/public/login";
|
||||
static const loginapi = "${baseurl}auth/user/login-password";
|
||||
|
||||
//Forgot Password
|
||||
static const forgotPasswordApi = "${baseurl}auth/public/forgot-password";
|
||||
static const resetPasswordApi = "${baseurl}auth/public/reset-password";
|
||||
//Password
|
||||
static const forgotPasswordApi = "${baseurl}auth/user/forgot-password";
|
||||
static const resetPasswordApi = "${baseurl}auth/user/reset-password";
|
||||
static const updatePasswordApi = "${baseurl}auth/user/update-password";
|
||||
|
||||
//Notification
|
||||
static const updateNotificationApi =
|
||||
"${baseurl}auth/user/update-notification";
|
||||
|
||||
//Language
|
||||
static const updateLanguageApi = "${baseurl}auth/user/update-language";
|
||||
|
||||
//Contact Admin
|
||||
static const contactAdminApi = "${baseurl}contactDetails/user/";
|
||||
|
||||
//IO
|
||||
static const availableIOApi = "${baseurl}io/available";
|
||||
static const closedIOApi = "${baseurl}io/closed";
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
// common_api.dart
|
||||
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../Api_Helper/base_manager.dart';
|
||||
import '../../core/utils/secure/secure_storage_service.dart';
|
||||
|
||||
class NetworkApiService {
|
||||
final SecureStorageService secureStorageService = SecureStorageService();
|
||||
|
||||
final Dio _dio = Dio(BaseOptions(
|
||||
validateStatus: (status) {
|
||||
return status != null &&
|
||||
@@ -16,12 +21,18 @@ class NetworkApiService {
|
||||
// Common function for GET requests
|
||||
Future<ResponseData> get(String url,
|
||||
{Map<String, dynamic>? queryParameters}) async {
|
||||
String token = await secureStorageService.read("accesstoken") ?? "";
|
||||
if (kDebugMode) {
|
||||
print("api url is >>> $url");
|
||||
}
|
||||
Response response;
|
||||
try {
|
||||
response = await _dio.get(url);
|
||||
response = await _dio.get(url,
|
||||
options: (token == "")
|
||||
? Options()
|
||||
: Options(headers: {
|
||||
"x-auth-token": token,
|
||||
}));
|
||||
if (response.statusCode == 201 || response.statusCode == 200) {
|
||||
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
|
||||
data: response.data);
|
||||
@@ -52,41 +63,30 @@ class NetworkApiService {
|
||||
|
||||
// Common function for POST requests
|
||||
Future<ResponseData> post(String url, dynamic data) async {
|
||||
String token = await secureStorageService.read("accesstoken") ?? "";
|
||||
log(token);
|
||||
if (kDebugMode) {
|
||||
print("data >>> $data");
|
||||
print("api url is >>> $url");
|
||||
}
|
||||
try {
|
||||
var response = await _dio.post(
|
||||
url,
|
||||
data: data,
|
||||
);
|
||||
var response = await _dio.post(url,
|
||||
data: data,
|
||||
options: (token == "")
|
||||
? Options()
|
||||
: Options(headers: {
|
||||
"x-auth-token": token,
|
||||
}));
|
||||
if (response.statusCode == 201 || response.statusCode == 200) {
|
||||
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
|
||||
data: response.data);
|
||||
} else if (response.statusCode == 400) {
|
||||
if (response.data['message'] == "Master Pin is not created") {
|
||||
return ResponseData<dynamic>(
|
||||
response.data['message'], ResponseStatus.PRIVATE,
|
||||
data: response.data);
|
||||
} else if (response.data['error']['message'] ==
|
||||
"MASTER PIN NOT MATCH") {
|
||||
return ResponseData<dynamic>(
|
||||
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||
data: response.data);
|
||||
} else if (response.data['error']['message'] ==
|
||||
"Account already exists. Please Login instead.") {
|
||||
return ResponseData<dynamic>(
|
||||
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||
data: response.data);
|
||||
} else {
|
||||
return ResponseData<dynamic>(
|
||||
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||
data: response.data);
|
||||
}
|
||||
return ResponseData<dynamic>(
|
||||
response.data['message'], ResponseStatus.PRIVATE,
|
||||
data: response.data);
|
||||
} else if (response.statusCode == 401) {
|
||||
return ResponseData<dynamic>(
|
||||
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||
response.data['message'], ResponseStatus.PRIVATE,
|
||||
data: response.data);
|
||||
} else if (response.statusCode == 500) {
|
||||
return ResponseData<dynamic>(
|
||||
@@ -95,8 +95,7 @@ class NetworkApiService {
|
||||
} else {
|
||||
try {
|
||||
return ResponseData<dynamic>(
|
||||
response.data['error']['message'].toString(),
|
||||
ResponseStatus.FAILED);
|
||||
response.data['message'].toString(), ResponseStatus.FAILED);
|
||||
} catch (_) {
|
||||
return ResponseData<dynamic>(
|
||||
data: response.data,
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||
|
||||
import '../../../../Api_Helper/base_manager.dart';
|
||||
import '../../../../core/utils/device_info/device_info_data.dart';
|
||||
import '../../../../features/MainScreens/Settings/domain/repository/settings_api.dart';
|
||||
import '../../../../features/register/Repository/RegisterApi.dart';
|
||||
import 'toggle_event.dart';
|
||||
import 'toggle_state.dart';
|
||||
|
||||
@@ -16,11 +22,75 @@ class ToggleBloc extends Bloc<ToggleEvent, ToggleState> {
|
||||
|
||||
void _onToggleSwitch(ToggleSwitch event, Emitter<ToggleState> emit) async {
|
||||
if (state is ToggleOn) {
|
||||
emit(ToggleOff());
|
||||
await secureStorageService.write(type, 'off');
|
||||
if (type == "biometric") {
|
||||
emit(ToggleOff());
|
||||
|
||||
Map<String, dynamic> biometricdata = {
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"is_2FA_on": false,
|
||||
"deviceId": await DeviceInfoData().getDeviceId(),
|
||||
"biometric_type": Platform.isIOS ? "face" : "fingerprint"
|
||||
};
|
||||
|
||||
ResponseData response =
|
||||
await RegisterAPIService().BiometricUpdate(biometricdata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write(type, 'off');
|
||||
await secureStorageService.write("biometric", 'of');
|
||||
} else {
|
||||
emit(ToggleOn());
|
||||
await secureStorageService.write(type, 'on');
|
||||
}
|
||||
} else if (type == "notification") {
|
||||
emit(ToggleOff());
|
||||
|
||||
ResponseData response = await SettingsApi().updateNotification();
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write(type, 'off');
|
||||
await secureStorageService.write("notification", 'of');
|
||||
} else {
|
||||
emit(ToggleOn());
|
||||
await secureStorageService.write(type, 'on');
|
||||
}
|
||||
} else {
|
||||
emit(ToggleOff());
|
||||
await secureStorageService.write(type, 'off');
|
||||
}
|
||||
} else {
|
||||
emit(ToggleOn());
|
||||
await secureStorageService.write(type, 'on');
|
||||
if (type == "biometric") {
|
||||
emit(ToggleOn());
|
||||
|
||||
Map<String, dynamic> biometricdata = {
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"is_2FA_on": true,
|
||||
"deviceId": await DeviceInfoData().getDeviceId(),
|
||||
"biometric_type": Platform.isIOS ? "face" : "fingerprint"
|
||||
};
|
||||
|
||||
ResponseData response =
|
||||
await RegisterAPIService().BiometricUpdate(biometricdata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write("biometric", 'on');
|
||||
await secureStorageService.write(type, 'on');
|
||||
} else {
|
||||
emit(ToggleOff());
|
||||
await secureStorageService.write(type, 'off');
|
||||
}
|
||||
} else if (type == "notification") {
|
||||
emit(ToggleOn());
|
||||
|
||||
ResponseData response = await SettingsApi().updateNotification();
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
await secureStorageService.write(type, 'on');
|
||||
await secureStorageService.write("notification", 'on');
|
||||
} else {
|
||||
emit(ToggleOff());
|
||||
await secureStorageService.write(type, 'off');
|
||||
}
|
||||
} else {
|
||||
emit(ToggleOn());
|
||||
await secureStorageService.write(type, 'on');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
110
lib/shared/components/forgot_password_log_out_dialog.dart
Normal file
110
lib/shared/components/forgot_password_log_out_dialog.dart
Normal file
@@ -0,0 +1,110 @@
|
||||
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 '../../core/routes/route_name.dart';
|
||||
import '../../core/routes/routes.dart';
|
||||
import '../../core/styles/app_color.dart';
|
||||
import '../../core/styles/app_text.dart';
|
||||
import '../../core/utils/language/localizations_delegate.dart';
|
||||
import '../../core/utils/secure/secure_storage_service.dart';
|
||||
import 'bloc/bottom_nav_bar/bottom_navigation_bloc.dart';
|
||||
import 'bloc/bottom_nav_bar/bottom_navigation_event.dart';
|
||||
import 'text_widget.dart';
|
||||
|
||||
forgotPasswordlogoutdialog(context) {
|
||||
var localizations = AppLocalizations.of(context);
|
||||
SecureStorageService secureStorageService = SecureStorageService();
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) => Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
AlertDialog(
|
||||
insetPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
side: BorderSide(
|
||||
color: AppColor.plainWhite,
|
||||
),
|
||||
),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextWidget().text17W700(
|
||||
localizations.translate(AppText.notificationText),
|
||||
clr: AppColor.plainBlack),
|
||||
const Gap(25),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 25,
|
||||
),
|
||||
child: TextWidget().text15W500(
|
||||
localizations
|
||||
.translate(AppText.toRestorePasswordYouWillBeLoggedOut),
|
||||
clr: AppColor.hintTextColor,
|
||||
),
|
||||
),
|
||||
const Gap(30),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pop();
|
||||
},
|
||||
child: Container(
|
||||
height: 48.h,
|
||||
width: 140.w,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: AppColor.primaryColor2,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(10.h),
|
||||
color: AppColor.plainWhite),
|
||||
child: Center(
|
||||
child: TextWidget().text18W700(
|
||||
localizations.translate(AppText.declineText),
|
||||
clr: AppColor.primaryColor2,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Gap(28.w),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
context.read<BottomNavigationBloc>().add(TabChanged(2));
|
||||
await secureStorageService.write('isLoginedIn', "false");
|
||||
await secureStorageService.write('accesstoken', '');
|
||||
await secureStorageService.write('refreshtoken', '');
|
||||
await secureStorageService.write('temp_token', '');
|
||||
|
||||
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
|
||||
"fromScreen": "registerStep",
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
height: 48.h,
|
||||
width: 140.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10.h),
|
||||
color: AppColor.primaryColor),
|
||||
child: Center(
|
||||
child: TextWidget().text18W700(
|
||||
localizations.translate(AppText.allowText),
|
||||
clr: AppColor.plainWhite,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -91,6 +91,7 @@ buildprofilelogoutdialog(context) {
|
||||
await secureStorageService.write('isLoginedIn', "false");
|
||||
await secureStorageService.write('accesstoken', '');
|
||||
await secureStorageService.write('refreshtoken', '');
|
||||
await secureStorageService.write('temp_token', '');
|
||||
|
||||
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
|
||||
"fromScreen": "registerStep",
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
||||
import 'package:tanami_app/core/styles/app_color.dart';
|
||||
import 'package:tanami_app/core/utils/device_info/device_info_data.dart';
|
||||
import 'package:tanami_app/shared/components/loader.dart';
|
||||
|
||||
import '../../core/routes/route_name.dart';
|
||||
@@ -85,12 +88,30 @@ permissionDialog(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pop();
|
||||
onTap: () async {
|
||||
Loader.loader(context);
|
||||
Map<String, dynamic> biometricdata = {
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"is_2FA_on": false,
|
||||
"deviceId": await DeviceInfoData().getDeviceId(),
|
||||
"biometric_type":
|
||||
Platform.isIOS ? "face" : "fingerprint"
|
||||
};
|
||||
|
||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
||||
"fromScreen": "register",
|
||||
});
|
||||
ResponseData response = await RegisterAPIService()
|
||||
.BiometricUpdate(biometricdata);
|
||||
if (response.status == ResponseStatus.SUCCESS) {
|
||||
goRouter.pop();
|
||||
|
||||
await secureStorageService.write("biometric", 'of');
|
||||
|
||||
goRouter.pop();
|
||||
|
||||
goRouter
|
||||
.goNamed(RouteName.pinScreen, pathParameters: {
|
||||
"fromScreen": "register",
|
||||
});
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 48.h,
|
||||
@@ -112,9 +133,11 @@ permissionDialog(
|
||||
onTap: () async {
|
||||
Loader.loader(context);
|
||||
Map<String, dynamic> biometricdata = {
|
||||
"token":
|
||||
await secureStorageService.read("temp_token"),
|
||||
"is_2FA_on": true
|
||||
"code": await secureStorageService.read("temp_token"),
|
||||
"is_2FA_on": true,
|
||||
"deviceId": await DeviceInfoData().getDeviceId(),
|
||||
"biometric_type":
|
||||
Platform.isIOS ? "face" : "fingerprint"
|
||||
};
|
||||
|
||||
ResponseData response = await RegisterAPIService()
|
||||
@@ -125,7 +148,7 @@ permissionDialog(
|
||||
await secureStorageService.write("biometric", 'on');
|
||||
successToastMessage(context,
|
||||
"Biometric/Face Id Enabled Sucessfully !");
|
||||
// successToastMessage(context, "successful !");
|
||||
|
||||
goRouter.pop();
|
||||
|
||||
goRouter
|
||||
|
||||
52
lib/shared/components/read_pdf.dart
Normal file
52
lib/shared/components/read_pdf.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
|
||||
|
||||
import '../../core/routes/routes.dart';
|
||||
import '../../core/styles/app_color.dart';
|
||||
import 'text_widget.dart';
|
||||
|
||||
class ReadPDF extends StatelessWidget {
|
||||
const ReadPDF({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.pdfUrl,
|
||||
});
|
||||
final String title;
|
||||
final String pdfUrl;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
appBar: AppBar(
|
||||
scrolledUnderElevation: 0.0,
|
||||
backgroundColor: AppColor.plainWhite,
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
title: TextWidget().text20W700(title, clr: AppColor.charcoalColor),
|
||||
leading: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 16.w,
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
goRouter.pop();
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 8.w),
|
||||
child: Icon(
|
||||
Icons.arrow_back_rounded,
|
||||
color: AppColor.appBarIconColor,
|
||||
size: 25.r,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: SfPdfViewer.network(
|
||||
pdfUrl,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
89
lib/shared/components/viemo_screen.dart
Normal file
89
lib/shared/components/viemo_screen.dart
Normal file
@@ -0,0 +1,89 @@
|
||||
import 'package:chewie/chewie.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tanami_app/core/routes/routes.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class VimeoScreen extends StatefulWidget {
|
||||
final String videoUrl;
|
||||
const VimeoScreen({
|
||||
super.key,
|
||||
required this.videoUrl,
|
||||
});
|
||||
|
||||
@override
|
||||
State<VimeoScreen> createState() => _VimeoScreenState();
|
||||
}
|
||||
|
||||
class _VimeoScreenState extends State<VimeoScreen> {
|
||||
late VideoPlayerController videoPlayerController;
|
||||
late ChewieController chewieController;
|
||||
var videoUrl1 =
|
||||
"https://player.vimeo.com/progressive_redirect/playback/848263896/rendition/1080p/file.mp4?loc=external&signature=440740807e0632840f08b973014d831dbb8d17516532a30d24bf10b44b9282cd";
|
||||
@override
|
||||
void initState() {
|
||||
_initializePlayer();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
_initializePlayer() async {
|
||||
try {
|
||||
videoPlayerController = VideoPlayerController.networkUrl(
|
||||
Uri.parse(videoUrl1),
|
||||
);
|
||||
|
||||
await videoPlayerController.initialize();
|
||||
initChewie();
|
||||
setState(() {});
|
||||
} catch (e) {
|
||||
print("Error initializing video player: $e");
|
||||
}
|
||||
}
|
||||
|
||||
initChewie() {
|
||||
chewieController = ChewieController(
|
||||
videoPlayerController: videoPlayerController,
|
||||
autoPlay: true,
|
||||
looping: false);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
videoPlayerController.dispose();
|
||||
chewieController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return videoPlayerController.value.isInitialized
|
||||
? Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
leading: InkWell(
|
||||
onTap: () => goRouter.pop(),
|
||||
child: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
// CommonAppbar(titleTxt: ""),
|
||||
body: Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: videoPlayerController.value.aspectRatio,
|
||||
child: Chewie(
|
||||
controller: chewieController,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: const Center(
|
||||
child:
|
||||
//ShimmerCommon(),
|
||||
CircularProgressIndicator(
|
||||
color: Color(0xFF0093FF),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user