Initial commit

This commit is contained in:
2025-12-08 23:25:00 +05:00
commit ee5cb4ac1a
851 changed files with 115172 additions and 0 deletions

View File

@@ -0,0 +1,390 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:dotted_border/dotted_border.dart';
import 'package:driver/constant/constant.dart';
import 'package:driver/constant/show_toast_dialog.dart';
import 'package:driver/controllers/verification_details_upload_controller.dart';
import 'package:driver/themes/app_them_data.dart';
import 'package:driver/themes/responsive.dart';
import 'package:driver/themes/round_button_fill.dart';
import 'package:driver/themes/theme_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
class VerificationDetailsUploadScreen extends StatelessWidget {
const VerificationDetailsUploadScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDark.value;
return GetX<DetailsUploadController>(
init: DetailsUploadController(),
builder: (controller) {
return Scaffold(
appBar: AppBar(
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
centerTitle: false,
automaticallyImplyLeading: false,
titleSpacing: 0,
leading: InkWell(
onTap: () {
Get.back();
},
child: Icon(
Icons.chevron_left_outlined,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
),
),
title: Text(
"${controller.documentModel.value.title}",
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.bold, fontSize: 18),
),
elevation: 0,
),
body: controller.isLoading.value
? Constant.loader()
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${'Upload'.tr} ${controller.documentModel.value.title} ${'for Verification'.tr}",
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.bold, fontSize: 22),
),
const SizedBox(
height: 5,
),
Text(
"${'Please upload a valid'.tr} ${controller.documentModel.value.title} ${'to verify your identity complete the registration process.'.tr}".tr,
style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
),
const SizedBox(
height: 20,
),
Visibility(
visible: controller.documentModel.value.frontSide == true ? true : false,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${'Front Side of'} ${controller.documentModel.value.title.toString()}",
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.bold, fontSize: 16),
),
const SizedBox(
height: 10,
),
controller.frontImage.value.isNotEmpty
? InkWell(
onTap: () {
if (controller.documents.value.status != "uploaded" || controller.documents.value.status == "rejected") {
buildBottomSheet(context, controller, "front");
}
},
child: SizedBox(
height: Responsive.height(20, context),
width: Responsive.width(90, context),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(10)),
child: Constant().hasValidUrl(controller.frontImage.value) == false
? Image.file(
File(controller.frontImage.value),
height: Responsive.height(20, context),
width: Responsive.width(80, context),
fit: BoxFit.fill,
)
: CachedNetworkImage(
imageUrl: controller.frontImage.value.toString(),
fit: BoxFit.fill,
height: Responsive.height(20, context),
width: Responsive.width(80, context),
placeholder: (context, url) => Constant.loader(),
errorWidget: (context, url, error) => Image.network(
'https://firebasestorage.googleapis.com/v0/b/goride-1a752.appspot.com/o/placeholderImages%2Fuser-placeholder.jpeg?alt=media&token=34a73d67-ba1d-4fe4-a29f-271d3e3ca115'),
),
),
),
)
: DottedBorder(
options: RoundedRectDottedBorderOptions(
radius: const Radius.circular(12),
dashPattern: const [6, 6, 6, 6],
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
),
child: Container(
decoration: BoxDecoration(
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
borderRadius: const BorderRadius.all(
Radius.circular(12),
),
),
child: SizedBox(
height: Responsive.height(22, context),
width: Responsive.width(90, context),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
'assets/icons/ic_folder.svg',
),
const SizedBox(
height: 10,
),
Text(
"Choose a image and upload here".tr,
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.medium,
fontSize: 16),
),
const SizedBox(
height: 5,
),
Text(
"JPEG, PNG".tr,
style: TextStyle(
fontSize: 12, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
),
const SizedBox(
height: 10,
),
RoundedButtonFill(
title: "Brows Image".tr,
color: AppThemeData.carRent50,
textColor: AppThemeData.primary300,
width: 30,
height: 5,
onPress: () async {
buildBottomSheet(context, controller, "front");
},
),
],
)),
),
),
],
),
),
),
Visibility(
visible: controller.documentModel.value.backSide == true ? true : false,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${'Back side of'.tr} ${controller.documentModel.value.title.toString()}",
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.bold, fontSize: 16),
),
const SizedBox(
height: 10,
),
controller.backImage.value.isNotEmpty
? InkWell(
onTap: () {
if (controller.documents.value.status != "uploaded" || controller.documents.value.status == "rejected") {
buildBottomSheet(context, controller, "back");
}
},
child: SizedBox(
height: Responsive.height(20, context),
width: Responsive.width(90, context),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(10)),
child: Constant().hasValidUrl(controller.backImage.value) == false
? Image.file(
File(controller.backImage.value),
height: Responsive.height(20, context),
width: Responsive.width(80, context),
fit: BoxFit.fill,
)
: CachedNetworkImage(
imageUrl: controller.backImage.value.toString(),
fit: BoxFit.fill,
height: Responsive.height(20, context),
width: Responsive.width(80, context),
placeholder: (context, url) => Constant.loader(),
errorWidget: (context, url, error) => Image.network(
'https://firebasestorage.googleapis.com/v0/b/goride-1a752.appspot.com/o/placeholderImages%2Fuser-placeholder.jpeg?alt=media&token=34a73d67-ba1d-4fe4-a29f-271d3e3ca115'),
),
),
),
)
: DottedBorder(
options: RoundedRectDottedBorderOptions(
radius: const Radius.circular(12),
dashPattern: const [6, 6, 6, 6],
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
),
child: Container(
decoration: BoxDecoration(
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
borderRadius: const BorderRadius.all(
Radius.circular(12),
),
),
child: SizedBox(
height: Responsive.height(22, context),
width: Responsive.width(90, context),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
'assets/icons/ic_folder.svg',
),
const SizedBox(
height: 10,
),
Text(
"Choose a image and upload here".tr,
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.medium,
fontSize: 16),
),
const SizedBox(
height: 5,
),
Text(
"JPEG, PNG".tr,
style: TextStyle(
fontSize: 12, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
),
const SizedBox(
height: 10,
),
RoundedButtonFill(
title: "Brows Image".tr,
color: AppThemeData.carRent50,
textColor: AppThemeData.primary300,
width: 30,
height: 5,
onPress: () async {
buildBottomSheet(context, controller, "back");
},
),
],
)),
),
),
],
),
),
),
const SizedBox(
height: 30,
),
],
),
),
),
bottomNavigationBar: controller.documents.value.status == "approved" || controller.documents.value.status == "uploaded"
? const SizedBox()
: InkWell(
onTap: () {
if (controller.documentModel.value.frontSide == true && controller.frontImage.value.isEmpty) {
ShowToastDialog.showToast("Please upload front side of document.".tr);
} else if (controller.documentModel.value.backSide == true && controller.backImage.value.isEmpty) {
ShowToastDialog.showToast("Please upload back side of document.".tr);
} else {
ShowToastDialog.showLoader("Please wait.".tr);
controller.uploadDocument();
}
},
child: Container(
color: AppThemeData.primary300,
width: Responsive.width(100, context),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Text(
"Upload Document".tr,
textAlign: TextAlign.center,
style: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
fontSize: 16,
fontFamily: AppThemeData.medium,
fontWeight: FontWeight.w400,
),
),
),
),
),
);
});
}
Future buildBottomSheet(BuildContext context, DetailsUploadController controller, String type) {
return showModalBottomSheet(
context: context,
builder: (context) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDark.value;
return StatefulBuilder(builder: (context, setState) {
return SizedBox(
height: Responsive.height(22, context),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 15),
child: Text(
"Please Select".tr,
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.bold, fontSize: 16),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
onPressed: () => controller.pickFile(source: ImageSource.camera, type: type),
icon: const Icon(
Icons.camera_alt,
size: 32,
)),
Padding(
padding: const EdgeInsets.only(top: 3),
child: Text("Camera".tr),
),
],
),
),
Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
onPressed: () => controller.pickFile(source: ImageSource.gallery, type: type),
icon: const Icon(
Icons.photo_library_sharp,
size: 32,
)),
Padding(
padding: const EdgeInsets.only(top: 3),
child: Text("Gallery".tr),
),
],
),
)
],
),
],
),
);
});
});
}
}

