diff --git a/ios/Podfile.lock b/ios/Podfile.lock index fb65ae25..9c86879d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -18,7 +18,7 @@ PODS: - Firebase/Messaging (6.33.0): - Firebase/CoreOnly - FirebaseMessaging (~> 4.7.0) - - firebase_core (0.5.2): + - firebase_core (0.5.3): - Firebase/CoreOnly (~> 6.33.0) - Flutter - firebase_core_web (0.1.0): @@ -250,7 +250,7 @@ SPEC CHECKSUMS: connectivity_macos: e2e9731b6b22dda39eb1b128f6969d574460e191 device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5 - firebase_core: 350ba329d1641211bc6183a3236893cafdacfea7 + firebase_core: 5d6a02f3d85acd5f8321c2d6d62877626a670659 firebase_core_web: d501d8b946b60c8af265428ce483b0fff5ad52d1 firebase_messaging: 0aea2cd5885b65e19ede58ee3507f485c992cc75 FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd diff --git a/ios/Runner/ClingoVideoCallViewController.swift b/ios/Runner/ClingoVideoCallViewController.swift new file mode 100644 index 00000000..b1bacdae --- /dev/null +++ b/ios/Runner/ClingoVideoCallViewController.swift @@ -0,0 +1,446 @@ +// +// ViewController.swift +// Lets-Build-OTPublisher +// +// Created by Roberto Perez Cubero on 11/08/16. +// Copyright © 2016 tokbox. All rights reserved. +// + +import UIKit +import OpenTok + +// The converted code is limited to 2 KB. +// Refill your credit or upgrade your plan to remove this limitation. +// +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +// +// ClingoVideoCallViewController.m +// Runner +// +// Created by Mohammad Aljammal & Elham on 23/6/20. +// Copyright © 2020 The Chromium Authors. All rights reserved. +// + + + + +import AVFoundation + +var dateFormatter: DateFormatter? + + +class ClingoVideoCallViewController : UIViewController, OTSessionDelegate, OTSubscriberDelegate, OTPublisherDelegate{ + + var kApiKey: String? + var kSessionId: String? + var kToken: String? + var session: OTSession? + var publisher: OTPublisher? + var subscriber: OTSubscriber? + var callDuration: String? + var warningDuration: String? + var appLang: String? + + + + @IBOutlet weak var localVideo: UIView! + @IBOutlet weak var remoteVideo: UIView! + @IBOutlet weak var controlButtons: UIView! + @IBOutlet weak var remoteVideoMutedIndicator: UIImageView! + @IBOutlet weak var localVideoMutedBg: UIImageView! + @IBOutlet weak var localVideoMutedIndicator: UIImageView! + @IBOutlet weak var remainingTimeLBL: UILabel! + @IBOutlet weak var pgView: UIProgressView! + var timer: Timer? + + + + + func viewDidLoad() { + super.viewDidLoad() + dateFormatter = DateFormatter() + + setupButtons() + askForMicrophonePermission() + requestCameraPermissionsIfNeeded() + hideVideoMuted() + setupSession() + // Do any additional setup after loading the view. + } + + func viewDidDisappear(_ animated: Bool) { + sessionDisconnect() + timer.invalidate() + timer = nil + PgView.hidden = true + remainingTimeLBL.hidden = true + } + +// MARK: -Microphone Camera and Permission Request + func askForMicrophonePermission() { + switch AVAudioSession.sharedInstance().recordPermission { + case AVAudioSessionRecordPermissionGranted: + break + case AVAudioSessionRecordPermissionDenied: + break + case AVAudioSessionRecordPermissionUndetermined: + // This is the initial state before a user has made any choice + // You can use this spot to request permission here if you want + AVAudioSession.sharedInstance().requestRecordPermission({ granted in + // Check for granted + }) + default: + break + } + } + + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +func requestCameraPermissionsIfNeeded() { + + // check camera authorization status + let authStatus: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video) + switch authStatus { + case .authorized: break + // camera authorized + // do camera intensive stuff + case .notDetermined: + // request authorization + + AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in + DispatchQueue.main.async(execute: { + + if granted { + // do camera intensive stuff + } else { + self.notifyUserOfCameraAccessDenial() + } + }) + }) + case .restricted, .denied: + DispatchQueue.main.async(execute: { + self.notifyUserOfCameraAccessDenial() + }) + default: + break + } +} + +func notifyUserOfCameraAccessDenial() { + // display a useful message asking the user to grant permissions from within Settings > Privacy > Camera +} + +// MARK: - OpenTok methods +func showAlert(_ string: String?) { + // show alertview on main UI + DispatchQueue.main.async(execute: { + let alertVC = UIAlertController( + title: "OTError", + message: string, + preferredStyle: .alert) + self.present(alertVC, animated: true) + }) +} + +// MARK: - OpenTok methods +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +/// Asynchronously begins the session connect process. Some time later, we will +/// expect a delegate method to call us back with the results of this action. +func setupSession() { + //setup one time session + if session { + session = nil + } + session = OTSession( + apiKey: kApiKey, + sessionId: kSessionId, + delegate: self) + do { + try session.connect(withToken: kToken) + } catch { + } + +} + +/// Sets up an instance of OTPublisher to use with this session. OTPubilsher +/// binds to the device camera and microphone, and will provide A/V streams +/// to the OpenTok session. +func setupPublisher() { + let settings = OTPublisherSettings() + settings.name = UIDevice.current.name + publisher = OTPublisher(delegate: self, settings: settings) + + var error: OTError? = nil + session.publish(publisher, error: &error) + if error != nil { + showAlert(error?.localizedDescription()) + } + localVideo.addSubview(publisher.view) + publisher.view.frame = CGRect(x: localVideo.bounds.origin.x, y: localVideo.bounds.origin.y, width: localVideo.bounds.size.width, height: localVideo.bounds.size.height) + +} + +/// Cleans up the publisher and its view. At this point, the publisher should not +/// be attached to the session any more. +func cleanupPublisher() { + publisher?.view.removeFromSuperview() + publisher = nil + // this is a good place to notify the end-user that publishing has stopped. +} + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +/// Instantiates a subscriber for the given stream and asynchronously begins the +/// process to begin receiving A/V content for this stream. Unlike doPublish, +/// this method does not add the subscriber to the view hierarchy. Instead, we +/// add the subscriber only after it has connected and begins receiving data. +func setupSubscribe(_ stream: OTStream?) { + subscriber = OTSubscriber(stream: stream, delegate: self) + + var error: OTError? = nil + session.subscribe(subscriber, error: &error) + if error != nil { + showAlert(error?.localizedDescription()) + } +} + +/// Cleans the subscriber from the view hierarchy, if any. +/// NB: You do *not* have to call unsubscribe in your controller in response to +/// a streamDestroyed event. Any subscribers (or the publisher) for a stream will +/// be automatically removed from the session during cleanup of the stream. +func cleanupSubscriber() { + subscriber.view.removeFromSuperview() + subscriber = nil +} + + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +// MARK: - OTSession delegate callbacks +func sessionDidConnect(_ session: OTSession?) { + if let sessionId = session?.sessionId { + print("sessionDidConnect (\(sessionId))") + } + + // Step 2: We have successfully connected, now instantiate a publisher and + // begin pushing A/V streams into OpenTok. + setupPublisher() +} + +func sessionDidDisconnect(_ session: OTSession?) { + var alertMessage: String? = nil + if let sessionId = session?.sessionId { + alertMessage = "Session disconnected: (\(sessionId))" + } + print("sessionDidDisconnect (\(alertMessage ?? ""))") +} + +func session( + _ mySession: OTSession?, + streamCreated stream: OTStream? +) { + if let streamId = stream?.streamId { + print("session streamCreated (\(streamId))") + } + + if nil == subscriber { + setupSubscribe(stream) + } +} + + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +func session( + _ session: OTSession?, + streamDestroyed stream: OTStream? +) { + if let streamId = stream?.streamId { + print("session streamDestroyed (\(streamId))") + } + + if subscriber.stream.streamId == stream?.streamId { + cleanupSubscriber() + } +} + +func session( + _ session: OTSession?, + connectionCreated connection: OTConnection? +) { + startTimer(callDuration, warningDuration) + if let connectionId = connection?.connectionId { + print("session connectionCreated (\(connectionId))") + } +} + +func session( + _ session: OTSession?, + connectionDestroyed connection: OTConnection? +) { + if let connectionId = connection?.connectionId { + print("session connectionDestroyed (\(connectionId))") + } + if subscriber.stream.connection.connectionId == connection?.connectionId { + cleanupSubscriber() + } + sessionDisconnect() +} + + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +func session( + _ session: ARSession, + didFailWithError error: Error +) { + print("didFailWithError: (\(error))") +} + +func session(_ session: OTSession, receivedSignalType type: String?, from connection: OTConnection?, with string: String?) { + print("\(session)") +} + +func sessionDisconnect() { + if session && session.sessionConnectionStatus == OTSessionConnectionStatusConnected { + print("disconnecting....") + session.disconnect(nil) + dismiss(animated: true) + return + } + dismiss(animated: true) +} + + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +//do { +// print( +// "subscriberDidConnectToStream (\(subscriber.stream.connection.connectionId))") +// assert(subscriber == subscriber) +// remoteVideo.addSubview(subscriber.view) +// subscriber.view.frame = remoteVideo.bounds +// // self.remoteVideo=_publisher.view; +//} + +- +do { + print( + "subscriber \(subscriber.stream.streamId) didFailWithError \(error)") +} + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +// MARK: - OTPublisher delegate callbacks +func publisher( + _ publisher: OTPublisherKit?, + streamCreated stream: OTStream? +) { + print("Publishing") +} + +func publisher( + _ publisher: OTPublisherKit?, + streamDestroyed stream: OTStream? +) { + if subscriber.stream.streamId == stream?.streamId { + cleanupSubscriber() + } + + cleanupPublisher() +} + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +func publisher( + _ publisher: OTPublisherKit?, + didFailWithError error: OTError? +) { + if let error = error { + print("publisher didFailWithError \(error)") + } + cleanupPublisher() +} + +// MARK: - Ui Handel +func hideVideoMuted() { + remoteVideoMutedIndicator.hidden = true + localVideoMutedBg.hidden = true + localVideoMutedIndicator.hidden = true +} + +func setupButtons() { + perform(#selector(hideControlButtons), with: nil, afterDelay: 3) + let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(remoteVideoTapped(_:))) + view.addGestureRecognizer(tapGestureRecognizer) + view.isUserInteractionEnabled = true +} + + // Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +@objc func hideControlButtons() { + controlButtons.hidden = true +} + +func remoteVideoTapped(_ recognizer: UITapGestureRecognizer?) { + if controlButtons.hidden { + controlButtons.hidden = false + perform(#selector(hideControlButtons), with: nil, afterDelay: 3) + } +} + +func resetHideButtonsTimer() { + ClingoVideoCallViewController.cancelPreviousPerformRequests(withTarget: self) + perform(#selector(hideControlButtons), with: nil, afterDelay: 3) +} + + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +@IBAction func didClickMuteButton(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + publisher.publishAudio = !sender.isSelected + resetHideButtonsTimer() +} + +@IBAction func didClickSpeakerButton(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + subscriber.subscribeToAudio = !sender.isSelected + resetHideButtonsTimer() +} + +@IBAction func didClickVideoMuteButton(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + if publisher.publishVideo { + publisher.publishVideo = false + } else { + publisher.publishVideo = true + } + localVideo.hidden = sender.isSelected + localVideoMutedBg.hidden = !sender.isSelected + localVideoMutedIndicator.hidden = !sender.isSelected + resetHideButtonsTimer() +} + + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +@IBAction func didClickSwitchCameraButton(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + if sender.isSelected { + publisher.cameraPosition = RPCameraPosition(rawValue: AVCaptureDevice.Position.back.rawValue) + } else { + publisher.cameraPosition = RPCameraPosition(rawValue: AVCaptureDevice.Position.front.rawValue) + } + resetHideButtonsTimer() +} + +@IBAction func hangUp(_ sender: UIButton) { + sessionDisconnect() +} + +// Converted to Swift 5.2 by Swiftify v5.2.26743 - https://swiftify.com/ +func startTimer(_ callDuration: String?, _ warningTime: String?) { +} + + func -currentTime as? Date! +do { + let startCallTime = Date() + dateFormatter.dateFormat = "yyyyMMddHHmmss" + let resultString = dateFormatter.string(from: startCallTime) + let date = dateFormatter.date(from: resultString) + return date +} + + +} diff --git a/lib/screens/patients/patients_screen.dart b/lib/screens/patients/patients_screen.dart index 50b89148..733a1b9c 100644 --- a/lib/screens/patients/patients_screen.dart +++ b/lib/screens/patients/patients_screen.dart @@ -1,12 +1,3 @@ -/* - *@author: Amjad Amireh Merge to Elham rababah - *@Date:27/4/2020 - *@param: - *@return:PatientsScreen - - *@desc: - */ - import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; @@ -19,6 +10,7 @@ import 'package:doctor_app_flutter/routes.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; import 'package:doctor_app_flutter/util/date-utils.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/patients/PatientCard.dart'; import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/dr_app_circular_progress_Indeicator.dart'; import 'package:doctor_app_flutter/widgets/shared/errors/dr_app_embedded_error.dart'; @@ -93,14 +85,6 @@ class _PatientsScreenState extends State { } } -/* - *@author: Amjad Amireh - *@Date:5/5/2020 - *@param: - *@return:Convert time from Milesecond to date with time - - *@desc: - */ convertDate(String str) { String timeConvert; const start = "/Date("; @@ -129,14 +113,6 @@ class _PatientsScreenState extends State { return newDateformat.toString(); } -/* - *@author: Amjad Amireh - *@Date:5/5/2020 - *@param: - *@return:Convert time from Milesecond to date - - *@desc: - */ convertDateFormat(String str) { String timeConvert; const start = "/Date("; @@ -156,24 +132,6 @@ class _PatientsScreenState extends State { return newDate.toString(); } - convertDateFormat2(String str) { - String timeConvert; - const start = "/Date("; - const end = "+0300)"; - - final startIndex = str.indexOf(start); - final endIndex = str.indexOf(end, startIndex + start.length); - - var date = new DateTime.fromMillisecondsSinceEpoch( - int.parse(str.substring(startIndex + start.length, endIndex))); - String newDate = date.year.toString() + - "/" + - date.month.toString().padLeft(2, '0') + - "/" + - date.day.toString().padLeft(2, '0'); - - return newDate.toString(); - } filterBooking(String str) { this.responseModelList = this.responseModelList2; @@ -228,14 +186,6 @@ class _PatientsScreenState extends State { return TranslationBase.of(context).all; } -/* - *@author: Amjad Amireh Modified New design - *@Date:21/5/2020 - *@param: - *@return:PatientsScreen - - *@desc: - */ @override Widget build(BuildContext context) { _locations = [ @@ -401,322 +351,19 @@ class _PatientsScreenState extends State { children: responseModelList .map((PatiantInformtion item) { - return Container( - decoration: - myBoxDecoration(), - child: InkWell( - child: Row( - children: [ - Column( - mainAxisAlignment: - MainAxisAlignment - .start, - children: < - Widget>[ - Padding( - padding: EdgeInsets - .only( - left: - 12.0), - child: - Container( - decoration: - BoxDecoration( - boxShadow: [ - BoxShadow( - color: Color.fromRGBO( - 0, - 0, - 0, - 0.08), - offset: Offset(0.0, - 5.0), - blurRadius: - 16.0) - ], - borderRadius: - BorderRadius.all( - Radius.circular(35.0)), - color: Color( - 0xffCCCCCC), - ), - width: 70, - height: 70, - child: Icon( - item.genderDescription == - "Male" - ? DoctorApp - .male - : DoctorApp - .female_icon, - size: 70, - color: Colors - .white, - ), - ), - ), - ], - ), - - SizedBox( - width: 10, - ), - - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - Column( - children: [ - SizedBox( - height: - 10.0, - ), - AppText( - item.firstName + - " " + - item.lastName, - fontSize: - 2.0 * SizeConfig.textMultiplier, - fontWeight: - FontWeight.bold, - backGroundcolor: - Colors.white, - ), - SizedBox( - height: - 5, - ), - ], - ), - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: < - Widget>[ - Wrap( - children: [ - AppText( - TranslationBase.of(context).fileNo, - fontSize: 1.8 * SizeConfig.textMultiplier, - fontWeight: FontWeight.bold, - backGroundcolor: Colors.white, - ), - AppText( - item.patientId.toString(), - fontSize: 1.8 * SizeConfig.textMultiplier, - fontWeight: FontWeight.w300, - backGroundcolor: Colors.white, - ), - SizedBox( - width: 10, - ), - ], - ), - SizedBox( - height: - 2.5, - ), - Container( - child: - AppText( - TranslationBase.of(context).nationality + " : " + (item.nationalityName ?? item.nationality), - fontSize: 1.8 * SizeConfig.textMultiplier, - fontWeight: FontWeight.bold, - backGroundcolor: Colors.white, - ), - margin: - EdgeInsets.only(right: projectsProvider.isArabic ? 0 : 10, left: projectsProvider.isArabic ? 10 : 0), - ), - SizedBox( - width: - 10, - ), - SizedBox( - height: - 15.5, - ), - SERVICES_PATIANT2[int.parse(patientType)] == "List_MyOutPatient" - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - height: 15, - width: 60, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(25), - color: HexColor("#20A169"), - ), - child: AppText( - item.startTime, - color: Colors.white, - fontSize: 1.5 * SizeConfig.textMultiplier, - textAlign: TextAlign.center, - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - width: 3.5, - ), - Container( - child: AppText( - convertDateFormat2(item.appointmentDate.toString()), - fontSize: 1.5 * SizeConfig.textMultiplier, - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 0.5, - ) - ], - ) - : SizedBox( - height: 5, - ), - ], - ), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - // mainAxisAlignment: - // MainAxisAlignment - // .spaceBetween, - children: < - Widget>[ - SizedBox( - height: - 0.5, - ), - SizedBox( - height: - 0, - ), - Wrap( - children: [ - AppText( - TranslationBase - .of( - context) - .age2, - fontSize: 1.8 * - SizeConfig - .textMultiplier, - fontWeight: FontWeight - .bold, - backGroundcolor: Colors - .white, - ), - AppText( - " ${DateUtils.getAgeByBirthday(item.dateofBirth, context)}", - - fontSize: 1.8 * - SizeConfig - .textMultiplier, - fontWeight: FontWeight - .w300, - backGroundcolor: Colors - .white, - ), - SizedBox( - width: 10, - ), - ], - ), - SizedBox( - height: - 2.5, - ), - - Wrap( - children: [ - AppText( - TranslationBase.of(context).gender2, - fontSize: 1.8 * SizeConfig.textMultiplier, - fontWeight: FontWeight.bold, - backGroundcolor: Colors.white, - ), - AppText( - item.gender.toString() == '1' ? 'Male' : 'Female', - fontSize: 1.8 * SizeConfig.textMultiplier, - fontWeight: FontWeight.w300, - backGroundcolor: Colors.white, - ), - ], - ), - SizedBox( - height: - 8, - ), - SERVICES_PATIANT2[int.parse(patientType)] == "List_MyOutPatient" - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - height: 15, - width: 60, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(25), - color: HexColor("#20A169"), - ), - child: AppText( - item.startTime, - color: Colors.white, - fontSize: 1.5 * SizeConfig.textMultiplier, - textAlign: TextAlign.center, - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - width: 3.5, - ), - Container( - child: AppText( - convertDateFormat2(item.appointmentDate.toString()), - fontSize: 1.5 * SizeConfig.textMultiplier, - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 25.5, - ), - ], - ) - : SizedBox( - height: 15, - ), - ], - ), - ), - ], - ), - ], - ), - ), - // Divider(color: Colors.grey) - ], - ), - onTap: () { - Navigator.of(context) - .pushNamed( - PATIENTS_PROFILE, - arguments: { - "patient": item, - "patientType":patientType, - "from" : patient.getFrom, - "to" : patient.getTo, - }); - }, - ), - ); + return PatientCard(patientInfo: item, + patientType: patientType, + onTap: () { + Navigator.of(context) + .pushNamed( + PATIENTS_PROFILE, + arguments: { + "patient": item, + "patientType":patientType, + "from" : patient.getFrom, + "to" : patient.getTo, + }); + },); }).toList(), ) : Center( @@ -754,88 +401,78 @@ class _PatientsScreenState extends State { } Widget _locationBar(BuildContext _context) { - return Expanded( - child: Container( - height: MediaQuery.of(context).size.height * 0.0619, - width: SizeConfig.screenWidth * 0.94, - decoration: BoxDecoration( - color: Color(0Xffffffff), - borderRadius: BorderRadius.circular(12.5), - border: Border.all( - width: 0.5, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.center, - children: _locations.map((item) { - bool _isActive = _locations[_activeLocation] == item ? true : false; - return Column(mainAxisSize: MainAxisSize.min, children: [ - InkWell( - child: Center( - child: Expanded( - child: Container( - height: MediaQuery.of(context).size.height * 0.058, - width: SizeConfig.screenWidth * 0.2334, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(12.5), - topRight: Radius.circular(12.5), - topLeft: Radius.circular(9.5), - bottomLeft: Radius.circular(9.5)), - color: - _isActive ? HexColor("#B8382B") : Colors.white, - ), - child: Center( - child: Text( - item, - style: TextStyle( - fontSize: 12, - color: _isActive - ? Colors.white - : Colors.black, //Colors.black, - - fontWeight: FontWeight.normal, - ), - ), - )), - ), - ), - onTap: () { - filterBooking(item.toString()); - - setState(() { - _activeLocation = _locations.indexOf(item); - }); - }), - _isActive - ? Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(10), - topRight: Radius.circular(10)), - color: Colors.white), - alignment: Alignment.center, - height: 1, - width: SizeConfig.screenWidth * 0.23, - ) - : Container() - ]); - }).toList(), + return Container( + height: MediaQuery.of(context).size.height * 0.0619, + width: SizeConfig.screenWidth * 0.94, + decoration: BoxDecoration( + color: Color(0Xffffffff), + borderRadius: BorderRadius.circular(12.5), + border: Border.all( + width: 0.5, ), ), - ); - } + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: _locations.map((item) { + bool _isActive = _locations[_activeLocation] == item ? true : false; + return Column(mainAxisSize: MainAxisSize.min, children: [ + InkWell( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height * 0.058, + width: SizeConfig.screenWidth * 0.2334, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(12.5), + topRight: Radius.circular(12.5), + topLeft: Radius.circular(9.5), + bottomLeft: Radius.circular(9.5)), + color: + _isActive ? HexColor("#B8382B") : Colors.white, + ), + child: Center( + child: Text( + item, + style: TextStyle( + fontSize: 12, + color: _isActive + ? Colors.white + : Colors.black, //Colors.black, + + fontWeight: FontWeight.normal, + ), + ), + )), + ), + onTap: () { + filterBooking(item.toString()); - myBoxDecoration() { - return BoxDecoration( - border: Border( - bottom: BorderSide( - color: Color(0xffCCCCCC), - width: 0.5, - ), + setState(() { + _activeLocation = _locations.indexOf(item); + }); + }), + _isActive + ? Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(10), + topRight: Radius.circular(10)), + color: Colors.white), + alignment: Alignment.center, + height: 1, + width: SizeConfig.screenWidth * 0.23, + ) + : Container() + ]); + }).toList(), ), ); } + + } + + + diff --git a/lib/widgets/patients/PatientCard.dart b/lib/widgets/patients/PatientCard.dart new file mode 100644 index 00000000..5ccae18f --- /dev/null +++ b/lib/widgets/patients/PatientCard.dart @@ -0,0 +1,244 @@ +import 'package:doctor_app_flutter/config/config.dart'; +import 'package:doctor_app_flutter/config/size_config.dart'; +import 'package:doctor_app_flutter/icons_app/doctor_app_icons.dart'; +import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; +import 'package:doctor_app_flutter/util/date-utils.dart'; +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; + +class PatientCard extends StatelessWidget { + final PatiantInformtion patientInfo; + final Function onTap; + final String patientType; + const PatientCard({Key key, this.patientInfo, this.onTap, this.patientType}) : super(key: key); + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(10), + decoration: myBoxDecoration(), + margin: EdgeInsets.only(bottom: 12), + child: InkWell( + child: Row( + children: [ + Column( + mainAxisAlignment: + MainAxisAlignment + .start, + children: < + Widget>[ + Padding( + padding: EdgeInsets + .only( + left: + 12.0), + child: + Container( + decoration: + BoxDecoration( + boxShadow: [ + BoxShadow( + color: Color.fromRGBO( + 0, + 0, + 0, + 0.08), + offset: Offset(0.0, + 5.0), + blurRadius: + 16.0) + ], + borderRadius: + BorderRadius.all( + Radius.circular(35.0)), + color: Color( + 0xffCCCCCC), + ), + width: 70, + height: 70, + child: Icon( + patientInfo.genderDescription == + "Male" + ? DoctorApp + .male + : DoctorApp + .female_icon, + size: 70, + color: Colors + .white, + ), + ), + ), + ], + ), + + SizedBox( + width: 10, + ), + Expanded( + child: Column( + crossAxisAlignment:CrossAxisAlignment.start, + children: [ + AppText( + patientInfo.firstName + + " " + + patientInfo.lastName, + fontSize: + 2.0 * SizeConfig.textMultiplier, + fontWeight: + FontWeight.bold, + backGroundcolor: + Colors.white, + ), + SizedBox(height: 12,), + Table( + border: TableBorder.symmetric( + // inside: BorderSide(width: 2.0, color: Colors.white), + ), + // defaultVerticalAlignment:TableCellVerticalAlignment.middle , + children: [ + TableRow(children: [ + Container( + child: RichText( + text: new TextSpan( + style: new TextStyle( + fontSize: 2.0 * SizeConfig.textMultiplier, color: Colors.black), + children: [ + new TextSpan( + text: TranslationBase.of(context).fileNo, + style: TextStyle(fontWeight: FontWeight.w700, fontSize: 2.2 * SizeConfig.textMultiplier)), + new TextSpan(text: patientInfo.patientId.toString()), + ],),), + ), + Container( + child: RichText( + text: new TextSpan( + style: new TextStyle( + fontSize: 2.0 * SizeConfig.textMultiplier, color: Colors.black), + children: [ + new TextSpan( + text: TranslationBase.of(context).age+ " : ", + style: TextStyle(fontWeight: FontWeight.w700, )), + new TextSpan(text: "${DateUtils.getAgeByBirthday(patientInfo.dateofBirth, context)}"), + ],),), + ), + ] + ), + TableRow(children: [ + SizedBox(height: 5,), + SizedBox(height: 5,) + ]), + TableRow(children: [ + Container( + child: RichText( + text: new TextSpan( + style: new TextStyle( + fontSize: 2.0 * SizeConfig.textMultiplier, color: Colors.black), + children: [ + new TextSpan( + text: TranslationBase.of(context).nationality + " : ", + style: TextStyle(fontWeight: FontWeight.w700, fontSize: 2.2 * SizeConfig.textMultiplier)), + new TextSpan(text: (patientInfo.nationalityName ?? patientInfo.nationality)), + ],),), + ), + + + Container( + child: RichText( + text: new TextSpan( + style: new TextStyle( + fontSize: 2.0 * SizeConfig.textMultiplier, color: Colors.black), + children: [ + new TextSpan( + text: TranslationBase.of(context).gender + " : ", + style: TextStyle(fontWeight: FontWeight.w700, )), + new TextSpan(text: patientInfo.gender.toString() == '1' ? 'Male' : 'Female'), + ],),), + ), + ] + ), + + ], + ), + if(SERVICES_PATIANT2[int.parse(patientType)] == "List_MyOutPatient") + Container( + + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + height: 15, + width: 60, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25), + color: HexColor("#20A169"), + ), + child: AppText( + patientInfo.startTime, + color: Colors.white, + fontSize: 1.5 * SizeConfig.textMultiplier, + textAlign: TextAlign.center, + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + width: 3.5, + ), + Container( + child: AppText( + convertDateFormat2(patientInfo.appointmentDate.toString()), + fontSize: 1.5 * SizeConfig.textMultiplier, + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + height: 0.5, + ) + ], + ), + margin: EdgeInsets.only(top: 8,), + ) + ], + ), + ), + + // Divider(color: Colors.grey) + ], + ), + onTap: onTap, + ), + ); + } + + convertDateFormat2(String str) { + String timeConvert; + const start = "/Date("; + const end = "+0300)"; + + final startIndex = str.indexOf(start); + final endIndex = str.indexOf(end, startIndex + start.length); + + var date = new DateTime.fromMillisecondsSinceEpoch( + int.parse(str.substring(startIndex + start.length, endIndex))); + String newDate = date.year.toString() + + "/" + + date.month.toString().padLeft(2, '0') + + "/" + + date.day.toString().padLeft(2, '0'); + + return newDate.toString(); + } + + myBoxDecoration() { + return BoxDecoration( + border: Border( + bottom: BorderSide( + color: Color(0xffCCCCCC), + width: 0.5, + ), + ), + ); + } +} \ No newline at end of file