You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
car_provider_app/lib/views/dashboard/widget/general_appointment_widget....

462 lines
20 KiB
Dart

import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:easy_localization/easy_localization.dart';
class GeneralAppointmentWidget extends StatelessWidget {
final AppointmentListModel appointmentListModel;
final bool isNeedTotalPayment;
final bool isNeedToShowItems;
final bool isNeedToShowToMoreText;
final bool isSelectable;
final bool isFromUpdateAppointmentPage;
final bool isNeedToShowAppointmentStatus;
final bool isNeedToShowMergeStatus;
final Function()? onTap;
const GeneralAppointmentWidget({
required this.appointmentListModel,
required this.onTap,
this.isNeedTotalPayment = false,
this.isNeedToShowItems = false,
this.isNeedToShowToMoreText = true,
this.isSelectable = false,
this.isNeedToShowAppointmentStatus = false,
this.isFromUpdateAppointmentPage = false,
this.isNeedToShowMergeStatus = false,
super.key,
});
List<Widget> buildServicesFromAppointment({required AppointmentListModel appointmentListModel}) {
if (appointmentListModel.appointmentServicesList == null || appointmentListModel.appointmentServicesList!.isEmpty) {
return [const SizedBox()];
}
if (appointmentListModel.appointmentServicesList!.length == 1) {
List<Widget> itemsList = [];
if (isNeedToShowItems) {
itemsList = List.generate(
appointmentListModel.appointmentServicesList?.first.serviceItems?.length ?? 0,
(mIndex) => showItems((appointmentListModel.appointmentServicesList?.first.serviceItems?[mIndex].name ?? "").toString(), MyAssets.modificationsIcon),
);
}
return [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
showServices(
"${appointmentListModel.appointmentServicesList!.first.providerServiceName} ${appointmentListModel.appointmentServicesList!.first.serviceId != 0 ? '- ${appointmentListModel.appointmentServicesList!.first.serviceId}' : ""}",
MyAssets.modificationsIcon,
),
if (isNeedToShowItems) ...itemsList,
],
)
];
}
List<Widget> servicesList = List.generate(
isNeedToShowToMoreText ? 2 : appointmentListModel.appointmentServicesList?.length ?? 0,
(index) {
List<Widget> itemsList = [];
if (isNeedToShowItems) {
itemsList = List.generate(
appointmentListModel.appointmentServicesList?[index].serviceItems?.length ?? 0,
(mIndex) => showItems((appointmentListModel.appointmentServicesList?[index].serviceItems?[mIndex].name ?? "").toString(), MyAssets.modificationsIcon),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
showServices(
"${appointmentListModel.appointmentServicesList![index].providerServiceName} ${appointmentListModel.appointmentServicesList![index].serviceId != 0 ? '- ${appointmentListModel.appointmentServicesList![index].serviceId}' : ""}",
MyAssets.modificationsIcon,
),
if (isNeedToShowItems) ...itemsList,
],
).paddingOnly(bottom: 6);
},
);
if (isNeedToShowToMoreText && appointmentListModel.appointmentServicesList!.length > 2) {
servicesList.add(
showServices(
"+ ${appointmentListModel.appointmentServicesList!.length - 2} More",
"",
isMoreText: true,
),
);
}
return servicesList;
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (isSelectable)
SizedBox(
child: const SizedBox(
width: 14,
height: 14,
).toContainer(
borderRadius: 24,
marginAll: 4,
paddingAll: 0,
backgroundColor: (appointmentListModel.isSelected ?? false) ? MyColors.primaryColor : MyColors.greyButtonColor,
),
).toContainer(
borderRadius: 24,
isEnabledBorder: true,
paddingAll: 0,
borderWidget: 3,
borderColor: MyColors.primaryColor,
),
if (isSelectable) 12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (isNeedToShowMergeStatus)
LocaleKeys.merged.tr().toText(color: MyColors.white).toContainer(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
borderRadius: 12,
backgroundColor: MyColors.greenColor,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(appointmentListModel.branchName ?? "").toText(
fontSize: 12,
color: MyColors.darkTextColor,
isBold: true,
),
(appointmentListModel.customerName ?? "").toText(color: MyColors.black, isBold: true, fontSize: 16),
Row(
children: [
"${LocaleKeys.phone.tr()}:".toText(
color: MyColors.lightTextColor,
),
2.width,
Expanded(
child: appointmentListModel.customerMobileNum.toString().toText(
fontSize: 12,
),
),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${LocaleKeys.time.tr()}:".toText(
color: MyColors.lightTextColor,
),
4.width,
Expanded(child: (appointmentListModel.duration ?? "").toText(fontSize: 8))
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${LocaleKeys.date.tr()}:".toText(
color: MyColors.lightTextColor,
),
4.width,
// Expanded(child: appointmentListModel.appointmentDate!.toFormattedDateWithoutTime().toText(fontSize: 8))
Expanded(
child: appointmentListModel.appointmentDate!
.toLocalizedFormattedDateWithoutTime(context)
.toText(fontSize: 8),
)
],
),
Row(
children: [
"${LocaleKeys.delivery.tr()}: ".toText(color: MyColors.lightTextColor),
2.width,
Expanded(
child: (appointmentListModel.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()).toText(
fontSize: 12,
),
),
],
),
Row(
children: [
"${LocaleKeys.createdOn.tr()}: ".toText(color: MyColors.lightTextColor),
2.width,
// Expanded(child: appointmentListModel.appointmentCreatedOn!.toFormattedDateWithoutTime().toText(fontSize: 8))
Expanded(
child: appointmentListModel.appointmentCreatedOn!
.toLocalizedFormattedDateWithoutTime(context)
.toText(fontSize: 8),
)
],
),
if (isFromUpdateAppointmentPage) ...[
if (appointmentListModel.appointmentAddress != null && appointmentListModel.appointmentAddress!.isNotEmpty) ...[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${LocaleKeys.address.tr()}: ".toText(color: MyColors.lightTextColor),
2.width,
Expanded(child: (appointmentListModel.appointmentAddress ?? "").toText(fontSize: 8))
],
),
],
Row(
children: [
"${LocaleKeys.paymentType.tr()}: ".toText(color: MyColors.lightTextColor),
2.width,
Expanded(child: (appointmentListModel.paymentType ?? "").toText(fontSize: 8)),
],
),
LocaleKeys.openMapLocation
.tr()
.toText(
isUnderLine: true,
color: MyColors.darkPrimaryColor,
fontSize: 10,
)
.onPress(() async {
double latitude, longitude = 0.0;
latitude = double.parse(appointmentListModel.appointmentLatitude!);
longitude = double.parse(appointmentListModel.appointmentLongitude!);
await Utils.openLocationInMaps(latitude: latitude, longitude: longitude);
}),
]
],
),
),
if (!isNeedTotalPayment)
if (appointmentListModel.customerAppointmentList != null && appointmentListModel.customerAppointmentList!.length > 1)
"${appointmentListModel.customerAppointmentList!.length - 1}+ appts".toText(fontSize: 8).toContainer(
borderRadius: 15,
backgroundColor: MyColors.lightGreyEAColor,
padding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 8,
),
),
if (isNeedToShowAppointmentStatus)
(appointmentListModel.appointmentStatusEnum!.getAppointmentNameFromEnum()).toText(color: MyColors.white).toContainer(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
borderRadius: 12,
backgroundColor: MyColors.primaryColor,
),
],
),
],
),
),
],
),
8.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...buildServicesFromAppointment(appointmentListModel: appointmentListModel),
if (isNeedTotalPayment)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
18.height,
LocaleKeys.totalAmount.tr().toText(
fontSize: 12,
color: MyColors.lightTextColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
appointmentListModel.totalAmount.toString().toText(fontSize: 16, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor),
],
),
2.height,
LocaleKeys.remainingAmount.tr().toText(
fontSize: 12,
color: MyColors.lightTextColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
appointmentListModel.remainingAmount.toString().toText(fontSize: 16, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor),
],
),
],
)
],
),
),
if (!isNeedToShowItems) const Icon(Icons.arrow_forward),
],
),
],
).toWhiteContainer(width: double.infinity, allPading: 12, onTap: onTap);
}
double calculateTotalPrice() {
double totalServiceListPrice = 0;
for (var servicesElement in appointmentListModel.appointmentServicesList!) {
for (var itemsElement in servicesElement.serviceItems!) {
totalServiceListPrice += double.parse(itemsElement.price ?? "0");
}
}
return totalServiceListPrice;
}
Widget showServices(String title, String icon, {bool isMoreText = false}) {
return Row(
children: [
if (icon != "") ...[
SvgPicture.asset(icon),
8.width,
],
Flexible(
child: title.toText(
fontSize: 12,
isBold: true,
color: isMoreText ? MyColors.primaryColor : MyColors.black,
),
),
],
);
}
Widget showItems(String title, String icon) {
return Row(
children: [
SvgPicture.asset(
icon,
color: Colors.transparent,
),
8.width,
Flexible(
child: title.toText(
fontSize: 10,
color: MyColors.lightTextColor,
),
),
],
);
}
}
// https://ms.hmg.com/api/ServiceProviders/ServiceProviderBranchDetail_Get?ID=1061&ServiceCategoryIDs=4
// {ID: 1061, ServiceCategoryIDs: [4]}
// {
// "messageStatus": 1,
// "totalItemsCount": 1,
// "data": [
// {
// "id": 1061,
// "serviceProviderID": 14,
// "serviceProviderName": "James Bond",
// "branchName": "Sawaidi Branch",
// "branchDescription": "This is Swaidi Branch",
// "cityID": 1,
// "cityName": "Riyadh",
// "address": "Riyadh, KSA",
// "latitude": "37.541014800226456",
// "longitude": "-122.36278831958771",
// "distanceKM": 12811.22,
// "openTime": "12:00",
// "closeTime": "22:45",
// "branchStatus": 3,
// "branchStatusText": "ApprovedOrActive",
// "branchRateAvg": 0.0,
// "serviceProviderServices": [
// {
// "serviceProviderServiceID": 1212,
// "providerServiceDescription": null,
// "categoryID": 4,
// "categoryName": "Care and Protection",
// "serviceID": 16,
// "serviceDescription": "film body protection",
// "serviceDescriptionN": "فلم حماية الدهان",
// "serviceStatus": 1,
// "statusText": null,
// "isAllowAppointment": true,
// "isAllowAppointmentHome": true,
// "customerLocationRange": 10,
// "rangePricePerKm": 15.0,
// "itemsCount": 1
// }
// ],
// "serviceProviderBranchImage": [
// {
// "id": 136,
// "imageName": "image_picker_929CDE1A-800C-4EFE-AC48-7060BB338D77-69034-00003ADB833C597D.jpg",
// "imageUrl": "https://ms.hmg.com/api/serviceProviders/ServiceProviderBranchImage?imageName=61aa8beb-99b0-4876-b47a-08dce8674a2c_50243415.png&sp=Provider_14&serviceProviderBranch=ServiceProviderBranch_1061",
// "imageStr": null,
// "serviceProviderBranchID": 1061,
// "serviceProviderBranch": null,
// "isActive": true,
// "createdBy": 101,
// "createdOn": "2024-12-16T14:47:48.6633333",
// "modifiedBy": null,
// "modifiedOn": null
// },
// {
// "id": 137,
// "imageName": "image_picker_EBF6BA32-3E4E-4AAE-BC2C-1B136A1C32B3-69034-00003ADB7C82E00F.jpg",
// "imageUrl": "https://ms.hmg.com/api/serviceProviders/ServiceProviderBranchImage?imageName=61aa8beb-99b0-4876-b47a-08dce8674a2c_51856527.png&sp=Provider_14&serviceProviderBranch=ServiceProviderBranch_1061",
// "imageStr": null,
// "serviceProviderBranchID": 1061,
// "serviceProviderBranch": null,
// "isActive": true,
// "createdBy": 101,
// "createdOn": "2024-12-16T14:47:48.6866667",
// "modifiedBy": null,
// "modifiedOn": null
// },
// {
// "id": 138,
// "imageName": "image_picker_168879D6-4707-4D0E-ACDA-0C956BD2AC4A-69034-00003AE6922D39CF.jpg",
// "imageUrl": "https://ms.hmg.com/api/serviceProviders/ServiceProviderBranchImage?imageName=61aa8beb-99b0-4876-b47a-08dce8674a2c_61115226.png&sp=Provider_14&serviceProviderBranch=ServiceProviderBranch_1061",
// "imageStr": null,
// "serviceProviderBranchID": 1061,
// "serviceProviderBranch": null,
// "isActive": true,
// "createdBy": 101,
// "createdOn": "2024-12-16T14:47:48.7066667",
// "modifiedBy": null,
// "modifiedOn": null
// }
// ]
// }
// ],
// "message": "Success"
// }