View File

@@ -0,0 +1,152 @@
import 'package:driver/constant/constant.dart';
import 'package:driver/controllers/verification_controller.dart';
import 'package:driver/models/document_model.dart';
import 'package:driver/models/driver_document_model.dart';
import 'package:driver/themes/app_them_data.dart';
import 'package:driver/themes/theme_controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'verification_details_upload_screen.dart';
class VerificationScreen extends StatelessWidget {
const VerificationScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
return Obx((){
final isDark = themeController.isDark.value;
return GetBuilder<VerificationController>(
init: VerificationController(),
builder: (controller) {
return Scaffold(
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: controller.isLoading.value
? Constant.loader()
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Document Verification".tr,
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.bold, fontSize: 22),
),
const SizedBox(
height: 5,
),
Text(
"Upload your ID Proof to complete the verification process and ensure compliance.".tr,
style: TextStyle(fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
),
const SizedBox(
height: 40,
),
Container(
decoration: ShapeDecoration(
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
child: ListView.separated(
itemCount: controller.documentList.length,
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
DocumentModel documentModel = controller.documentList[index];
Documents documents = Documents();
var contain = controller.driverDocumentList.where((element) => element.documentId == documentModel.id);
if (contain.isNotEmpty) {
documents = controller.driverDocumentList.firstWhere((itemToCheck) => itemToCheck.documentId == documentModel.id);
}
return InkWell(
onTap: () {
Get.to(const VerificationDetailsUploadScreen(), arguments: {'documentModel': documentModel})!.then(
(value) {
if (value == true) {
controller.getDocument();
}
},
);
},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${documentModel.title}",
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.bold,
fontSize: 16,
),
),
const SizedBox(
height: 5,
),
Text(
"${documentModel.frontSide == true ? "Front" : ""} ${documentModel.backSide == true ? "And Back" : ""} ${'Photo'.tr}",
style: TextStyle(
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
fontFamily: AppThemeData.regular,
),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
child: Text(
documents.status == "approved"
? "Verified".tr
: documents.status == "rejected"
? "Rejected".tr
: documents.status == "uploaded"
? "Uploaded".tr
: "Pending".tr,
style: TextStyle(
color: documents.status == "approved"
? Colors.green
: documents.status == "rejected"
? Colors.red
: documents.status == "uploaded"
? AppThemeData.primary300
: Colors.orange,
fontFamily: AppThemeData.medium,
fontSize: 16),
),
),
const Icon(
Icons.arrow_forward_ios_rounded,
size: 20,
)
],
),
);
},
separatorBuilder: (BuildContext context, int index) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 10),
child: Divider(),
);
},
),
),
),
],
),
),
);
});
});
}
}