Merge pull request 'haroon_dev' (#107) from haroon_dev into master
Reviewed-on: https://34.17.182.140/Haroon6138/HMG_Patient_App_New/pulls/107pull/110/head
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 222 B |
|
After Width: | Height: | Size: 412 B |
@ -0,0 +1,22 @@
|
||||
export const icons = {
|
||||
chatSend: require('./chat-send.png'),
|
||||
defaultAvatar: require('./default-avatar.png'),
|
||||
locked: require('./locked.png'),
|
||||
more: require('./more.png'),
|
||||
mute: require('./mute.png'),
|
||||
muted: require('./muted.png'),
|
||||
shareOn: require('./share-on.png'),
|
||||
shareOff: require('./share-off.png'),
|
||||
speakerOn: require('./speaker-on.png'),
|
||||
speakerOff: require('./speaker-off.png'),
|
||||
switchCamera: require('./switch-camera.png'),
|
||||
hamburger: require('./hamburger.png'),
|
||||
questionBalloon: require('./question-ballon.png'),
|
||||
talking: require('./talking.png'),
|
||||
unmute: require('./unmute.png'),
|
||||
unlocked: require('./unlocked.png'),
|
||||
videoOn: require('./video-on.png'),
|
||||
videoOff: require('./video-off.png'),
|
||||
};
|
||||
|
||||
export type IconTypes = keyof typeof icons;
|
||||
|
After Width: | Height: | Size: 376 B |
|
After Width: | Height: | Size: 567 B |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 877 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 634 B |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 27 KiB |
@ -0,0 +1,4 @@
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="48" height="48" rx="10" fill="#FEE9EA"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.9293 15.7788C22.9291 15.779 22.9294 15.7785 22.9293 15.7788L21.1713 19.3237C20.9847 19.7062 20.6726 20.0338 20.3511 20.2741C20.029 20.5149 19.6281 20.7199 19.2149 20.7907L19.2123 20.7911L16.023 21.3254C15.1361 21.4744 14.8447 21.8265 14.7764 22.0421C14.7072 22.2607 14.7447 22.7225 15.3814 23.3644L17.8611 25.8646C18.1828 26.189 18.3978 26.6224 18.5163 27.0398C18.6349 27.4576 18.6791 27.9375 18.5806 28.3802L18.5795 28.3851L17.8696 31.4802C17.6047 32.6346 17.8722 33.0603 18.0105 33.162C18.1449 33.2609 18.6222 33.3909 19.6332 32.786L22.6284 30.9983C23.0448 30.754 23.5438 30.6532 24.0016 30.6532C24.4586 30.6532 24.9578 30.7537 25.3721 31.0012C25.372 31.0011 25.3722 31.0012 25.3721 31.0012L28.3612 32.7852C28.361 32.7852 28.3613 32.7853 28.3612 32.7852C29.3805 33.3922 29.8572 33.2626 29.9892 33.1656C30.1243 33.0662 30.3919 32.6431 30.1259 31.4796L29.415 28.3802C29.3166 27.9375 29.3608 27.4576 29.4794 27.0398C29.5979 26.6224 29.8128 26.189 30.1346 25.8646L32.6143 23.3644L32.6161 23.3625C33.2569 22.7208 33.2925 22.2603 33.2234 22.0435C33.1545 21.8272 32.8603 21.4745 31.9726 21.3254L28.7834 20.7911C28.366 20.721 27.9619 20.5167 27.6372 20.2751C27.3136 20.0343 27.0011 19.7064 26.8143 19.3237L25.055 15.776C24.6328 14.92 24.2045 14.75 23.9966 14.75C23.7873 14.75 23.3564 14.9223 22.9293 15.7788ZM26.4 15.1119C25.8724 14.0425 25.0459 13.25 23.9966 13.25C22.9485 13.25 22.1194 14.0411 21.5868 15.1096L21.5861 15.111L19.8263 18.6597L19.8236 18.6652C19.7701 18.7754 19.6431 18.9305 19.453 19.0727C19.2632 19.2146 19.0797 19.2917 18.9628 19.312C18.9625 19.3121 18.9621 19.3121 18.9618 19.3122L15.7748 19.8461C14.6219 20.0398 13.6581 20.6052 13.3464 21.5893C13.0357 22.5704 13.4931 23.5906 14.3163 24.4206L16.7961 26.9209C16.8943 27.0199 17.0043 27.2064 17.0733 27.4494C17.1418 27.6908 17.1479 27.9107 17.1168 28.0527C17.1167 28.0534 17.1165 28.0541 17.1164 28.0547L16.4076 31.1447C16.4076 31.1448 16.4076 31.1447 16.4076 31.1447C16.1126 32.43 16.215 33.7032 17.1216 34.3702C18.032 35.04 19.2745 34.7487 20.4034 34.0732L23.3874 32.2921C23.3881 32.2917 23.3887 32.2914 23.3893 32.291C23.5231 32.2132 23.7432 32.1532 24.0016 32.1532C24.2618 32.1532 24.4775 32.214 24.603 32.289L27.593 34.0736C28.7232 34.7467 29.9672 35.0433 30.8776 34.3742C31.7848 33.7073 31.8822 32.4317 31.5882 31.1454L30.8793 28.0547C30.8791 28.0541 30.879 28.0534 30.8788 28.0527C30.8478 27.9107 30.8539 27.6908 30.9224 27.4494C30.9914 27.2064 31.1014 27.0199 31.1996 26.9209L33.6775 24.4225C33.6778 24.4222 33.6781 24.4219 33.6783 24.4216C34.5068 23.5916 34.9658 22.5705 34.6526 21.5879C34.339 20.6045 33.3734 20.0397 32.2212 19.8461L29.0316 19.3118C28.909 19.2912 28.7228 19.2131 28.5326 19.0716C28.3421 18.93 28.2155 18.7751 28.1621 18.6652L26.4 15.1119C26.4001 15.1121 26.4 15.1118 26.4 15.1119Z" fill="#ED1C2B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,7 @@
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="48" height="48" rx="10" fill="#FEE9EA"/>
|
||||
<path d="M17.3238 34.75C16.8934 34.75 16.453 34.71 16.0226 34.6301C15.7623 34.5801 15.5421 34.4002 15.452 34.1503C15.362 33.9004 15.412 33.6205 15.5722 33.4206C16.0426 32.8409 16.3629 32.1512 16.503 31.4016C16.5431 31.1717 16.4229 30.8918 16.1827 30.6419C14.291 28.7228 13.25 26.204 13.25 23.5652C13.25 17.8779 18.0745 13.25 24.01 13.25C24.7307 13.25 25.4514 13.32 26.152 13.4499C26.5624 13.5299 26.8226 13.9197 26.7426 14.3295C26.6625 14.7393 26.2721 14.9992 25.8617 14.9192C25.2512 14.7993 24.6306 14.7393 24 14.7393C18.8952 14.7393 14.7414 18.6975 14.7414 23.5552C14.7414 25.8042 15.6322 27.9432 17.2437 29.5824C17.8443 30.1821 18.1045 30.9518 17.9644 31.6714C17.8643 32.2212 17.6841 32.7409 17.4439 33.2307C18.3347 33.2107 19.2155 32.9808 20.0163 32.561L20.0959 32.5198C20.583 32.2673 20.8312 32.1387 21.0973 32.0912C21.3876 32.0513 21.6678 32.1012 22.1983 32.2012C22.7889 32.3111 23.3994 32.3411 23.99 32.3611C29.0947 32.3611 33.2486 28.413 33.2486 23.5452C33.2486 23.1354 33.5889 22.7956 33.9993 22.7956C34.4097 22.7956 34.75 23.1354 34.75 23.5452C34.75 29.2326 29.9255 33.8604 23.99 33.8604C23.3294 33.8604 22.5987 33.8005 21.9181 33.6705C21.8571 33.6592 21.7957 33.6475 21.7364 33.6361C21.5326 33.597 21.354 33.5628 21.3075 33.5706C21.2667 33.5909 21.0067 33.7208 20.737 33.8704C19.666 34.4401 18.4849 34.73 17.3038 34.73L17.3238 34.75Z" fill="#ED1C2B"/>
|
||||
<path d="M24.02 25.0052C23.4695 25.0052 23.0191 24.5552 23.0191 24.0052C23.0191 23.4552 23.4595 23.0052 24.02 23.0052C24.5706 23.0052 25.021 23.4552 25.021 24.0052C25.021 24.5552 24.5706 25.0052 24.02 25.0052Z" fill="#ED1C2B"/>
|
||||
<path d="M20.0263 25.0052C19.4758 25.0052 19.0254 24.5552 19.0254 24.0052C19.0254 23.4552 19.4658 23.0052 20.0263 23.0052C20.5768 23.0052 21.0273 23.4552 21.0273 24.0052C21.0273 24.5552 20.5768 25.0052 20.0263 25.0052Z" fill="#ED1C2B"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.6415 22.4355C25.8818 22.6654 26.1921 22.7954 26.5224 22.7954L26.5124 22.7853C26.6024 22.7853 26.6925 22.7754 26.7826 22.7554L29.0147 22.2756C29.5552 22.1756 30.0557 21.9158 30.456 21.5159L34.0794 17.8277C34.5098 17.4079 34.74 16.8381 34.74 16.2384C34.74 15.6387 34.5098 15.069 34.0794 14.6492L33.3888 13.9595C32.538 13.1099 31.0566 13.1099 30.2058 13.9595L26.5324 17.6277C26.142 18.0176 25.8818 18.5173 25.7817 19.0471L25.3012 21.286C25.2111 21.7058 25.3413 22.1356 25.6415 22.4355ZM31.2768 15.019C31.4169 14.879 31.6071 14.7991 31.8073 14.7991V14.809C32.0075 14.809 32.1976 14.889 32.3378 15.0289L33.0284 15.7186C33.1686 15.8586 33.2486 16.0485 33.2486 16.2484C33.2486 16.4483 33.1786 16.6282 33.0284 16.7781L29.405 20.4664C29.2249 20.6463 28.9947 20.7663 28.7244 20.8163L26.8527 21.2261L27.253 19.3469C27.3031 19.0971 27.4232 18.8672 27.6034 18.6872L31.2768 15.019Z" fill="#ED1C2B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31">
|
||||
<g id="Group_8325" data-name="Group 8325" transform="translate(-75 -236)">
|
||||
<circle id="Ellipse_223" data-name="Ellipse 223" cx="15.5" cy="15.5" r="15.5" transform="translate(75 236)" fill="#359846"/>
|
||||
<path id="hour-glass" d="M8.73,10.811a1.46,1.46,0,0,0,0-2.122L8.647,8.61C7.085,7.119,5.878,5.968,5.515,3.556A1.413,1.413,0,0,1,6.992,2h7.091A1.413,1.413,0,0,1,15.56,3.556C15.2,5.968,13.99,7.119,12.429,8.61l-.083.079a1.46,1.46,0,0,0,0,2.122l.083.079c1.562,1.491,2.768,2.642,3.132,5.054A1.413,1.413,0,0,1,14.083,17.5H6.992a1.413,1.413,0,0,1-1.477-1.556c.364-2.412,1.57-3.563,3.132-5.054Zm.529,1.316-.006,0c-1.19,1.064-2.076,1.856-2.191,3.816a.363.363,0,0,0,.13.3.382.382,0,0,0,.247.09h6.194a.382.382,0,0,0,.282-.122.361.361,0,0,0,.1-.268c-.115-1.959-1-2.752-2.191-3.816-.315-.281-.651-.582-1-.928a.4.4,0,0,0-.569,0c-.347.344-.681.643-.993.923Z" transform="translate(80.35 241.75)" fill="#fff" fill-rule="evenodd"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1021 B |
@ -0,0 +1,38 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/zoom_config.dart';
|
||||
|
||||
String makeId(int length) {
|
||||
String result = "";
|
||||
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
int charactersLength = characters.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += characters[Random().nextInt(charactersLength)];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String generateJwt(String sessionName, String roleType) {
|
||||
try {
|
||||
var iat = DateTime.now();
|
||||
var exp = DateTime.now().add(Duration(days: 2));
|
||||
final jwt = JWT(
|
||||
{
|
||||
'app_key': configs["ZOOM_SDK_KEY"],
|
||||
'version': 1,
|
||||
'user_identity': makeId(10),
|
||||
'iat': (iat.millisecondsSinceEpoch / 1000).round(),
|
||||
'exp': (exp.millisecondsSinceEpoch / 1000).round(),
|
||||
'tpc': sessionName,
|
||||
'role_type': int.parse(roleType),
|
||||
'cloud_recording_option': 1,
|
||||
},
|
||||
);
|
||||
var token = jwt.sign(SecretKey(configs["ZOOM_SDK_SECRET"]));
|
||||
return token;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
const Map configs = {
|
||||
'ZOOM_SDK_KEY': 'b9T74nhfTg-ioP9urm970A',
|
||||
'ZOOM_SDK_SECRET': 'KOzmjBNXQ1f4IPHpnngfL29uZvJMufSy2Fk8',
|
||||
};
|
||||
@ -0,0 +1,318 @@
|
||||
class PrescriptionDeliveryResponseModel {
|
||||
int? iD;
|
||||
int? patientId;
|
||||
int? patientOutSa;
|
||||
bool? isOutPatient;
|
||||
int? projectId;
|
||||
int? nearestProjectId;
|
||||
dynamic longitude;
|
||||
dynamic latitude;
|
||||
dynamic appointmentNo;
|
||||
dynamic dischargeId;
|
||||
int? statusId;
|
||||
int? serviceId;
|
||||
int? channel;
|
||||
Orderpayment? orderpayment;
|
||||
dynamic orderselectedservice;
|
||||
dynamic wforder;
|
||||
dynamic orderapprovalobj;
|
||||
String? created;
|
||||
dynamic createdBy;
|
||||
dynamic modified;
|
||||
dynamic modifiedBy;
|
||||
bool? isDeleted;
|
||||
String? statusText;
|
||||
int? paymentStatus;
|
||||
dynamic clientRequestid;
|
||||
dynamic paymentStatusText;
|
||||
String? projectName;
|
||||
String? nearestProjectName;
|
||||
dynamic paymentAmount;
|
||||
WFOrder? wFOrder;
|
||||
String? serviceText;
|
||||
bool? isSentForApproval;
|
||||
int? exaCartOrderId;
|
||||
bool? isTimer;
|
||||
int? timeSeconds;
|
||||
int? totalPendingSeconds;
|
||||
int? timeMinute;
|
||||
int? timeHour;
|
||||
int? timeTotalSeconds;
|
||||
int? timeTotalMinute;
|
||||
int? timeTotalHour;
|
||||
dynamic approvalStatus;
|
||||
bool? isActive;
|
||||
int? clickButton;
|
||||
List<dynamic>? procedures;
|
||||
dynamic pickupLocation;
|
||||
dynamic dropOffLocation;
|
||||
dynamic clinicName;
|
||||
dynamic doctorName;
|
||||
dynamic branch;
|
||||
dynamic time;
|
||||
dynamic notes;
|
||||
|
||||
PrescriptionDeliveryResponseModel(
|
||||
{this.iD,
|
||||
this.patientId,
|
||||
this.patientOutSa,
|
||||
this.isOutPatient,
|
||||
this.projectId,
|
||||
this.nearestProjectId,
|
||||
this.longitude,
|
||||
this.latitude,
|
||||
this.appointmentNo,
|
||||
this.dischargeId,
|
||||
this.statusId,
|
||||
this.serviceId,
|
||||
this.channel,
|
||||
this.orderpayment,
|
||||
this.orderselectedservice,
|
||||
this.wforder,
|
||||
this.orderapprovalobj,
|
||||
this.created,
|
||||
this.createdBy,
|
||||
this.modified,
|
||||
this.modifiedBy,
|
||||
this.isDeleted,
|
||||
this.statusText,
|
||||
this.paymentStatus,
|
||||
this.clientRequestid,
|
||||
this.paymentStatusText,
|
||||
this.projectName,
|
||||
this.nearestProjectName,
|
||||
this.paymentAmount,
|
||||
this.wFOrder,
|
||||
this.serviceText,
|
||||
this.isSentForApproval,
|
||||
this.exaCartOrderId,
|
||||
this.isTimer,
|
||||
this.timeSeconds,
|
||||
this.totalPendingSeconds,
|
||||
this.timeMinute,
|
||||
this.timeHour,
|
||||
this.timeTotalSeconds,
|
||||
this.timeTotalMinute,
|
||||
this.timeTotalHour,
|
||||
this.approvalStatus,
|
||||
this.isActive,
|
||||
this.clickButton,
|
||||
this.procedures,
|
||||
this.pickupLocation,
|
||||
this.dropOffLocation,
|
||||
this.clinicName,
|
||||
this.doctorName,
|
||||
this.branch,
|
||||
this.time,
|
||||
this.notes});
|
||||
|
||||
PrescriptionDeliveryResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
iD = json['ID'];
|
||||
patientId = json['PatientId'];
|
||||
patientOutSa = json['PatientOutSa'];
|
||||
isOutPatient = json['IsOutPatient'];
|
||||
projectId = json['ProjectId'];
|
||||
nearestProjectId = json['NearestProjectId'];
|
||||
longitude = json['Longitude'];
|
||||
latitude = json['Latitude'];
|
||||
appointmentNo = json['AppointmentNo'];
|
||||
dischargeId = json['DischargeId'];
|
||||
statusId = json['StatusId'];
|
||||
serviceId = json['ServiceId'];
|
||||
channel = json['Channel'];
|
||||
orderpayment = json['orderpayment'] != null ? new Orderpayment.fromJson(json['orderpayment']) : null;
|
||||
orderselectedservice = json['orderselectedservice'];
|
||||
wforder = json['wforder'];
|
||||
orderapprovalobj = json['orderapprovalobj'];
|
||||
created = json['Created'];
|
||||
createdBy = json['CreatedBy'];
|
||||
modified = json['Modified'];
|
||||
modifiedBy = json['ModifiedBy'];
|
||||
isDeleted = json['IsDeleted'];
|
||||
statusText = json['StatusText'];
|
||||
paymentStatus = json['PaymentStatus'];
|
||||
clientRequestid = json['ClientRequestid'];
|
||||
paymentStatusText = json['PaymentStatusText'];
|
||||
projectName = json['ProjectName'];
|
||||
nearestProjectName = json['NearestProjectName'];
|
||||
paymentAmount = json['PaymentAmount'];
|
||||
wFOrder = json['WF_order'] != null ? new WFOrder.fromJson(json['WF_order']) : null;
|
||||
serviceText = json['ServiceText'];
|
||||
isSentForApproval = json['isSentForApproval'];
|
||||
exaCartOrderId = json['ExaCart_OrderId'];
|
||||
isTimer = json['isTimer'];
|
||||
timeSeconds = json['TimeSeconds'];
|
||||
totalPendingSeconds = json['TotalPendingSeconds'];
|
||||
timeMinute = json['TimeMinute'];
|
||||
timeHour = json['TimeHour'];
|
||||
timeTotalSeconds = json['TimeTotalSeconds'];
|
||||
timeTotalMinute = json['TimeTotalMinute'];
|
||||
timeTotalHour = json['TimeTotalHour'];
|
||||
approvalStatus = json['ApprovalStatus'];
|
||||
isActive = json['isActive'];
|
||||
clickButton = json['ClickButton'];
|
||||
pickupLocation = json['PickupLocation'];
|
||||
dropOffLocation = json['DropOffLocation'];
|
||||
clinicName = json['clinicName'];
|
||||
doctorName = json['DoctorName'];
|
||||
branch = json['Branch'];
|
||||
time = json['Time'];
|
||||
notes = json['Notes'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['ID'] = this.iD;
|
||||
data['PatientId'] = this.patientId;
|
||||
data['PatientOutSa'] = this.patientOutSa;
|
||||
data['IsOutPatient'] = this.isOutPatient;
|
||||
data['ProjectId'] = this.projectId;
|
||||
data['NearestProjectId'] = this.nearestProjectId;
|
||||
data['Longitude'] = this.longitude;
|
||||
data['Latitude'] = this.latitude;
|
||||
data['AppointmentNo'] = this.appointmentNo;
|
||||
data['DischargeId'] = this.dischargeId;
|
||||
data['StatusId'] = this.statusId;
|
||||
data['ServiceId'] = this.serviceId;
|
||||
data['Channel'] = this.channel;
|
||||
if (this.orderpayment != null) {
|
||||
data['orderpayment'] = this.orderpayment!.toJson();
|
||||
}
|
||||
data['orderselectedservice'] = this.orderselectedservice;
|
||||
|
||||
data['wforder'] = this.wforder;
|
||||
data['orderapprovalobj'] = this.orderapprovalobj;
|
||||
data['Created'] = this.created;
|
||||
data['CreatedBy'] = this.createdBy;
|
||||
data['Modified'] = this.modified;
|
||||
data['ModifiedBy'] = this.modifiedBy;
|
||||
data['IsDeleted'] = this.isDeleted;
|
||||
data['StatusText'] = this.statusText;
|
||||
data['PaymentStatus'] = this.paymentStatus;
|
||||
data['ClientRequestid'] = this.clientRequestid;
|
||||
data['PaymentStatusText'] = this.paymentStatusText;
|
||||
data['ProjectName'] = this.projectName;
|
||||
data['NearestProjectName'] = this.nearestProjectName;
|
||||
data['PaymentAmount'] = this.paymentAmount;
|
||||
if (this.wFOrder != null) {
|
||||
data['WF_order'] = this.wFOrder!.toJson();
|
||||
}
|
||||
data['ServiceText'] = this.serviceText;
|
||||
data['isSentForApproval'] = this.isSentForApproval;
|
||||
data['ExaCart_OrderId'] = this.exaCartOrderId;
|
||||
data['isTimer'] = this.isTimer;
|
||||
data['TimeSeconds'] = this.timeSeconds;
|
||||
data['TotalPendingSeconds'] = this.totalPendingSeconds;
|
||||
data['TimeMinute'] = this.timeMinute;
|
||||
data['TimeHour'] = this.timeHour;
|
||||
data['TimeTotalSeconds'] = this.timeTotalSeconds;
|
||||
data['TimeTotalMinute'] = this.timeTotalMinute;
|
||||
data['TimeTotalHour'] = this.timeTotalHour;
|
||||
data['ApprovalStatus'] = this.approvalStatus;
|
||||
data['isActive'] = this.isActive;
|
||||
data['ClickButton'] = this.clickButton;
|
||||
data['PickupLocation'] = this.pickupLocation;
|
||||
data['DropOffLocation'] = this.dropOffLocation;
|
||||
data['clinicName'] = this.clinicName;
|
||||
data['DoctorName'] = this.doctorName;
|
||||
data['Branch'] = this.branch;
|
||||
data['Time'] = this.time;
|
||||
data['Notes'] = this.notes;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Orderpayment {
|
||||
int? iD;
|
||||
int? orderId;
|
||||
dynamic clientRequestId;
|
||||
dynamic totalAmount;
|
||||
int? paymentStatus;
|
||||
dynamic order;
|
||||
String? created;
|
||||
dynamic createdBy;
|
||||
dynamic modified;
|
||||
dynamic modifiedBy;
|
||||
bool? isDeleted;
|
||||
|
||||
Orderpayment({this.iD, this.orderId, this.clientRequestId, this.totalAmount, this.paymentStatus, this.order, this.created, this.createdBy, this.modified, this.modifiedBy, this.isDeleted});
|
||||
|
||||
Orderpayment.fromJson(Map<String, dynamic> json) {
|
||||
iD = json['ID'];
|
||||
orderId = json['OrderId'];
|
||||
clientRequestId = json['ClientRequestId'];
|
||||
totalAmount = json['TotalAmount'];
|
||||
paymentStatus = json['PaymentStatus'];
|
||||
order = json['Order'];
|
||||
created = json['Created'];
|
||||
createdBy = json['CreatedBy'];
|
||||
modified = json['Modified'];
|
||||
modifiedBy = json['ModifiedBy'];
|
||||
isDeleted = json['IsDeleted'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['ID'] = this.iD;
|
||||
data['OrderId'] = this.orderId;
|
||||
data['ClientRequestId'] = this.clientRequestId;
|
||||
data['TotalAmount'] = this.totalAmount;
|
||||
data['PaymentStatus'] = this.paymentStatus;
|
||||
data['Order'] = this.order;
|
||||
data['Created'] = this.created;
|
||||
data['CreatedBy'] = this.createdBy;
|
||||
data['Modified'] = this.modified;
|
||||
data['ModifiedBy'] = this.modifiedBy;
|
||||
data['IsDeleted'] = this.isDeleted;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class WFOrder {
|
||||
dynamic wfButtonsDTO;
|
||||
int? iD;
|
||||
int? orderId;
|
||||
int? previousStep;
|
||||
int? nextStep;
|
||||
int? serviceId;
|
||||
dynamic order;
|
||||
String? created;
|
||||
dynamic createdBy;
|
||||
dynamic modified;
|
||||
dynamic modifiedBy;
|
||||
bool? isDeleted;
|
||||
|
||||
WFOrder({this.wfButtonsDTO, this.iD, this.orderId, this.previousStep, this.nextStep, this.serviceId, this.order, this.created, this.createdBy, this.modified, this.modifiedBy, this.isDeleted});
|
||||
|
||||
WFOrder.fromJson(Map<String, dynamic> json) {
|
||||
wfButtonsDTO = json['wf_ButtonsDTO'];
|
||||
iD = json['ID'];
|
||||
orderId = json['OrderId'];
|
||||
previousStep = json['PreviousStep'];
|
||||
nextStep = json['NextStep'];
|
||||
serviceId = json['ServiceId'];
|
||||
order = json['Order'];
|
||||
created = json['Created'];
|
||||
createdBy = json['CreatedBy'];
|
||||
modified = json['Modified'];
|
||||
modifiedBy = json['ModifiedBy'];
|
||||
isDeleted = json['IsDeleted'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['wf_ButtonsDTO'] = this.wfButtonsDTO;
|
||||
data['ID'] = this.iD;
|
||||
data['OrderId'] = this.orderId;
|
||||
data['PreviousStep'] = this.previousStep;
|
||||
data['NextStep'] = this.nextStep;
|
||||
data['ServiceId'] = this.serviceId;
|
||||
data['Order'] = this.order;
|
||||
data['Created'] = this.created;
|
||||
data['CreatedBy'] = this.createdBy;
|
||||
data['Modified'] = this.modified;
|
||||
data['ModifiedBy'] = this.modifiedBy;
|
||||
data['IsDeleted'] = this.isDeleted;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,161 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||
import 'package:hmg_patient_app_new/core/common_models/privilege/ProjectDetailListModel.dart';
|
||||
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
||||
import 'package:hmg_patient_app_new/core/location_util.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/book_appointment/review_appointment_page.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
|
||||
class WaitingAppointmentOnlineCheckinSheet extends StatelessWidget {
|
||||
WaitingAppointmentOnlineCheckinSheet({super.key, required this.bookAppointmentsViewModel});
|
||||
|
||||
BookAppointmentsViewModel bookAppointmentsViewModel;
|
||||
|
||||
bool _supportsNFC = false;
|
||||
|
||||
late LocationUtils locationUtils;
|
||||
late AppState appState;
|
||||
ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appState = getIt.get<AppState>();
|
||||
locationUtils = getIt.get<LocationUtils>();
|
||||
locationUtils.isShowConfirmDialog = true;
|
||||
FlutterNfcKit.nfcAvailability.then((value) {
|
||||
_supportsNFC = (value == NFCAvailability.available);
|
||||
});
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_location_icon,
|
||||
"Live Location".needTranslation,
|
||||
"Verify your location to be at hospital to check in".needTranslation,
|
||||
).onPress(() {
|
||||
// locationUtils = LocationUtils(
|
||||
// isShowConfirmDialog: false,
|
||||
// navigationService: myAppointmentsViewModel.navigationService,
|
||||
// appState: myAppointmentsViewModel.appState,
|
||||
// );
|
||||
locationUtils.getCurrentLocation(onSuccess: (value) {
|
||||
projectDetailListModel = Utils.getProjectDetailObj(appState, bookAppointmentsViewModel.waitingAppointmentProjectID);
|
||||
double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000;
|
||||
print(dist);
|
||||
if (dist <= projectDetailListModel.geofenceRadius!) {
|
||||
checkScannedNFCAndQRCode(projectDetailListModel.checkInQrCode!, context);
|
||||
} else {
|
||||
showCommonBottomSheetWithoutHeight(context,
|
||||
title: "Error".needTranslation,
|
||||
child: Utils.getErrorWidget(loadingText: "Please ensure you're within the hospital location to perform online check-in.".needTranslation), callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
}, isFullScreen: false);
|
||||
}
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_nfc_icon,
|
||||
"NFC (Near Field Communication)".needTranslation,
|
||||
"Scan your phone via NFC board to check in".needTranslation,
|
||||
).onPress(() {
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
showNfcReader(context, onNcfScan: (String nfcId) {
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
checkScannedNFCAndQRCode(nfcId, context);
|
||||
});
|
||||
}, onCancel: () {});
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_qr_icon,
|
||||
"QR Code".needTranslation,
|
||||
"Scan QR code with your camera to check in".needTranslation,
|
||||
).onPress(() async {
|
||||
String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent));
|
||||
if (onlineCheckInQRCode != "") {
|
||||
checkScannedNFCAndQRCode(onlineCheckInQRCode, context);
|
||||
} else {}
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget checkInOptionCard(String icon, String title, String subTitle) {
|
||||
return Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
title.toText16(isBold: true, color: AppColors.textColor),
|
||||
subTitle.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon_small,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 18.h,
|
||||
height: 13.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
).paddingAll(16.h),
|
||||
);
|
||||
}
|
||||
|
||||
void checkScannedNFCAndQRCode(String scannedCode, BuildContext context) async {
|
||||
LoaderBottomSheet.showLoader(loadingText: "Processing Check-In...".needTranslation);
|
||||
bookAppointmentsViewModel.checkScannedNFCAndQRCode(
|
||||
scannedCode,
|
||||
bookAppointmentsViewModel.waitingAppointmentProjectID,
|
||||
onSuccess: (value) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
bookAppointmentsViewModel.setIsWaitingAppointmentSelected(true);
|
||||
Navigator.of(context).push(
|
||||
CustomPageRoute(
|
||||
page: ReviewAppointmentPage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
onError: (err) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(context, title: "Error".needTranslation, child: Utils.getErrorWidget(loadingText: err), callBackFunc: () {
|
||||
// Navigator.of(context).pop();
|
||||
}, isFullScreen: false);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,644 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||
import 'package:hmg_patient_app_new/core/cache_consts.dart';
|
||||
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
||||
import 'package:hmg_patient_app_new/core/enums.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/in_app_browser/InAppBrowser.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:smooth_corner/smooth_corner.dart';
|
||||
|
||||
class WaitingAppointmentPaymentPage extends StatefulWidget {
|
||||
WaitingAppointmentPaymentPage({super.key});
|
||||
|
||||
// PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
|
||||
|
||||
@override
|
||||
State<WaitingAppointmentPaymentPage> createState() => _WaitingAppointmentPaymentPageState();
|
||||
}
|
||||
|
||||
class _WaitingAppointmentPaymentPageState extends State<WaitingAppointmentPaymentPage> {
|
||||
late BookAppointmentsViewModel bookAppointmentsViewModel;
|
||||
late MyAppointmentsViewModel myAppointmentsViewModel;
|
||||
late PayfortViewModel payfortViewModel;
|
||||
late AppState appState;
|
||||
|
||||
MyInAppBrowser? browser;
|
||||
String selectedPaymentMethod = "";
|
||||
|
||||
String transID = "";
|
||||
|
||||
bool isShowTamara = false;
|
||||
String tamaraPaymentStatus = "";
|
||||
String tamaraOrderID = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
scheduleMicrotask(() {
|
||||
payfortViewModel.initPayfortViewModel();
|
||||
payfortViewModel.setIsApplePayConfigurationLoading(false);
|
||||
// myAppointmentsViewModel.getPatientShareAppointment(
|
||||
// widget.patientAppointmentHistoryResponseModel.projectID,
|
||||
// widget.patientAppointmentHistoryResponseModel.clinicID,
|
||||
// widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(), widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false, onSuccess: (val) {
|
||||
// myAppointmentsViewModel.getTamaraInstallmentsDetails().then((val) {
|
||||
// if (myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax! >= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! &&
|
||||
// myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax! <= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) {
|
||||
// setState(() {
|
||||
// isShowTamara = true;
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }, onError: (err) {
|
||||
// Navigator.of(context).pop();
|
||||
// Navigator.of(context).pop();
|
||||
// });
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appState = getIt.get<AppState>();
|
||||
bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context);
|
||||
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context);
|
||||
payfortViewModel = Provider.of<PayfortViewModel>(context);
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CollapsingListView(
|
||||
title: "Appointment Payment".needTranslation,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 24.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(AppAssets.mada, width: 72.h, height: 25.h),
|
||||
SizedBox(height: 16.h),
|
||||
"Mada".needTranslation.toText16(isBold: true),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 8.h),
|
||||
const Spacer(),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon_small,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 18.h,
|
||||
height: 13.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.h, 16.h),
|
||||
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||
selectedPaymentMethod = "MADA";
|
||||
openPaymentURL("mada");
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
|
||||
SizedBox(width: 8.h),
|
||||
Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
"Visa or Mastercard".needTranslation.toText16(isBold: true),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 8.h),
|
||||
const Spacer(),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon_small,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 18.h,
|
||||
height: 13.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.h, 16.h),
|
||||
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||
selectedPaymentMethod = "VISA";
|
||||
openPaymentURL("visa");
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
isShowTamara
|
||||
? Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h),
|
||||
SizedBox(height: 16.h),
|
||||
"Tamara".needTranslation.toText16(isBold: true),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 8.h),
|
||||
const Spacer(),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon_small,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 18.h,
|
||||
height: 13.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.h, 16.h),
|
||||
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||
selectedPaymentMethod = "TAMARA";
|
||||
openPaymentURL("tamara");
|
||||
})
|
||||
: SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 24.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Consumer<PayfortViewModel>(builder: (context, payfortVM, child) {
|
||||
//TODO: Need to add loading state & animation for Apple Pay Configuration
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
(bookAppointmentsVM.patientWalkInAppointmentShareResponseModel!.isCash ?? true)
|
||||
? Container(
|
||||
height: 50.h,
|
||||
decoration: ShapeDecoration(
|
||||
color: AppColors.secondaryLightRedBorderColor,
|
||||
shape: SmoothRectangleBorder(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
|
||||
smoothness: 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
"Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
|
||||
CustomButton(
|
||||
text: LocaleKeys.updateInsurance.tr(context: context),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
CustomPageRoute(
|
||||
page: InsuranceHomePage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
backgroundColor: AppColors.primaryRedColor,
|
||||
borderColor: AppColors.secondaryLightRedBorderColor,
|
||||
textColor: AppColors.whiteColor,
|
||||
fontSize: 10.f,
|
||||
fontWeight: FontWeight.w500,
|
||||
borderRadius: 8,
|
||||
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
height: 30.h,
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
],
|
||||
),
|
||||
)
|
||||
: const SizedBox(),
|
||||
SizedBox(height: 24.h),
|
||||
"Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
|
||||
SizedBox(height: 17.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
"Amount before tax".needTranslation.toText14(isBold: true),
|
||||
Utils.getPaymentAmountWithSymbol(bookAppointmentsVM.patientWalkInAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
|
||||
isSaudiCurrency: true),
|
||||
],
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
"VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
|
||||
Utils.getPaymentAmountWithSymbol(
|
||||
bookAppointmentsVM.patientWalkInAppointmentShareResponseModel!.patientTaxAmount!.toString().toText14(isBold: true, color: AppColors.greyTextColor),
|
||||
AppColors.greyTextColor,
|
||||
13,
|
||||
isSaudiCurrency: true),
|
||||
],
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
SizedBox(height: 17.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
"".needTranslation.toText14(isBold: true),
|
||||
Utils.getPaymentAmountWithSymbol(
|
||||
bookAppointmentsVM.patientWalkInAppointmentShareResponseModel!.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
|
||||
isSaudiCurrency: true),
|
||||
],
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
Platform.isIOS
|
||||
? Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.apple_pay_button,
|
||||
width: 200.h,
|
||||
height: 80.h,
|
||||
fit: BoxFit.contain,
|
||||
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||
// payfortVM.setIsApplePayConfigurationLoading(true);
|
||||
if (Utils.havePrivilege(103)) {
|
||||
startApplePay();
|
||||
} else {
|
||||
openPaymentURL("ApplePay");
|
||||
}
|
||||
})
|
||||
: SizedBox(height: 12.h),
|
||||
SizedBox(height: 12.h),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
onBrowserLoadStart(String url) {
|
||||
print("onBrowserLoadStart");
|
||||
print(url);
|
||||
|
||||
if (selectedPaymentMethod == "tamara") {
|
||||
if (Platform.isAndroid) {
|
||||
Uri uri = new Uri.dataFromString(url);
|
||||
tamaraPaymentStatus = uri.queryParameters['status']!;
|
||||
tamaraOrderID = uri.queryParameters['AuthorizePaymentId']!;
|
||||
} else {
|
||||
Uri uri = new Uri.dataFromString(url);
|
||||
tamaraPaymentStatus = uri.queryParameters['paymentStatus']!;
|
||||
tamaraOrderID = uri.queryParameters['orderId']!;
|
||||
}
|
||||
}
|
||||
|
||||
// if(selectedPaymentMethod != "TAMARA") {
|
||||
MyInAppBrowser.successURLS.forEach((element) {
|
||||
if (url.contains(element)) {
|
||||
browser?.close();
|
||||
MyInAppBrowser.isPaymentDone = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
// }
|
||||
|
||||
// if(selectedPaymentMethod != "TAMARA") {
|
||||
MyInAppBrowser.errorURLS.forEach((element) {
|
||||
if (url.contains(element)) {
|
||||
browser?.close();
|
||||
MyInAppBrowser.isPaymentDone = false;
|
||||
return;
|
||||
}
|
||||
});
|
||||
// }
|
||||
}
|
||||
|
||||
onBrowserExit(bool isPaymentMade) async {
|
||||
checkPaymentStatus();
|
||||
}
|
||||
|
||||
void checkPaymentStatus() async {
|
||||
LoaderBottomSheet.showLoader(loadingText: "Checking payment status, Please wait...".needTranslation);
|
||||
if (selectedPaymentMethod == "TAMARA") {
|
||||
await payfortViewModel.checkTamaraPaymentStatus(
|
||||
transactionID: transID,
|
||||
onSuccess: (apiResponse) async {
|
||||
if (apiResponse.data["status"].toString().toLowerCase() == "success") {
|
||||
tamaraOrderID = apiResponse.data["tamara_order_id"].toString();
|
||||
await payfortViewModel.updateTamaraRequestStatus(responseMessage: "success", status: "14", clientRequestID: transID, tamaraOrderID: tamaraOrderID);
|
||||
await payfortViewModel.markAppointmentAsTamaraPaid(projectID: bookAppointmentsViewModel.selectedDoctor.projectID!, appointmentNo: DateTime.now().millisecondsSinceEpoch);
|
||||
// await myAppointmentsViewModel.addAdvanceNumberRequest(
|
||||
// advanceNumber: "Tamara-Advance-0000",
|
||||
// paymentReference: tamaraOrderID,
|
||||
// appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
|
||||
// onSuccess: (value) async {
|
||||
// if (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!) {
|
||||
// //TODO: Implement LiveCare Check-In API Call
|
||||
// await myAppointmentsViewModel.insertLiveCareVIDARequest(
|
||||
// clientRequestID: tamaraOrderID,
|
||||
// patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
|
||||
// onSuccess: (apiResponse) {
|
||||
// Future.delayed(Duration(milliseconds: 500), () {
|
||||
// LoaderBottomSheet.hideLoader();
|
||||
// Navigator.pushAndRemoveUntil(
|
||||
// context,
|
||||
// CustomPageRoute(
|
||||
// page: LandingNavigation(),
|
||||
// ),
|
||||
// (r) => false);
|
||||
// });
|
||||
// },
|
||||
// onError: (error) {});
|
||||
// } else {
|
||||
// await myAppointmentsViewModel.generateAppointmentQR(
|
||||
// clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
|
||||
// projectID: widget.patientAppointmentHistoryResponseModel.projectID,
|
||||
// appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
|
||||
// isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!,
|
||||
// onSuccess: (apiResponse) {
|
||||
// Future.delayed(Duration(milliseconds: 500), () {
|
||||
// LoaderBottomSheet.hideLoader();
|
||||
// Navigator.pushAndRemoveUntil(
|
||||
// context,
|
||||
// CustomPageRoute(
|
||||
// page: LandingNavigation(),
|
||||
// ),
|
||||
// (r) => false);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
} else {
|
||||
await payfortViewModel.updateTamaraRequestStatus(responseMessage: "Failed", status: "00", clientRequestID: transID, tamaraOrderID: tamaraOrderID);
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getErrorWidget(loadingText: "Payment Failed! Please try again.".needTranslation),
|
||||
callBackFunc: () {},
|
||||
isFullScreen: false,
|
||||
isCloseButtonVisible: true,
|
||||
);
|
||||
}
|
||||
},
|
||||
onError: (err) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getErrorWidget(loadingText: err),
|
||||
callBackFunc: () {},
|
||||
isFullScreen: false,
|
||||
isCloseButtonVisible: true,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
await payfortViewModel.checkPaymentStatus(
|
||||
transactionID: transID,
|
||||
onSuccess: (apiResponse) async {
|
||||
print(apiResponse.data);
|
||||
if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
LoaderBottomSheet.showLoader(loadingText: "Booking Waiting Appointment, Please wait...".needTranslation);
|
||||
await bookAppointmentsViewModel.insertSpecificAppointmentForWalkIn(onSuccess: (val) async {
|
||||
String appointmentNo = val.data['AppointmentNo'].toString();
|
||||
await myAppointmentsViewModel.createAdvancePayment(
|
||||
paymentMethodName: selectedPaymentMethod,
|
||||
projectID: bookAppointmentsViewModel.waitingAppointmentProjectID,
|
||||
clinicID: bookAppointmentsViewModel.selectedDoctor.clinicID!,
|
||||
appointmentNo: appointmentNo,
|
||||
payedAmount: payfortViewModel.payfortCheckPaymentStatusResponseModel!.amount!,
|
||||
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
|
||||
patientID: appState.getAuthenticatedUser()!.patientId.toString(),
|
||||
patientType: appState.getAuthenticatedUser()!.patientType!,
|
||||
onSuccess: (value) async {
|
||||
print(value);
|
||||
await myAppointmentsViewModel.addAdvanceNumberRequest(
|
||||
advanceNumber: Utils.isVidaPlusProject(bookAppointmentsViewModel.waitingAppointmentProjectID)
|
||||
? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
|
||||
: value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
|
||||
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
|
||||
appointmentNo: appointmentNo,
|
||||
onSuccess: (value) async {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
sendCheckInRequest(bookAppointmentsViewModel.waitingAppointmentNFCCode, appointmentNo, context);
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getErrorWidget(loadingText: "Payment Failed! Please try again.".needTranslation),
|
||||
callBackFunc: () {},
|
||||
isFullScreen: false,
|
||||
isCloseButtonVisible: true,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
openPaymentURL(String paymentMethod) {
|
||||
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
|
||||
transID = Utils.getAppointmentTransID(
|
||||
bookAppointmentsViewModel.selectedDoctor.projectID!,
|
||||
bookAppointmentsViewModel.selectedDoctor.clinicID!,
|
||||
bookAppointmentsViewModel.selectedDoctor.doctorID!,
|
||||
);
|
||||
|
||||
//TODO: Need to pass dynamic params to the payment request instead of static values
|
||||
browser?.openPaymentBrowser(
|
||||
bookAppointmentsViewModel.patientWalkInAppointmentShareResponseModel!.patientShareWithTax!,
|
||||
"Appointment check in",
|
||||
transID,
|
||||
bookAppointmentsViewModel.selectedDoctor.projectID.toString(),
|
||||
"CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
|
||||
selectedPaymentMethod,
|
||||
appState.getAuthenticatedUser()!.patientType.toString(),
|
||||
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
|
||||
appState.getAuthenticatedUser()!.patientId.toString(),
|
||||
appState.getAuthenticatedUser()!,
|
||||
browser!,
|
||||
false,
|
||||
"2",
|
||||
"",
|
||||
context,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"3");
|
||||
}
|
||||
|
||||
startApplePay() async {
|
||||
showCommonBottomSheet(context,
|
||||
child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
|
||||
transID = Utils.getAppointmentTransID(
|
||||
bookAppointmentsViewModel.selectedDoctor.projectID!,
|
||||
bookAppointmentsViewModel.selectedDoctor.clinicID!,
|
||||
bookAppointmentsViewModel.selectedDoctor.doctorID!,
|
||||
);
|
||||
|
||||
ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
|
||||
|
||||
await payfortViewModel.getPayfortConfigurations(
|
||||
serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum(), projectId: bookAppointmentsViewModel.selectedDoctor.projectID!, integrationId: 2);
|
||||
|
||||
applePayInsertRequest.clientRequestID = transID;
|
||||
applePayInsertRequest.clinicID = bookAppointmentsViewModel.selectedDoctor.clinicID!;
|
||||
|
||||
applePayInsertRequest.currency = appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
|
||||
applePayInsertRequest.customerEmail = "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com";
|
||||
applePayInsertRequest.customerID = appState.getAuthenticatedUser()!.patientId.toString();
|
||||
applePayInsertRequest.customerName = "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}";
|
||||
|
||||
applePayInsertRequest.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
|
||||
applePayInsertRequest.voipToken = await Utils.getStringFromPrefs(CacheConst.voipToken);
|
||||
applePayInsertRequest.doctorID = bookAppointmentsViewModel.selectedDoctor.doctorID;
|
||||
applePayInsertRequest.projectID = bookAppointmentsViewModel.selectedDoctor.projectID.toString();
|
||||
applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
|
||||
applePayInsertRequest.channelID = 3;
|
||||
applePayInsertRequest.patientID = appState.getAuthenticatedUser()!.patientId.toString();
|
||||
applePayInsertRequest.patientTypeID = appState.getAuthenticatedUser()!.patientType;
|
||||
applePayInsertRequest.patientOutSA = appState.getAuthenticatedUser()!.outSa;
|
||||
applePayInsertRequest.appointmentDate = DateUtil.convertDateToString(DateTime.now());
|
||||
applePayInsertRequest.appointmentNo = DateTime.now().millisecondsSinceEpoch;
|
||||
applePayInsertRequest.orderDescription = "Appointment Payment";
|
||||
applePayInsertRequest.liveServiceID = "0";
|
||||
applePayInsertRequest.latitude = "0.0";
|
||||
applePayInsertRequest.longitude = "0.0";
|
||||
applePayInsertRequest.amount = bookAppointmentsViewModel.patientWalkInAppointmentShareResponseModel!.patientShareWithTax!.toString();
|
||||
applePayInsertRequest.isSchedule = "0";
|
||||
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
|
||||
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
|
||||
applePayInsertRequest.userName = appState.getAuthenticatedUser()!.patientId;
|
||||
applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
|
||||
applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
|
||||
applePayInsertRequest.paymentOption = "ApplePay";
|
||||
|
||||
applePayInsertRequest.isMobSDK = true;
|
||||
applePayInsertRequest.merchantReference = transID;
|
||||
applePayInsertRequest.merchantIdentifier = payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier;
|
||||
applePayInsertRequest.commandType = "PURCHASE";
|
||||
applePayInsertRequest.signature = payfortViewModel.payfortProjectDetailsRespModel!.signature;
|
||||
applePayInsertRequest.accessCode = payfortViewModel.payfortProjectDetailsRespModel!.accessCode;
|
||||
applePayInsertRequest.shaRequestPhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaRequest;
|
||||
applePayInsertRequest.shaResponsePhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaResponse;
|
||||
applePayInsertRequest.returnURL = "";
|
||||
|
||||
//TODO: Need to pass dynamic params to the Apple Pay instead of static values
|
||||
await payfortViewModel.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest).then((value) {
|
||||
payfortViewModel.paymentWithApplePay(
|
||||
customerName: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
|
||||
// customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress,
|
||||
customerEmail: "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
|
||||
orderDescription: "Appointment Payment",
|
||||
orderAmount: double.parse(bookAppointmentsViewModel.patientWalkInAppointmentShareResponseModel!.patientShareWithTax!.toString()),
|
||||
merchantReference: transID,
|
||||
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
|
||||
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,
|
||||
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
|
||||
currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
|
||||
onFailed: (failureResult) async {
|
||||
log("failureResult: ${failureResult.message.toString()}");
|
||||
Navigator.of(context).pop();
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getErrorWidget(loadingText: failureResult.message.toString()),
|
||||
callBackFunc: () {},
|
||||
isFullScreen: false,
|
||||
isCloseButtonVisible: true,
|
||||
);
|
||||
},
|
||||
onSucceeded: (successResult) async {
|
||||
log("successResult: ${successResult.responseMessage.toString()}");
|
||||
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
|
||||
checkPaymentStatus();
|
||||
},
|
||||
// projectId: appo.projectID,
|
||||
// serviceTypeEnum: ServiceTypeEnum.appointmentPayment,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void sendCheckInRequest(String scannedCode, String appointmentNo, BuildContext context) async {
|
||||
LoaderBottomSheet.showLoader(loadingText: "Processing Check-In...".needTranslation);
|
||||
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel = PatientAppointmentHistoryResponseModel(
|
||||
appointmentNo: appointmentNo,
|
||||
clinicID: bookAppointmentsViewModel.selectedDoctor.clinicID,
|
||||
projectID: bookAppointmentsViewModel.selectedDoctor.projectID,
|
||||
);
|
||||
await myAppointmentsViewModel.sendCheckInNfcRequest(
|
||||
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
|
||||
scannedCode: scannedCode,
|
||||
checkInType: 2,
|
||||
onSuccess: (apiResponse) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(context, title: "Success".needTranslation, child: Utils.getSuccessWidget(loadingText: apiResponse.data["SuccessMsg"]), callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
CustomPageRoute(
|
||||
page: LandingNavigation(),
|
||||
),
|
||||
(r) => false);
|
||||
}, isFullScreen: false);
|
||||
},
|
||||
onError: (error) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(context, title: "Error".needTranslation, child: Utils.getErrorWidget(loadingText: error), callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
}, isFullScreen: false);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void insertWalkInAppointment() async {}
|
||||
}
|
||||
@ -0,0 +1,174 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class PrescriptionDeliveryOrderSummaryPage extends StatelessWidget {
|
||||
PrescriptionDeliveryOrderSummaryPage({super.key});
|
||||
|
||||
late PrescriptionsViewModel prescriptionsViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(context, listen: false);
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CollapsingListView(
|
||||
title: LocaleKeys.orderSummary.tr(context: context),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 16.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.r,
|
||||
hasShadow: true,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LocaleKeys.orderDetail.tr(context: context).toText16(isBold: true),
|
||||
SizedBox(height: 16.h),
|
||||
...List.generate(
|
||||
prescriptionsViewModel.prescriptionDetailsList.length,
|
||||
(index) => Container(
|
||||
margin: EdgeInsets.all(0.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(5.r),
|
||||
),
|
||||
child: Image.network(
|
||||
prescriptionsViewModel.prescriptionDetailsList[index].imageSRCUrl!,
|
||||
fit: BoxFit.cover,
|
||||
width: 60.w,
|
||||
height: 70.h,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8.h),
|
||||
child: Center(
|
||||
child: prescriptionsViewModel.prescriptionDetailsList[index].itemDescription!.trim().toText12(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.r,
|
||||
hasShadow: true,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LocaleKeys.deliveryLocation.tr(context: context).toText16(isBold: true),
|
||||
SizedBox(height: 16.h),
|
||||
ClipRRect(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
borderRadius: BorderRadius.circular(20.r),
|
||||
child: Image.network(
|
||||
"https://maps.googleapis.com/maps/api/staticmap?center=${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&zoom=15&size=350x165&maptype=roadmap&markers=color:red%7C${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(24.w, 0),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 24.h,
|
||||
hasShadow: true,
|
||||
),
|
||||
child: CustomButton(
|
||||
text: LocaleKeys.submit.tr(context: context),
|
||||
onPressed: () async {
|
||||
LoaderBottomSheet.showLoader(loadingText: "Submitting your request...");
|
||||
await prescriptionsViewModel.submitPrescriptionDeliveryRequest(
|
||||
latitude: prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat.toString(),
|
||||
longitude: prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng.toString(),
|
||||
appointmentNo: prescriptionsViewModel.prescriptionDetailsList.first.appointmentNo.toString(),
|
||||
dischargeID: "0",
|
||||
projectID: prescriptionsViewModel.prescriptionDetailsList.first.projectID.toString(),
|
||||
onSuccess: (val) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getSuccessWidget(loadingText: "Request sent successfully.".needTranslation),
|
||||
callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
title: "",
|
||||
isCloseButtonVisible: true,
|
||||
isDismissible: false,
|
||||
isFullScreen: false,
|
||||
);
|
||||
},
|
||||
onError: (err) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getErrorWidget(loadingText: err),
|
||||
callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
title: "",
|
||||
isCloseButtonVisible: true,
|
||||
isDismissible: false,
|
||||
isFullScreen: false,
|
||||
);
|
||||
});
|
||||
},
|
||||
backgroundColor: AppColors.successColor,
|
||||
borderColor: AppColors.successColor.withOpacity(0.01),
|
||||
textColor: AppColors.whiteColor,
|
||||
fontSize: 16.f,
|
||||
fontWeight: FontWeight.w500,
|
||||
borderRadius: 12.r,
|
||||
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||
height: 50.h,
|
||||
icon: AppAssets.prescription_refill_icon,
|
||||
iconColor: AppColors.whiteColor,
|
||||
iconSize: 20.h,
|
||||
).paddingSymmetrical(24.h, 24.h),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/emergency_services/history/widget/RequestStatus.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class PrescriptionDeliveryOrdersListPage extends StatelessWidget {
|
||||
const PrescriptionDeliveryOrdersListPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: CollapsingListView(
|
||||
title: LocaleKeys.orders.tr(context: context),
|
||||
child: SingleChildScrollView(
|
||||
child: Consumer<PrescriptionsViewModel>(builder: (context, model, child) {
|
||||
return Column(
|
||||
children: [
|
||||
ListView.builder(
|
||||
itemCount: model.isPrescriptionsDeliveryOrdersLoading
|
||||
? 4
|
||||
: model.prescriptionsOrderList.isNotEmpty
|
||||
? model.prescriptionsOrderList.length
|
||||
: 1,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.only(left: 0, right: 8),
|
||||
itemBuilder: (context, index) {
|
||||
return model.isPrescriptionsDeliveryOrdersLoading
|
||||
? LabResultItemView(
|
||||
onTap: () {},
|
||||
labOrder: null,
|
||||
index: index,
|
||||
isLoading: true,
|
||||
)
|
||||
: model.prescriptionsOrderList.isNotEmpty
|
||||
? AnimationConfiguration.staggeredList(
|
||||
position: index,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: SlideAnimation(
|
||||
verticalOffset: 100.0,
|
||||
child: FadeInAnimation(
|
||||
child: AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
margin: EdgeInsets.symmetric(vertical: 8.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 8.h,
|
||||
children: [
|
||||
RequestStatus(status: model.prescriptionsOrderList[index].statusId ?? 0),
|
||||
"Req ID: ${model.prescriptionsOrderList[index].iD}".toText16(color: AppColors.textColor, weight: FontWeight.w600),
|
||||
Row(
|
||||
spacing: 4.w,
|
||||
children: [
|
||||
chip(Utils.getDayMonthYearDateFormatted(DateTime.tryParse(model.prescriptionsOrderList[index].created!)), AppAssets.calendar,
|
||||
AppColors.blackBgColor),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Utils.getNoDataWidget(context, noDataText: "You don't have any prescription orders yet.".needTranslation);
|
||||
},
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
chip(String title, String iconString, Color iconColor) {
|
||||
return AppCustomChipWidget(
|
||||
labelText: title,
|
||||
icon: iconString,
|
||||
iconColor: iconColor,
|
||||
iconSize: 12.h,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,258 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_zoom_videosdk/flutter_zoom_view.dart' as FlutterZoomView;
|
||||
import 'package:flutter_zoom_videosdk/native/zoom_videosdk.dart';
|
||||
|
||||
const SHOW_TALKING_ICON_DURATION = 2000;
|
||||
|
||||
class VideoView extends FlutterZoomView.ZoomView {
|
||||
const VideoView({
|
||||
super.key,
|
||||
required super.user,
|
||||
required super.sharing,
|
||||
required super.preview,
|
||||
required super.focused,
|
||||
required super.hasMultiCamera,
|
||||
required super.multiCameraIndex,
|
||||
required super.videoAspect,
|
||||
required super.fullScreen,
|
||||
required super.resolution,
|
||||
required super.isPiPView,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var isVideoOn = useState(false);
|
||||
var isTalking = useState(false);
|
||||
var isMuted = useState(false);
|
||||
var isMounted = useIsMounted();
|
||||
var zoom = ZoomVideoSdk();
|
||||
var isSharing = useState(false);
|
||||
user?.audioStatus?.isMuted().then((muted) => isMuted.value = muted);
|
||||
|
||||
useEffect(() {
|
||||
updateVideoStatus() {
|
||||
if (user == null) return;
|
||||
Future<void>.microtask(() async {
|
||||
if (isMounted()) {
|
||||
isVideoOn.value = (await user!.videoStatus!.isOn());
|
||||
isSharing.value = sharing;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
resetAudioStatus() {
|
||||
isTalking.value = false;
|
||||
isMuted.value = false;
|
||||
}
|
||||
|
||||
updateAudioStatus() async {
|
||||
if (!isMounted()) return;
|
||||
var talking = await user?.audioStatus?.isTalking();
|
||||
var muted = await user?.audioStatus?.isMuted();
|
||||
isMuted.value = muted!;
|
||||
isTalking.value = talking!;
|
||||
if (talking) {
|
||||
Timer(
|
||||
const Duration(milliseconds: SHOW_TALKING_ICON_DURATION),
|
||||
() => {
|
||||
if (isMounted())
|
||||
{
|
||||
isTalking.value = false,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateVideoStatus();
|
||||
return null;
|
||||
}, [zoom, user]);
|
||||
|
||||
ImageIcon audioStatusIcon;
|
||||
if (isTalking.value) {
|
||||
audioStatusIcon = const ImageIcon(
|
||||
AssetImage("assets/images/png/zoom/talking@2x.png"),
|
||||
);
|
||||
} else if (isMuted.value) {
|
||||
audioStatusIcon = const ImageIcon(
|
||||
AssetImage("assets/images/png/zoom/muted@2x.png"),
|
||||
);
|
||||
}
|
||||
// Pass parameters to the platform side.
|
||||
final Map<String, dynamic> creationParams = <String, dynamic>{};
|
||||
creationParams.putIfAbsent("userId", () => user?.userId);
|
||||
creationParams.putIfAbsent("sharing", () => sharing);
|
||||
creationParams.putIfAbsent("preview", () => preview);
|
||||
creationParams.putIfAbsent("focused", () => focused);
|
||||
creationParams.putIfAbsent("hasMultiCamera", () => hasMultiCamera);
|
||||
if (videoAspect.isEmpty) {
|
||||
creationParams.putIfAbsent("videoAspect", () => VideoAspect.PanAndScan);
|
||||
} else {
|
||||
creationParams.putIfAbsent("videoAspect", () => videoAspect);
|
||||
}
|
||||
creationParams.putIfAbsent("fullScreen", () => fullScreen);
|
||||
if (resolution.isNotEmpty) {
|
||||
creationParams.putIfAbsent("videoAspect", () => videoAspect);
|
||||
}
|
||||
|
||||
if (fullScreen) {
|
||||
if (sharing) {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
alignment: Alignment.center,
|
||||
child: FlutterZoomView.View(creationParams: creationParams),
|
||||
);
|
||||
} else if (isVideoOn.value) {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
alignment: Alignment.center,
|
||||
child: FlutterZoomView.View(creationParams: creationParams),
|
||||
);
|
||||
} else {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 0),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
child: const Image(
|
||||
image: AssetImage("assets/images/png/zoom/default-avatar.png"),
|
||||
)),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (isVideoOn.value || sharing) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
height: 110,
|
||||
width: 110,
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 110,
|
||||
width: 110,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xff232323),
|
||||
border: Border.all(
|
||||
color: const Color(0xff666666),
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: FlutterZoomView.View(creationParams: creationParams),
|
||||
),
|
||||
Container(
|
||||
height: 110,
|
||||
width: 110,
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 110,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.black26,
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.bottomLeft,
|
||||
margin: const EdgeInsets.only(left: 5),
|
||||
child: Text(
|
||||
user!.userName,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.bottomRight,
|
||||
margin: const EdgeInsets.only(right: 5, bottom: 5),
|
||||
// height: 110,
|
||||
// width: 110,
|
||||
child: Image(
|
||||
height: 12,
|
||||
width: 12,
|
||||
image: isMuted.value ? const AssetImage("assets/images/png/zoom/muted@2x.png") : const AssetImage("assets/images/png/zoom/talking@2x.png"),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
height: 110,
|
||||
width: 110,
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 110,
|
||||
width: 110,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xff232323),
|
||||
border: Border.all(
|
||||
color: const Color(0xff666666),
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
child: const Image(
|
||||
height: 60,
|
||||
width: 60,
|
||||
image: AssetImage("assets/images/png/zoom/default-avatar.png"),
|
||||
)),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 110,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.black26,
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.bottomLeft,
|
||||
margin: const EdgeInsets.only(left: 5),
|
||||
child: Text(
|
||||
user!.userName,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.bottomRight,
|
||||
margin: const EdgeInsets.only(right: 5, bottom: 5),
|
||||
child: Image(
|
||||
height: 12,
|
||||
width: 12,
|
||||
image: isMuted.value ? const AssetImage("assets/images/png/zoom/muted@2x.png") : const AssetImage("assets/images/png/zoom/talking@2x.png"),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
|
||||
Widget buildTime(Duration duration, {bool isHomePage = false}) {
|
||||
String twoDigits(int n) => n.toString().padLeft(2, '0');
|
||||
final hours = twoDigits(duration.inHours);
|
||||
final minutes = twoDigits(duration.inMinutes.remainder(60));
|
||||
final seconds = twoDigits(duration.inSeconds.remainder(60));
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
buildTimeColumn(hours, "Hours".needTranslation),
|
||||
buildTimeColumn(minutes, "Mins".needTranslation),
|
||||
buildTimeColumn(seconds, "Secs".needTranslation, isLast: true),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTimeColumn(String time, String label, {bool isLast = false}) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
buildDigit(time[0]),
|
||||
buildDigit(time[1]),
|
||||
if (!isLast) buildTimeSeparator(),
|
||||
],
|
||||
),
|
||||
buildLabel(label),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildDigit(String digit) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
// margin: const EdgeInsets.symmetric(horizontal: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: ClipRect(
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
switchInCurve: Curves.easeOutExpo,
|
||||
switchOutCurve: Curves.easeInExpo,
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
SlideTransition(
|
||||
position: Tween<Offset>(
|
||||
begin: const Offset(0, -1),
|
||||
end: const Offset(0, 1),
|
||||
).animate(CurvedAnimation(
|
||||
parent: animation,
|
||||
curve: Curves.easeOutCubic,
|
||||
)),
|
||||
child: FadeTransition(
|
||||
opacity: animation,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
SlideTransition(
|
||||
position: Tween<Offset>(
|
||||
begin: const Offset(0, -1),
|
||||
end: const Offset(0, 0),
|
||||
).animate(CurvedAnimation(
|
||||
parent: animation,
|
||||
curve: Curves.bounceIn,
|
||||
)),
|
||||
child: FadeTransition(
|
||||
opacity: animation,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
digit,
|
||||
key: ValueKey<String>(digit),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
fontSize: 14.f,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildLabel(String label) {
|
||||
return label.toText12(isBold: true);
|
||||
}
|
||||
|
||||
Widget buildTimeSeparator() {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
||||
child: Text(
|
||||
":",
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||