Merge remote-tracking branch 'refs/remotes/origin/design_3.0_waseem' into design_3.0_sdk_upgrade

# Conflicts:
#	lib/controllers/providers/api/service_requests_provider.dart
#	lib/dashboard_latest/dashboard_view.dart
#	lib/dashboard_latest/widgets/progress_fragment.dart
#	lib/extensions/text_extensions.dart
#	lib/models/lookup.dart
#	lib/new_views/app_style/app_themes.dart
#	lib/new_views/common_widgets/app_bottom_nav_bar.dart
#	lib/new_views/common_widgets/app_dashed_button.dart
#	lib/new_views/common_widgets/app_filled_button.dart
#	lib/new_views/pages/land_page/land_page.dart
#	lib/new_views/pages/land_page/requests_list_page.dart
#	lib/providers/work_order/reason_provider.dart
#	lib/service_request_latest/views/components/bottom_sheets/action_bottomsheet.dart
#	lib/service_request_latest/views/components/bottom_sheets/activity_type_bottomsheet.dart
#	lib/service_request_latest/views/components/bottom_sheets/initial_visit_bottomsheet.dart
#	lib/service_request_latest/views/components/bottom_sheets/reject_request_bottomsheet.dart
#	lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart
#	lib/service_request_latest/views/components/request_detail_view.dart
#	lib/service_request_latest/views/components/verify_arrival_view.dart
#	lib/service_request_latest/views/forms/spare_part/spare_part_request.dart
#	lib/utilities/general_utils.dart
#	lib/views/widgets/date_and_time/date_picker.dart
#	lib/views/widgets/date_and_time/time_picker.dart
#	lib/views/widgets/e_signature/e_signature.dart
#	lib/views/widgets/images/multi_image_picker.dart
#	pubspec.yaml
design_3.0_demo_module
Sikander Saleem 2 years ago
commit 0d876a41fc

@ -0,0 +1,4 @@
<svg width="38" height="38" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="19" cy="19" r="19" fill="#3B3D4A"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18 20.6666V28.6667H20V20.6666H28.6667V18.6666H20V10L18 10V18.6666H10V20.6666H18Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 298 B

@ -0,0 +1,5 @@
<svg width="16" height="23" viewBox="0 0 16 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5878 1.85777C11.0729 1.49004 10.5046 1.2034 9.90276 1.00781C9.26894 0.802485 8.60665 0.698604 7.9404 0.700011C6.63333 0.694288 5.35747 1.09927 4.29297 1.85777C1.62997 3.75614 0.921755 7.41248 2.63004 10.2008L5.11728 14.2624L7.3194 17.8563C7.38449 17.963 7.47592 18.0512 7.5849 18.1124C7.69389 18.1736 7.81677 18.2057 7.94175 18.2057C8.06674 18.2057 8.18962 18.1736 8.29861 18.1124C8.40759 18.0512 8.49902 17.963 8.5641 17.8563L10.7646 14.2632L13.2518 10.2016C14.9604 7.41248 14.2508 3.75614 11.5878 1.85777ZM7.9404 11.6736C6.99781 11.6736 6.07639 11.3941 5.29266 10.8704C4.50892 10.3467 3.89808 9.60242 3.53738 8.73157C3.17668 7.86072 3.08232 6.90247 3.26623 5.978C3.45014 5.05352 3.90406 4.20434 4.57059 3.53785C5.23712 2.87135 6.08633 2.41748 7.01081 2.23362C7.9353 2.04976 8.89355 2.14418 9.76437 2.50493C10.6352 2.86568 11.3795 3.47657 11.9031 4.26033C12.4268 5.04409 12.7062 5.96553 12.7062 6.90812C12.7061 8.17203 12.204 9.38416 11.3102 10.2779C10.4165 11.1716 9.20432 11.6736 7.9404 11.6736Z" fill="white"/>
<path d="M6.95141 9.11802C6.76142 9.11784 6.57926 9.04229 6.44489 8.90796L4.94072 7.40406C4.87421 7.33753 4.82145 7.25854 4.78545 7.17162C4.74946 7.08469 4.73094 6.99153 4.73096 6.89745C4.73098 6.70744 4.80649 6.52523 4.94086 6.39089C5.07523 6.25655 5.25747 6.1811 5.44748 6.18112C5.63748 6.18115 5.8197 6.25665 5.95403 6.39102L6.95141 7.3884L9.43217 4.90764C9.49871 4.84113 9.57769 4.78837 9.66462 4.75237C9.75154 4.71638 9.84471 4.69786 9.93879 4.69788C10.0329 4.69789 10.126 4.71643 10.2129 4.75245C10.2999 4.78846 10.3788 4.84124 10.4454 4.90778C10.5119 4.97431 10.5646 5.0533 10.6006 5.14022C10.6366 5.22715 10.6551 5.32031 10.6551 5.41439C10.6551 5.50848 10.6366 5.60163 10.6005 5.68855C10.5645 5.77547 10.5117 5.85444 10.4452 5.92095L7.45793 8.90796C7.32362 9.04237 7.14143 9.11793 6.95141 9.11802Z" fill="white"/>
<path d="M11.33 14.3719L11.0662 14.8039L10.5851 15.5891C11.4696 15.7724 12.2701 16.0451 12.9284 16.3902C13.9317 16.9164 14.5309 17.5698 14.5309 18.1382C14.5309 18.7065 13.9317 19.3599 12.9284 19.8859C11.6375 20.5617 9.81936 20.95 7.94043 20.95C6.0615 20.95 4.24332 20.5617 2.95272 19.8851C1.9494 19.3591 1.35027 18.7057 1.35027 18.1374C1.35027 17.569 1.9494 16.9156 2.95272 16.3894C3.61098 16.0443 4.41072 15.7716 5.29578 15.5883L4.65669 14.545L4.55085 14.3719C1.86084 15.0386 0 16.4742 0 18.1374C0 20.437 3.55509 22.3 7.94043 22.3C12.3258 22.3 15.8809 20.437 15.8809 18.1374C15.8809 16.4742 14.02 15.0386 11.33 14.3719Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@ -1,5 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.26821 0C3.56161 0 2.90522 0.350859 2.51311 0.939328L0.590535 3.82327C0.50841 3.94627 0.468988 4.08787 0.403503 4.2188H11.2969V0H4.26821Z" fill="#767676"/> <path d="M26.3534 13.804L20.5662 11.875V2.9003C20.5662 2.55985 20.3483 2.25758 20.0253 2.1499L13.6973 0.0405392C13.5349 -0.0135658 13.3593 -0.0134603 13.197 0.0405392L6.86891 2.1499C6.54591 2.25753 6.32807 2.5598 6.32807 2.9003V11.875L0.540839 13.804C0.217844 13.9117 0 14.214 0 14.5545V24.0993C0 24.4398 0.217844 24.7421 0.540839 24.8497L6.86891 26.9591C6.95012 26.9861 7.0346 26.9997 7.11908 26.9997C7.20356 26.9997 7.28804 26.9861 7.36925 26.9591L13.4471 24.9331L19.5251 26.9591C19.6063 26.9861 19.6908 26.9997 19.7752 26.9997C19.8596 26.9997 19.9442 26.9861 20.0253 26.9591L26.3534 24.8497C26.6764 24.7421 26.8943 24.4398 26.8943 24.0993V14.5545C26.8943 14.214 26.6764 13.9117 26.3534 13.804ZM19.7752 15.83L15.9485 14.5545L19.7752 13.2789L23.6019 14.5545L19.7752 15.83ZM7.11908 13.2789L10.9457 14.5545L7.11908 15.83L3.29239 14.5545L7.11908 13.2789ZM12.6561 5.57976V13.457L7.91009 11.875V3.99774L12.6561 5.57976ZM18.9842 11.875L14.2382 13.457V5.57976L18.9842 3.99774V11.875ZM7.91009 17.234L12.6561 15.6519V23.5292L7.91009 25.1112V17.234ZM13.4471 1.62472L17.2738 2.9003L13.4471 4.17583L9.62046 2.9003L13.4471 1.62472ZM1.58202 15.6519L6.32807 17.234V25.1112L1.58202 23.5292V15.6519ZM14.2382 15.6519L18.9842 17.234V25.1112L14.2382 23.5292V15.6519ZM20.5662 25.1112V17.234L25.3123 15.6519V23.5292L20.5662 25.1112Z" fill="#7D859A"/>
<path d="M23.4095 3.82322L21.4868 0.939328C21.0948 0.350859 20.3915 0 19.6849 0H12.7031V4.21875H23.5965C23.531 4.08787 23.4916 3.94627 23.4095 3.82322Z" fill="#767676"/>
<path d="M23.9781 5.625H0.0218906C0.0197344 5.67548 0 5.72259 0 5.77331V21.8906C0 23.0538 0.946219 24 2.10938 24H21.8906C23.0538 24 24 23.0538 24 21.8906V5.77331C24 5.72259 23.9803 5.67548 23.9781 5.625ZM14.8125 12.6562H9.1875C8.02434 12.6562 7.07812 11.71 7.07812 10.5469C7.07812 9.38372 8.02434 8.4375 9.1875 8.4375H14.8125C15.9757 8.4375 16.9219 9.38372 16.9219 10.5469C16.9219 11.71 15.9757 12.6562 14.8125 12.6562Z" fill="#767676"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 878 B

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 0.25C12.2812 0.25 15.75 3.71875 15.75 8C15.75 12.2812 12.2812 15.75 8 15.75C3.71875 15.75 0.25 12.2812 0.25 8C0.25 3.71875 3.71875 0.25 8 0.25ZM8 14.25C11.4375 14.25 14.25 11.4688 14.25 8C14.25 4.5625 11.4375 1.75 8 1.75C4.53125 1.75 1.75 4.5625 1.75 8C1.75 11.4688 4.53125 14.25 8 14.25ZM9.90625 11L7.25 9.0625C7.15625 9 7.125 8.875 7.125 8.78125V3.625C7.125 3.4375 7.28125 3.25 7.5 3.25H8.5C8.6875 3.25 8.875 3.4375 8.875 3.625V8.0625L10.9375 9.59375C11.125 9.71875 11.1562 9.9375 11.0312 10.125L10.4375 10.9062C10.3125 11.0938 10.0938 11.125 9.90625 11Z" fill="#3B3D4A"/>
</svg>

After

Width:  |  Height:  |  Size: 690 B

@ -0,0 +1,5 @@
<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.7103 3.53696C20.4293 1.25596 17.3964 -0.000127577 14.1708 9.71869e-09C13.6422 9.71869e-09 13.2139 0.428436 13.2139 0.956899C13.2139 1.48536 13.6423 1.9138 14.1708 1.9138C16.8853 1.91367 19.4374 2.97073 21.357 4.89027C23.2766 6.80981 24.3337 9.36205 24.3335 12.0767C24.3335 12.6052 24.7619 13.0336 25.2904 13.0336C25.8189 13.0336 26.2473 12.6052 26.2473 12.0768C26.2475 8.85081 24.9914 5.81795 22.7103 3.53696Z" fill="#7D859A"/>
<path d="M18.774 12.0768C18.774 12.6053 19.2024 13.0337 19.731 13.0336C20.2595 13.0336 20.6878 12.6052 20.6878 12.0767C20.6875 8.48387 17.764 5.56048 14.1709 5.55997C14.1708 5.55997 14.171 5.55997 14.1709 5.55997C13.6424 5.55997 13.214 5.98828 13.2139 6.51674C13.2139 7.0452 13.6422 7.47364 14.1706 7.47377C16.7087 7.47415 18.7737 9.53901 18.774 12.0768Z" fill="#7D859A"/>
<path d="M16.6566 16.9557C15.198 16.8802 14.4549 17.965 14.0986 18.486C13.8001 18.9222 13.9119 19.5177 14.3481 19.8161C14.7844 20.1145 15.3798 20.0028 15.6782 19.5665C16.0993 18.9509 16.29 18.8541 16.5487 18.8664C17.3769 18.9637 20.6387 21.3539 20.9653 22.1013C21.0472 22.3214 21.0441 22.5372 20.9562 22.7996C20.6138 23.816 20.0469 24.5302 19.3166 24.865C18.6228 25.183 17.7722 25.1542 16.8573 24.7819C13.4409 23.3894 10.4561 21.4462 7.98603 19.0059C7.98501 19.0049 7.98399 19.004 7.98309 19.003C5.54797 16.5353 3.60828 13.5544 2.21809 10.1433C1.84567 9.22757 1.81683 8.37682 2.13491 7.68314C2.46969 6.95283 3.18392 6.38596 4.19938 6.0439C4.46272 5.95561 4.67809 5.95281 4.89614 6.03395C5.64622 6.36172 8.0363 9.62335 8.13275 10.4422C8.14653 10.7106 8.04893 10.9013 7.43383 11.3215C6.99749 11.6196 6.88534 12.215 7.18351 12.6514C7.48155 13.0877 8.07687 13.1997 8.51334 12.9017C9.03466 12.5457 10.1191 11.8047 10.0439 10.3411C9.96094 8.81241 6.98715 4.76395 5.56622 4.24149C4.93428 4.00596 4.26956 4.00188 3.58978 4.23C2.06027 4.74507 0.955624 5.66344 0.395263 6.88572C-0.148256 8.07151 -0.131032 9.44728 0.44566 10.865C1.93345 14.5155 4.01502 17.7097 6.63246 20.359C6.63884 20.3655 6.64535 20.3719 6.65198 20.3781C9.2994 22.9907 12.4898 25.0685 16.1355 26.5545C16.8655 26.8514 17.5845 27 18.2721 27C18.9194 27 19.5392 26.8683 20.1142 26.6047C21.3366 26.0445 22.2548 24.94 22.7703 23.4095C22.9979 22.731 22.9942 22.0665 22.7604 21.4375C22.2362 20.0127 18.1877 17.0389 16.6566 16.9557Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -0,0 +1,3 @@
<svg width="17" height="9" viewBox="0 0 17 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.72464 3.5C1.38354 3.5 1.0501 3.39736 0.766481 3.20507C0.482866 3.01278 0.261815 2.73947 0.131281 2.4197C0.00074726 2.09993 -0.0334063 1.74806 0.0331392 1.40859C0.0996847 1.06913 0.26394 0.757306 0.505135 0.512564C0.74633 0.267822 1.05363 0.101151 1.38818 0.0336265C1.72273 -0.0338976 2.06949 0.000758249 2.38463 0.133212C2.69977 0.265665 2.96912 0.489967 3.15862 0.777753C3.34813 1.06554 3.44928 1.40388 3.44928 1.75C3.44928 2.21413 3.26757 2.65925 2.94414 2.98744C2.62071 3.31563 2.18204 3.5 1.72464 3.5ZM10.2246 1.75C10.2246 1.40388 10.1235 1.06554 9.93398 0.777753C9.74448 0.489967 9.47513 0.265665 9.15999 0.133212C8.84485 0.000758249 8.49809 -0.0338976 8.16354 0.0336265C7.82899 0.101151 7.52169 0.267822 7.2805 0.512564C7.0393 0.757306 6.87505 1.06913 6.8085 1.40859C6.74196 1.74806 6.77611 2.09993 6.90664 2.4197C7.03718 2.73947 7.25823 3.01278 7.54184 3.20507C7.82546 3.39736 8.1589 3.5 8.5 3.5C8.9574 3.5 9.39607 3.31563 9.7195 2.98744C10.0429 2.65925 10.2246 2.21413 10.2246 1.75ZM17 1.75C17 1.40388 16.8989 1.06554 16.7093 0.777753C16.5198 0.489967 16.2505 0.265665 15.9354 0.133212C15.6202 0.000758249 15.2734 -0.0338976 14.9389 0.0336265C14.6044 0.101151 14.2971 0.267822 14.0559 0.512564C13.8147 0.757306 13.6504 1.06913 13.5839 1.40859C13.5173 1.74806 13.5515 2.09993 13.682 2.4197C13.8125 2.73947 14.0336 3.01278 14.3172 3.20507C14.6008 3.39736 14.9343 3.5 15.2754 3.5C15.7328 3.5 16.1714 3.31563 16.4949 2.98744C16.8183 2.65925 17 2.21413 17 1.75ZM3.44928 7.25C3.44928 6.90388 3.34813 6.56554 3.15862 6.27775C2.96912 5.98997 2.69977 5.76566 2.38463 5.63321C2.06949 5.50076 1.72273 5.4661 1.38818 5.53363C1.05363 5.60115 0.74633 5.76782 0.505135 6.01256C0.26394 6.25731 0.0996847 6.56912 0.0331392 6.90859C-0.0334063 7.24806 0.00074726 7.59993 0.131281 7.9197C0.261815 8.23947 0.482866 8.51278 0.766481 8.70507C1.0501 8.89736 1.38354 9 1.72464 9C2.18204 9 2.62071 8.81563 2.94414 8.48744C3.26757 8.15925 3.44928 7.71413 3.44928 7.25ZM10.2246 7.25C10.2246 6.90388 10.1235 6.56554 9.93398 6.27775C9.74448 5.98997 9.47513 5.76566 9.15999 5.63321C8.84485 5.50076 8.49809 5.4661 8.16354 5.53363C7.82899 5.60115 7.52169 5.76782 7.2805 6.01256C7.0393 6.25731 6.87505 6.56912 6.8085 6.90859C6.74196 7.24806 6.77611 7.59993 6.90664 7.9197C7.03718 8.23947 7.25823 8.51278 7.54184 8.70507C7.82546 8.89736 8.1589 9 8.5 9C8.9574 9 9.39607 8.81563 9.7195 8.48744C10.0429 8.15925 10.2246 7.71413 10.2246 7.25ZM17 7.25C17 6.90388 16.8989 6.56554 16.7093 6.27775C16.5198 5.98997 16.2505 5.76566 15.9354 5.63321C15.6202 5.50076 15.2734 5.4661 14.9389 5.53363C14.6044 5.60115 14.2971 5.76782 14.0559 6.01256C13.8147 6.25731 13.6504 6.56912 13.5839 6.90859C13.5173 7.24806 13.5515 7.59993 13.682 7.9197C13.8125 8.23947 14.0336 8.51278 14.3172 8.70507C14.6008 8.89736 14.9343 9 15.2754 9C15.7328 9 16.1714 8.81563 16.4949 8.48744C16.8183 8.15925 17 7.71413 17 7.25Z" fill="#535561"/>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@ -0,0 +1,3 @@
<svg width="20" height="18" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.977 8.50317V14.3339C20.0371 14.8263 19.9792 15.3252 19.8076 15.7933C19.636 16.2614 19.3551 16.6866 18.9861 17.0371C18.617 17.3876 18.1693 17.6543 17.6764 17.8172C17.1835 17.9802 16.6581 18.0352 16.1397 17.9781H3.86032C3.34187 18.0352 2.81653 17.9802 2.32362 17.8172C1.83071 17.6543 1.38298 17.3876 1.01393 17.0371C0.644868 16.6866 0.364038 16.2614 0.192443 15.7933C0.0208482 15.3252 -0.03707 14.8263 0.0230211 14.3339V4.61601C-0.03707 4.12364 0.0208482 3.62474 0.192443 3.15663C0.364038 2.68852 0.644868 2.26332 1.01393 1.91284C1.38298 1.56235 1.83071 1.29565 2.32362 1.13269C2.81653 0.969728 3.34187 0.914724 3.86032 0.971791H11.0233C11.2268 0.971791 11.422 1.04858 11.566 1.18526C11.7099 1.32195 11.7907 1.50733 11.7907 1.70063C11.7907 1.89394 11.7099 2.07932 11.566 2.216C11.422 2.35269 11.2268 2.42948 11.0233 2.42948H3.86032C2.24661 2.42948 1.55794 3.08349 1.55794 4.61601V13.6051L4.15707 11.1367C4.35027 10.9547 4.61142 10.8525 4.8836 10.8525C5.15578 10.8525 5.41693 10.9547 5.61013 11.1367L6.57201 12.0502C6.66765 12.1392 6.79624 12.1891 6.93016 12.1891C7.06408 12.1891 7.19267 12.1392 7.28831 12.0502L12.3433 7.24956C12.5365 7.0675 12.7977 6.96533 13.0698 6.96533C13.342 6.96533 13.6032 7.0675 13.7964 7.24956L18.4421 11.6615V8.50317C18.4421 8.30987 18.5229 8.12449 18.6668 7.9878C18.8108 7.85112 19.006 7.77433 19.2095 7.77433C19.4131 7.77433 19.6083 7.85112 19.7522 7.9878C19.8961 8.12449 19.977 8.30987 19.977 8.50317ZM5.89972 5.34485C5.55998 5.34575 5.2345 5.47467 4.99477 5.7033C4.75504 5.93192 4.62066 6.24156 4.62113 6.5642C4.6216 6.88685 4.7569 7.19613 4.9973 7.42411C5.2377 7.6521 5.56356 7.78016 5.9033 7.78016C6.24304 7.78016 6.56889 7.6521 6.8093 7.42411C7.0497 7.19613 7.18499 6.88685 7.18547 6.5642C7.18594 6.24156 7.05156 5.93192 6.81183 5.7033C6.5721 5.47467 6.24662 5.34575 5.90688 5.34485H5.89972ZM15.1164 3.40127H16.3955V4.61601C16.3955 4.80931 16.4764 4.99469 16.6203 5.13138C16.7642 5.26806 16.9594 5.34485 17.163 5.34485C17.3665 5.34485 17.5617 5.26806 17.7056 5.13138C17.8496 4.99469 17.9304 4.80931 17.9304 4.61601V3.40127H19.2095C19.4131 3.40127 19.6083 3.32448 19.7522 3.1878C19.8961 3.05111 19.977 2.86573 19.977 2.67243C19.977 2.47912 19.8961 2.29374 19.7522 2.15706C19.6083 2.02037 19.4131 1.94358 19.2095 1.94358H17.9304V0.728843C17.9304 0.535542 17.8496 0.350158 17.7056 0.213473C17.5617 0.0767885 17.3665 0 17.163 0C16.9594 0 16.7642 0.0767885 16.6203 0.213473C16.4764 0.350158 16.3955 0.535542 16.3955 0.728843V1.94358H15.1164C14.9129 1.94358 14.7176 2.02037 14.5737 2.15706C14.4298 2.29374 14.3489 2.47912 14.3489 2.67243C14.3489 2.86573 14.4298 3.05111 14.5737 3.1878C14.7176 3.32448 14.9129 3.40127 15.1164 3.40127Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,3 @@
<svg width="19" height="17" viewBox="0 0 19 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.2188 17H1.78125C0.79748 17 0 16.0486 0 14.875V2.125C0 0.95138 0.79748 0 1.78125 0H17.2188C18.2025 0 19 0.95138 19 2.125V14.875C19 16.0486 18.2025 17 17.2188 17ZM4.15625 2.47917C3.00853 2.47917 2.07812 3.58912 2.07812 4.95833C2.07812 6.32754 3.00853 7.4375 4.15625 7.4375C5.30397 7.4375 6.23438 6.32754 6.23438 4.95833C6.23438 3.58912 5.30397 2.47917 4.15625 2.47917ZM2.375 14.1667H16.625V9.20833L13.3774 5.33397C13.2035 5.12652 12.9215 5.12652 12.7476 5.33397L7.71875 11.3333L5.65862 8.87564C5.48473 8.66818 5.20277 8.66818 5.02884 8.87564L2.375 12.0417V14.1667Z" fill="#3B3D4A"/>
</svg>

After

Width:  |  Height:  |  Size: 697 B

@ -1,5 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="28" height="26" viewBox="0 0 28 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.0106 24C15.0694 24 17.8642 22.85 19.987 20.9604L11.5133 12.4867C11.3814 12.3549 11.3073 12.176 11.3073 11.9895V0C5.01077 0.365427 0 5.60294 0 11.9894C0 18.6121 5.38796 24 12.0106 24Z" fill="#163A51"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M15.696 26H0.820312C0.367218 26 0 25.6363 0 25.1875V25V3V2.4374C0 1.98885 0.367218 1.62493 0.820312 1.62493H3.28146V0.812467C3.28146 0.363706 3.64868 0 4.10178 0H12.4145C12.6354 0 12.8458 0.0903446 12.9947 0.238027L17.9166 5.11283C18.0642 5.25882 18.1569 5.4649 18.1569 5.68748V8.67372C18.736 8.94518 19.2782 9.31713 19.7565 9.79086C21.7985 11.8134 21.9778 14.9923 20.2948 17.2184L21.4384 18.351L22.0186 17.7763C22.3388 17.4592 22.8583 17.4592 23.1785 17.7763L27.2803 21.8389C28.2399 22.7893 28.2399 24.3357 27.2803 25.2861C26.3207 26.2363 24.7593 26.2363 23.8 25.2861L19.6982 21.2236C19.3777 20.9062 19.3777 20.3919 19.6982 20.0745L20.2782 19.5001L19.1349 18.3675C18.8253 18.597 18.4974 18.7917 18.1569 18.9512V21.9375C18.1569 22.3862 17.7897 22.7499 17.3366 22.7499H16.5163V25.1875C16.5163 25.6363 16.149 26 15.696 26ZM26.1201 24.137C26.4401 23.8203 26.4401 23.3047 26.1201 22.9879L22.5985 19.5001L21.4384 20.6491L24.9599 24.137C25.2799 24.4538 25.8003 24.4538 26.1201 24.137ZM12.7956 16.6852C14.3948 18.2691 16.9971 18.2691 18.5963 16.6852C20.1955 15.1011 20.1955 12.5238 18.5963 10.94C16.9969 9.35585 14.3948 9.35606 12.7956 10.94C11.1964 12.5238 11.1964 15.1011 12.7956 16.6852ZM15.3561 4.87501L13.235 2.77402V4.87501H15.3561ZM11.5942 1.62493H4.92209V21.125H16.5163V19.4393C14.7635 19.6879 12.9481 19.1342 11.6354 17.8341C9.39642 15.6165 9.39642 12.0084 11.6354 9.79086C12.9637 8.47526 14.7861 7.94017 16.5163 8.1856V6.49995H12.4145C11.9616 6.49995 11.5942 6.13624 11.5942 5.68748V1.62493Z" fill="#1E95DE"/>
<path d="M13.7084 12.6927L20.9816 19.9659C22.7252 18.007 23.8384 15.4757 24 12.6927H13.7084Z" fill="#163A51"/>
<path d="M12.7141 11.2861H24.0002C23.6483 5.22241 18.7778 0.351924 12.7141 0V11.2861Z" fill="#163A51"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,3 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.1512 17.6694C22.3808 19.8946 23.6086 22.8531 23.6086 26H21.5734C21.5734 20.6238 17.191 16.25 11.8043 16.25C6.41762 16.25 2.03522 20.6238 2.03522 26H0C0 22.8531 1.22785 19.8946 3.45739 17.6694C4.71521 16.414 6.20703 15.477 7.83455 14.8986C6.11025 13.6519 4.9863 11.6265 4.9863 9.34375C4.9863 5.56364 8.06768 2.48828 11.8552 2.48828C12.2747 2.48828 12.6856 2.52616 13.0845 2.59843C12.8894 3.22568 12.7838 3.89909 12.7727 4.60708C12.4755 4.54985 12.1689 4.51953 11.8552 4.51953C9.18991 4.51953 7.02153 6.68368 7.02153 9.34375C7.02153 12.0038 9.18991 14.168 11.8552 14.168C13.4103 14.168 14.7959 13.4311 15.6806 12.2891H17.1971C17.2008 12.2891 17.2045 12.2891 17.2082 12.2891C17.3927 12.2891 17.7054 12.2756 18.0946 12.2087C17.5909 13.2973 16.809 14.2321 15.841 14.923C17.4425 15.5032 18.9107 16.4313 20.1512 17.6694ZM26 4.7321C26 7.67066 23.8554 9.49609 20.4031 9.49609C20.0731 9.49609 19.757 9.46679 19.4635 9.42744C18.5533 10.1879 17.546 10.2578 17.2107 10.2578C17.2074 10.2578 17.2041 10.2578 17.2008 10.2578L15.3395 10.25L16.3354 8.70873C16.3483 8.68649 16.4185 8.56233 16.5012 8.35763C15.4014 7.52934 14.8062 6.27032 14.8062 4.73205C14.8062 3.15783 15.4159 1.88632 16.5693 1.05498C17.5269 0.364812 18.8526 0 20.4031 0C21.9537 0 23.2794 0.364812 24.2369 1.05498C25.3903 1.88632 26 3.15788 26 4.7321ZM23.9648 4.7321C23.9648 3.81179 23.664 3.14768 23.0454 2.70177C22.4368 2.26307 21.5231 2.03125 20.4031 2.03125C19.2831 2.03125 18.3694 2.26307 17.7609 2.70171C17.1422 3.14762 16.8415 3.81174 16.8415 4.73205C16.8415 5.821 17.2703 6.56134 18.1522 6.99532L18.705 7.2673L18.7209 7.24882L19.2873 7.3448C19.6457 7.40548 20.0271 7.46479 20.4031 7.46479C22.028 7.46484 23.9648 6.99075 23.9648 4.7321Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,3 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.1512 17.6694C22.3808 19.8946 23.6086 22.8531 23.6086 26H21.5734C21.5734 20.6238 17.191 16.25 11.8043 16.25C6.41762 16.25 2.03522 20.6238 2.03522 26H0C0 22.8531 1.22785 19.8946 3.45739 17.6694C4.71521 16.414 6.20703 15.477 7.83455 14.8986C6.11025 13.6519 4.9863 11.6265 4.9863 9.34375C4.9863 5.56364 8.06768 2.48828 11.8552 2.48828C12.2747 2.48828 12.6856 2.52616 13.0845 2.59843C12.8894 3.22568 12.7838 3.89909 12.7727 4.60708C12.4755 4.54985 12.1689 4.51953 11.8552 4.51953C9.18991 4.51953 7.02153 6.68368 7.02153 9.34375C7.02153 12.0038 9.18991 14.168 11.8552 14.168C13.4103 14.168 14.7959 13.4311 15.6806 12.2891H17.1971C17.2008 12.2891 17.2045 12.2891 17.2082 12.2891C17.3927 12.2891 17.7054 12.2756 18.0946 12.2087C17.5909 13.2973 16.809 14.2321 15.841 14.923C17.4425 15.5032 18.9107 16.4313 20.1512 17.6694ZM26 4.7321C26 7.67066 23.8554 9.49609 20.4031 9.49609C20.0731 9.49609 19.757 9.46679 19.4635 9.42744C18.5533 10.1879 17.546 10.2578 17.2107 10.2578C17.2074 10.2578 17.2041 10.2578 17.2008 10.2578L15.3395 10.25L16.3354 8.70873C16.3483 8.68649 16.4185 8.56233 16.5012 8.35763C15.4014 7.52934 14.8062 6.27032 14.8062 4.73205C14.8062 3.15783 15.4159 1.88632 16.5693 1.05498C17.5269 0.364812 18.8526 0 20.4031 0C21.9537 0 23.2794 0.364812 24.2369 1.05498C25.3903 1.88632 26 3.15788 26 4.7321ZM23.9648 4.7321C23.9648 3.81179 23.664 3.14768 23.0454 2.70177C22.4368 2.26307 21.5231 2.03125 20.4031 2.03125C19.2831 2.03125 18.3694 2.26307 17.7609 2.70171C17.1422 3.14762 16.8415 3.81174 16.8415 4.73205C16.8415 5.821 17.2703 6.56134 18.1522 6.99532L18.705 7.2673L18.7209 7.24882L19.2873 7.3448C19.6457 7.40548 20.0271 7.46479 20.4031 7.46479C22.028 7.46484 23.9648 6.99075 23.9648 4.7321Z" fill="#7D859A"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,8 @@
<svg width="24" height="20" viewBox="0 0 24 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.072 6.36365C20.6186 6.36365 20.165 6.02276 20.165 5.45454V3.18188C20.165 2.38644 19.4847 1.81821 18.8045 1.81821H16.5369C16.0834 1.81821 15.6299 1.47733 15.6299 0.909106C15.6299 0.340996 15.9701 -1.90735e-06 16.5369 -1.90735e-06H18.8045C20.5052 -1.90735e-06 21.979 1.36366 21.979 3.18188V5.45454C21.979 5.90909 21.5256 6.36365 21.072 6.36365Z" fill="white"/>
<path d="M16.5369 18.1818H18.8045C19.5982 18.1818 20.165 17.5 20.165 16.8182V14.5455C20.165 14.0909 20.5053 13.6364 21.0722 13.6364C21.639 13.6364 21.9792 13.9773 21.9792 14.5455V16.8182C21.9792 18.5227 20.6186 20 18.8045 20H16.5369C16.0835 20 15.6299 19.6591 15.6299 19.0909C15.6299 18.5227 16.0835 18.1818 16.5369 18.1818Z" fill="white"/>
<path d="M7.46667 1.81821H5.19911C4.40545 1.81821 3.83856 2.49999 3.83856 3.18188V5.45454C3.83856 5.90909 3.49843 6.36365 2.93153 6.36365C2.36465 6.36365 2.02451 5.90909 2.02451 5.45454V3.18188C2.02451 1.47733 3.38505 -1.90735e-06 5.19911 -1.90735e-06H7.46667C7.92019 -1.90735e-06 8.3737 0.340996 8.3737 0.909106C8.3737 1.47733 7.92019 1.81821 7.46667 1.81821Z" fill="white"/>
<path d="M2.93156 13.6364C3.38508 13.6364 3.83859 13.9773 3.83859 14.5455V16.8182C3.83859 17.6136 4.51886 18.1818 5.19913 18.1818H7.4667C7.92021 18.1818 8.37372 18.5227 8.37372 19.0909C8.37372 19.6591 7.92021 20 7.4667 20H5.19913C3.49845 20 2.02454 18.5227 2.02454 16.8182V14.5455C2.02454 14.0909 2.47805 13.6364 2.93156 13.6364Z" fill="white"/>
<path d="M16.5369 3.18184C17.7842 3.18184 18.8046 4.2045 18.8046 5.4545V7.49994H5.19914V5.4545C5.19914 4.2045 6.21955 3.18184 7.46671 3.18184H16.5369Z" fill="white"/>
<path d="M22.2059 10.9091H18.8046V14.5454C18.8046 15.7954 17.7842 16.8181 16.5369 16.8181H7.4667C6.21954 16.8181 5.19913 15.7954 5.19913 14.5454V10.6817H1.79779C1.34426 10.6817 0.890755 10.3409 0.890755 9.77263C0.890755 9.20452 1.23089 8.86364 1.79779 8.86364H22.2059C22.6594 8.86364 23.1129 9.20452 23.1129 9.77263C23.1129 10.3409 22.6594 10.9091 22.2059 10.9091Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -0,0 +1,186 @@
import 'package:flutter/material.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'base_step_delegate.dart';
typedef OnStepReached = void Function(int index);
enum StepShape { circle, rRectangle }
enum BorderType { normal, dotted }
class BaseStep extends StatelessWidget {
const BaseStep({
Key key,
@required this.step,
@required this.isActive,
@required this.isFinished,
@required this.isAlreadyReached,
@required this.radius,
@required this.isUnreached,
@required this.activeStepBackgroundColor,
@required this.unreachedBackgroundColor,
@required this.activeStepBorderColor,
@required this.unreachedBorderColor,
@required this.activeTextColor,
@required this.activeIconColor,
@required this.unreachedTextColor,
@required this.unreachedIconColor,
@required this.padding,
@required this.stepRadius,
@required this.showStepBorder,
@required this.lineLength,
@required this.enabled,
}) : super(key: key);
final StepModel step;
final bool isActive;
final bool isUnreached;
final bool isFinished;
final bool isAlreadyReached ;
final double radius;
final Color activeStepBackgroundColor;
final Color unreachedBackgroundColor;
final Color activeStepBorderColor;
final Color unreachedBorderColor;
final Color activeTextColor;
final Color activeIconColor;
final Color unreachedTextColor;
final Color unreachedIconColor;
final double padding;
final double stepRadius;
final bool showStepBorder;
final double lineLength;
final bool enabled;
@override
Widget build(BuildContext context) {
return SizedBox(
width: (radius * 2) + (padding ?? 0),
height: radius * 2.5 + 25,
child: CustomMultiChildLayout(
delegate: BaseStepDelegate(
stepRadius: radius,
topTitle: step.topTitle,
direction: Axis.horizontal),
children: [
LayoutId(
id: BaseStepElem.step,
child: Material(
color: Colors.transparent,
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.circular(stepRadius ?? 0),
child: Container(
width: radius * 2,
height: radius * 2,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _handleColor(context, isFinished, isActive,
isAlreadyReached)),
alignment: Alignment.center,
child: _buildIcon(context),
),
)),
LayoutId(
id: BaseStepElem.title, child: _buildStepTitle(context))
],
),
);
}
Color _handleColor(BuildContext context, bool isFinished, bool isActive,
bool isAlreadyReached) {
if (isActive) {
return activeStepBackgroundColor ?? Colors.transparent;
} else {
if (isFinished) {
return AppColor.primary10;
} else if (isAlreadyReached) {
return AppColor.primary10;
} else {
return unreachedBackgroundColor ?? Colors.transparent;
}
}
}
Color _handleTitleColor(BuildContext context, bool isFinished, bool isActive,
bool isAlreadyReached) {
if (isActive) {
return activeTextColor ?? Theme.of(context).colorScheme.primary;
} else {
if (isFinished) {
return Colors.transparent;
} else if (isAlreadyReached) {
return Colors.transparent;
} else {
return unreachedTextColor ?? Colors.grey.shade400;
}
}
}
Widget _buildStepTitle(BuildContext context) {
return SizedBox(
width: (radius * 4.5) +
(padding ?? 0),
child: step.customTitle ??
Text(
step.title ?? '',
maxLines: 3,
textAlign: TextAlign.center,
softWrap: false,
overflow: TextOverflow.visible,
style: Theme.of(context).textTheme.bodyMedium.copyWith(
color: _handleTitleColor(
context, isFinished, isActive, isAlreadyReached),
height: 1,
// fontSize: radius * 0.45,
),
),
);
}
SizedBox _buildIcon(BuildContext context) {
return SizedBox(
width: radius * 2,
height: radius * 2,
child: Center(
child: step.customStep ??
Icon(
isActive && step.activeIcon != null
? step.activeIcon.icon
: isFinished && step.finishIcon != null
? step.finishIcon.icon
: step.icon.icon,
size: radius * 0.9,
color: Colors.white,
),
),
);
}
}
class StepModel {
final Icon icon;
final Icon finishIcon;
final Icon activeIcon;
final Widget customStep;
final String title;
final Widget customTitle;
final String lineText;
final Widget customLineWidget;
final bool topTitle;
final bool enabled;
const StepModel({
this.icon,
this.finishIcon,
this.activeIcon,
this.title,
this.lineText,
this.customStep,
this.customTitle,
this.customLineWidget,
this.topTitle = false,
this.enabled = true,
}) : assert(icon != null || customStep != null);
}

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
enum BaseStepElem { step, title }
class BaseStepDelegate extends MultiChildLayoutDelegate {
final double stepRadius;
final Axis direction;
final bool topTitle;
BaseStepDelegate({
@required this.stepRadius,
@required this.direction,
this.topTitle = false,
});
@override
void performLayout(Size size) {
assert(hasChild(BaseStepElem.step));
layoutChild(
BaseStepElem.step,
BoxConstraints.loose(
size), // This just says that the child cannot be bigger than the whole layout.
);
positionChild(
BaseStepElem.step,
Offset(
(size.width - 2 * stepRadius) / 2,
direction == Axis.horizontal
? 0
: (size.height - 2 * stepRadius) / 2));
if (hasChild(BaseStepElem.title)) {
final Size titleSize = layoutChild(
BaseStepElem.title,
const BoxConstraints(),
);
Offset titleOffset = Offset(-titleSize.width / 2 + (size.width / 2),
topTitle ? -(stepRadius + titleSize.height) : (stepRadius * 2.35));
positionChild(BaseStepElem.title, titleOffset);
}
}
@override
bool shouldRelayout(BaseStepDelegate oldDelegate) {
return false;
}
}

@ -0,0 +1,80 @@
import 'package:flutter/material.dart';
class EasyLine extends StatelessWidget {
final double length;
final double width;
final Color color;
final double thickness;
final double spacing;
final LineType lineType;
final Axis axis;
const EasyLine({
key,
this.length = 50.0,
this.color = Colors.grey,
this.thickness = 3,
this.spacing = 3.0,
this.width = 2.0,
this.lineType = LineType.normal,
this.axis = Axis.horizontal,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: axis == Axis.horizontal
? length
: thickness,
height: axis == Axis.vertical
? length : thickness,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(100),
),
);
}
}
enum LineType {
normal,
dotted,
dashed,
}
class LineStyle {
final Color defaultLineColor;
final Color unreachedLineColor;
final Color activeLineColor;
final Color finishedLineColor;
final double lineLength;
final double lineThickness;
final double lineWidth;
final double lineSpace;
final LineType lineType;
final LineType unreachedLineType;
final Color progressColor;
final double progress;
const LineStyle({
Key key,
this.lineType = LineType.dotted,
this.defaultLineColor,
this.unreachedLineColor,
this.activeLineColor,
this.finishedLineColor,
this.lineLength = 40,
this.lineWidth = 4,
this.lineThickness = 1,
this.lineSpace = 5,
this.unreachedLineType,
this.progressColor,
this.progress,
}) : assert(
progressColor == null || progress != null,
'progress should be defined to use progressColor',
),
assert(
progress == null || (progress >= 0 && progress <= 1),
'progress value should be between 0 and 1',
);
}

@ -0,0 +1,289 @@
library easy_stepper;
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'components/base_step.dart';
import 'components/custom_line.dart';
class CustomStepper extends StatefulWidget {
final List<StepModel> steps;
final OnStepReached onStepReached;
final Color unreachedStepBackgroundColor;
final Color unreachedStepTextColor;
final Color unreachedStepIconColor;
final Color unreachedStepBorderColor;
final BorderType unreachedStepBorderType;
final Color activeStepBackgroundColor;
final Color activeStepTextColor;
final Color activeStepIconColor;
final Color activeStepBorderColor;
final BorderType activeStepBorderType;
final Color finishedStepBackgroundColor;
final Color finishedStepBorderColor;
final Color finishedStepTextColor;
final Color finishedStepIconColor;
final BorderType finishedStepBorderType;
final double stepRadius;
final int activeStep;
final int maxReachedStep;
final Set<int> reachedSteps;
final AlignmentGeometry alignment;
final double internalPadding;
final EdgeInsetsGeometry padding;
final bool titlesAreLargerThanSteps;
final Curve stepAnimationCurve;
final Duration stepAnimationDuration;
final double borderThickness;
final StepShape stepShape;
final double stepBorderRadius;
final bool showStepBorder;
final bool showScrollbar;
final bool fitWidth;
final LineStyle lineStyle;
const CustomStepper({
Key key,
@required this.activeStep,
@required this.steps,
this.reachedSteps,
this.maxReachedStep,
this.onStepReached,
this.unreachedStepBackgroundColor,
this.unreachedStepTextColor,
this.unreachedStepIconColor,
this.unreachedStepBorderColor,
this.activeStepTextColor,
this.activeStepIconColor=AppColor.primary10,
this.activeStepBackgroundColor=AppColor.primary10,
this.activeStepBorderColor=AppColor.primary10,
this.finishedStepBackgroundColor=AppColor.primary10,
this.finishedStepBorderColor,
this.finishedStepIconColor,
this.stepRadius = 20,
this.alignment = Alignment.center,
this.fitWidth = true,
this.showScrollbar = false,
this.padding=EdgeInsetsDirectional.zero,
this.titlesAreLargerThanSteps = false,
this.internalPadding = 8,
this.stepAnimationCurve = Curves.linear,
this.stepAnimationDuration = const Duration(seconds: 1),
this.borderThickness = 1,
this.stepShape = StepShape.circle,
this.stepBorderRadius,
this.unreachedStepBorderType,
this.activeStepBorderType,
this.finishedStepBorderType,
this.showStepBorder = false,
this.lineStyle, this.finishedStepTextColor,
}) : assert(maxReachedStep == null || reachedSteps == null,
'only "maxReachedStep" or "reachedSteps" allowed'),
super(key: key);
@override
State<CustomStepper> createState() => _CustomStepperState();
}
class _CustomStepperState extends State<CustomStepper> {
ScrollController _scrollController;
int _selectedIndex;
LineStyle lineStyle;
EdgeInsetsGeometry _padding;
@override
void initState() {
lineStyle = widget.lineStyle ?? const LineStyle();
_selectedIndex = widget.activeStep;
_scrollController = ScrollController();
_padding = const EdgeInsetsDirectional.all(10);
if (widget.steps.any((element) => element.topTitle)) {
_padding = _padding.add(const EdgeInsetsDirectional.only(top: 45));
}
if (widget.titlesAreLargerThanSteps) {
_padding = _padding.add(EdgeInsetsDirectional.symmetric(
horizontal: lineStyle.lineLength / 2));
}
if (widget.padding != null) {
_padding.add(widget.padding);
}
super.initState();
}
@override
void didUpdateWidget(CustomStepper oldWidget) {
super.didUpdateWidget(oldWidget);
// Verify that the active step falls within a valid range.
if (widget.activeStep >= 0 && widget.activeStep < widget.steps.length) {
_selectedIndex = widget.activeStep;
}
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
/// Controls the step scrolling.
void _afterLayout(_) {
for (int i = 0; i < widget.steps.length; i++) {
_scrollController.animateTo(
i *
((widget.stepRadius * 2) +
widget.internalPadding +
lineStyle.lineLength),
duration: widget.stepAnimationDuration,
curve: widget.stepAnimationCurve,
);
if (_selectedIndex == i) break;
}
}
@override
Widget build(BuildContext context) {
lineStyle = widget.lineStyle ?? const LineStyle();
return Align(
alignment: widget.alignment,
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (OverscrollIndicatorNotification overscroll) {
overscroll.disallowIndicator();
return false;
},
child: FittedBox(
fit: widget.fitWidth ? BoxFit.fitWidth : BoxFit.none,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: _buildEasySteps(),
),
)
),
);
}
List<Widget> _buildEasySteps() {
return List.generate(widget.steps.length, (index) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildStep(index),
_buildLine(index, Axis.horizontal),
],
);
});
}
BaseStep _buildStep(int index) {
final step = widget.steps[index];
return BaseStep(
step: step,
radius: widget.stepRadius,
isActive: index == widget.activeStep,
isFinished: widget.reachedSteps != null
? index < widget.activeStep && widget.reachedSteps.contains(index)
: index < widget.activeStep,
isUnreached: index > widget.activeStep,
isAlreadyReached: widget.reachedSteps != null
? widget.reachedSteps.contains(index)
: widget.maxReachedStep != null
? index <= widget.maxReachedStep
: false,
activeStepBackgroundColor: widget.activeStepBackgroundColor,
activeStepBorderColor: widget.activeStepBorderColor,
activeTextColor: widget.activeStepTextColor,
activeIconColor: widget.activeStepIconColor,
unreachedBackgroundColor: widget.unreachedStepBackgroundColor,
unreachedBorderColor: widget.unreachedStepBorderColor,
unreachedTextColor: widget.unreachedStepTextColor,
unreachedIconColor: widget.unreachedStepIconColor,
padding: max(widget.internalPadding, 0),
stepRadius: widget.stepBorderRadius,
showStepBorder: widget.showStepBorder,
lineLength: lineStyle.lineLength,
enabled: widget.steps[index].enabled,
);
}
// BorderType _handleBorderType(int index) {
// if (index == widget.activeStep) {
// //Active Step
// return widget.activeStepBorderType ?? widget.defaultStepBorderType;
// } else if (index > widget.activeStep) {
// //Unreached Step
// return widget.unreachedStepBorderType ?? widget.defaultStepBorderType;
// } else if (index < widget.activeStep) {
// //Finished Step
// return widget.finishedStepBorderType ?? widget.defaultStepBorderType;
// } else {
// return widget.defaultStepBorderType;
// }
// }
Color _getLineColor(int index) {
Color preferredColor;
if (index == widget.activeStep) {
//Active Step
preferredColor = lineStyle.activeLineColor;
} else if (index > widget.activeStep) {
//Unreached Step
preferredColor = lineStyle.unreachedLineColor;
} else if (index < widget.activeStep) {
//Finished Step
preferredColor = lineStyle.finishedLineColor;
}
return preferredColor ??
lineStyle.defaultLineColor ??
Theme.of(context).colorScheme.primary;
}
Widget _buildLine(int index, Axis axis) {
return index < widget.steps.length - 1
? Column(
children: [
Padding(
padding: EdgeInsets.only(
top: axis == Axis.horizontal
? (widget.stepRadius - lineStyle.lineThickness)
: 0,
),
child: _buildBaseLine(index, axis),
),
if (axis == Axis.horizontal &&
widget.steps[index].lineText != null) ...[
const SizedBox(height: 5),
SizedBox(
width: lineStyle.lineLength,
child: widget.steps[index].customLineWidget ??
Text(
widget.steps[index].lineText,
maxLines: 3,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.labelSmall,
),
),
],
],
)
: const Offstage();
}
EasyLine _buildBaseLine(int index, Axis axis) {
return EasyLine(
length: lineStyle.lineLength,
color: _getLineColor(index),
thickness: lineStyle.lineThickness,
spacing: lineStyle.lineSpace,
width: lineStyle.lineWidth,
axis: axis,
lineType:
index > widget.activeStep - 1 && lineStyle.unreachedLineType != null
? lineStyle.unreachedLineType
: lineStyle.lineType,
);
}
}

@ -83,6 +83,41 @@ class ApiManager {
return response; return response;
} }
Future<http.Response> postWithOutBody(
String url, {
Map<String, String> headers,
}) async {
headers ??= {};
headers.addAll(_headers);
Uri _url = Uri.parse(url);
if (!kReleaseMode) {
print("URL:$_url");
print("Headers:$headers");
}
var request = http.Request('POST', _url);
request.headers.addAll(headers);
http.StreamedResponse _streamedResponse = await request.send();
http.Response response = await http.Response.fromStream(_streamedResponse);
try {
if (response.statusCode == 401) {
showLoginDialog();
} else {
if (jsonDecode(response.body) is Map<String, dynamic>) {
final message = jsonDecode(response.body)["message"];
if (message != null && message.toString().isNotEmpty) {
Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
}
}
}
} catch (ex) {}
return response;
}
Future<http.Response> put(String url, {Map<String, String>? headers, required Map<String, dynamic> body}) async { Future<http.Response> put(String url, {Map<String, String>? headers, required Map<String, dynamic> body}) async {
headers ??= {}; headers ??= {};

@ -25,7 +25,22 @@ class URLs {
static get getSites => "$_baseUrl/Customer/GetCustomers"; // get static get getSites => "$_baseUrl/Customer/GetCustomers"; // get
static get getSitesAutoComplete => "$_baseUrl/Customer/GetCustomersAutoComplete"; // get static get getSitesAutoComplete => "$_baseUrl/Customer/GetCustomersAutoComplete"; // get
static get getSiteAutoCompleteWithoutConditionSites => "$_baseUrl/Customer/GetCustomersAutoCompleteWithoutConditionSites"; // get static get getSiteAutoCompleteWithoutConditionSites => "$_baseUrl/Customer/GetCustomersAutoCompleteWithoutConditionSites"; // get
static get nurseDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseCount';
static get nurseDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseDetails';
static get nurseConfirmReopenUrl=> '$_baseUrl/ServiceRequest/NurseConfirmReopen';
static get nurseConfirmCloseUrl=> '$_baseUrl/ServiceRequest/NurseConfirmClose';
static get engineerDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerCount';
static get engineerDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails';
static get engineerAcceptUrl=> '$_baseUrl/ServiceRequest/EngineerAccept';
static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject';
static get engineerFixRemotlyUrl=> '$_baseUrl/ServiceRequest/EngineerFixRemotly';
static get engineerNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerNeedVisit';
static get engineerMarkAsFixUrl=> '$_baseUrl/ServiceRequest/EngineerMarkAsFix';
static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById';
static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart';
static get createActivitySparePartUrl=> '$_baseUrl/ServiceRequest/CreateActivitySparePart';
static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart';
static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder';
static get getDepartments => "$_baseUrl/Customer/GetDepartmentLookup"; // get static get getDepartments => "$_baseUrl/Customer/GetDepartmentLookup"; // get
static get getAssets => "$_baseUrl/Asset/GetAssets"; // get static get getAssets => "$_baseUrl/Asset/GetAssets"; // get
static get getAssetById => "$_baseUrl/Asset/GetAssetById?assetId="; // get static get getAssetById => "$_baseUrl/Asset/GetAssetById?assetId="; // get

@ -1,12 +1,16 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/models/issue.dart';
import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart'; import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/models/service_request/service_report.dart'; import 'package:test_sa/models/service_request/service_report.dart';
@ -26,6 +30,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
// number of items call in each request // number of items call in each request
final pageItemNumber = 10; final pageItemNumber = 10;
//reset provider data //reset provider data
void reset() { void reset() {
workOrders = []; workOrders = [];
@ -37,8 +42,16 @@ class ServiceRequestsProvider extends ChangeNotifier {
// state code of current request to defied error message // state code of current request to defied error message
// like 400 customer request failed // like 400 customer request failed
// 500 service not available // 500 service not available
int? stateCode; int stateCode;
bool _isDetialLoading = false; bool _isDetialLoading=false;
bool _ackhnowledge = false;
bool get ackhnowledge => _ackhnowledge;
set ackhnowledge(bool value) {
_ackhnowledge = value;
notifyListeners();
}
bool get isDetialLoading => _isDetialLoading; bool get isDetialLoading => _isDetialLoading;
@ -46,23 +59,32 @@ class ServiceRequestsProvider extends ChangeNotifier {
_isDetialLoading = value; _isDetialLoading = value;
notifyListeners(); notifyListeners();
} // true if there is next page in product list and false if not } // true if there is next page in product list and false if not
bool nextPage = true; bool nextPage = true;
TimeOfDay? _selectedTime; TimeOfDay _selectedTime ;
TimeOfDay? get selectedTime => _selectedTime; TimeOfDay get selectedTime => _selectedTime;
set selectedTime(TimeOfDay? value) { set selectedTime(TimeOfDay value) {
_selectedTime = value; _selectedTime = value;
notifyListeners(); notifyListeners();
} // list of user requests } // list of user requests
List<ServiceRequest> serviceRequests;
List<ServiceRequest>? serviceRequests;
List<SearchWorkOrder> workOrders = []; List<SearchWorkOrder> workOrders = [];
SearchWorkOrder _formWorkOrder=SearchWorkOrder();
SearchWorkOrder get formWorkOrder => _formWorkOrder;
set formWorkOrder(SearchWorkOrder value) {
_formWorkOrder = value;
notifyListeners();
}
List<SparePartsWorkOrders> _sparePartList = []; List<SparePartsWorkOrders> _sparePartList = [];
SparePartsWorkOrders _initialSelectedSparePart = SparePartsWorkOrders(); SparePartsWorkOrders _initialSelectedSparePart = SparePartsWorkOrders();
ServiceRequest? _currentSelectedRequest; ServiceRequest _currentSelectedRequest;
int _selectedListIndex = 0; int _selectedListIndex = 0;
int get selectedListIndex => _selectedListIndex; int get selectedListIndex => _selectedListIndex;
@ -72,17 +94,19 @@ class ServiceRequestsProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
ServiceRequest? get currentSelectedRequest => _currentSelectedRequest; ServiceRequest get currentSelectedRequest => _currentSelectedRequest;
set currentSelectedRequest(ServiceRequest? value) { set currentSelectedRequest(ServiceRequest value) {
_currentSelectedRequest = value; _currentSelectedRequest = value;
print('notify listner for current selected request Called...');
notifyListeners(); notifyListeners();
} }
// when requests in-process _loading = true // when requests in-process _loading = true
// done _loading = true // done _loading = true
// failed _loading = false // failed _loading = false
bool isLoading = false; bool isLoading;
ServiceRequestSearch search = ServiceRequestSearch(); ServiceRequestSearch search = ServiceRequestSearch();
@ -91,7 +115,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
/// return state code if request complete may be 200, 404 or 403 /// return state code if request complete may be 200, 404 or 403
/// for more details check http state manager /// for more details check http state manager
/// lib\controllers\http_status_manger\http_status_manger.dart /// lib\controllers\http_status_manger\http_status_manger.dart
Future<int> getRequests({required int hospitalId}) async { Future<int> getRequests({@required int hospitalId}) async {
if (isLoading == true) return -2; if (isLoading == true) return -2;
isLoading = true; isLoading = true;
if (serviceRequests?.isEmpty ?? false) notifyListeners(); if (serviceRequests?.isEmpty ?? false) notifyListeners();
@ -113,7 +137,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
List requestsListJson = json.decode(response.body)["data"]; List requestsListJson = json.decode(response.body)["data"];
List<ServiceRequest> serviceRequestsPage = requestsListJson.map((request) => ServiceRequest.fromJson(request)).toList(); List<ServiceRequest> serviceRequestsPage = requestsListJson.map((request) => ServiceRequest.fromJson(request)).toList();
serviceRequests ??= []; serviceRequests ??= [];
serviceRequests!.addAll(serviceRequestsPage); serviceRequests.addAll(serviceRequestsPage);
notifyListeners(); notifyListeners();
if (serviceRequestsPage.length == pageItemNumber) { if (serviceRequestsPage.length == pageItemNumber) {
nextPage = true; nextPage = true;
@ -132,46 +156,46 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
// Future<ServiceRequest> getSingleServiceRequest({ Future<ServiceRequest> getSingleServiceRequest({
// required String requestId, @required String requestId,
// required String host, @required String host,
// required User user, @required User user,
// required AppLocalizations subtitle, @required AppLocalizations subtitle,
// }) async { }) async {
// String userData = ''; String userData = '';
// if (user != null) { if (user != null) {
// userData += "&uid=" + user!.id!; userData += "&uid=" + user.id;
// userData += "&token=" + user!.token!; userData += "&token=" + user.token;
// } }
//
// Response response; Response response;
// try { try {
// response = await get(Uri.parse( response = await get(Uri.parse(
// host + host +
// URLs.getSingleServiceRequest + URLs.getSingleServiceRequest +
// '?call_nid=$requestId' '?call_nid=$requestId'
// '$userData', '$userData',
// )); ));
// } catch (error) { } catch (error) {
// throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle)); throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle));
// } }
//
// // If the call to the server was successful, parse the JSON. // If the call to the server was successful, parse the JSON.
// if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// // If the call to the server was successful, parse the JSON. // If the call to the server was successful, parse the JSON.
// List jsonList = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); List jsonList = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
// List<ServiceRequest> _requests = jsonList.map((i) => ServiceRequest.fromJson(i)).toList(); List<ServiceRequest> _requests = jsonList.map((i) => ServiceRequest.fromJson(i)).toList();
// return _requests[0]; return _requests[0];
// } else { } else {
// throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle)); throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle));
// } }
// } }
Future<void> createRequest({ Future<void> createRequest({
required BuildContext context, @required BuildContext context,
required String host, @required String host,
required User user, @required User user,
required ServiceRequest serviceRequest, @required ServiceRequest serviceRequest,
}) async { }) async {
var body = { var body = {
"id": 0, "id": 0,
@ -182,7 +206,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
"requestedTime": DateTime.now().toIso8601String(), "requestedTime": DateTime.now().toIso8601String(),
"client": user.clientId, "client": user.clientId,
"callComments": serviceRequest.callComments, "callComments": serviceRequest.callComments,
if (serviceRequest.devicePhotos?.isNotEmpty ?? false) "attachmentsCallRequest": serviceRequest.devicePhotos!.map((e) => {"name": e}).toList(), if (serviceRequest.devicePhotos.isNotEmpty) "attachmentsCallRequest": serviceRequest.devicePhotos.map((e) => {"name": e}).toList(),
"priority": serviceRequest.priority?.toJson(), "priority": serviceRequest.priority?.toJson(),
"defectType": serviceRequest.defectType?.toJson(), "defectType": serviceRequest.defectType?.toJson(),
"typeofRequest": serviceRequest.type?.toJson(), "typeofRequest": serviceRequest.type?.toJson(),
@ -223,7 +247,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
if (serviceRequests != null) { if (serviceRequests != null) {
var data = json.decode(utf8.decode(response.bodyBytes)); var data = json.decode(utf8.decode(response.bodyBytes));
if (data is List) { if (data is List) {
serviceRequests!.insert(0, ServiceRequest.fromJson(data[0])); serviceRequests.insert(0, ServiceRequest.fromJson(data[0]));
} else { } else {
if (data["data"] != null && data["data"] == true) { if (data["data"] != null && data["data"] == true) {
// serviceRequests.insert(0, ServiceRequest.fromJson(data[0])); // serviceRequests.insert(0, ServiceRequest.fromJson(data[0]));
@ -243,33 +267,33 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
// Future<int> createIssueReport({ Future<int> createIssueReport({
// required String host, @required String host,
// required User user, @required User user,
// required Issue issue, @required Issue issue,
// }) async { }) async {
// Response response; Response response;
// Map<String, String> body = issue.toMap(); Map<String, String> body = issue.toMap();
// body["uid"] = user.id; body["uid"] = user.id;
// body["token"] = user.token; body["token"] = user.token;
// try { try {
// response = await post( response = await post(
// Uri.parse(host + URLs.createReport), Uri.parse(host + URLs.createReport),
// body: body, body: body,
// ); );
//
// stateCode = response.statusCode; stateCode = response.statusCode;
// if (response.statusCode >= 200 && response.statusCode < 300) {} if (response.statusCode >= 200 && response.statusCode < 300) {}
// return response.statusCode; return response.statusCode;
// } catch (error) { } catch (error) {
// return -1; return -1;
// } }
// } }
Future<PendingAssetServiceRequest?> checkAssetPendingRequest(int assetId) async { Future<PendingAssetServiceRequest> checkAssetPendingRequest(int assetId) async {
Response response; Response response;
try { try {
response = await ApiManager.instance.get(URLs.CheckIfAssetHasAnotherServiceRequest + "?assetId=$assetId"); response = await await ApiManager.instance.get(URLs.CheckIfAssetHasAnotherServiceRequest + "?assetId=$assetId");
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {} if (response.statusCode >= 200 && response.statusCode < 300) {}
return PendingAssetServiceRequest.fromJson(json.decode(response.body)["data"]); return PendingAssetServiceRequest.fromJson(json.decode(response.body)["data"]);
@ -279,16 +303,16 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<int> updateRequest({required User user, required ServiceRequest request}) async { Future<int> updateRequest({@required User user, @required ServiceRequest request}) async {
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
Map<String, dynamic> serviceRequest = await getServiceRequestById(requestId: request.id!); Map<String, dynamic> serviceRequest = await getServiceRequestById(requestId: request.id) ?? "";
final List callSiteContacts = (serviceRequest['callSiteContactPerson'] as List); final List callSiteContacts = (serviceRequest['callSiteContactPerson'] as List);
final Map<String, dynamic> callSiteContactPerson = callSiteContacts.isEmpty ? {} : callSiteContacts[0]; final Map<String, dynamic> callSiteContactPerson = callSiteContacts.isEmpty ? {} : callSiteContacts[0];
Response response; Response response;
try { try {
if ((request.audio ?? "").isNotEmpty) { if ((request.audio ?? "").isNotEmpty) {
request.audio = request.audio!.substring(request.audio!.indexOf("=") + 1, request.audio!.length); request.audio = request.audio.substring(request.audio.indexOf("=") + 1, request.audio.length);
} }
} catch (ex) {} } catch (ex) {}
@ -304,7 +328,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
"requestedThrough": request.requestedThrough?.toJson(), "requestedThrough": request.requestedThrough?.toJson(),
"voiceNote": request.audio, "voiceNote": request.audio,
"assets": request.deviceId == null ? [] : [request.deviceId], "assets": request.deviceId == null ? [] : [request.deviceId],
"attachmentsCallRequest": (request.devicePhotos?.isNotEmpty ?? false) ? request.devicePhotos?.map((e) => {"name": e.getFileName}).toList() : [], "attachmentsCallRequest": (request.devicePhotos?.isNotEmpty ?? false) ? request.devicePhotos?.map((e) => {"name": e.getFileName})?.toList() : [],
"assignedEmployee": { "assignedEmployee": {
"id": request.engineerId, "id": request.engineerId,
"name": request.engineerName, "name": request.engineerName,
@ -363,12 +387,12 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<int> createServiceReport(BuildContext context, {required ServiceReport report, required User user, required ServiceRequest request}) async { Future<int> createServiceReport(BuildContext context, {@required ServiceReport report, @required User user, @required ServiceRequest request}) async {
Response response; Response response;
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
final body = report.toJson(); final body = report.toJson();
final callRequest = CallRequest(id: num.tryParse(request.id ?? "")).toJson(); final callRequest = CallRequest(id: num.tryParse(request?.id ?? "")).toJson();
final contactPerson = [ final contactPerson = [
{ {
"id": 0, "id": 0,
@ -402,7 +426,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<int> createSubWorkOrder({required SearchWorkOrder workOrder, bool makeSuppPersonsEmpty = false}) async { Future<int> createSubWorkOrder({@required SearchWorkOrder workOrder, bool makeSuppPersonsEmpty = false}) async {
Response response; Response response;
try { try {
if (makeSuppPersonsEmpty) workOrder.supplier?.suppPersons = []; if (makeSuppPersonsEmpty) workOrder.supplier?.suppPersons = [];
@ -420,17 +444,19 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
CallRequest? callRequestForWorkOrder; CallRequest callRequestForWorkOrder;
Future<CallRequest?> getCallRequestForWorkOrder({required String callId}) async { Future<CallRequest> getCallRequestForWorkOrder({String callId}) async {
Response response; Response response;
try { try {
response = await ApiManager.instance.get(URLs.getCallRequestForWorkOrder + "?callId=$callId"); response = await ApiManager.instance.get(
URLs.getCallRequestForWorkOrder + "?callId=$callId",
);
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
Map<String, dynamic> listJson = json.decode(response.body)["data"]; Map<String, dynamic> listJson = json.decode(response.body)["data"];
// log(listJson?.toString()); log(listJson?.toString());
callRequestForWorkOrder = CallRequest.fromJson(listJson); callRequestForWorkOrder = CallRequest.fromJson(listJson);
} }
@ -442,13 +468,13 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<List<SearchWorkOrder>> searchWorkOrders({required String callId}) async { Future<List<SearchWorkOrder>> searchWorkOrders({@required String callId}) async {
Response response; Response response;
try { try {
var body = { var body = {
"pageSize": pageItemNumber, "pageSize": pageItemNumber,
"pageNumber": ((workOrders.length ?? 0) ~/ pageItemNumber) + 1, "pageNumber": ((workOrders?.length ?? 0) ~/ pageItemNumber) + 1,
"callId": callId, "callId": callId,
}; };
response = await ApiManager.instance.post(URLs.searchWorkOrders, body: body); response = await ApiManager.instance.post(URLs.searchWorkOrders, body: body);
@ -469,7 +495,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<ServiceReport?> getSubWorkOrderDetails({required String parentId}) async { Future<ServiceReport> getSubWorkOrderDetails({@required String parentId}) async {
Response response; Response response;
try { try {
response = await ApiManager.instance.get(URLs.getSubWorkerInfoAccordingToPreviousStep + "?parentId=$parentId"); response = await ApiManager.instance.get(URLs.getSubWorkerInfoAccordingToPreviousStep + "?parentId=$parentId");
@ -486,38 +512,38 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
// Future<int> createDuplicatedReport({ Future<int> createDuplicatedReport({
// required String host, @required String host,
// required User user, @required User user,
// required ServiceRequest request, @required ServiceRequest request,
// }) async { }) async {
// Response response; Response response;
// String userData = ''; String userData = '';
// if (user != null) { if (user != null) {
// userData += "&uid=" + user.id; userData += "&uid=" + user.id;
// userData += "&token=" + user.token; userData += "&token=" + user.token;
// } }
//
// try { try {
// response = await get( response = await get(
// Uri.parse(host + URLs.createDuplicatedReport + "?nid=${request.id}" + userData), Uri.parse(host + URLs.createDuplicatedReport + "?nid=${request.id}" + userData),
// ); );
//
// stateCode = response.statusCode; stateCode = response.statusCode;
//
// if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// reset(); reset();
// notifyListeners(); notifyListeners();
// } }
// return response.statusCode; return response.statusCode;
// } catch (error) { } catch (error) {
// return -1; return -1;
// } }
// } }
Future<int> updateServiceReport(BuildContext context, {required ServiceReport report}) async { Future<int> updateServiceReport(BuildContext context, {@required ServiceReport report}) async {
Response response; Response response;
report.callRequest = CallRequest(id: report.callRequest!.id!); report.callRequest = CallRequest(id: report.callRequest.id);
Map<String, dynamic> body = report.toJson(); Map<String, dynamic> body = report.toJson();
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
@ -528,7 +554,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); Fluttertoast.showToast(msg: context.translation.successfulRequestMessage);
Navigator.of(context).pop(); Navigator.of(context).pop();
} else { } else {
Fluttertoast.showToast(msg: context.translation.failedToCompleteRequest); Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest}");
} }
Navigator.of(context).pop(); Navigator.of(context).pop();
return response.statusCode; return response.statusCode;
@ -539,7 +565,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<int> updateWorkOrderDetails({required SearchWorkOrder workOrder}) async { Future<int> updateWorkOrderDetails({@required SearchWorkOrder workOrder}) async {
Response response; Response response;
//Map<String,dynamic> body = report.toMap(request); //Map<String,dynamic> body = report.toMap(request);
// body["uid"] = user.id; // body["uid"] = user.id;
@ -568,15 +594,20 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<int> updateServiceReportTimer({required String host, required User user, required TimerModel timer, required ServiceRequest request}) async { Future<int> updateServiceReportTimer({
@required String host,
@required User user,
@required TimerModel timer,
@required ServiceRequest request,
}) async {
Response response; Response response;
Map<String, dynamic> body = {}; Map<String, dynamic> body = {};
body["uid"] = user.id; body["uid"] = user.id;
body["token"] = user.token; body["token"] = user.token;
body["job_id"] = request.id; body["job_id"] = request.id;
body["start_time"] = (timer.startAt!.millisecondsSinceEpoch / 1000).toStringAsFixed(0); body["start_time"] = (timer.startAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
body["end_time"] = (timer.endAt!.millisecondsSinceEpoch / 1000).toStringAsFixed(0); body["end_time"] = (timer.endAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0);
body["working_hours"] = (timer.durationInSecond! / 60 / 60).toStringAsFixed(5); body["working_hours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5);
body["report_id"] = request.reportID; body["report_id"] = request.reportID;
try { try {
response = await post( response = await post(
@ -595,7 +626,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<ServiceReport> getSingleServiceReport(BuildContext context, {required int reportId}) async { Future<ServiceReport> getSingleServiceReport(BuildContext context, {@required int reportId}) async {
Response response; Response response;
try { try {
response = await ApiManager.instance.get(URLs.getServiceReport + "?workOrderId=$reportId"); response = await ApiManager.instance.get(URLs.getServiceReport + "?workOrderId=$reportId");
@ -612,27 +643,29 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<ServiceRequest?> getServiceRequestObjectById({required String requestId}) async { Future<ServiceRequest> getServiceRequestObjectById({@required String requestId}) async {
try { try {
isDetialLoading = true; isDetialLoading = true;
Response response = await ApiManager.instance.get(URLs.getServiceRequestById + "?callRequestId=$requestId"); Response response = await ApiManager.instance.get(URLs.getServiceRequestById + "?callRequestId=$requestId");
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
isDetialLoading = false; isDetialLoading=false;
return ServiceRequest.fromJson(json.decode(response.body)["data"]); return ServiceRequest.fromJson(json.decode(response.body)["data"]);
} else { } else {
isDetialLoading = false; isDetialLoading=false;
return null; return null;
} }
} catch (error) { } catch (error) {
isDetialLoading = false; isDetialLoading=false;
return null; return null;
} }
} }
Future<Map<String, dynamic>> getServiceRequestById({required String requestId}) async { Future<Map<String, dynamic>> getServiceRequestById({@required String requestId}) async {
Response response; Response response;
try { try {
response = await ApiManager.instance.get(URLs.getServiceRequestById + "?callRequestId=$requestId"); response = await ApiManager.instance.get(
URLs.getServiceRequestById + "?callRequestId=$requestId",
);
} catch (error) { } catch (error) {
print(error); print(error);
return {}; return {};
@ -662,17 +695,20 @@ class ServiceRequestsProvider extends ChangeNotifier {
try { try {
var body = { var body = {
"pageSize": pageItemNumber, "pageSize": pageItemNumber,
"pageNumber": ((workOrders.length ?? 0) ~/ pageItemNumber) + 1, "pageNumber": ((workOrders?.length ?? 0) ~/ pageItemNumber) + 1,
if (callerId.isNotEmpty ?? false) "callId": callerId, if (callerId?.isNotEmpty ?? false) "callId": callerId,
if (search.assetType != null) "assetSerialNo": search.assetType?.name, if (search.assetType != null) "assetSerialNo": search.assetType?.name,
if (search.workOrderNo != null) "workOrderNo": search.workOrderNo, if (search.workOrderNo != null) "workOrderNo": search.workOrderNo,
if (search.id != null) "workOrderNo": search.id.toString(), if (search.id != null) "workOrderNo": search.id?.toString(),
if (search.calllastSituation != null) "callslastSituationWO": search.calllastSituation!.toJson(), if (search.calllastSituation != null) "callslastSituationWO": search.calllastSituation.toJson(),
if (search.assignedEmployee != null) "assignedEmployees": [search.assignedEmployee!.id], if (search.assignedEmployee != null)
"assignedEmployees": [
search.assignedEmployee.id,
],
// "statusWO": [], // "statusWO": [],
if (site.isNotEmpty ?? false) "site": site, if (site?.isNotEmpty ?? false) "site": site,
if (search.visitDate != null) "visitDateSymbol": dateOperator.toJson(), if (search.visitDate != null && dateOperator != null) "visitDateSymbol": dateOperator?.toJson(),
if (search.visitDate != null) "visitDateFrom": search.visitDate, if (search.visitDate != null && dateOperator != null) "visitDateFrom": search.visitDate,
}; };
print(body); print(body);
response = await ApiManager.instance.post(URLs.searchWorkOrders, body: body); response = await ApiManager.instance.post(URLs.searchWorkOrders, body: body);
@ -695,11 +731,11 @@ class ServiceRequestsProvider extends ChangeNotifier {
} }
} }
Future<SuppEngineerWorkOrders?> addSupplierEngineer(SupplierEngineer supplierEngineer) async { Future<SuppEngineerWorkOrders> addSupplierEngineer(SupplierEngineer supplierEngineer) async {
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
Response response; Response response;
SuppEngineerWorkOrders? res; SuppEngineerWorkOrders res;
try { try {
response = await ApiManager.instance.post(URLs.addSupplierEngineer, body: supplierEngineer.toJson()); response = await ApiManager.instance.post(URLs.addSupplierEngineer, body: supplierEngineer.toJson());
stateCode = response.statusCode; stateCode = response.statusCode;
@ -722,7 +758,6 @@ class ServiceRequestsProvider extends ChangeNotifier {
_initialSelectedSparePart = value; _initialSelectedSparePart = value;
notifyListeners(); notifyListeners();
} }
List<SparePartsWorkOrders> get sparePartList => _sparePartList; List<SparePartsWorkOrders> get sparePartList => _sparePartList;
set sparePartList(List<SparePartsWorkOrders> value) { set sparePartList(List<SparePartsWorkOrders> value) {

@ -0,0 +1,142 @@
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/new_models/dashboardCount.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart';
class DashBoardProvider extends ChangeNotifier {
bool isAllCountLoading = false;
bool isLoading = false;
bool _isDetailLoading = false;
int _status =0;
int get status => _status;
set status(int value) {
_status = value;
notifyListeners();
}
int _currentListIndex = 0;
int get currentListIndex => _currentListIndex;
set currentListIndex(int value) {
_currentListIndex = value;
notifyListeners();
}
int stateCode;
DashboardCount dashboardCount;
DashboardDetail _requestDetailList;
DashboardDetail get requestDetailList => _requestDetailList;
set requestDetailList(DashboardDetail value) {
_requestDetailList = value;
notifyListeners();
}
final pageItemNumber = 10;
int pageNum = 1;
bool nextPage = true;
void reset() {
pageNum = 1;
nextPage = true;
stateCode = null;
}
Future<int> getDashBoardCount({@required UsersTypes usersType}) async {
isAllCountLoading = true;
String url='';
if(usersType==UsersTypes.engineer){
url = URLs.engineerDashboardCountUrl;
}
if(usersType==UsersTypes.nurse){
url=URLs.nurseDashboardCountUrl;
}
Response response;
try {
response = await ApiManager.instance.postWithOutBody(url);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
dashboardCount = DashboardCount.fromJson(json.decode(response.body));
}
notifyListeners();
isAllCountLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isAllCountLoading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
Future<int> getRequestDetail({bool showLoader = true,UsersTypes usersType, int status}) async {
isDetailLoading =showLoader;
Response response;
String url='';
if(usersType==UsersTypes.engineer){
url = URLs.engineerDashboardDetailsUrl;
}
if(usersType==UsersTypes.nurse){
url=URLs.nurseDashboardDetailsUrl;
}
try {
Map<String, dynamic> body = {
"statusValue": status,
"pageNumber": pageNum,
"pageSize" : pageItemNumber,
};
response = await ApiManager.instance.post(url, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
if (requestDetailList == null) {
requestDetailList = DashboardDetail.fromJson(json.decode(response.body));
isDetailLoading = false;
notifyListeners();
} else {
requestDetailList.data.addAll(DashboardDetail.fromJson(json.decode(response.body)["data"][0]).data);
isDetailLoading = false;
notifyListeners();
}
if (requestDetailList.data.length >= pageItemNumber) {
nextPage = true;
} else {
nextPage = false;
}
notifyListeners();
} else {
requestDetailList = null;
}
isDetailLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isDetailLoading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
bool get isDetailLoading => _isDetailLoading;
set isDetailLoading(bool value) {
_isDetailLoading = value;
notifyListeners();
}
}

@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -9,37 +10,42 @@ import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/notifications_provider.dart'; import 'package:test_sa/controllers/providers/api/notifications_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart'; import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/user.dart';
import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/progress_fragment.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/requests_fragment.dart'; import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart';
import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
import 'package:test_sa/utilities/request_utils.dart'; import 'package:test_sa/utilities/request_utils.dart';
import '../new_views/pages/land_page/dashboard_fragments/request_category_fragment.dart'; import 'widgets/request_category_fragment.dart';
class DashboardView extends StatefulWidget { class DashboardView extends StatefulWidget {
final VoidCallback onDrawerPress; final VoidCallback onDrawerPress;
const DashboardView({Key? key, required this.onDrawerPress}) : super(key: key); const DashboardView({Key key, this.onDrawerPress}) : super(key: key);
@override @override
State<DashboardView> createState() => _DashboardViewState(); State<DashboardView> createState() => _DashboardViewState();
} }
class _DashboardViewState extends State<DashboardView> { class _DashboardViewState extends State<DashboardView> {
final int _currentPage = 0; int _currentPage = 0;
bool isFCM = true; bool isFCM = true;
late User user; User user;
late SettingProvider settingProvider; SettingProvider settingProvider;
late UserProvider userProvider; UserProvider userProvider;
late AllRequestsProvider allRequestsProvider; AllRequestsProvider allRequestsProvider;
late NotificationsProvider notificationsProvider; NotificationsProvider notificationsProvider;
late ScrollController _scrollController; ScrollController _scrollController;
@override @override
void initState() { void initState() {
@ -52,15 +58,19 @@ class _DashboardViewState extends State<DashboardView> {
scheduleMicrotask(() async { scheduleMicrotask(() async {
userProvider = Provider.of<UserProvider>(context, listen: false); userProvider = Provider.of<UserProvider>(context, listen: false);
settingProvider = Provider.of<SettingProvider>(context, listen: false); settingProvider = Provider.of<SettingProvider>(context, listen: false);
RequestDetailProvider requestDetailProvider = Provider.of<RequestDetailProvider>(context, listen: false);
allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false); allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false);
notificationsProvider = Provider.of<NotificationsProvider>(context, listen: false); notificationsProvider = Provider.of<NotificationsProvider>(context, listen: false);
user = userProvider.user!; user = userProvider.user;
log('user token i got is ${user.token}');
await getAllRequests(); await getAllRequests();
await requestDetailProvider.engineerRejectWorkOrder(id: '3',feedBack: 'Abcdef');
if (isFCM) { if (isFCM) {
FirebaseNotificationManger.initialized(context); FirebaseNotificationManger.initialized(context);
NotificationManger.initialisation((notificationDetails) { NotificationManger.initialisation((notificationDetails) {
FirebaseNotificationManger.handleMessage(context, json.decode(notificationDetails.payload!)); FirebaseNotificationManger.handleMessage(context, json.decode(notificationDetails.payload));
}, (id, title, body, payload) async {}); }, (id, title, body, payload) async {});
isFCM = false; isFCM = false;
@ -73,7 +83,7 @@ class _DashboardViewState extends State<DashboardView> {
allRequestsProvider.isFilterRequestLoading = true; allRequestsProvider.isFilterRequestLoading = true;
allRequestsProvider.currentListIndex = 0; allRequestsProvider.currentListIndex = 0;
allRequestsProvider.filterRequest = null; allRequestsProvider.filterRequest = null;
var tabs = RequestUtils.getTabs(userType: userProvider.user!.type!, context: context); var tabs = RequestUtils.getTabs(userType: userProvider.user.type, context: context);
allRequestsProvider.status = tabs[0]['status']; allRequestsProvider.status = tabs[0]['status'];
allRequestsProvider.getRequests(); allRequestsProvider.getRequests();
allRequestsProvider.pageNum = 1; allRequestsProvider.pageNum = 1;
@ -81,19 +91,22 @@ class _DashboardViewState extends State<DashboardView> {
allRequestsProvider.requestDetailList = allRequestsProvider.filterRequest; allRequestsProvider.requestDetailList = allRequestsProvider.filterRequest;
}); });
allRequestsProvider.isAllLoading = false; allRequestsProvider.isAllLoading = false;
notificationsProvider.getSystemNotifications(user: userProvider.user!, resetProvider: true); notificationsProvider.getSystemNotifications(user: userProvider.user, resetProvider: true);
} }
void handleScroll() async { void handleScroll() async{
_scrollController = ScrollController(); _scrollController = ScrollController();
_scrollController.addListener(() async { _scrollController.addListener(() async {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !allRequestsProvider.isFilterRequestLoading) { if (_scrollController?.position?.pixels ==
_scrollController?.position?.maxScrollExtent &&
!allRequestsProvider.isFilterRequestLoading) {
allRequestsProvider.pageNum = allRequestsProvider.pageNum + 1; allRequestsProvider.pageNum = allRequestsProvider.pageNum + 1;
await allRequestsProvider.getFilterRequests(showLoader: false, status: allRequestsProvider.status); await allRequestsProvider.getFilterRequests(showLoader:false,status: allRequestsProvider.status);
} }
}); });
} }
@override @override
void dispose() { void dispose() {
_scrollController.dispose(); _scrollController.dispose();
@ -104,7 +117,11 @@ class _DashboardViewState extends State<DashboardView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
// backgroundColor: AppColor.background(context), // backgroundColor: AppColor.background(context),
appBar: PreferredSize(preferredSize: const Size.fromHeight(kToolbarHeight), child: AppBarWidget(onDrawerPress: widget.onDrawerPress)), appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: AppBarWidget(
onDrawerPress: widget.onDrawerPress,
)),
body: RefreshIndicator( body: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
getInitialData(); getInitialData();
@ -118,7 +135,15 @@ class _DashboardViewState extends State<DashboardView> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [14.height, ProgressFragment(), 25.height, SizedBox(height: 110.toScreenHeight, child: const RequestsFragment()), 16.height, const RequestCategoryFragment()], children: [
14.height,
ProgressFragment(),
25.height,
SizedBox(
height: 110.toScreenHeight, child: const RequestsFragment()),
16.height,
const RequestCategoryFragment()
],
).paddingOnly(start: 16, end: 16, top: 0, bottom: 8), ).paddingOnly(start: 16, end: 16, top: 0, bottom: 8),
), ),
), ),

@ -14,7 +14,7 @@
// import '../../../../models/enums/user_types.dart'; // import '../../../../models/enums/user_types.dart';
// //
// class ProgressFragment extends StatelessWidget { // class ProgressFragment extends StatelessWidget {
// ProgressFragment({Key? key}) : super(key: key); // ProgressFragment({Key key}) : super(key: key);
// //
// UserProvider _userProvider; // UserProvider _userProvider;
// //
@ -159,18 +159,20 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import '../../../../controllers/providers/api/user_provider.dart'; import '../../controllers/providers/api/user_provider.dart';
import '../../../../models/enums/user_types.dart'; import '../../models/enums/user_types.dart';
class ProgressFragment extends StatelessWidget { class ProgressFragment extends StatelessWidget {
ProgressFragment({Key? key}) : super(key: key); ProgressFragment({Key key}) : super(key: key);
late UserProvider _userProvider; UserProvider _userProvider;
AllRequestsProvider _provider;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
bool isCurrentUserNotEngineer = (_userProvider.user!.type != UsersTypes.engineer); bool isCurrentUserNotEngineer = (_userProvider.user.type != UsersTypes.engineer);
return Consumer<AllRequestsProvider>( return Consumer<AllRequestsProvider>(
builder: (context, snapshot, _) { builder: (context, snapshot, _) {
int total = (snapshot.completedRequests?.total?.count ?? 0) + (snapshot.inProgressRequests?.total?.count ?? 0) + (isCurrentUserNotEngineer ? (snapshot.openRequests?.total?.count ?? 0) : 0); int total = (snapshot.completedRequests?.total?.count ?? 0) + (snapshot.inProgressRequests?.total?.count ?? 0) + (isCurrentUserNotEngineer ? (snapshot.openRequests?.total?.count ?? 0) : 0);
@ -184,9 +186,6 @@ class ProgressFragment extends StatelessWidget {
if (isCurrentUserNotEngineer) { if (isCurrentUserNotEngineer) {
chartData.insert(1, ChartData('Open', snapshot.openRequests?.total?.count?.toDouble() ?? 0.0, AppColor.blueStatus(context))); chartData.insert(1, ChartData('Open', snapshot.openRequests?.total?.count?.toDouble() ?? 0.0, AppColor.blueStatus(context)));
} }
print('conditon value is ${snapshot.isInProgressLoading}');
print('conditon value is ${snapshot.isCompleteLoading}');
print('conditon value is ${snapshot.isOpenLoading}');
return Column( return Column(
children: [ children: [

@ -80,7 +80,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/new_views/common_widgets/tab_button.dart'; import 'package:test_sa/new_views/common_widgets/tab_button.dart';
import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/request_category_list.dart'; import 'package:test_sa/dashboard_latest/widgets/request_category_list.dart';
import 'package:test_sa/utilities/request_utils.dart'; import 'package:test_sa/utilities/request_utils.dart';
class RequestCategoryFragment extends StatelessWidget { class RequestCategoryFragment extends StatelessWidget {

@ -10,6 +10,14 @@ extension StringExtensions on String {
DateTime dateTime = DateTime.parse(this); DateTime dateTime = DateTime.parse(this);
return "${DateFormat('dd MMM, yyyy').format(dateTime)}\n${DateFormat('hh:mm a').format(dateTime)}"; return "${DateFormat('dd MMM, yyyy').format(dateTime)}\n${DateFormat('hh:mm a').format(dateTime)}";
} }
String get toDragAbleTimerFormat {
DateTime dateTime = DateTime.tryParse(this);
return DateFormat('HH:mm:ss').format(dateTime);
}
String get toInitialVisitCardFormat {
DateTime dateTime = DateTime.tryParse(this);
return "${DateFormat('dd MMM, yyyy').format(dateTime)} at ${DateFormat('hh:mm a').format(dateTime)}";
}
String get toServiceRequestDetailsFormat { String get toServiceRequestDetailsFormat {
try { try {

@ -16,7 +16,7 @@ extension TextStyles on String {
Text heading4(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading4, context.isDark ? AppColor.neutral30 : AppColor.neutral50); Text heading4(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading4, context.isDark ? AppColor.neutral30 : AppColor.neutral50);
Text heading5(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading5, context.isDark ? AppColor.neutral30 : AppColor.neutral50); Text heading5(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading5, context.isDark ? AppColor.neutral30 : AppColor.neutral50);
Text bottomSheetHeadingTextStyle(BuildContext context) => getTextWithStyle(this, AppTextStyles.bottomSheetHeadingTextStyle, context.isDark ? AppColor.neutral30 : AppColor.black20);
Text customHeadingText(BuildContext context) => getTextWithStyle(this, AppTextStyles.customHeadingText, context.isDark ? AppColor.neutral30 : AppColor.neutral50); Text customHeadingText(BuildContext context) => getTextWithStyle(this, AppTextStyles.customHeadingText, context.isDark ? AppColor.neutral30 : AppColor.neutral50);
Text heading6(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading6, context.isDark ? AppColor.neutral30 : AppColor.neutral50); Text heading6(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading6, context.isDark ? AppColor.neutral30 : AppColor.neutral50);
@ -33,18 +33,11 @@ extension TextStyles on String {
} }
extension CustomText on Text { extension CustomText on Text {
Text custom({ Text custom({Color color, FontWeight fontWeight, TextAlign align,double fontSize,double lineHeight,double letterSpacing}) {
Color? color,
FontWeight? fontWeight,
TextAlign? align,
double? fontSize,
double? lineHeight,
double? letterSpacing,
}) {
return Text( return Text(
data!, data,
textAlign: align, textAlign: align,
style: style?.copyWith( style: style.copyWith(
color: color, color: color,
height: lineHeight, height: lineHeight,
letterSpacing: letterSpacing, letterSpacing: letterSpacing,
@ -93,16 +86,18 @@ abstract class AppTextStyles {
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
decoration: TextDecoration.none, decoration: TextDecoration.none,
); );
static final TextStyle bottomSheetHeadingTextStyle = TextStyle(
fontSize: 21.toScreenWidth,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
decoration: TextDecoration.none,
);
static const TextStyle customHeadingText = TextStyle( static const TextStyle customHeadingText = TextStyle(
fontFamily: 'Poppins', fontFamily: 'Poppins',
fontSize: 27, fontSize: 27, // Font size in logical pixels
// Font size in logical pixels fontWeight: FontWeight.w500, // Equivalent to font-weight: 500
fontWeight: FontWeight.w500, height: 31 / 27, // Line height (in Flutter, it's a multiplier of font size)
// Equivalent to font-weight: 500 letterSpacing: -0.04 * 27, // Letter spacing, converted to logical pixels
height: 31 / 27,
// Line height (in Flutter, it's a multiplier of font size)
letterSpacing: -0.04 * 27,
// Letter spacing, converted to logical pixels
color: Colors.black, // Set your desired text color color: Colors.black, // Set your desired text color
); );
@ -133,6 +128,12 @@ abstract class AppTextStyles {
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
decoration: TextDecoration.none, decoration: TextDecoration.none,
); );
static final TextStyle tinyFont2 = TextStyle(
fontSize: 10.toScreenWidth,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
decoration: TextDecoration.none,
);
static final TextStyle overline = TextStyle( static final TextStyle overline = TextStyle(
fontSize: 9.toScreenWidth, fontSize: 9.toScreenWidth,
@ -154,31 +155,31 @@ extension CapExtension on String {
String get capitalizeFirstOfEach => trim().isNotEmpty String get capitalizeFirstOfEach => trim().isNotEmpty
? trim().toLowerCase().split(" ").map((str) { ? trim().toLowerCase().split(" ").map((str) {
return str.trim().inCaps ?? ""; return str.trim()?.inCaps ?? "";
}).join(" ") }).join(" ")
: ""; : "";
} }
extension FilesExtension on String { extension FilesExtension on String {
SvgPicture toSvgAsset({ SvgPicture toSvgAsset({
int? width, int width,
int? height, int height,
Color? color, Color color,
BoxFit fit = BoxFit.contain, BoxFit fit = BoxFit.contain,
}) => }) =>
SvgPicture.asset("assets/images/$this.svg", width: width?.toScreenWidth, height: height?.toScreenHeight, color: color, fit: fit); SvgPicture.asset("assets/images/$this.svg", width: width?.toScreenWidth, height: height?.toScreenHeight, color: color, fit: fit);
Image toPngAsset({ Image toPngAsset({
int? width, int width,
int? height, int height,
Color? color, Color color,
BoxFit fit = BoxFit.contain, BoxFit fit = BoxFit.contain,
}) => }) =>
Image.asset("assets/images/$this.png", width: width?.toScreenWidth, height: height?.toScreenHeight, color: color, fit: fit); Image.asset("assets/images/$this.png", width: width?.toScreenWidth, height: height?.toScreenHeight, color: color, fit: fit);
LottieBuilder toLottieAsset({ LottieBuilder toLottieAsset({
int? width, int width,
int? height, int height,
BoxFit fit = BoxFit.contain, BoxFit fit = BoxFit.contain,
bool repeat = true, bool repeat = true,
}) => }) =>

@ -1,3 +1,4 @@
import 'package:another_flushbar/flushbar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
@ -12,11 +13,35 @@ extension WidgetExtensions on Widget {
Widget get center => Center(child: this); Widget get center => Center(child: this);
BoxShadow get boxShadowR14 => BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14, offset: const Offset(0, 0), spreadRadius: 0); BoxShadow get boxShadowR14 => BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 5, offset: const Offset(0, 0), spreadRadius: 0);
Widget circle(double value) => ClipRRect(borderRadius: BorderRadius.circular(value), child: this); Widget circle(double value) => ClipRRect(borderRadius: BorderRadius.circular(value), child: this);
Widget paddingAll(double value) => Padding(padding: EdgeInsets.all(value), child: this); Widget paddingAll(double value) => Padding(padding: EdgeInsets.all(value), child: this);
Widget indicatorWidget({double height,double width,Color color})=> Container(
width: height??40.toScreenWidth,
height: width??5.toScreenHeight,
decoration: BoxDecoration(color:color?? AppColor.white50, borderRadius: BorderRadius.circular(30)),
child: this,
);
Widget flushBar({@required BuildContext context,String title,String message,double duration,Color backgroundColor})=>Flushbar(
flushbarPosition: FlushbarPosition.TOP,
backgroundColor:backgroundColor?? AppColor.green70,
title: title ?? "Hey Ninja",
message: message ?? "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
duration: Duration(seconds: duration ?? 3),
flushbarStyle: FlushbarStyle.GROUNDED,
reverseAnimationCurve: Curves.easeInOut,
mainButton: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: const Icon(
Icons.close,
color: AppColor.white20,
),
),
)..show(context);
Widget paddingOnly({int start = 0, int end = 0, int top = 0, int bottom = 0}) => Widget paddingOnly({int start = 0, int end = 0, int top = 0, int bottom = 0}) =>
Padding(padding: EdgeInsetsDirectional.only(start: start.toScreenWidth, end: end.toScreenWidth, top: top.toScreenHeight, bottom: bottom.toScreenHeight), child: this); Padding(padding: EdgeInsetsDirectional.only(start: start.toScreenWidth, end: end.toScreenWidth, top: top.toScreenHeight, bottom: bottom.toScreenHeight), child: this);
@ -62,6 +87,15 @@ extension WidgetExtensions on Widget {
child: this, child: this,
) )
: this; : this;
Widget bottomSheetContainer(BuildContext context, { EdgeInsets padding}) => Container(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
decoration: BoxDecoration(
color:AppColor.background(context),
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: this,);
Widget toShadowCircleContainer(BuildContext context, {bool showShadow = true, double padding = 16}) => showShadow Widget toShadowCircleContainer(BuildContext context, {bool showShadow = true, double padding = 16}) => showShadow
? Container( ? Container(

@ -73,6 +73,21 @@
"brand": "ماركة", "brand": "ماركة",
"clearSearch": "تنظيف البحث", "clearSearch": "تنظيف البحث",
"closed": "غلق", "closed": "غلق",
"close": "يغلق",
"attachFiles": "إرفاق الملفات",
"hours": "ساعات",
"internal": "داخلي",
"external": "خارجي",
"addInternalActivity": "إضافة نشاط داخلي",
"addExternalActivity": "إضافة نشاط خارجي",
"remotely": "عن بُعد",
"workshop": "ورشة",
"activityStatus": "حالة النشاط",
"scanOrPickAsset": "امسح أو اختر الأصل",
"takeAction": "اتخذ إجراء",
"pleaseConfirmTheIssueHasBeenResolved": "يرجى تأكيد أن المشكلة قد تم حلها",
"nurseAcknowledge": "أقر بإكمال أمر العمل هذا",
"abroad": "خارج البلاد",
"create": "انشاء", "create": "انشاء",
"createServiceRequest": "انشاء طلب خدمة", "createServiceRequest": "انشاء طلب خدمة",
"delete": "مسح", "delete": "مسح",
@ -269,9 +284,25 @@
"requiredField" : "الحقل مطلوب", "requiredField" : "الحقل مطلوب",
"passwordLengthMessage" : "يجب أن تتكون كلمة السر من 6 خانات على الأقل", "passwordLengthMessage" : "يجب أن تتكون كلمة السر من 6 خانات على الأقل",
"overview" : "نظرة عامة", "overview" : "نظرة عامة",
"myRequests" : "طلباتي", "request" : "طلب",
"myAssets" : "ممتلكاتي", "assets" : "الأصول",
"contactUs": "اتصل بنا", "contact": "اتصال",
"feedBack": "تعليقات",
"timeAndDuration": "الوقت والمدة",
"assetsCondition": "حالة الأصول",
"attachmentsAcknowledge": "إقرار & المرفقات",
"up_and_running": "قيد التشغيل",
"partially_down": "معطل جزئيًا",
"fully_down": "معطل تمامًا",
"verify_asset_details": "تحقق من تفاصيل الأصل",
"equipment_status": "حالة المعدات",
"failureReason": "سبب الفشل",
"visitDateAndTime": "تاريخ ووقت الزيارة",
"markAsFixed": "تحديد كإصلاح",
"iHaveArrived": "لقد وصلت",
"fixedRemotely": "تم الإصلاح عن بُعد",
"needAVisit": "بحاجة إلى زيارة",
"solutions": "الحلول",
"welcome" : "مرحبا،", "welcome" : "مرحبا،",
"openWhatsapp" : "الإنتقال الى الواتس اب", "openWhatsapp" : "الإنتقال الى الواتس اب",
"callUs" : "إتصل بنا", "callUs" : "إتصل بنا",

@ -69,6 +69,21 @@
"brand": "manufacture", "brand": "manufacture",
"clearSearch": "Clear Search", "clearSearch": "Clear Search",
"closed": "Closed", "closed": "Closed",
"close": "Close",
"scanOrPickAsset": "Scan or Pick Asset",
"attachFiles": "Attach Files",
"activityStatus": "Activity Status",
"takeAction": "Take Action",
"pleaseConfirmTheIssueHasBeenResolved": "Please confirm the issue has been resolved",
"nurseAcknowledge": "I acknowledge the completion of this work order",
"hours": "Hours",
"internal": "Internal",
"external": "External",
"addInternalActivity": "Add Internal Activity",
"addExternalActivity": "Add External Activity",
"remotely": "Remotely",
"workshop": "Workshop",
"abroad": "Abroad",
"create": "Create", "create": "Create",
"createServiceRequest": "Create Service Request", "createServiceRequest": "Create Service Request",
"delete": "Delete", "delete": "Delete",
@ -240,13 +255,29 @@
"requiredField" : "Required Field", "requiredField" : "Required Field",
"passwordLengthMessage" : "Password must has at least 6 characters", "passwordLengthMessage" : "Password must has at least 6 characters",
"overview" : "Overview", "overview" : "Overview",
"myRequests" : "My Requests", "request" : "Request",
"myAssets" : "My Assets", "assets" : "Assets",
"contactUs": "Contact Us", "contact": "Contact",
"welcome" : "Welcome,", "welcome" : "Welcome,",
"openWhatsapp" : "Open WhatsApp", "openWhatsapp" : "Open WhatsApp",
"timeAndDuration": "Time and Duration",
"assetsCondition": "Assets Condition",
"attachmentsAcknowledge": "Attachments & Acknowledge",
"up_and_running": "Up & Running",
"partially_down": "Partially Down",
"needAVisit": "Need a Visit",
"fixedRemotely": "Fixed Remotely",
"iHaveArrived": "I have arrived",
"verify_asset_details": "Verify Asset Details",
"equipment_status": "Equipment Status",
"failureReason": "Failure Reason",
"visitDateAndTime": "Visit Date & Time",
"markAsFixed": "Mark as Fixed",
"fully_down": "Fully Down",
"solutions": "Solutions",
"callUs" : "Call Us", "callUs" : "Call Us",
"liveChat" : "Live Chat", "liveChat" : "Live Chat",
"feedBack" : "Feedback",
"gasRefillRequest" : "Gas Refill Request", "gasRefillRequest" : "Gas Refill Request",
"transferRequest" : "Transfer Request", "transferRequest" : "Transfer Request",
"serviceRequest" : "Service Request", "serviceRequest" : "Service Request",

@ -55,6 +55,7 @@ import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/providers/work_order/service_type_provider.dart'; import 'package:test_sa/providers/work_order/service_type_provider.dart';
import 'package:test_sa/providers/work_order/supplier_engineer_provider.dart'; import 'package:test_sa/providers/work_order/supplier_engineer_provider.dart';
import 'package:test_sa/providers/work_order/vendor_provider.dart'; import 'package:test_sa/providers/work_order/vendor_provider.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
import 'package:test_sa/views/pages/device_transfer/asset_filter_screen.dart'; import 'package:test_sa/views/pages/device_transfer/asset_filter_screen.dart';
import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart'; import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart';
import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart';
@ -77,6 +78,7 @@ import 'package:test_sa/views/widgets/equipment/single_device_picker.dart';
import 'controllers/providers/api/gas_refill_comments.dart'; import 'controllers/providers/api/gas_refill_comments.dart';
import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/api/user_provider.dart';
import 'controllers/providers/settings/setting_provider.dart'; import 'controllers/providers/settings/setting_provider.dart';
import 'dashboard_latest/dashboard_provider.dart';
import 'new_views/pages/new_gas_refill_request_page.dart'; import 'new_views/pages/new_gas_refill_request_page.dart';
import 'providers/service_request_providers/loan_availability_provider.dart'; import 'providers/service_request_providers/loan_availability_provider.dart';
@ -131,6 +133,9 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ServiceRequestsProvider()), ChangeNotifierProvider(create: (_) => ServiceRequestsProvider()),
ChangeNotifierProvider(create: (_) => DepartmentsProvider()), ChangeNotifierProvider(create: (_) => DepartmentsProvider()),
ChangeNotifierProvider(create: (_) => NotificationsProvider()), ChangeNotifierProvider(create: (_) => NotificationsProvider()),
//new providers according to new Api's..
ChangeNotifierProvider(create: (_) => DashBoardProvider()),
ChangeNotifierProvider(create: (_) => RequestDetailProvider()),
// ChangeNotifierProvider(create: (_) => PreventiveMaintenanceVisitsProvider()), // ChangeNotifierProvider(create: (_) => PreventiveMaintenanceVisitsProvider()),
ChangeNotifierProvider(create: (_) => PpmProvider()), ChangeNotifierProvider(create: (_) => PpmProvider()),
ChangeNotifierProvider(create: (_) => PartsProvider()), ChangeNotifierProvider(create: (_) => PartsProvider()),

@ -1,4 +1,5 @@
enum UsersTypes { enum UsersTypes {
engineer, // 0 engineer, // 0
normal_user, // 1 normal_user, // 1
nurse, // 1
} }

@ -0,0 +1,64 @@
class ActivitySparePartModel {
int id;
int workOrderId;
int partCatalogItemId;
int quantity;
String comment;
List<SparePartAttachments> sparePartAttachments;
ActivitySparePartModel(
{this.id,
this.workOrderId,
this.partCatalogItemId,
this.quantity,
this.comment,
this.sparePartAttachments});
ActivitySparePartModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
workOrderId = json['workOrderId'];
partCatalogItemId = json['partCatalogItemId'];
quantity = json['quantity'];
comment = json['comment'];
if (json['acitiySparePartAttachments'] != null) {
sparePartAttachments = <SparePartAttachments>[];
json['acitiySparePartAttachments'].forEach((v) {
sparePartAttachments
.add(SparePartAttachments.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['workOrderId'] = workOrderId;
data['partCatalogItemId'] = partCatalogItemId;
data['quantity'] = quantity;
data['comment'] = comment;
if (sparePartAttachments != null) {
data['acitiySparePartAttachments'] =
sparePartAttachments.map((v) => v.toJson()).toList();
}
return data;
}
}
class SparePartAttachments {
int id;
String name;
SparePartAttachments({this.id, this.name});
SparePartAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
return data;
}
}

@ -0,0 +1,35 @@
class FixRemotely {
int workOrderId;
DateTime startDate;
DateTime endDate;
int workingHour;
String comment;
FixRemotely({
this.workOrderId,
this.startDate,
this.endDate,
this.workingHour,
this.comment,
});
factory FixRemotely.fromJson(Map<String, dynamic> json) {
return FixRemotely(
workOrderId: json['workOrderId'],
startDate: DateTime.parse(json['startDate']),
endDate: DateTime.parse(json['endDate']),
workingHour: json['workingHour'],
comment: json['comment'],
);
}
Map<String, dynamic> toJson() {
return {
'workOrderId': workOrderId,
'startDate': startDate.toIso8601String(),
'endDate': endDate.toIso8601String(),
'workingHour': workingHour,
'comment': comment,
};
}
}

@ -0,0 +1,23 @@
class MarkAsFixed {
int workOrderId;
String feedback;
MarkAsFixed({
this.workOrderId,
this.feedback,
});
factory MarkAsFixed.fromJson(Map<String, dynamic> json) {
return MarkAsFixed(
workOrderId: json['workOrderId'],
feedback: json['feedback'],
);
}
Map<String, dynamic> toJson() {
return {
'workOrderId': workOrderId,
'feedback': feedback,
};
}
}

@ -0,0 +1,27 @@
class NeedVisit {
int workOrderId;
DateTime visitDate;
String comment;
NeedVisit({
this.workOrderId,
this.visitDate,
this.comment,
});
factory NeedVisit.fromJson(Map<String, dynamic> json) {
return NeedVisit(
workOrderId: json['workOrderId'],
visitDate: DateTime.parse(json['visitDate']),
comment: json['comment'],
);
}
Map<String, dynamic> toJson() {
return {
'workOrderId': workOrderId,
'visitDate': visitDate.toIso8601String(),
'comment': comment,
};
}
}

@ -0,0 +1,27 @@
class NurseActionModel {
int workOrderId;
String feedback;
String signatureNurse;
NurseActionModel({
this.workOrderId,
this.feedback,
this.signatureNurse,
});
factory NurseActionModel.fromJson(Map<String, dynamic> json) {
return NurseActionModel(
workOrderId: json['workOrderId'],
feedback: json['feedback'],
signatureNurse: json['signatureNurse'],
);
}
Map<String, dynamic> toJson() {
return {
'workOrderId': workOrderId,
'feedback': feedback,
'signatureNurse': signatureNurse,
};
}
}

@ -1,26 +1,21 @@
import 'base.dart'; import 'base.dart';
class Lookup extends Base { class Lookup extends Base {
int? id; // Now nullable final int id, value;
int? value; // Now nullable
@override
String? name; // Now nullable
Lookup({this.id, this.value, this.name}) : super(identifier: id?.toString(), name: name); Lookup({this.id, this.value, String name}) : super(identifier: id?.toString(), name: name);
@override @override
bool operator ==(Object other) => identical(this, other) || other is Lookup && ((value != null && value == other.value) || (id != null && id == other.id)); bool operator ==(Object other) => identical(this, other) || other is Lookup && ((value != null && value == other.value) || (id != null && id == other.id));
@override @override
int get hashCode => id.hashCode ^ value.hashCode; // Use XOR for hash code combination int get hashCode => id?.hashCode ?? value?.hashCode;
Map<String, dynamic> toJson() { toJson() {
// Return a Map instead of calling a function
return {"id": id, "name": name, "value": value}; return {"id": id, "name": name, "value": value};
} }
static Lookup? fromStatus(Lookup? old) { factory Lookup.fromStatus(Lookup old) {
// Now accepts nullable Lookup and returns nullable Lookup
if (old == null) return null; if (old == null) return null;
return Lookup( return Lookup(
name: old.name, name: old.name,
@ -29,13 +24,9 @@ class Lookup extends Base {
); );
} }
// CreatedBy.fromJson(dynamic json) {
// userId = json['userId'] ?? '';
// userName = json['userName'] ?? '';
// }
factory Lookup.fromJson(Map<String, dynamic> parsedJson) { factory Lookup.fromJson(Map<String, dynamic> parsedJson) {
// if (parsedJson == null) return null;
if (parsedJson == null) return null;
return Lookup( return Lookup(
name: parsedJson["name"], name: parsedJson["name"],
id: parsedJson["id"], id: parsedJson["id"],

@ -0,0 +1,75 @@
class DashboardCount {
Data data;
String message;
String title;
String innerMessage;
int responseCode;
bool isSuccess;
DashboardCount(
{this.data,
this.message,
this.title,
this.innerMessage,
this.responseCode,
this.isSuccess});
DashboardCount.fromJson(Map<String, dynamic> json) {
data = json['data'] != null ? Data.fromJson(json['data']) : null;
message = json['message'];
title = json['title'];
innerMessage = json['innerMessage'];
responseCode = json['responseCode'];
isSuccess = json['isSuccess'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (this.data != null) {
data['data'] = this.data.toJson();
}
data['message'] = message;
data['title'] = title;
data['innerMessage'] = innerMessage;
data['responseCode'] = responseCode;
data['isSuccess'] = isSuccess;
return data;
}
}
class Data {
int countOpen;
int countInprogress;
int countComplete;
int countAcknowledge;
int countHighPriority;
int countOverdue;
Data(
{this.countOpen,
this.countInprogress,
this.countComplete,
this.countAcknowledge,
this.countHighPriority,
this.countOverdue});
Data.fromJson(Map<String, dynamic> json) {
countOpen = json['countOpen']??0;
countInprogress = json['countInprogress']??0;
countComplete = json['countComplete']??0;
countAcknowledge = json['countAcknowledge']??0;
countHighPriority = json['countHighPriority']??0;
countOverdue = json['countOverdue']??0;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['countOpen'] = countOpen;
data['countInprogress'] = countInprogress;
data['countComplete'] = countComplete;
data['countAcknowledge'] = countAcknowledge;
data['countHighPriority'] = countHighPriority;
data['countOverdue'] = countOverdue;
return data;
}
}

@ -0,0 +1,140 @@
class DashboardDetail {
List<Data> data;
int totalRows;
String message;
String title;
String innerMessage;
int responseCode;
bool isSuccess;
DashboardDetail(
{this.data,
this.totalRows,
this.message,
this.title,
this.innerMessage,
this.responseCode,
this.isSuccess});
DashboardDetail.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = <Data>[];
json['data'].forEach((v) {
data.add(Data.fromJson(v));
});
}
totalRows = json['totalRows'];
message = json['message'];
title = json['title'];
innerMessage = json['innerMessage'];
responseCode = json['responseCode'];
isSuccess = json['isSuccess'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
data['totalRows'] = totalRows;
data['message'] = message;
data['title'] = title;
data['innerMessage'] = innerMessage;
data['responseCode'] = responseCode;
data['isSuccess'] = isSuccess;
return data;
}
}
class Data {
int id;
String typeTransaction;
String transactionDate;
String statusName;
String priorityName;
bool isHighPriority;
String assetName;
String assetNumber;
String requestTypeName;
String requestNo;
Data(
{this.id,
this.typeTransaction,
this.transactionDate,
this.statusName,
this.priorityName,
this.isHighPriority,
this.assetName,
this.assetNumber,
this.requestTypeName,
this.requestNo});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
typeTransaction = json['typeTransaction'];
transactionDate = json['transactionDate'];
statusName = json['statusName'];
priorityName = json['priorityName'];
isHighPriority = json['isHighPriority'];
assetName = json['assetName'];
assetNumber = json['assetNumber'];
requestTypeName = json['requestTypeName'];
requestNo = json['requestNo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['typeTransaction'] = typeTransaction;
data['transactionDate'] = transactionDate;
data['statusName'] = statusName;
data['priorityName'] = priorityName;
data['isHighPriority'] = isHighPriority;
data['assetName'] = assetName;
data['assetNumber'] = assetNumber;
data['requestTypeName'] = requestTypeName;
data['requestNo'] = requestNo;
return data;
}
}
class CommonResponseModel{
bool data;
String message;
String title;
String innerMessage;
int responseCode;
bool isSuccess;
CommonResponseModel({
this.data,
this.message,
this.title,
this.innerMessage,
this.responseCode,
this.isSuccess,
});
factory CommonResponseModel.fromJson(Map<String, dynamic> json) {
return CommonResponseModel(
data: json['data'],
message: json['message'] ?? '',
title: json['title'],
innerMessage: json['innerMessage'],
responseCode: json['responseCode'],
isSuccess: json['isSuccess'],
);
}
Map<String, dynamic> toJson() {
return {
'data': data,
'message': message,
'title': title,
'innerMessage': innerMessage,
'responseCode': responseCode,
'isSuccess': isSuccess,
};
}
}

@ -0,0 +1,842 @@
import 'package:test_sa/models/lookup.dart';
class WorkOrderDetail {
WorkOrder data;
String message;
String title;
String innerMessage;
int responseCode;
bool isSuccess;
WorkOrderDetail({
this.data,
this.message,
this.title,
this.innerMessage,
this.responseCode,
this.isSuccess,
});
factory WorkOrderDetail.fromJson(Map<String, dynamic> json) {
return WorkOrderDetail(
data: WorkOrder.fromJson(json['data']),
message: json['message'],
title: json['title'],
innerMessage: json['innerMessage'],
responseCode: json['responseCode'],
isSuccess: json['isSuccess'],
);
}
Map<String, dynamic> toJson() {
return {
'data': data?.toJson(),
'message': message,
'title': title,
'innerMessage': innerMessage,
'responseCode': responseCode,
'isSuccess': isSuccess,
};
}
}
class WorkOrder {
String workOrderNo;
WorkOrderCreatedBy workOrderCreatedBy;
DateTime requestedDate;
Asset asset;
Lookup assetGroup;
Lookup manufacturer;
Lookup model;
Lookup assetNDModel;
Site site;
Lookup building;
Lookup floor;
Lookup department;
dynamic room;
Lookup assetType;
AssignedEmployee assignedEmployee;
dynamic lastActivityStatus;
Lookup status;
Lookup nextStep;
dynamic assetVerificationType;
List<WorkOrderContactPerson> workOrderContactPerson;
EquipmentStatus equipmentStatus;
Priority priority;
RequestedThrough requestedThrough;
TypeOfRequest typeofRequest;
dynamic loanAvailablity;
dynamic assetLoan;
dynamic safety;
ProblemDescription problemDescription;
String comments;
String voiceNote;
List<dynamic> workOrderAttachments;
dynamic returnToService;
dynamic serviceType;
dynamic failureReasone;
dynamic solution;
dynamic totalWorkingHours;
List<WorkOrderHistory> workOrderHistory;
List<dynamic> activityMaintenances;
List<dynamic> activitySpareParts;
List<dynamic> activityAssetToBeRetireds;
WorkOrder({
this.workOrderNo,
this.workOrderCreatedBy,
this.requestedDate,
this.asset,
this.assetGroup,
this.manufacturer,
this.model,
this.assetNDModel,
this.site,
this.building,
this.floor,
this.department,
this.room,
this.assetType,
this.assignedEmployee,
this.lastActivityStatus,
this.status,
this.nextStep,
this.assetVerificationType,
this.workOrderContactPerson,
this.equipmentStatus,
this.priority,
this.requestedThrough,
this.typeofRequest,
this.loanAvailablity,
this.assetLoan,
this.safety,
this.problemDescription,
this.comments,
this.voiceNote,
this.workOrderAttachments,
this.returnToService,
this.serviceType,
this.failureReasone,
this.solution,
this.totalWorkingHours,
this.workOrderHistory,
this.activityMaintenances,
this.activitySpareParts,
this.activityAssetToBeRetireds,
});
factory WorkOrder.fromJson(Map<String, dynamic> json) {
return WorkOrder(
workOrderNo: json['workOrderNo'],
workOrderCreatedBy: WorkOrderCreatedBy.fromJson(json['workOrderCreatedBy']),
requestedDate: DateTime.parse(json['requestedDate']),
asset: Asset.fromJson(json['asset']),
assetGroup: json['assetGroup']??Lookup.fromJson(json['assetGroup']),
manufacturer:json['manufacturer']?? Lookup.fromJson(json['manufacturer']),
model: json['model']?? Lookup.fromJson(json['model']),
assetNDModel:json['assetNDModel']?? Lookup.fromJson(json['assetNDModel']),
site: Site.fromJson(json['site']),
building: json['building']??Lookup.fromJson(json['building']),
floor: json['floor']??Lookup.fromJson(json['floor']),
department:json['department']?? Lookup.fromJson(json['department']),
room: json['room'],
assetType: json['assetType']??Lookup.fromJson(json['assetType']),
assignedEmployee: AssignedEmployee.fromJson(json['assignedEmployee']),
lastActivityStatus: json['lastActivityStatus'],
status: json['status']??Lookup.fromJson(json['status']),
nextStep: json['nextStep']??Lookup.fromJson(json['nextStep']),
assetVerificationType: json['assetVerificationType'],
workOrderContactPerson: (json['workOrderContactPerson'] as List)
.map((i) => WorkOrderContactPerson.fromJson(i))
.toList(),
equipmentStatus: EquipmentStatus.fromJson(json['equipmentStatus']),
priority: Priority.fromJson(json['priority']),
requestedThrough: RequestedThrough.fromJson(json['requestedThrough']),
typeofRequest: TypeOfRequest.fromJson(json['typeofRequest']),
loanAvailablity: json['loanAvailablity'],
assetLoan: json['assetLoan'],
safety: json['safety'],
problemDescription: ProblemDescription.fromJson(json['problemDescription']),
comments: json['comments'],
voiceNote: json['voiceNote'],
workOrderAttachments: json['workOrderAttachments'] as List,
returnToService: json['returnToService'],
serviceType: json['serviceType'],
failureReasone: json['failureReasone'],
solution: json['solution'],
totalWorkingHours: json['totalWorkingHours'],
workOrderHistory: (json['workOrderHistory'] as List)
.map((i) => WorkOrderHistory.fromJson(i))
.toList(),
activityMaintenances: json['activityMaintenances'] as List,
activitySpareParts: json['activitySpareParts'] as List,
activityAssetToBeRetireds: json['activityAssetToBeRetireds'] as List,
);
}
Map<String, dynamic> toJson() {
return {
'workOrderNo': workOrderNo,
'workOrderCreatedBy': workOrderCreatedBy.toJson(),
'requestedDate': requestedDate.toIso8601String(),
'asset': asset.toJson(),
'assetGroup': assetGroup.toJson(),
'manufacturer': manufacturer.toJson(),
'model': model.toJson(),
'assetNDModel': assetNDModel.toJson(),
'site': site.toJson(),
'building': building.toJson(),
'floor': floor.toJson(),
'department': department.toJson(),
'room': room,
'assetType': assetType.toJson(),
'assignedEmployee': assignedEmployee.toJson(),
'lastActivityStatus': lastActivityStatus,
'status': status.toJson(),
'nextStep': nextStep.toJson(),
'assetVerificationType': assetVerificationType,
'workOrderContactPerson': workOrderContactPerson.map((i) => i.toJson()).toList(),
'equipmentStatus': equipmentStatus.toJson(),
'priority': priority.toJson(),
'requestedThrough': requestedThrough.toJson(),
'typeofRequest': typeofRequest.toJson(),
'loanAvailablity': loanAvailablity,
'assetLoan': assetLoan,
'safety': safety,
'problemDescription': problemDescription.toJson(),
'comments': comments,
'voiceNote': voiceNote,
'workOrderAttachments': workOrderAttachments,
'returnToService': returnToService,
'serviceType': serviceType,
'failureReasone': failureReasone,
'solution': solution,
'totalWorkingHours': totalWorkingHours,
'workOrderHistory': workOrderHistory.map((i) => i.toJson()).toList(),
'activityMaintenances': activityMaintenances,
'activitySpareParts': activitySpareParts,
'activityAssetToBeRetireds': activityAssetToBeRetireds,
};
}
}
class WorkOrderCreatedBy {
String id;
String userName;
WorkOrderCreatedBy({this.id, this.userName});
factory WorkOrderCreatedBy.fromJson(Map<String, dynamic> json) {
return WorkOrderCreatedBy(
id: json['id'],
userName: json['userName'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'userName': userName,
};
}
}
class Asset {
int id;
String assetNumber;
Asset({this.id, this.assetNumber});
factory Asset.fromJson(Map<String, dynamic> json) {
return Asset(
id: json['id'],
assetNumber: json['assetNumber'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'assetNumber': assetNumber,
};
}
}
class WorkOrderContactPerson {
int id;
String name;
String employeeId;
String position;
String extension;
String email;
String mobilePhone;
ContactUser contactUser;
WorkOrderContactPerson({
this.id,
this.name,
this.employeeId,
this.position,
this.extension,
this.email,
this.mobilePhone,
this.contactUser,
});
factory WorkOrderContactPerson.fromJson(Map<String, dynamic> json) {
return WorkOrderContactPerson(
id: json['id'],
name: json['name'],
employeeId: json['employeeId'],
position: json['position'],
extension: json['extension'],
email: json['email'],
mobilePhone: json['mobilePhone'],
contactUser: ContactUser.fromJson(json['contactUser']),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'employeeId': employeeId,
'position': position,
'extension': extension,
'email': email,
'mobilePhone': mobilePhone,
'contactUser': contactUser.toJson(),
};
}
}
class ContactUser {
String id;
String userName;
ContactUser({
this.id,
this.userName,
});
factory ContactUser.fromJson(Map<String, dynamic> json) {
return ContactUser(
id: json['id'],
userName: json['userName'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'userName': userName,
};
}
}
class AssignedEmployee {
String id;
String userName;
AssignedEmployee({this.id, this.userName});
factory AssignedEmployee.fromJson(Map<String, dynamic> json) {
return AssignedEmployee(
id: json['id'],
userName: json['userName'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'userName': userName,
};
}
}
class Site {
int id;
String siteName;
Site({this.id, this.siteName});
factory Site.fromJson(Map<String, dynamic> json) {
return Site(
id: json['id'],
siteName: json['siteName'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'siteName': siteName,
};
}
}
///
// class AssetGroup {
// int id;
// String name;
//
// AssetGroup({this.id, this.name});
//
// factory AssetGroup.fromJson(Map<String, dynamic> json) {
// return AssetGroup(
// id: json['id'],
// name: json['name'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// };
// }
//
// }
//
// class Manufacturer {
// int id;
// String name;
//
// Manufacturer({this.id, this.name});
//
// factory Manufacturer.fromJson(Map<String, dynamic> json) {
// return Manufacturer(
// id: json['id'],
// name: json['name'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// };
// }
// }
//
// class Model {
// int id;
// String name;
//
// Model({this.id, this.name});
//
// factory Model.fromJson(Map<String, dynamic> json) {
// return Model(
// id: json['id'],
// name: json['name'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// };
// }
// }
//
// class AssetNDModel {
// int id;
// String name;
//
// AssetNDModel({this.id, this.name});
//
// factory AssetNDModel.fromJson(Map<String, dynamic> json) {
// return AssetNDModel(
// id: json['id'],
// name: json['name'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// };
// }
// }
//
// class Building {
// int id;
// String name;
// int value;
//
// Building({this.id, this.name, this.value});
//
// factory Building.fromJson(Map<String, dynamic> json) {
// return Building(
// id: json['id'],
// name: json['name'],
// value: json['value'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// 'value': value,
// };
// }
// }
//
// class Floor {
// int id;
// String name;
// int value;
//
// Floor({this.id, this.name, this.value});
//
// factory Floor.fromJson(Map<String, dynamic> json) {
// return Floor(
// id: json['id'],
// name: json['name'],
// value: json['value'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// 'value': value,
// };
// }
// }
//
// class Department {
// int id;
// String name;
//
// Department({this.id, this.name});
//
// factory Department.fromJson(Map<String, dynamic> json) {
// return Department(
// id: json['id'],
// name: json['name'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// };
// }
// }
//
// class AssetType {
// int id;
// String name;
// int value;
//
// AssetType({this.id, this.name, this.value});
//
// factory AssetType.fromJson(Map<String, dynamic> json) {
// return AssetType(
// id: json['id'],
// name: json['name'],
// value: json['value'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// 'value': value,
// };
// }
// }
//
// class Status {
// int id;
// String name;
// int value;
//
// Status({this.id, this.name, this.value});
//
// factory Status.fromJson(Map<String, dynamic> json) {
// return Status(
// id: json['id'],
// name: json['name'],
// value: json['value'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// 'value': value,
// };
// }
// }
//
// class NextStep {
// int id;
// String name;
// int value;
//
// NextStep({this.id, this.name, this.value});
//
// factory NextStep.fromJson(Map<String, dynamic> json) {
// return NextStep(
// id: json['id'],
// name: json['name'],
// value: json['value'],
// );
// }
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// 'value': value,
// };
// }
// }
class EquipmentStatus {
int id;
String name;
int value;
EquipmentStatus({this.id, this.name, this.value});
factory EquipmentStatus.fromJson(Map<String, dynamic> json) {
return EquipmentStatus(
id: json['id'],
name: json['name'],
value: json['value'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'value': value,
};
}
}
class Priority {
int id;
String name;
int value;
Priority({this.id, this.name, this.value});
factory Priority.fromJson(Map<String, dynamic> json) {
return Priority(
id: json['id'],
name: json['name'],
value: json['value'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'value': value,
};
}
}
class RequestedThrough {
int id;
String name;
RequestedThrough({this.id, this.name});
factory RequestedThrough.fromJson(Map<String, dynamic> json) {
return RequestedThrough(
id: json['id'],
name: json['name'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
};
}
}
class TypeOfRequest {
int id;
String name;
TypeOfRequest({this.id, this.name});
factory TypeOfRequest.fromJson(Map<String, dynamic> json) {
return TypeOfRequest(
id: json['id'],
name: json['name'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
};
}
}
class ProblemDescription {
int id;
String name;
ProblemDescription({this.id, this.name});
factory ProblemDescription.fromJson(Map<String, dynamic> json) {
return ProblemDescription(
id: json['id'],
name: json['name'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
};
}
}
class WorkOrderHistory {
int id;
Lookup workOrderStatus;
dynamic activityStatus; // Since activityStatus is null, it's dynamic
String date;
HistoryUser user;
Lookup step;
dynamic fixRemotelyStartTime; // Since it's null, it's dynamic
dynamic fixRemotelyEndTime; // Since it's null, it's dynamic
dynamic fixRemotelyWorkingHours; // Since it's null, it's dynamic
String comments;
dynamic needAVisitDateTime; // Since it's null, it's dynamic
WorkOrderHistory({
this.id,
this.workOrderStatus,
this.activityStatus,
this.date,
this.user,
this.step,
this.fixRemotelyStartTime,
this.fixRemotelyEndTime,
this.fixRemotelyWorkingHours,
this.comments,
this.needAVisitDateTime,
});
factory WorkOrderHistory.fromJson(Map<String, dynamic> json) {
return WorkOrderHistory(
id: json['id'],
//json['assetType'] != null ? Lookup.fromJson(json['assetType']) : null;
workOrderStatus:json['workorderStatus']??Lookup.fromJson(json['workorderStatus']),
activityStatus: json['activityStatus'],
date: json['date'],
user: HistoryUser.fromJson(json['user']),
step: json['step']??Lookup.fromJson(json['step']),
fixRemotelyStartTime: json['fixRemotlyStartTime'],
fixRemotelyEndTime: json['fixRemotlyEndTime'],
fixRemotelyWorkingHours: json['fixRemotlyWorkingHours'],
comments: json['comments'] ?? "",
needAVisitDateTime: json['needAVisitDateTime'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
// Lookup.fromJson(json['workorderStatus'])
'workorderStatus': workOrderStatus.toJson(),
'activityStatus': activityStatus,
'date': date,
'user': user.toJson(),
'step': step.toJson(),
'fixRemotelyStartTime': fixRemotelyStartTime,
'fixRemotelyEndTime': fixRemotelyEndTime,
'fixRemotelyWorkingHours': fixRemotelyWorkingHours,
'comments': comments,
'needAVisitDateTime': needAVisitDateTime,
};
}
}
// class WorkOrderStatus {
// int id;
// String name;
// int value;
//
// WorkOrderStatus({
// this.id,
// this.name,
// this.value,
// });
//
// factory WorkOrderStatus.fromJson(Map<String, dynamic> json) {
// return WorkOrderStatus(
// id: json['id'],
// name: json['name'],
// value: json['value'],
// );
// }
//
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// 'value': value,
// };
// }
// }
class HistoryUser {
String id;
String userName;
HistoryUser({
this.id,
this.userName,
});
factory HistoryUser.fromJson(Map<String, dynamic> json) {
return HistoryUser(
id: json['id'],
userName: json['userName'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'userName': userName,
};
}
}
// class Step {
// int id;
// String name;
// int value;
//
// Step({
// this.id,
// this.name,
// this.value,
// });
//
// factory Step.fromJson(Map<String, dynamic> json) {
// return Step(
// id: json['id'],
// name: json['name'],
// value: json['value'],
// );
// }
//
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'name': name,
// 'value': value,
// };
// }
// }

@ -12,6 +12,7 @@ class AppColor {
static const Color primary60 = Color(0xff3B7097); static const Color primary60 = Color(0xff3B7097);
static const Color primary70 = Color(0xff163A51); static const Color primary70 = Color(0xff163A51);
static const Color primary80 = Color(0xff161D27); static const Color primary80 = Color(0xff161D27);
static const Color primary90 = Color(0xff1E95DE);
//texts //texts
static const Color neutral10 = Color(0xffBCBCBC); static const Color neutral10 = Color(0xffBCBCBC);
@ -37,6 +38,8 @@ class AppColor {
static const Color white20 = Color(0xffF7F9FB); static const Color white20 = Color(0xffF7F9FB);
static const Color white30 = Color(0xffE7EBF2); static const Color white30 = Color(0xffE7EBF2);
static const Color white40 = Color(0xffE4EBEE); static const Color white40 = Color(0xffE4EBEE);
static const Color white50 = Color(0xffECECEC);
static const Color white60 = Color(0xffEFEFEF);
//black //black
static const Color black10 = Color(0xff3B3D4A); static const Color black10 = Color(0xff3B3D4A);
@ -47,6 +50,7 @@ class AppColor {
static const Color red40 = Color(0xffFFDBDC); static const Color red40 = Color(0xffFFDBDC);
static const Color red50 = Color(0xffD02127); static const Color red50 = Color(0xffD02127);
static const Color red60 = Color(0xff8C050A); static const Color red60 = Color(0xff8C050A);
static const Color red70 = Color(0xffF63939);
//green //green
static const Color green40 = Color(0xffBAFFE1); static const Color green40 = Color(0xffBAFFE1);

@ -19,10 +19,10 @@ class AppThemes {
), ),
bottomNavigationBarTheme: BottomNavigationBarThemeData( bottomNavigationBarTheme: BottomNavigationBarThemeData(
type: BottomNavigationBarType.fixed, type: BottomNavigationBarType.fixed,
unselectedLabelStyle: ThemeData.light().textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w500), unselectedLabelStyle: ThemeData.light().textTheme.bodySmall.copyWith(fontWeight: FontWeight.w500),
selectedLabelStyle: ThemeData.light().textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w500), selectedLabelStyle: ThemeData.light().textTheme.bodySmall.copyWith(fontWeight: FontWeight.w500),
selectedItemColor: AppColor.primary70, selectedItemColor: AppColor.primary90,
unselectedItemColor: AppColor.neutral20, unselectedItemColor: AppColor.neutral120,
backgroundColor: Colors.white, backgroundColor: Colors.white,
), ),
appBarTheme: AppBarTheme(elevation: 0, backgroundColor: Colors.white, iconTheme: ThemeData.light().iconTheme.copyWith(color: AppColor.neutral50)), appBarTheme: AppBarTheme(elevation: 0, backgroundColor: Colors.white, iconTheme: ThemeData.light().iconTheme.copyWith(color: AppColor.neutral50)),
@ -47,8 +47,8 @@ class AppThemes {
), ),
bottomNavigationBarTheme: BottomNavigationBarThemeData( bottomNavigationBarTheme: BottomNavigationBarThemeData(
type: BottomNavigationBarType.fixed, type: BottomNavigationBarType.fixed,
unselectedLabelStyle: ThemeData.dark().textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w500), unselectedLabelStyle: ThemeData.dark().textTheme.bodySmall.copyWith(fontWeight: FontWeight.w500),
selectedLabelStyle: ThemeData.dark().textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w500), selectedLabelStyle: ThemeData.dark().textTheme.bodySmall.copyWith(fontWeight: FontWeight.w500),
selectedItemColor: AppColor.primary40, selectedItemColor: AppColor.primary40,
unselectedItemColor: AppColor.neutral10, unselectedItemColor: AppColor.neutral10,
backgroundColor: AppColor.neutral60, backgroundColor: AppColor.neutral60,

@ -12,15 +12,13 @@ class AppBottomNavigationBar extends StatelessWidget {
final Function(int index) onPressed; final Function(int index) onPressed;
final int selectedIndex; final int selectedIndex;
const AppBottomNavigationBar({Key? key, required this.onPressed, required this.selectedIndex}) : super(key: key); const AppBottomNavigationBar({Key key, @required this.onPressed, @required this.selectedIndex}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool isEngineer = (Provider.of<UserProvider>(context, listen: false).user!.type) == UsersTypes.engineer; bool isEngineer = (Provider.of<UserProvider>(context, listen: false).user.type) == UsersTypes.engineer;
return ClipRRect( return Container(
borderRadius: const BorderRadius.only(topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)), // height: 86.toScreenHeight,
child: Container(
height: 120.toScreenHeight,
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColor.background(context), color: AppColor.background(context),
boxShadow: [boxShadowR14], boxShadow: [boxShadowR14],
@ -28,31 +26,35 @@ class AppBottomNavigationBar extends StatelessWidget {
child: BottomNavigationBar( child: BottomNavigationBar(
items: <BottomNavigationBarItem>[ items: <BottomNavigationBarItem>[
navBarItem(context, index: 0, iconName: "overview", label: context.translation.overview), navBarItem(context, index: 0, iconName: "overview", label: context.translation.overview),
navBarItem(context, index: 1, iconName: "requests", label: context.translation.myRequests), navBarItem(context, index: 1, iconName: "request_icon", label: context.translation.request),
navBarItem(context, index: 2, iconName: "assets", label: context.translation.myAssets), if (!isEngineer) navBarItem(context, index: 2, iconName: "add_icon", label: context.translation.calendar, showLabel: false),
if (isEngineer) navBarItem(context, index: 3, iconName: "calender_bottom", label: context.translation.calendar), navBarItem(context, index: !isEngineer ? 3 : 2, iconName: "assets", label: context.translation.assets),
navBarItem(context, index: isEngineer ? 4 : 3, iconName: "message", label: context.translation.contactUs), navBarItem(context, index: !isEngineer ? 4 : 3, iconName: "contact", label: context.translation.contact),
], ],
currentIndex: selectedIndex, currentIndex: selectedIndex,
onTap: onPressed, onTap: onPressed,
selectedLabelStyle: AppTextStyles.tinyFont, selectedLabelStyle: AppTextStyles.tinyFont2,
unselectedLabelStyle: AppTextStyles.tinyFont, unselectedLabelStyle: AppTextStyles.tinyFont2,
selectedItemColor: Theme.of(context).bottomNavigationBarTheme.selectedItemColor, selectedItemColor: Theme.of(context).bottomNavigationBarTheme.selectedItemColor,
unselectedItemColor: Theme.of(context).bottomNavigationBarTheme.unselectedItemColor, unselectedItemColor: Theme.of(context).bottomNavigationBarTheme.unselectedItemColor,
), ),
),
); );
} }
BottomNavigationBarItem navBarItem(BuildContext context, {required int index, required String iconName, required String label}) { BottomNavigationBarItem navBarItem(BuildContext context, {@required int index, @required String iconName, @required String label, bool showLabel = true}) {
return BottomNavigationBarItem( return BottomNavigationBarItem(
icon: iconName icon: iconName
.toSvgAsset( ?.toSvgAsset(
width: 24, width: showLabel ? 28 : 38,
color: selectedIndex == index ? Theme.of(context).bottomNavigationBarTheme.selectedItemColor : Theme.of(context).bottomNavigationBarTheme.unselectedItemColor, height: showLabel ? 26 : 40,
color: showLabel||(showLabel && selectedIndex != 2)
? selectedIndex == index
? Theme.of(context).bottomNavigationBarTheme.selectedItemColor
: Theme.of(context).bottomNavigationBarTheme.unselectedItemColor
: null,
) )
.paddingOnly(top: 10, bottom: 10), ?.paddingOnly(top: 21, bottom: showLabel ? 4 : 0),
label: label, label: showLabel ? label : '',
); );
} }
} }

@ -10,23 +10,36 @@ import '../app_style/app_color.dart';
class AppDashedButton extends StatelessWidget { class AppDashedButton extends StatelessWidget {
final String title; final String title;
final VoidCallback onPressed; final VoidCallback onPressed;
double height;
Color buttonColor;
Widget icon;
const AppDashedButton({required this.title, required this.onPressed, Key? key}) : super(key: key); AppDashedButton({@required this.title, @required this.onPressed, Key key,this.height,this.icon,this.buttonColor}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: double.infinity, width: double.infinity,
height: height,
padding: EdgeInsets.symmetric(horizontal: 2.toScreenWidth), padding: EdgeInsets.symmetric(horizontal: 2.toScreenWidth),
decoration: BoxDecoration(color: AppColor.background(context), borderRadius: BorderRadius.circular(10)), decoration: BoxDecoration(color: AppColor.background(context), borderRadius: BorderRadius.circular(10)),
child: DottedBorder( child: DottedBorder(
strokeWidth: 2, strokeWidth: 1,
padding: EdgeInsets.symmetric(vertical: 16.toScreenHeight, horizontal: 16.toScreenWidth), padding: EdgeInsets.symmetric(vertical: 16.toScreenHeight, horizontal: 16.toScreenWidth),
color: context.isDark ? AppColor.primary40 : AppColor.primary10, color: context.isDark ? AppColor.primary40 : buttonColor?? AppColor.black20,
dashPattern: const [4, 3], dashPattern: const [4, 3],
radius: const Radius.circular(10), radius: const Radius.circular(10),
borderType: BorderType.RRect, borderType: BorderType.RRect,
child: title.heading6(context).custom(color: context.isDark ? AppColor.primary40 : AppColor.primary10).center, child:icon!=null?
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
icon,
7.width,
title.heading6(context).custom(color: context.isDark ? AppColor.primary40 : buttonColor??AppColor.black10).center,
],
):
title.heading6(context).custom(color: context.isDark ? AppColor.primary40 : buttonColor?? AppColor.primary10).center,
), ),
).onPress(onPressed); ).onPress(onPressed);
} }

@ -5,15 +5,27 @@ import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
class AppFilledButton extends StatelessWidget { class AppFilledButton extends StatelessWidget {
final VoidCallback? onPressed; final VoidCallback onPressed;
final String label; final String label;
final bool maxWidth, loading; final bool maxWidth, loading;
final Color? buttonColor; final Color buttonColor;
final Color? textColor; final Color textColor;
final bool showBorder; final bool showBorder;
final bool showIcon;
final Widget icon;
const AppFilledButton({ this.onPressed, required this.label, this.maxWidth = false, this.loading = false, this.showBorder = false, this.buttonColor, this.textColor, Key? key}) const AppFilledButton({
: super(key: key); @required this.onPressed,
@required this.label,
this.maxWidth = false,
this.icon,
this.loading = false,
this.showBorder = false,
this.showIcon = false,
this.buttonColor,
this.textColor,
Key key,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -35,7 +47,18 @@ class AppFilledButton extends StatelessWidget {
strokeWidth: 2, strokeWidth: 2,
), ),
) )
: label.heading6(context).custom(color: textColor ?? AppColor.background(context)), : showIcon&&icon!=null?
Center(
child: Row(
mainAxisSize:MainAxisSize.min,
children: [
icon,
8.width,
label.heading6(context).custom(color: textColor ?? AppColor.background(context))
],
),
):
label.heading6(context).custom(color: textColor ?? AppColor.background(context)),
).onPress(onPressed); ).onPress(onPressed);
} }
} }

@ -104,7 +104,7 @@ class _MonthlyFragmentState extends State<MonthlyFragment> {
children: [ children: [
const CircleAvatar(backgroundColor: AppColor.primary40, radius: 8), const CircleAvatar(backgroundColor: AppColor.primary40, radius: 8),
8.width, 8.width,
context.translation.myRequests.heading6(context), context.translation.request.heading6(context),
], ],
), ),
16.height, 16.height,

@ -37,7 +37,7 @@ class ContactUsBottomSheet extends StatelessWidget {
Align( Align(
alignment: AlignmentDirectional.centerStart, alignment: AlignmentDirectional.centerStart,
child: Text( child: Text(
context.translation.contactUs, context.translation.contact,
style: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), style: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
), ),
), ),

@ -14,9 +14,9 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/user.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/progress_fragment.dart'; import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart';
import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/recent_activites_fragment.dart'; import 'package:test_sa/dashboard_latest/widgets/recent_activites_fragment.dart';
import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/requests_fragment.dart'; import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart';
import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_page.dart';
class DashboardPage extends StatefulWidget { class DashboardPage extends StatefulWidget {

@ -1,3 +1,4 @@
import 'dart:developer';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -23,11 +24,12 @@ import '../../../views/widgets/dialogs/dialog.dart';
import '../../common_widgets/app_bottom_nav_bar.dart'; import '../../common_widgets/app_bottom_nav_bar.dart';
import '../../common_widgets/app_drawer.dart'; import '../../common_widgets/app_drawer.dart';
import 'contact_us_bottom_sheet.dart'; import 'contact_us_bottom_sheet.dart';
import 'dashboard_page.dart';
class LandPage extends StatefulWidget { class LandPage extends StatefulWidget {
static const String routeName = "/land-page"; static const String routeName = "/land-page";
const LandPage({Key? key}) : super(key: key); const LandPage({Key key}) : super(key: key);
@override @override
State<LandPage> createState() => _LandPageState(); State<LandPage> createState() => _LandPageState();
@ -37,8 +39,8 @@ class _LandPageState extends State<LandPage> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
int currentPageIndex = 0; int currentPageIndex = 0;
bool showAppbar = true; bool showAppbar = true;
late List<Widget> _pages; List<Widget> _pages;
UserProvider? _userProvider; UserProvider _userProvider;
@override @override
void initState() { void initState() {
@ -50,7 +52,7 @@ class _LandPageState extends State<LandPage> {
if (await Provider.of<SettingProvider>(context, listen: false).auth.isDeviceSupported()) { if (await Provider.of<SettingProvider>(context, listen: false).auth.isDeviceSupported()) {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey(ASettings.localAuth)) { if (!prefs.containsKey(ASettings.localAuth)) {
(Provider.of<SettingProvider>(context, listen: false)).setAuth(false); (await Provider.of<SettingProvider>(context, listen: false)).setAuth(false);
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
useSafeArea: true, useSafeArea: true,
@ -102,12 +104,12 @@ class _LandPageState extends State<LandPage> {
_userProvider = Provider.of<UserProvider>(context, listen: false); _userProvider = Provider.of<UserProvider>(context, listen: false);
_pages = <Widget>[ _pages = <Widget>[
DashboardView(onDrawerPress: (() { DashboardView(onDrawerPress: (() {
_scaffoldKey.currentState!.isDrawerOpen ? _scaffoldKey.currentState!.closeDrawer() : _scaffoldKey.currentState!.openDrawer(); _scaffoldKey.currentState.isDrawerOpen ? _scaffoldKey.currentState.closeDrawer() : _scaffoldKey.currentState.openDrawer();
})), })),
// const old_page.LandPage(), // const old_page.LandPage(),
const MyRequestsPage(), const MyRequestsPage(),
if (_userProvider.user.type != UsersTypes.engineer) const CalendarPage(),
const MyAssetsPage(fromBottomBar: true), const MyAssetsPage(fromBottomBar: true),
if (_userProvider!.user!.type == UsersTypes.engineer) const CalendarPage(),
]; ];
checkLocalAuth(); checkLocalAuth();
} }
@ -133,9 +135,8 @@ class _LandPageState extends State<LandPage> {
bottomNavigationBar: AppBottomNavigationBar( bottomNavigationBar: AppBottomNavigationBar(
selectedIndex: currentPageIndex, selectedIndex: currentPageIndex,
onPressed: (index) { onPressed: (index) {
bool isEngineer = _userProvider!.user!.type == UsersTypes.engineer; bool isEngineer = _userProvider.user.type == UsersTypes.engineer;
if (index == (!isEngineer ? 4 : 3)) {
if (index == (isEngineer ? 4 : 3)) {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
useSafeArea: true, useSafeArea: true,

@ -21,6 +21,7 @@ class RequestPaginatedList extends StatelessWidget {
itemCount: list.length < totalCount ? list.length + 1 : list.length, itemCount: list.length < totalCount ? list.length + 1 : list.length,
controller: scrollController, controller: scrollController,
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == list.length) { if (index == list.length) {
return const ListTile( return const ListTile(

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
@ -7,23 +8,27 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart';
import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/dashboard_latest/widgets/request_category_list.dart';
import 'package:test_sa/new_views/pages/land_page/requests/request_paginated_listview.dart'; import 'package:test_sa/new_views/pages/land_page/requests/request_paginated_listview.dart';
import 'package:test_sa/new_views/pages/land_page/widgets/request_item_view_list.dart';
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
class RequestsListPage extends StatefulWidget { class RequestsListPage extends StatefulWidget {
static const String routeName = "/requests-list-page"; static const String routeName = "/requests-list-page";
final int index; final int index;
final String title; final String title;
const RequestsListPage(this.index, this.title, {Key? key}) : super(key: key); const RequestsListPage(this.index, this.title, {Key key}) : super(key: key);
@override @override
State<RequestsListPage> createState() => _RequestsListPageState(); State<RequestsListPage> createState() => _RequestsListPageState();
} }
class _RequestsListPageState extends State<RequestsListPage> { class _RequestsListPageState extends State<RequestsListPage> {
late AllRequestsProvider _provider; AllRequestsProvider _provider;
late ScrollController _scrollController; ScrollController _scrollController;
@override @override
void initState() { void initState() {
@ -46,11 +51,12 @@ class _RequestsListPageState extends State<RequestsListPage> {
void handleScroll() async { void handleScroll() async {
_scrollController = ScrollController(); _scrollController = ScrollController();
int pageNo = 1; int pageNo =1;
_scrollController.addListener(() async { _scrollController.addListener(() async {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_provider.isRequestCategoryLoading) { if (_scrollController?.position?.pixels == _scrollController?.position?.maxScrollExtent && !_provider.isRequestCategoryLoading) {
pageNo = pageNo + 1; pageNo = pageNo + 1;
callRequestApis(showLoader: false, pageNo: pageNo); callRequestApis(showLoader: false,pageNo: pageNo);
} }
}); });
} }
@ -71,28 +77,30 @@ class _RequestsListPageState extends State<RequestsListPage> {
}, },
); );
} else { } else {
WidgetsBinding.instance.addPostFrameCallback((_) {
snapshot.requestDetailList = snapshot.selectedRequestCategory; snapshot.requestDetailList = snapshot.selectedRequestCategory;
return RequestPaginatedList(snapshot.selectedRequestCategory!.requestsDetails ?? [], snapshot.isRequestCategoryLoading, snapshot.selectedRequestCategory!.total!.count!, _scrollController); });
return RequestPaginatedList(snapshot.selectedRequestCategory.requestsDetails ?? [], snapshot.isRequestCategoryLoading, snapshot.selectedRequestCategory.total.count, _scrollController);
} }
// bool isLoading = widget.index == 0 bool isLoading = widget.index == 0
// ? snapshot.isHighPriorityLoading ? snapshot.isHighPriorityLoading
// : widget.index == 1 : widget.index == 1
// ? snapshot.isOverdueLoading ? snapshot.isOverdueLoading
// : widget.index == 2 : widget.index == 2
// ? snapshot.isOpenLoading ? snapshot.isOpenLoading
// : widget.index == 3 : widget.index == 3
// ? snapshot.isCompleteLoading ? snapshot.isCompleteLoading
// : false; : false;
//
// List<RequestsDetails> list = widget.index == 0 List<RequestsDetails> list = widget.index == 0
// ? snapshot.highPriorityRequests?.requestsDetails ?? [] ? snapshot.highPriorityRequests?.requestsDetails ?? []
// : widget.index == 1 : widget.index == 1
// ? snapshot.overdueRequests?.requestsDetails ?? [] ? snapshot.overdueRequests?.requestsDetails ?? []
// : widget.index == 2 : widget.index == 2
// ? snapshot.openRequests?.requestsDetails ?? [] ? snapshot.openRequests?.requestsDetails ?? []
// : widget.index == 3 : widget.index == 3
// ? snapshot.completedRequests?.requestsDetails ?? [] ? snapshot.completedRequests?.requestsDetails ?? []
// : []; : [];
})); }));
} }
@ -101,7 +109,7 @@ class _RequestsListPageState extends State<RequestsListPage> {
int pageNo = 1, int pageNo = 1,
int pageSize = 10, int pageSize = 10,
}) async { }) async {
UsersTypes usersTypes = Provider.of<UserProvider>(context, listen: false).user!.type!; UsersTypes usersTypes = Provider.of<UserProvider>(context, listen: false).user.type;
print('i am here at ${widget.index}'); print('i am here at ${widget.index}');
if (widget.index == 0) { if (widget.index == 0) {

@ -8,8 +8,8 @@ import '../../controllers/api_routes/urls.dart';
import '../../models/lookup.dart'; import '../../models/lookup.dart';
class ReasonProvider extends LoadingListNotifier<Lookup> { class ReasonProvider extends LoadingListNotifier<Lookup> {
String? serviceRequestId;
String serviceRequestId;
@override @override
Future getDate() async { Future getDate() async {
if (loading == true) return -2; if (loading == true) return -2;
@ -18,7 +18,8 @@ class ReasonProvider extends LoadingListNotifier<Lookup> {
loading = true; loading = true;
notifyListeners(); notifyListeners();
try { try {
Response response = await ApiManager.instance.get(URLs.getServiceReportReasons + "&serviceRequestId=$serviceRequestId"); print('get reson data called...$serviceRequestId');
Response response = await ApiManager.instance.get(URLs.getServiceReportReasons+"&serviceRequestId=$serviceRequestId");
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received

@ -0,0 +1,424 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/fix_remotely_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/mark_as_fixed_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/need_visit_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/nurse_action_model.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart';
import 'package:test_sa/models/new_models/workOrderDetail.dart';
class RequestDetailProvider extends ChangeNotifier {
final pageItemNumber = 10;
void reset() {
nextPage = true;
stateCode = null;
}
DateTime timerStartTime = DateTime(0, 0, 0, 0, 0, 0); // Start from 00:00:00
Timer timer;
bool isTimerRunning = false;
void startTimer() {
if (isTimerRunning) return;
timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
timerStartTime = timerStartTime.add(const Duration(seconds: 1));
notifyListeners(); // Notify UI when time is updated
});
isTimerRunning = true;
notifyListeners(); // Notify UI when timer starts
}
void stopTimer() {
timer?.cancel();
isTimerRunning = false;
notifyListeners(); // Notify UI when timer stops
}
void resetTimer() {
timerStartTime = DateTime(0, 0, 0, 0, 0, 0); // Reset to 00:00:00
notifyListeners();
}
// Getter to get the current time
DateTime get currentTime => timerStartTime;
bool _isLoading = false;
bool get isLoading => _isLoading;
set isLoading(bool value) {
_isLoading = value;
notifyListeners();
}
WorkOrderDetail _currentWorkOrder;
FixRemotely _fixRemotelyModel;
NeedVisit _needVisitModel;
MarkAsFixed _markAsFixed;
ActivitySparePartModel _activitySparePartModel;
ActivitySparePartModel get activitySparePartModel => _activitySparePartModel;
set activitySparePartModel(ActivitySparePartModel value) {
_activitySparePartModel = value;
notifyListeners();
}
MarkAsFixed get markAsFixed => _markAsFixed;
set markAsFixed(MarkAsFixed value) {
_markAsFixed = value;
notifyListeners();
}
NurseActionModel _nurseActionModel;
NurseActionModel get nurseActionModel => _nurseActionModel;
set nurseActionModel(NurseActionModel value) {
_nurseActionModel = value;
notifyListeners();
}
NeedVisit get needVisitModel => _needVisitModel;
set needVisitModel(NeedVisit value) {
_needVisitModel = value;
notifyListeners();
}
FixRemotely get fixRemotelyModel => _fixRemotelyModel;
set fixRemotelyModel(FixRemotely value) {
_fixRemotelyModel = value;
notifyListeners();
}
WorkOrderDetail get currentWorkOrder => _currentWorkOrder;
set currentWorkOrder(WorkOrderDetail value) {
_currentWorkOrder = value;
notifyListeners();
}
int stateCode;
// true if there is next page in product list and false if not
bool nextPage = true;
TimeOfDay _selectedTime ;
TimeOfDay get selectedTime => _selectedTime;
set selectedTime(TimeOfDay value) {
_selectedTime = value;
notifyListeners();
} // list of user requests
int _selectedListIndex = 0;
int get selectedListIndex => _selectedListIndex;
set selectedListIndex(int value) {
_selectedListIndex = value;
notifyListeners();
}
//getWorkOrderById......
Future<WorkOrderDetail> getWorkOrderById({@required String id}) async {
try {
isLoading = true;
final response = await ApiManager.instance.get(URLs.getWorkOrderByIdUrl+"?workOrderId=$id");
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
notifyListeners();
isLoading = false;
return currentWorkOrder;
}
isLoading= false;
notifyListeners();
return null;
}
catch (e) {
log("getSubWorkOrderDetails [error] : $e");
isLoading = false;
notifyListeners();
return null;
}
}
//engineerAcceptWorkOrder......
Future<CommonResponseModel> engineerAcceptWorkOrder({@required String id}) async {
try {
final body = {
"workOrderId": id,
};
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerAcceptUrl,body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer accept workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
//engineerRejectWorkOrder......
Future<CommonResponseModel> engineerRejectWorkOrder({@required String id,String feedBack}) async {
try {
final body = {
"workOrderId": id,
"feedback": feedBack,
};
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerRejectUrl,body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer reject workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
//engineerFixRemotelyWorkOrder......
Future<CommonResponseModel> engineerFixRemotely() async {
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerFixRemotlyUrl,body: fixRemotelyModel.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer fixremotely workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
//engineerNeedAVisitWorkOrder......
Future<CommonResponseModel> engineerNeedVisit() async {
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerNeedVisitUrl,body: needVisitModel.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer fixremotely workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
//engineerMarkAsFixed......
Future<CommonResponseModel> engineerMarkAsFixed() async {
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.engineerMarkAsFixUrl,body: markAsFixed.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer mark as fixed ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
//assignEngineerToWorkOrder......
Future<CommonResponseModel> assignEngineerWorkOrder({@required String workOrderId,@required String engineerId}) async {
try {
final body = {
"workOrderId": workOrderId,
"assignedEngineerId": engineerId,
};
isLoading = true;
final response = await ApiManager.instance.post(URLs.assignEngineerToWorkOrderUrl,body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of Engineer assignEngineer workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
//Nurse confirm reopen
Future<CommonResponseModel> nurseReopen() async {
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.nurseConfirmReopenUrl,body: nurseActionModel.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of nurse confirmreopen workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
//Nurse confirm close
Future<CommonResponseModel> nurseClose() async {
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.nurseConfirmCloseUrl,body: nurseActionModel.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
CommonResponseModel commonResponseModel = CommonResponseModel.fromJson(json.decode(response.body));
print('response of nurse confirmreopen workorder ${commonResponseModel.toJson()}');
notifyListeners();
isLoading = false;
return commonResponseModel;
}
isLoading= false;
notifyListeners();
return CommonResponseModel();
}
catch (e) {
log("engineer accept [error] : $e");
isLoading = false;
notifyListeners();
return CommonResponseModel();
}
}
Future<int> updateActivitySparePart({@required ActivitySparePartModel activitySparePartModel}) async {
isLoading = true;
try {
final response = await ApiManager.instance.put(
URLs.updateActivitySparePartUrl,
body: activitySparePartModel.toJson(),
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// request.engineerName = employee.name;
notifyListeners();
}
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
notifyListeners();
return -1;
}
}
Future<int> deleteActivitySparePart({@required int id,@required int workOrderId}) async {
isLoading = true;
var body = {
'id':id,
'workOrderId':workOrderId,
};
try {
final response = await ApiManager.instance.post(
URLs.deleteActivitySparePartUrl,
body: body,
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
//map to the model...
notifyListeners();
}
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
notifyListeners();
return -1;
}
}
Future<int> createActivitySparePart({@required ActivitySparePartModel activitySparePartModel}) async {
isLoading = true;
try {
final response = await ApiManager.instance.put(
URLs.createActivitySparePartUrl,
body: activitySparePartModel.toJson(),
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// request.engineerName = employee.name;
notifyListeners();
}
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
notifyListeners();
return -1;
}
}
}

@ -0,0 +1,165 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';
class FooterActionButton {
static Widget footerContainer({@required Widget child}){
return Align(
alignment: Alignment.bottomCenter,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth,vertical: 16.toScreenHeight),
color: AppColor.white10,
child: child,
),
);
}
static Widget footerWidget({@required int status,@required BuildContext context}){
switch(status){
//accept reject...
case 1:
return footerContainer(
child:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
AppFilledButton(
label: context.translation.reject,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
ServiceRequestBottomSheet.rejectRequestBottomSheet(context: context);
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.accept,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
},
).expanded,
],
)
);
break;
//need visit fixed remotely
case 2:
return footerContainer(
child:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
AppFilledButton(
label: context.translation.needAVisit,
maxWidth: true,
buttonColor: AppColor.neutral50,
onPressed: () async {
ServiceRequestBottomSheet.initialVisitBottomSheet(context: context);
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.fixedRemotely,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context);
},
).expanded,
],
)
);
break;
//verify Asset Details
case 3:
return footerContainer(
child:
AppFilledButton(
label: context.translation.verify_asset_details,
// maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
},
)
);
break;
//Activities
case 4:
return footerContainer(
child:
AppFilledButton(
label: context.translation.activities,
// maxWidth: true,
buttonColor: AppColor.neutral50,
onPressed: () async {
ServiceRequestBottomSheet.activityTypeBottomSheet(context: context);
},
)
);
break;
//I have arrived...
case 5:
return footerContainer(
child:
AppFilledButton(
label: context.translation.iHaveArrived,
showIcon: true,
icon: 'arrived_icon'.toSvgAsset(),
buttonColor: AppColor.green70,
onPressed: () async {
},
)
);
break;
//Close..
case 6:
return footerContainer(
child:
AppFilledButton(
label: context.translation.close,
// maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
},
)
);
break;
//for nurse to take action...
case 7:
return footerContainer(
child:
AppFilledButton(
label: context.translation.takeAction,
// maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
},
)
);
break;
default:
return const SizedBox();
}
}
}

@ -1,84 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:provider/provider.dart';
// import 'package:test_sa/extensions/context_extension.dart';
// import 'package:test_sa/extensions/int_extensions.dart';
// import 'package:test_sa/extensions/text_extensions.dart';
// import 'package:test_sa/extensions/widget_extensions.dart';
//
// import '../../../../controllers/providers/api/service_requests_provider.dart';
// import '../../../../new_views/app_style/app_color.dart';
// import '../../../../new_views/common_widgets/app_filled_button.dart';
//
// class ActionBottomSheet extends StatelessWidget {
// final String title;
// final String button1Text;
// final String button2Text;
// final VoidCallback button1Tap;
// final VoidCallback button2Tap;
//
// ActionBottomSheet({Key? key, required this.title, this.button1Text, this.button2Text, this.button1Tap, this.button2Tap}) : super(key: key);
//
// final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
//
// @override
// Widget build(BuildContext context) {
// return Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
// return Wrap(
// children: [
// Container(
// clipBehavior: Clip.antiAlias,
// margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
// decoration: BoxDecoration(
// color: Theme.of(context).scaffoldBackgroundColor,
// borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
// ),
// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// Container(
// width: 40.toScreenWidth,
// height: 5.toScreenHeight,
// decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)),
// ),
// Align(
// alignment: AlignmentDirectional.centerStart,
// child: title.heading4(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16),
// ),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// SizedBox(
// width: 200.toScreenHeight,
// child: AppFilledButton(
// label: button1Text ?? context.translation.no,
// loading: false,
// buttonColor: AppColor.neutral40,
// textColor: AppColor.black10,
// onPressed: button1Tap ??
// () async {
// Navigator.pop(context);
// // await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest);
// // Navigator.pop(context, true);
// },
// ),
// ),
// SizedBox(
// width: 200.toScreenHeight,
// child: AppFilledButton(
// label: context.translation.yes,
// buttonColor: AppColor.primary10,
// loading: false,
// onPressed: button2Tap,
// ),
// ),
// ],
// )
// ],
// ),
// )
// ],
// );
// });
// }
// }

@ -1,120 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/app_strings/app_asset.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/service_request_latest/views/components/spare_part_request.dart';
class ActivityTypeBottomSheet extends StatelessWidget {
const ActivityTypeBottomSheet({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final List<Map<String, String>> items = [
{'heading': context.translation.sparePartRequest, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.sparePartIcon},
{'heading': context.translation.maintenanceRequest, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.maintenanceIcon},
{'heading': context.translation.assetToBeRetired, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.retiredAssetIcon},
];
return Wrap(
children: [
Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestsProvider, child) {
return Container(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
decoration: BoxDecoration(
color: AppColor.background(context),
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: SafeArea(
child: Column(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.selectActivityType.heading4(context).paddingOnly(top: 16, bottom: 16),
),
ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return listItem(
icon: item['icon']!,
heading: item['heading']!,
subHeading: item['subHeading']!,
context: context,
onTap: () {
onItemTap(serviceRequest: serviceRequestsProvider.currentSelectedRequest!, index: index, context: context);
});
},
),
],
),
),
);
}),
],
);
}
Widget listItem({required BuildContext context, required String icon, required String heading, required String subHeading, required VoidCallback onTap}) {
return Padding(
padding: EdgeInsets.only(bottom: 8.toScreenHeight),
child: Card(
color: AppColor.neutral80,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
// Circular border radius
),
// color: Colors.white,
child: ListTile(
minVerticalPadding: 8,
horizontalTitleGap: 10,
onTap: onTap,
contentPadding: const EdgeInsets.all(8),
leading: SvgPicture.asset(icon),
title: Text(
heading,
style: AppTextStyles.heading5,
),
subtitle: Text(
subHeading,
style: AppTextStyles.bodyText,
),
),
),
);
}
void onItemTap({required int index, required ServiceRequest serviceRequest, required BuildContext context}) {
print('on item tap i got index is $index');
switch (index) {
case 0:
Navigator.of(context).push(MaterialPageRoute(builder: (_) => const SparePartRequest()));
break;
case 1:
//push to specific screen...
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => ActivitiesListView()),
// );
break;
case 2:
//push to specific screen...
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => const ScanQrView()),
// );
break;
}
// ScanQr
}
}

@ -1,204 +0,0 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/service_request_latest/views/components/verify_arrival_view.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import '../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../new_views/app_style/app_color.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/app_text_form_field.dart';
class InitialVisitBottomSheet extends StatelessWidget {
InitialVisitBottomSheet({Key? key,}) : super(key: key);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context, listen: false);
return Consumer<ServiceRequestsProvider>(
builder: (context, serviceRequestProvider,child) {
return Wrap(
children: [
Container(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: [
Container(
width: 40.toScreenWidth,
height: 5.toScreenHeight,
decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)),
),
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.setVisitDate.heading5(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16),
),
8.height,
ADatePicker(
label: context.translation.visitDate,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.visitDate ?? ""),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.date!))) {
"Visit Date time must be greater then request date".showToast;
return;
}
serviceRequestProvider.currentSelectedRequest?.visitDate = selectedDateTime.toIso8601String();
}
});
},
),
// ],
if (serviceRequestProvider.currentSelectedRequest?.firstAction?.id == 404 && Provider.of<SettingProvider>(context, listen: false).assetGroup!.id == 1) ...[
8.height,
Row(
children: [
ADatePicker(
label: context.translation.startDate,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.startDate ?? ""),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
serviceRequestProvider.currentSelectedRequest?.startDate = selectedDateTime.toIso8601String();
}
});
},
).expanded,
8.width,
ADatePicker(
label: context.translation.endDate,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest?.endDate ?? ""),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
serviceRequestProvider.currentSelectedRequest?.endDate = selectedDateTime.toIso8601String();
serviceRequestProvider.currentSelectedRequest?.workingHours =
(((DateTime.parse(serviceRequestProvider.currentSelectedRequest!.endDate!).difference(DateTime.parse(serviceRequestProvider.currentSelectedRequest!.startDate!)).inSeconds ?? 0) / 60) / 60).toStringAsFixed(2);
}
});
},
).expanded,
],
)
],
/// Loan availability not required
// 8.height,
// SingleItemDropDownMenu<Lookup, LoanAvailabilityProvider>(
// context: context,
// title: context.translation.loanAvailability,
// initialValue: _serviceRequest.loanAvailability,
// onSelect: (status) {
// setState(() {
// _serviceRequest.loanAvailability = status;
// if (_serviceRequest.loanAvailability.value != 1) {
// asset = null;
// }
// });
// },
// ),
// if (_serviceRequest?.loanAvailability?.value == 1) 8.height,
// if (_serviceRequest?.loanAvailability?.value == 1)
// PickAsset(
// device: asset ?? _serviceRequest.device,
// onPickAsset: (asset) {
// setState(() {
// this.asset = asset;
// });
// },
// ),
8.height,
AppTextFormField(
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
alignLabelWithHint: true,
onChange: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
onSaved: (text) {
serviceRequestProvider.currentSelectedRequest?.comments = text;
},
),
16.height,
Consumer<ServiceRequestsProvider>(
builder: (context, snapshot, _) => AppFilledButton(
label: context.translation.save,
loading: snapshot.isLoading ?? false,
onPressed: () async {
_formKey.currentState!.save();
// await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest);
// Navigator.pop(context, true);
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => const VerifyArrivalView()));
},
),
),
16.height,
],
),
),
),
)
],
);
}
);
}
}

@ -1,235 +0,0 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import '../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../models/lookup.dart';
import '../../../../new_views/app_style/app_color.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../../providers/service_request_providers/first_action_provider.dart';
class RejectRequestBottomSheet extends StatelessWidget {
RejectRequestBottomSheet({
Key? key,
}) : super(key: key);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Asset? asset;
@override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context, listen: false);
return Consumer<ServiceRequestsProvider>(builder: (context, requestDetailProvider, child) {
return Wrap(
children: [
Container(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: [
Container(
width: 40.toScreenWidth,
height: 5.toScreenHeight,
decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)),
),
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.rejectionReason.heading3(context).custom(fontWeight: FontWeight.w600).paddingOnly(top: 16, bottom: 16),
),
SingleItemDropDownMenu<Lookup, FirstActionStatusProvider>(
context: context,
title: context.translation.rejectionReason,
initialValue: requestDetailProvider.currentSelectedRequest?.firstAction, //_currentSelectedRequest.firstAction,
onSelect: (value) {
// setState(() {
//_currentSelectedRequest.firstAction = value;
requestDetailProvider.currentSelectedRequest?.firstAction = value;
if (requestDetailProvider.currentSelectedRequest?.firstAction!.value != 2) {
requestDetailProvider.currentSelectedRequest?.visitDate = null;
}
// });
},
),
// if (requestDetailProvider.currentSelectedRequest.firstAction?.value == 2) ...[
// 8.height,
// ADatePicker(
// label: context.translation.visitDate,
// date: DateTime.tryParse(requestDetailProvider.currentSelectedRequest.visitDate ?? ""),
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// if (selectedDate != null) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(
// selectedDate.year,
// selectedDate.month,
// selectedDate.day,
// selectedTime.hour,
// selectedTime.minute,
// );
// if (selectedDateTime != null) {
// if (selectedDateTime.isBefore(DateTime.parse(requestDetailProvider.currentSelectedRequest.date))) {
// "Visit Date time must be greater then request date".showToast;
// return;
// }
//
// // setState(() {
// requestDetailProvider.currentSelectedRequest.visitDate = selectedDateTime?.toIso8601String();
// // });
// }
// }
// });
// }
// },
// ),
// ],
//
// if (requestDetailProvider.currentSelectedRequest.firstAction?.id == 404 && Provider.of<SettingProvider>(context, listen: false).assetGroup.id == 1) ...[
// 8.height,
// Row(
// children: [
// ADatePicker(
// label: context.translation.startDate,
// date: DateTime.tryParse(requestDetailProvider.currentSelectedRequest.startDate ?? ""),
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// if (selectedDate != null) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(
// selectedDate.year,
// selectedDate.month,
// selectedDate.day,
// selectedTime.hour,
// selectedTime.minute,
// );
// if (selectedDateTime != null) {
// requestDetailProvider.currentSelectedRequest.startDate = selectedDateTime?.toIso8601String();
// }
// }
// });
// }
// },
// ).expanded,
// 8.width,
// ADatePicker(
// label: context.translation.endDate,
// date: DateTime.tryParse(requestDetailProvider.currentSelectedRequest.endDate ?? ""),
// formatDateWithTime: true,
// onDatePicker: (selectedDate) {
// if (selectedDate != null) {
// showTimePicker(
// context: context,
// initialTime: TimeOfDay.now(),
// ).then((selectedTime) {
// // Handle the selected date and time here.
// if (selectedTime != null) {
// DateTime selectedDateTime = DateTime(
// selectedDate.year,
// selectedDate.month,
// selectedDate.day,
// selectedTime.hour,
// selectedTime.minute,
// );
// if (selectedDateTime != null) {
// requestDetailProvider.currentSelectedRequest.endDate = selectedDateTime?.toIso8601String();
// requestDetailProvider.currentSelectedRequest.workingHours =
// (((DateTime.parse(requestDetailProvider.currentSelectedRequest.endDate).difference(DateTime.parse(requestDetailProvider.currentSelectedRequest.startDate)).inSeconds ?? 0) / 60) / 60).toStringAsFixed(2);
// }
// }
// });
// }
// },
// ).expanded,
// ],
// )
// ],
/// Loan availability not required
// 8.height,
// SingleItemDropDownMenu<Lookup, LoanAvailabilityProvider>(
// context: context,
// title: context.translation.loanAvailability,
// initialValue: _currentSelectedRequest.loanAvailability,
// onSelect: (status) {
// setState(() {
// _currentSelectedRequest.loanAvailability = status;
// if (_currentSelectedRequest.loanAvailability.value != 1) {
// asset = null;
// }
// });
// },
// ),
// if (_currentSelectedRequest?.loanAvailability?.value == 1) 8.height,
// if (_currentSelectedRequest?.loanAvailability?.value == 1)
// PickAsset(
// device: asset ?? _currentSelectedRequest.device,
// onPickAsset: (asset) {
// setState(() {
// this.asset = asset;
// });
// },
// ),
8.height,
AppTextFormField(
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
alignLabelWithHint: true,
onChange: (text) {
requestDetailProvider.currentSelectedRequest?.comments = text;
},
onSaved: (text) {
requestDetailProvider.currentSelectedRequest?.comments = text;
},
),
16.height,
Consumer<ServiceRequestsProvider>(
builder: (context, snapshot, _) => AppFilledButton(
label: context.translation.reject,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red50,
showBorder: true,
loading: snapshot.isLoading ?? false,
onPressed: () async {
_formKey.currentState!.save();
// requestDetailProvider.serviceRequest.device = asset;
await snapshot.updateRequest(user: userProvider.user!, request: requestDetailProvider.currentSelectedRequest!);
Navigator.pop(context, true);
},
),
),
16.height,
],
),
),
),
)
],
);
});
}
}

@ -0,0 +1,42 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class InitialVisitCard extends StatelessWidget {
const InitialVisitCard({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColor.white10,
),
padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 14.toScreenHeight),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(
DateTime.now().toString().toInitialVisitCardFormat,
textAlign: TextAlign.end,
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() {
//open bottom sheet again with the informations added...
}),
]),
2.height,
context.translation.visitDateAndTime.heading6(context).custom(color: AppColor.neutral120),
8.height,
'Comments for the visit will be visible here for reference'.heading6(context).custom(color: AppColor.neutral120),
],
),
);
}
}

@ -14,8 +14,12 @@ import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';
import 'package:test_sa/service_request_latest/views/components/verify_otp_view.dart'; import 'package:test_sa/service_request_latest/views/components/initial_visit_card.dart';
import 'package:test_sa/service_request_latest/views/components/timer_widget.dart';
import 'package:test_sa/service_request_latest/views/forms/asset_retired/asset_retired.dart';
import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart';
import 'package:test_sa/views/pages/user/requests/comments_bottom_sheet.dart'; import 'package:test_sa/views/pages/user/requests/comments_bottom_sheet.dart';
import 'package:test_sa/views/pages/user/requests/update_service_request_page.dart'; import 'package:test_sa/views/pages/user/requests/update_service_request_page.dart';
import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart'; import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart';
@ -24,12 +28,15 @@ import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart';
import '../../../models/lookup.dart';
import '../forms/maintenance_request/maintenance_request_main.dart';
class RequestDetailView extends StatefulWidget { class RequestDetailView extends StatefulWidget {
static const String id = "/call-details"; static const String id = "/call-details";
ServiceRequest serviceRequest; ServiceRequest serviceRequest;
bool fromTabView = false; bool fromTabView = false;
RequestDetailView({Key? key, required this.serviceRequest, this.fromTabView = false}) : super(key: key); RequestDetailView({Key key, this.serviceRequest, this.fromTabView = false}) : super(key: key);
@override @override
State<RequestDetailView> createState() => _RequestDetailViewState(); State<RequestDetailView> createState() => _RequestDetailViewState();
@ -42,7 +49,7 @@ class _RequestDetailViewState extends State<RequestDetailView> {
getServiceRequest(requestId: widget.serviceRequest.id); getServiceRequest(requestId: widget.serviceRequest.id);
} }
void getServiceRequest({required dynamic requestId}) { void getServiceRequest({@required dynamic requestId}) {
// setState(() {}); // setState(() {});
WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) async { WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) async {
Provider.of<CommentsProvider>(context, listen: false).reset(); Provider.of<CommentsProvider>(context, listen: false).reset();
@ -51,27 +58,41 @@ class _RequestDetailViewState extends State<RequestDetailView> {
// setState(() {}); // setState(() {});
}); });
} }
final GlobalKey _detailsCardKey = GlobalKey();
void createBreakPoint(){
final RenderBox detailContainerBox =
_detailsCardKey.currentContext?.findRenderObject() as RenderBox;
final detailContainerHeight = detailContainerBox?.size?.height;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false); UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
return !widget.fromTabView return !widget.fromTabView
? Scaffold( ? Scaffold(
appBar: DefaultAppBar(title: context.translation.serviceDetails), appBar: DefaultAppBar(title: context.translation.serviceDetails),
body: Padding( body: Padding(
padding: EdgeInsets.only(top: 12.toScreenHeight), padding: EdgeInsets.only(top: 12.toScreenHeight),
child: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestsProvider, child) { child: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestsProvider, child) {
return requestDetailCard(serviceRequestsProvider: serviceRequestsProvider, userProvider: userProvider); return requestDetailCard(serviceRequestsProvider: serviceRequestsProvider, userProvider: _userProvider);
}), }),
), ),
) )
: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestsProvider, child) { : Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestsProvider, child) {
return requestDetailCard(serviceRequestsProvider: serviceRequestsProvider, userProvider: userProvider); return requestDetailCard(serviceRequestsProvider: serviceRequestsProvider, userProvider: _userProvider);
}); });
} }
Widget requestDetailCard({required ServiceRequestsProvider serviceRequestsProvider, required UserProvider userProvider}) { Widget requestDetailCard({ServiceRequestsProvider serviceRequestsProvider, UserProvider userProvider}) {
if(!serviceRequestsProvider.isDetialLoading){
createBreakPoint();
}
return SafeArea( return SafeArea(
key: _detailsCardKey,
child: serviceRequestsProvider.isDetialLoading child: serviceRequestsProvider.isDetialLoading
? const ALoading().center ? const ALoading().center
: serviceRequestsProvider.currentSelectedRequest == null : serviceRequestsProvider.currentSelectedRequest == null
@ -79,115 +100,26 @@ class _RequestDetailViewState extends State<RequestDetailView> {
context.translation.noDataFound, context.translation.noDataFound,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
).center ).center
: Column( : Stack(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SingleChildScrollView( SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
child: informationCard(serviceRequestsProvider.currentSelectedRequest!, userProvider), child: Column(
).expanded,
Center(
child: InkWell(
onTap: () async {
try {
//use a common list
AllRequestsProvider allRequestProvider = Provider.of<AllRequestsProvider>(context, listen: false);
int index = allRequestProvider.requestDetailList!.requestsDetails!.indexWhere((element) => element.id.toString() == serviceRequestsProvider.currentSelectedRequest?.id);
if (index != -1 && index != allRequestProvider.requestDetailList!.requestsDetails!.length) {
getServiceRequest(requestId: allRequestProvider.requestDetailList!.requestsDetails![index + 1].id.toString());
}
} catch (e) {
print(e);
}
},
child: Text(
context.translation.skipForLater,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, decoration: TextDecoration.underline, fontSize: 16),
),
),
),
20.height,
if (userProvider.user!.type == UsersTypes.engineer ||
(serviceRequestsProvider.currentSelectedRequest?.statusValue == 5 || serviceRequestsProvider.currentSelectedRequest?.statusValue == 3))
(serviceRequestsProvider.currentSelectedRequest?.firstAction == null
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppFilledButton( informationCard(serviceRequestsProvider.currentSelectedRequest, userProvider),
label: context.translation.reject,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red50,
showBorder: true,
onPressed: () async {
ServiceRequestBottomSheet.rejectRequestBottomSheet(context: context);
// bool shouldReloadData = (await showModalBottomSheet(
// context: context,
// useSafeArea: true,
// isScrollControlled: true,
// backgroundColor: Colors.transparent,
// builder: (context) => RejectRequestBottomSheet(),
// )) as bool;
// if (shouldReloadData ?? false) {
// getServiceRequest();
// }
},
).expanded,
const SizedBox(
width: 20,
),
AppFilledButton(
label: context.translation.accept,
maxWidth: true,
buttonColor: AppColor.green70,
onPressed: () async {
// GeneralUtils.showFlushBar(context: context);
Navigator.of(context).push(MaterialPageRoute(builder: (_) => const VerifyOtpView()));
// ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context); 40.height,
// bool shouldReloadData = (await showModalBottomSheet( // skipForLater(serviceRequestsProvider.currentSelectedRequest),
// context: context, // 20.height,
// useSafeArea: true, const InitialVisitCard(),
// isScrollControlled: true, 20.height,
// backgroundColor: Colors.transparent,
// builder: (context) => InitialVisitBottomSheet(),
// )) as bool;
// if (shouldReloadData ?? false) {
// getServiceRequest();
// }
},
).expanded,
], ],
) ),
// ? AppFilledButton( ),
// label: context.translation.firstAction, FooterActionButton.footerWidget(status: 1, context: context),
// maxWidth: true, const TimerWidget(),
// onPressed: () async {
// bool shouldReloadData = (await showModalBottomSheet(
// context: context,
// useSafeArea: true,
// isScrollControlled: true,
// backgroundColor: Colors.transparent,
// builder: (context) => FirstActionBottomSheet(request: serviceRequestsProvider.serviceRequest),
// )) as bool;
// if (shouldReloadData ?? false) {
// getServiceRequest();
// }
// },
// )
: AppFilledButton(
label: context.translation.viewWorkOrder,
maxWidth: true,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WorkOrderListPage(serviceRequest: serviceRequestsProvider.currentSelectedRequest!)),
);
// Navigator.of(context).pushNamed(WorkOrderListPage.id, arguments: serviceRequest);
},
))
.paddingOnly(start: 16, end: 16, bottom: 24),
], ],
), ),
); );
@ -211,30 +143,30 @@ class _RequestDetailViewState extends State<RequestDetailView> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
StatusLabel( StatusLabel(
label: serviceRequest.priority?.name, label: serviceRequest.priority.name,
id: serviceRequest.priority!.id!, id: serviceRequest.priority.id,
radius: 4, radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, serviceRequest.priority!.id!), textColor: AppColor.getPriorityStatusTextColor(context, serviceRequest.priority.id),
backgroundColor: AppColor.getPriorityStatusColor(context, serviceRequest.priority!.id!), backgroundColor: AppColor.getPriorityStatusColor(context, serviceRequest.priority.id),
), ),
8.width, 8.width,
StatusLabel( StatusLabel(
radius: 4, radius: 4,
label: serviceRequest.statusLabel!, label: serviceRequest.statusLabel,
textColor: AppColor.getRequestStatusTextColor(context, serviceRequest.statusValue!), textColor: AppColor.getRequestStatusTextColor(context, serviceRequest.statusValue),
backgroundColor: AppColor.getRequestStatusColor(context, serviceRequest.statusValue!), backgroundColor: AppColor.getRequestStatusColor(context, serviceRequest.statusValue),
), ),
1.width.expanded, 1.width.expanded,
Column( Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
if (userProvider.user!.type == UsersTypes.normal_user) if (userProvider.user.type == UsersTypes.normal_user)
context.translation.code.toSvgAsset(width: 48).onPress(() { context.translation.code.toSvgAsset(width: 48).onPress(() {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest))); Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest)));
}), }),
if (userProvider.user!.type == UsersTypes.engineer) 16.height, if (userProvider.user.type == UsersTypes.engineer) 16.height,
Text( Text(
serviceRequest.date!.toServiceRequestCardFormat, serviceRequest.date.toServiceRequestCardFormat,
textAlign: TextAlign.end, textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
), ),
@ -247,7 +179,7 @@ class _RequestDetailViewState extends State<RequestDetailView> {
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
), ),
8.height, 8.height,
'${context.translation.assetName}: ${serviceRequest.deviceEnName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.assetName}: ${serviceRequest.deviceEnName?.cleanupWhitespace?.capitalizeFirstOfEach}'.bodyText(context),
// 8.height, // 8.height,
Text( Text(
'${context.translation.assetNumber}: ${serviceRequest.device?.assetNumber}', '${context.translation.assetNumber}: ${serviceRequest.device?.assetNumber}',
@ -259,31 +191,31 @@ class _RequestDetailViewState extends State<RequestDetailView> {
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
'${context.translation.manufacture}: ${serviceRequest.device!.modelDefinition?.manufacturerName?.cleanupWhitespace.capitalizeFirstOfEach}', '${context.translation.manufacture}: ${serviceRequest.device.modelDefinition.manufacturerName?.cleanupWhitespace?.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
'${context.translation.model}: ${serviceRequest.device!.modelDefinition?.modelName?.cleanupWhitespace.capitalizeFirstOfEach}', '${context.translation.model}: ${serviceRequest.device.modelDefinition.modelName?.cleanupWhitespace?.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
'${context.translation.site}: ${serviceRequest.device!.site?.custName?.cleanupWhitespace.capitalizeFirstOfEach}', '${context.translation.site}: ${serviceRequest.device.site?.custName?.cleanupWhitespace?.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
'${context.translation.building}: ${serviceRequest.device!.building?.name?.cleanupWhitespace.capitalizeFirstOfEach}', '${context.translation.building}: ${serviceRequest.device.building?.name?.cleanupWhitespace?.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
'${context.translation.floor}: ${serviceRequest.device!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}', '${context.translation.floor}: ${serviceRequest.device.floor?.name?.cleanupWhitespace?.capitalizeFirstOfEach ?? ""}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
'${context.translation.department}: ${serviceRequest.device!.department?.departmentName?.cleanupWhitespace.capitalizeFirstOfEach}', '${context.translation.department}: ${serviceRequest.device.department?.departmentName?.cleanupWhitespace?.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
'${context.translation.room}: ${(serviceRequest.device!.room?.name ?? "").cleanupWhitespace.capitalizeFirstOfEach}', '${context.translation.room}: ${(serviceRequest.device.room?.name ?? "").cleanupWhitespace?.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
], ],
@ -300,7 +232,7 @@ class _RequestDetailViewState extends State<RequestDetailView> {
), ),
8.height, 8.height,
Text( Text(
'${context.translation.requestType}: ${serviceRequest.type!.name}', '${context.translation.requestType}: ${serviceRequest.type.name}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
Text( Text(
@ -317,24 +249,24 @@ class _RequestDetailViewState extends State<RequestDetailView> {
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
8.height, 8.height,
Text( Text(
serviceRequest.callComments!, serviceRequest.callComments,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
), ),
], ],
if (serviceRequest.devicePhotos?.isNotEmpty ?? false) ...[ if (serviceRequest.devicePhotos.isNotEmpty) ...[
8.height, 8.height,
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
FilesList(images: serviceRequest.devicePhotos!), FilesList(images: serviceRequest.devicePhotos),
], ],
if (serviceRequest.audio?.isNotEmpty ?? false) ...[ if (serviceRequest.audio?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
16.height, 16.height,
ASoundPlayer(audio: serviceRequest.audio!), ASoundPlayer(audio: serviceRequest.audio),
8.height, 8.height,
], ],
], ],
).paddingOnly(start: 16, end: 16, top: 16, bottom: 8), ).paddingOnly(start: 16, end: 16, top: 16, bottom: 8),
(userProvider.user!.type == UsersTypes.normal_user (userProvider.user.type == UsersTypes.normal_user
? Container( ? Container(
height: 50, height: 50,
padding: const EdgeInsets.only(left: 16, right: 16), padding: const EdgeInsets.only(left: 16, right: 16),
@ -387,10 +319,59 @@ class _RequestDetailViewState extends State<RequestDetailView> {
isScrollControlled: true, isScrollControlled: true,
useRootNavigator: true, useRootNavigator: true,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
builder: (context) => CommentsBottomSheet(requestId: serviceRequest.id!), builder: (context) => CommentsBottomSheet(requestId: serviceRequest.id),
); );
}), }),
//set condition for show asset detail button...
if(true)...[
assetRetiredButton(serviceRequest: serviceRequest),
]
], ],
).toShadowContainer(context, padding: 0); ).toShadowContainer(context, padding: 0);
} }
Widget assetRetiredButton({ServiceRequest serviceRequest}){
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenHeight,vertical: 12.toScreenWidth),
child: AppFilledButton(
label: context.translation.assetToBeRetired,
maxWidth: true,
buttonColor: Colors.white54,
textColor: AppColor.red30,
showBorder: true,
onPressed: () async {
// ServiceRequestBottomSheet.nurseTakeActionBottomSheet(context: context);
Navigator.push(context, MaterialPageRoute(builder: (context)=>const AssetRetired()));
}
),
);
}
Widget skipForLater (ServiceRequest serviceRequest){
return Center(
child: InkWell(
onTap: () async {
try {
//use a common list
AllRequestsProvider allRequestProvider = Provider.of<AllRequestsProvider>(context, listen: false);
int index = allRequestProvider.requestDetailList.requestsDetails.indexWhere((element) => element.id.toString() == serviceRequest.id);
if (index != -1 && index != allRequestProvider.requestDetailList.requestsDetails.length) {
getServiceRequest(requestId: allRequestProvider.requestDetailList.requestsDetails[index + 1].id.toString());
}
} catch (e) {
print(e);
}
},
child: Text(
context.translation.skipForLater,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, decoration: TextDecoration.underline, fontSize: 16),
),
),
);
}
} }

@ -0,0 +1,195 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/models/size_config.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
class TimerWidget extends StatefulWidget {
const TimerWidget({Key key}) : super(key: key);
@override
_TimerWidgetState createState() => _TimerWidgetState();
}
class _TimerWidgetState extends State<TimerWidget> {
Offset position = Offset(SizeConfig.screenWidth - 100, SizeConfig.screenHeight / 2 - 50);
@override
void initState() {
// TODO: implement initState
Provider.of<RequestDetailProvider>(context,listen: false).startTimer();
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
//dispose the timer...
super.dispose();
}
@override
Widget build(BuildContext context) {
return Consumer<RequestDetailProvider>(
builder: (context, provider, child) {
return Positioned(
left: position.dx,
top: position.dy,
child: GestureDetector(
onPanEnd: (details){},
onPanUpdate: (details) {
setState(() {
if (position.dy + details.delta.dy > 0 && position.dy + details.delta.dy < 560) {
position = Offset(
position.dx + details.delta.dx, // Update the X position
position.dy + details.delta.dy, // Update the Y position
);
}
});
},
child: buildTimerWidget(provider),
),
);
},
);
}
Widget buildTimerWidget(RequestDetailProvider provider) {
return GestureDetector(
onTap: () {
if (provider.isTimerRunning) {
provider.stopTimer();
} else {
provider.startTimer();
}
},
child: Container(
padding: EdgeInsets.all(8.toScreenHeight),
width: 80.toScreenWidth,
decoration: BoxDecoration(
color: AppColor.black10,
borderRadius: BorderRadius.circular(10),
),
child:
Column(
children: [
'drag_icon'.toSvgAsset(),
12.height,
provider.currentTime.toString().toDragAbleTimerFormat.tinyFont(context).custom(color: AppColor.white10, fontWeight: FontWeight.w600),
2.height,
context.translation.hours.tinyFont(context).custom(color: AppColor.white10, fontWeight: FontWeight.w600),
],
),
),
);
}
}
//older code...
// DateTime startTime = DateTime(0, 0, 0, 0, 0, 0); // Start from 00:00:00
// Timer timer;
// bool isRunning = false;
//
// @override
// void initState() {
// super.initState();
// startTimer();
// }
//
// void startTimer() {
// if (isRunning) return;
// timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
// setState(() {
// startTime = startTime.add(const Duration(seconds: 1));
// });
// });
// setState(() {
// isRunning = true;
// });
// }
//
// void stopTimer() {
// timer?.cancel();
// setState(() {
// isRunning = false;
// });
// }
// @override
// void dispose() {
// timer?.cancel();
// super.dispose();
// }
//
// @override
// Widget build(BuildContext context) {
// return Positioned(
// left: position.dx,
// top: position.dy,
// child: GestureDetector(
// onPanUpdate: (details) {
// setState(() {
// //calculate the exact bonds to be restrict the drag..
// if(position.dy + details.delta.dy>0&&position.dy + details.delta.dy<560){
// position = Offset(
// position.dx + details.delta.dx, // Update the X position
// position.dy + details.delta.dy, // Update the Y position
// );
// }
// });
// },
// child: buildTimerWidget(),
// ),
// );
// // return Positioned(
// // left: position.dx,
// // top: position.dy,
// // child: Draggable(
// // feedback: buildTimerWidget(),
// // childWhenDragging: Container(),
// // onDragEnd: (dragDetails) {
// // setState(() {
// // // Get the RenderBox of the parent widget (Stack)
// // final renderBox = context.findRenderObject() as RenderBox;
// //
// // // Convert the global position to a local position inside the Stack
// // position = dragDetails.offset;
// // });
// // },
// // child: buildTimerWidget(),
// // ),
// // );
// }
//
// Widget buildTimerWidget() {
// return GestureDetector(
// onTap: (){
// if(isRunning){
// stopTimer();
// }else{
// startTimer();
// }
// },
// child: Container(
// padding: EdgeInsets.all(8.toScreenHeight),
// width: 80.toScreenWidth,
// decoration: BoxDecoration(
// color: AppColor.black10,
// borderRadius: BorderRadius.circular(10),
// ),
// child: Column(
// children: [
// 'drag_icon'.toSvgAsset(),
// 12.height,
// startTime.toString().toDragAbleTimerFormat.tinyFont(context).custom(color: AppColor.white10, fontWeight: FontWeight.w600),
// 2.height,
// context.translation.hours.tinyFont(context).custom(color: AppColor.white10, fontWeight: FontWeight.w600),
// ],
// ),
// ),
// );
// }

@ -6,14 +6,16 @@ import 'package:test_sa/controllers/providers/api/service_requests_provider.dart
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/service_request_latest/views/components/scan_qr_view.dart'; import 'package:test_sa/service_request_latest/views/components/scan_qr_view.dart';
import 'package:test_sa/views/widgets/qr/scan_qr.dart';
import 'activities_list_view.dart'; import 'activities_list_view.dart';
class VerifyArrivalView extends StatelessWidget { class VerifyArrivalView extends StatelessWidget {
const VerifyArrivalView({Key? key}) : super(key: key); VerifyArrivalView({Key key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -35,12 +37,13 @@ class VerifyArrivalView extends StatelessWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = items[index]; final item = items[index];
return listItem( return listItem(
icon: item['icon']!, icon: item['icon'],
heading: item['heading']!, heading: item['heading'],
subHeading: item['subHeading']!, subHeading: item['subHeading'],
//context: context, context: context,
onTap: () { onTap: () {
onItemTap(serviceRequest: serviceRequestsProvider.currentSelectedRequest!, index: index, context: context);
onItemTap(serviceRequest: serviceRequestsProvider.currentSelectedRequest, index: index,context: context);
}); });
}, },
), ),
@ -49,44 +52,55 @@ class VerifyArrivalView extends StatelessWidget {
); );
} }
Widget listItem({required String icon, required String heading, required String subHeading, required VoidCallback onTap}) { Widget listItem({@required BuildContext context, @required String icon, @required String heading, @required String subHeading, @required VoidCallback onTap}) {
return Padding( return Padding(
padding: EdgeInsets.only(left: 16.toScreenWidth, right: 16.toScreenWidth, bottom: 12.toScreenHeight), padding: EdgeInsets.only(left: 16.toScreenWidth,right: 16.toScreenWidth,bottom: 12.toScreenHeight),
child: Card( child: Card(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14), // Circular border radius borderRadius: BorderRadius.circular(14), // Circular border radius
), ),
color: Colors.white, color: Colors.white,
child: ListTile( child:
ListTile(
minVerticalPadding: 12, minVerticalPadding: 12,
horizontalTitleGap: 10, horizontalTitleGap: 10,
onTap: onTap, onTap: onTap,
// contentPadding: const EdgeInsets.all(12), // contentPadding: const EdgeInsets.all(12),
leading: SvgPicture.asset(icon), leading: SvgPicture.asset(icon),
title: Text(heading, style: AppTextStyles.heading5), title: Text(
subtitle: Text(subHeading, style: AppTextStyles.bodyText), heading,
style: AppTextStyles.heading5,
),
subtitle: Text(
subHeading,
style: AppTextStyles.bodyText,
),
), ),
), ),
); );
} }
void onItemTap({required int index, required ServiceRequest serviceRequest, required BuildContext context}) { void onItemTap({@required int index, @required ServiceRequest serviceRequest,@required BuildContext context}) {
print('on item tap i got index is $index'); switch(index){
switch (index) {
case 0: case 0:
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) => const ScanQrView()), MaterialPageRoute(builder: (context) => const ScanQrView()),
); );
break; break;case 1:
case 1:
//push to specific screen... //push to specific screen...
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) => const ActivitiesListView()), MaterialPageRoute(builder: (context) => ActivitiesListView()),
); );
break; break;case 2:
case 2: //push to specific screen...
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => const ScanQrView()),
// );
break;case 2:
//push to specific screen... //push to specific screen...
// Navigator.push( // Navigator.push(
// context, // context,

@ -10,6 +10,7 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/service_request/service_report.dart'; import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
@ -19,7 +20,6 @@ import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../../models/lookup.dart'; import '../../../../../models/lookup.dart';
@ -29,21 +29,21 @@ import '../../../../../new_views/common_widgets/default_app_bar.dart';
import '../../../controllers/validator/validator.dart'; import '../../../controllers/validator/validator.dart';
class SparePartRequest extends StatefulWidget { class SparePartRequest extends StatefulWidget {
static const String id = "/spare-part-request"; static const String id = "/verify-assets-detail";
const SparePartRequest({Key? key}) : super(key: key); const SparePartRequest({Key key}) : super(key: key);
@override @override
_SparePartRequestState createState() => _SparePartRequestState(); _SparePartRequestState createState() => _SparePartRequestState();
} }
class _SparePartRequestState extends State<SparePartRequest> with TickerProviderStateMixin { class _SparePartRequestState extends State<SparePartRequest> with TickerProviderStateMixin {
late UserProvider _userProvider; UserProvider _userProvider;
late SettingProvider _settingProvider; SettingProvider _settingProvider;
late ServiceRequestsProvider _serviceRequestsProvider; ServiceRequestsProvider _serviceRequestsProvider;
late ServiceStatusProvider _assetTypeProvider; ServiceStatusProvider _assetTypeProvider;
late PartsProvider _partsProvider; PartsProvider _partsProvider;
late ServiceReport _serviceReport; ServiceReport _serviceReport;
bool _isLoading = false; bool _isLoading = false;
List<SparePart> _spareParts = []; List<SparePart> _spareParts = [];
@ -68,12 +68,12 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false); ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset(); Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).reset(); Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest?.id; Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest.id;
} }
// _isLoading = true; // _isLoading = true;
} }
//Asset loanAvailabilityAsset; Asset loanAvailabilityAsset;
@override @override
void dispose() { void dispose() {
@ -87,12 +87,12 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
_isLoading = true; _isLoading = true;
setState(() {}); setState(() {});
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false); ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
_serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: serviceRequestsProvider.currentSelectedRequest!.id!); _serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: serviceRequestsProvider.currentSelectedRequest.id);
await _assetTypeProvider.getTypes(); await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host);
_serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee; _serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee;
_serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType; _serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType;
_serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web _serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web
_spareParts = await _partsProvider.getPartsList(assetId: serviceRequestsProvider.currentSelectedRequest?.deviceId); _spareParts = await _partsProvider.getPartsList(assetId: serviceRequestsProvider.currentSelectedRequest.deviceId);
_isLoading = false; _isLoading = false;
setState(() {}); setState(() {});
} }
@ -109,7 +109,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
} }
_serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere( _serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere(
(element) => element.value == _serviceReport.callRequest?.assetType, (element) => element.value == _serviceReport.callRequest?.assetType,
orElse: null, orElse: () => null,
); );
return Scaffold( return Scaffold(
@ -156,7 +156,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight), contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight),
showWithoutDecoration: true, showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
enable: serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null, enable: serviceRequestProvider.initialSelectedSparePart != null && serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null,
validator: (value) => value == null || value.isEmpty validator: (value) => value == null || value.isEmpty
? context.translation.requiredField ? context.translation.requiredField
: Validator.isNumeric(value) : Validator.isNumeric(value)
@ -174,7 +174,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight), contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight),
showWithoutDecoration: true, showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
enable: serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null, enable: serviceRequestProvider.initialSelectedSparePart != null && serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null,
validator: (value) => value == null || value.isEmpty validator: (value) => value == null || value.isEmpty
? context.translation.requiredField ? context.translation.requiredField
: Validator.isNumeric(value) : Validator.isNumeric(value)
@ -187,7 +187,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
), ),
15.height, 15.height,
AppTextFormField( AppTextFormField(
initialValue: _serviceReport.comment ?? "", initialValue: _serviceReport?.comment,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
labelText: context.translation.description, labelText: context.translation.description,
alignLabelWithHint: true, alignLabelWithHint: true,

@ -0,0 +1,88 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/service_request/search_work_order.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/pages/user/requests/work_order/update_service_report.dart';
import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart';
import '../../../../views/widgets/requests/request_status.dart';
class WorkOrderCardView extends StatelessWidget {
final SearchWorkOrder workOrder;
final ServiceRequest serviceRequest;
final bool showShadow;
WorkOrderCardView(this.workOrder, this.serviceRequest, {Key key, this.showShadow = true}) : super(key: key);
@override
Widget build(BuildContext context) {
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusLabel(
label: workOrder.currentSituation.name,
textColor: AppColor.getRequestStatusTextColorByName(context, workOrder.currentSituation.name),
backgroundColor: AppColor.getRequestStatusColorByName(context, workOrder.currentSituation.name),
),
8.height,
Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
Text(
'${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName?.cleanupWhitespace?.capitalizeFirstOfEach}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
),
Text(
'${context.translation.currentSituation}: ${workOrder.currentSituation.name}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
),
16.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.readCompleteThread,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context), decoration: TextDecoration.underline),
),
// 4.width,
// Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
),
],
).onPress(() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: workOrder, serviceRequest: serviceRequest)),
);
}).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)
"edit_icon".toSvgAsset(height: 21, width: 21).onPress(() {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrder)),
);
}),
if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) 8.height,
Text(workOrder.visitDate?.toServiceRequestCardFormat ?? "",
textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : const Color(0xFF3B3D4A))),
],
)
],
).toShadowContainer(context);
}
}

@ -0,0 +1,168 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../../../models/lookup.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
class AssetRetired extends StatefulWidget {
static const String id = "/asset-tobe-retired";
const AssetRetired({Key key}) : super(key: key);
@override
_AssetRetiredState createState() => _AssetRetiredState();
}
class _AssetRetiredState extends State<AssetRetired> with TickerProviderStateMixin {
UserProvider _userProvider;
SettingProvider _settingProvider;
ServiceRequestsProvider _serviceRequestsProvider;
ServiceStatusProvider _assetTypeProvider;
ServiceReport _serviceReport;
bool _isLoading = false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
void initState() {
_serviceReport = ServiceReport(
// returnToService: DateTime.now(),
// //type: const Lookup(value: 2),
// device: widget.request.device,
sparePartsWorkOrders: [],
);
super.initState();
if (context.mounted) {
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest.id;
}
// _isLoading = true;
}
Asset loanAvailabilityAsset;
void getRequestForWorkOrder() async {
_isLoading = true;
setState(() {});
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
_serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: serviceRequestsProvider.currentSelectedRequest.id);
await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host);
_serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee;
_serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType;
_serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web
_isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_assetTypeProvider = Provider.of<ServiceStatusProvider>(context);
if (_serviceReport.callRequest == null) {
getRequestForWorkOrder();
}
_serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere(
(element) => element.value == _serviceReport.callRequest?.assetType,
orElse: () => null,
);
final List<File> _files = [];
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.assetToBeRetired),
body: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
child: Card(
child: Column(
children: [
12.height,
SingleItemDropDownMenu<Lookup, ReasonProvider>(
context: context,
title: context.translation.failureReason,
backgroundColor: AppColor.neutral100,
height: 70.toScreenHeight,
showShadow: false,
// initialValue: _subWorkOrders.reason,
onSelect: (value) {
if (value != null) {
// _subWorkOrders.reason = value;
}
},
),
8.height,
AppTextFormField(
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100,
alignLabelWithHint: true,
onChange: (text) {
serviceRequestProvider.currentSelectedRequest.comments = text;
},
onSaved: (text) {
serviceRequestProvider.currentSelectedRequest.comments = text;
},
),
23.height,
MultiFilesPicker(label: context.translation.attachFiles,
files: _files,
buttonIcon: 'image-plus'?.toSvgAsset(),
),
],
).paddingOnly(start:13,end: 13,top: 16,bottom: 16),
).paddingAll(16),
).expanded,
FooterActionButton.footerContainer(
child: AppFilledButton(
label: context.translation.submit,
buttonColor: AppColor.primary10,
onPressed: () async {
//
},
),
),
],
),
),
),
);
}),
);
}
}

@ -0,0 +1,283 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/loan_availability_provider.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/pick_asset.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../../../models/lookup.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
class VerifyAssetDetails extends StatefulWidget {
static const String id = "/verify-asset-detail";
const VerifyAssetDetails({Key key}) : super(key: key);
@override
_VerifyAssetDetailsState createState() => _VerifyAssetDetailsState();
}
class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProviderStateMixin {
UserProvider _userProvider;
SettingProvider _settingProvider;
ServiceRequestsProvider _serviceRequestsProvider;
ServiceStatusProvider _assetTypeProvider;
PartsProvider _partsProvider;
ServiceReport _serviceReport;
bool _isLoading = false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
int _selectedValue = 1;
@override
void initState() {
_serviceReport = ServiceReport(
// returnToService: DateTime.now(),
// //type: const Lookup(value: 2),
// device: widget.request.device,
sparePartsWorkOrders: [],
);
super.initState();
if (context.mounted) {
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest.id;
}
// _isLoading = true;
}
Asset loanAvailabilityAsset;
void getRequestForWorkOrder() async {
_isLoading = true;
setState(() {});
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
_serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: serviceRequestsProvider.currentSelectedRequest.id);
await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host);
_serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee;
_serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType;
_serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web
_isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_assetTypeProvider = Provider.of<ServiceStatusProvider>(context);
_partsProvider = Provider.of<PartsProvider>(context);
if (_serviceReport.callRequest == null) {
getRequestForWorkOrder();
}
_serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere(
(element) => element.value == _serviceReport.callRequest?.assetType,
orElse: () => null,
);
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.verify_asset_details),
body: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
context.translation.equipmentStatus.bodyText(context).custom(color: AppColor.black20),
12.height,
assetStatusWidget(context),
24.height,
ADatePicker(
label: context.translation.returnToService,
hideShadow: true,
height: 70.toScreenHeight,
backgroundColor: AppColor.neutral100,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.startDate ?? ""),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
if (selectedDate != null) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (selectedDateTime != null) {
if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest.date))) {
"Visit Date time must be greater then request date".showToast;
return;
}
setState(() {
serviceRequestProvider.currentSelectedRequest.startDate = selectedDateTime?.toIso8601String();
});
print('start date i got is ${serviceRequestProvider.currentSelectedRequest.startDate}');
}
}
});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, LoanAvailabilityProvider>(
context: context,
title: context.translation.loanAvailability,
initialValue: _serviceReport?.loanAvailablity,
onSelect: (status) {
if (status != null) {
setState(() {
_serviceReport.loanAvailablity = status;
if (_serviceReport.loanAvailablity.value != 1) {
loanAvailabilityAsset = null;
_serviceReport.assetLoan = null;
}
});
}
},
),
if (_serviceReport?.loanAvailablity?.value == 1) 8.height,
if (_serviceReport?.loanAvailablity?.value == 1)
PickAsset(
device: loanAvailabilityAsset, // ?? _serviceReport.device,
onPickAsset: (asset) {
if (asset != null) {
_serviceReport.assetLoan = AssetInfo.fromJson(asset.toJson());
setState(() {
loanAvailabilityAsset = asset;
});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, ReasonProvider>(
context: context,
title: context.translation.failureReason,
backgroundColor: AppColor.neutral100,
height: 70.toScreenHeight,
showShadow: false,
// initialValue: _subWorkOrders.reason,
onSelect: (value) {
if (value != null) {
// _subWorkOrders.reason = value;
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, ReasonProvider>(
context: context,
title: context.translation.faultDescription,
backgroundColor: AppColor.neutral100,
height: 70.toScreenHeight,
showShadow: false,
// initialValue: _subWorkOrders.reason,
onSelect: (value) {
if (value != null) {
// _subWorkOrders.reason = value;
}
},
),
11.height,
context.translation.solutions.heading6(context).custom(color: AppColor.neutral50),
11.height,
//TODO solution from api...
'Solution number one \nSolution number two'.heading6(context).custom(color: AppColor.neutral50),
],
).paddingOnly(start:13,end: 13,top: 16,bottom: 16),
).paddingAll(16),
).expanded,
Container(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth,vertical: 16.toScreenHeight),
color: AppColor.white10,
child: AppFilledButton(
label: context.translation.verify_asset_details,
buttonColor: AppColor.primary10,
onPressed: () async {
},
),
),
],
),
),
),
);
}),
);
}
Widget assetStatusWidget(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
radioButtonWidget(label: context.translation.up_and_running, value: 1),
radioButtonWidget(label: context.translation.partially_down, value: 2),
radioButtonWidget(label: context.translation.fully_down, value: 3),
],
);
}
Widget radioButtonWidget({@required String label, @required dynamic value}) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 20.toScreenWidth,
height: 40.toScreenHeight,
//TODO use the type required according data..
child: Radio<int>(
activeColor: AppColor.primary10,
value: value,
groupValue: _selectedValue,
onChanged: (int value) {
setState(() {
_selectedValue = value;
});
},
),
),
8.width,
Text(
label,
style: AppTextStyles.tinyFont,
),
13.width,
],
);
}
}

@ -0,0 +1,279 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/widgets/date_and_time/time_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../../models/lookup.dart';
import '../../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
class ExternalMaintenanceRequest extends StatefulWidget {
static const String id = "/add-external-activity";
const ExternalMaintenanceRequest({Key key}) : super(key: key);
@override
_ExternalMaintenanceRequestState createState() => _ExternalMaintenanceRequestState();
}
class _ExternalMaintenanceRequestState extends State<ExternalMaintenanceRequest> with TickerProviderStateMixin {
UserProvider _userProvider;
SettingProvider _settingProvider;
ServiceRequest _request;
ServiceRequestsProvider _serviceRequestsProvider;
ServiceStatusProvider _assetTypeProvider;
ServiceReport _serviceReport;
bool _isLoading = false;
TimeOfDay _startTime;
int _selectedValue = 1;
TimeOfDay _endTime;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _faultController = TextEditingController();
final TextEditingController _workPreformedController = TextEditingController();
final TextEditingController _partQtyController = TextEditingController();
@override
void initState() {
_serviceReport = ServiceReport(
// returnToService: DateTime.now(),
// //type: const Lookup(value: 2),
// device: widget.request.device,
sparePartsWorkOrders: [],
);
super.initState();
if (context.mounted) {
_request = Provider.of<ServiceRequestsProvider>(context, listen: false).currentSelectedRequest;
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = _request.id;
}
// _isLoading = true;
}
Asset loanAvailabilityAsset;
@override
void dispose() {
_faultController.dispose();
_workPreformedController.dispose();
_partQtyController.dispose();
super.dispose();
}
void getRequestForWorkOrder() async {
_isLoading = true;
setState(() {});
_serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: _request.id);
await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host);
_serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee;
_serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType;
_serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web
_isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_assetTypeProvider = Provider.of<ServiceStatusProvider>(context);
if (_serviceReport.callRequest == null) {
getRequestForWorkOrder();
}
_serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere(
(element) => element.value == _serviceReport.callRequest?.assetType,
orElse: () => null,
);
return LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: Stack(
children: [
SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
8.height,
SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context,
height: 70.toScreenHeight,
title: context.translation.supplier,
showShadow: false,
backgroundColor: AppColor.neutral100,
staticData: Provider.of<ServiceReportLastCallsProvider>(context).calls,
initialValue: _serviceReport?.calllastSituation,
onSelect: (status) {
_serviceReport.calllastSituation = status;
},
),
// Container(
// height: 60.toScreenHeight,
// width: 60.toScreenWidth,
// decoration: BoxDecoration(
// color: _subWorkOrders.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.background(context),
// borderRadius: BorderRadius.circular(10),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
// ),
// child: Icon(
// Icons.add,
// color: context.isDark ? null : AppColor.neutral60,
// ),
// ).onPress(_subWorkOrders.supplier?.suppliername == null
// ? null
// : () async {
// SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet(
// context: context,
// useSafeArea: true,
// isScrollControlled: true,
// backgroundColor: Colors.transparent,
// builder: (context) => AddSupplierEngineerBottomSheet(_subWorkOrders.supplier.id),
// )) as SuppEngineerWorkOrders;
// if (suppEngineer != null) {
// _subWorkOrders?.supplier?.suppPersons ??= [];
// _subWorkOrders?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson()));
// engineer = suppEngineer;
// setState(() {});
// }
// }),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
ATimePicker(
label: context.translation.startTime,
hint: context.translation.select,
withBorder: false,
icon: 'clock',
withIcon: true,
backgroundColor: AppColor.neutral100,
height: 70.toScreenHeight,
time: _startTime,
onTimePicker: (selectedTime) {
if (selectedTime != null) {
print('time selected $selectedTime');
setState(() {
_startTime = selectedTime;
});
}
},
).expanded,
8.width,
ATimePicker(
label: context.translation.endTime,
hint: context.translation.select,
icon: 'clock',
withIcon: true,
backgroundColor: AppColor.neutral100,
withBorder: false,
height: 70.toScreenHeight,
time: _endTime,
onTimePicker: (selectedTime) {
if (selectedTime != null) {
setState(() {
_endTime = selectedTime;
});
}
},
).expanded,
],
),
8.height,
AppTextFormField(
labelText: context.translation.workingHours,
backgroundColor: AppColor.neutral80,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth),
initialValue: _serviceReport?.workingHours.toString(),
textAlign: TextAlign.center,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
],
),
),
).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12),
FooterActionButton.footerContainer(
child: AppFilledButton(
label:context.translation.addExternalActivity, // Use the dynamic label
buttonColor: AppColor.primary10,
onPressed: () async {
// Handle button press
},
),
),
],
),
);
}
Widget repairLocationWidget(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
radioButtonWidget(label: context.translation.remotely, value: 1),
radioButtonWidget(label: context.translation.workshop, value: 2),
radioButtonWidget(label: context.translation.abroad, value: 3),
],
);
}
Widget radioButtonWidget({@required String label, @required dynamic value}) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 20.toScreenWidth,
height: 40.toScreenHeight,
//TODO use the type required according data..
child: Radio<int>(
activeColor: AppColor.primary10,
value: value,
groupValue: _selectedValue,
onChanged: (int value) {
setState(() {
_selectedValue = value;
});
},
),
),
8.width,
Text(
label,
style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120),
),
13.width,
],
);
}
}

@ -0,0 +1,303 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/widgets/date_and_time/time_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../../models/lookup.dart';
import '../../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
class InternalMaintenanceRequest extends StatefulWidget {
static const String id = "/add-internal-activity";
const InternalMaintenanceRequest({Key key}) : super(key: key);
@override
_InternalMaintenanceRequestState createState() => _InternalMaintenanceRequestState();
}
class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest> with TickerProviderStateMixin {
UserProvider _userProvider;
SettingProvider _settingProvider;
ServiceRequest _request;
ServiceRequestsProvider _serviceRequestsProvider;
ServiceStatusProvider _assetTypeProvider;
PartsProvider _partsProvider;
ServiceReport _serviceReport;
bool _isLoading = false;
TimeOfDay _startTime;
int _selectedValue = 1;
TimeOfDay _endTime;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _faultController = TextEditingController();
final TextEditingController _workPreformedController = TextEditingController();
final TextEditingController _partQtyController = TextEditingController();
@override
void initState() {
_serviceReport = ServiceReport(
// returnToService: DateTime.now(),
// //type: const Lookup(value: 2),
// device: widget.request.device,
sparePartsWorkOrders: [],
);
super.initState();
if (context.mounted) {
_request = Provider.of<ServiceRequestsProvider>(context, listen: false).currentSelectedRequest;
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = _request.id;
}
// _isLoading = true;
}
Asset loanAvailabilityAsset;
@override
void dispose() {
_faultController.dispose();
_workPreformedController.dispose();
_partQtyController.dispose();
super.dispose();
}
void getRequestForWorkOrder() async {
_isLoading = true;
setState(() {});
_serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: _request.id);
await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host);
_serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee;
_serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType;
_serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web
_isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_assetTypeProvider = Provider.of<ServiceStatusProvider>(context);
_partsProvider = Provider.of<PartsProvider>(context);
if (_serviceReport.callRequest == null) {
getRequestForWorkOrder();
}
_serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere(
(element) => element.value == _serviceReport.callRequest?.assetType,
orElse: () => null,
);
return LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: Stack(
children: [
SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
8.height,
SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context,
height: 70.toScreenHeight,
title: context.translation.activityStatus,
showShadow: false,
backgroundColor: AppColor.neutral100,
staticData: Provider.of<ServiceReportLastCallsProvider>(context).calls,
initialValue: _serviceReport?.calllastSituation,
onSelect: (status) {
_serviceReport.calllastSituation = status;
},
),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
ATimePicker(
label: context.translation.startTime,
hint: context.translation.select,
withBorder: false,
icon: 'clock',
withIcon: true,
backgroundColor: AppColor.neutral100,
height: 70.toScreenHeight,
time: _startTime,
onTimePicker: (selectedTime) {
if (selectedTime != null) {
print('time selected $selectedTime');
setState(() {
_startTime = selectedTime;
});
}
},
).expanded,
8.width,
ATimePicker(
label: context.translation.endTime,
hint: context.translation.select,
icon: 'clock',
withIcon: true,
backgroundColor: AppColor.neutral100,
withBorder: false,
height: 70.toScreenHeight,
time: _endTime,
onTimePicker: (selectedTime) {
if (selectedTime != null) {
setState(() {
_endTime = selectedTime;
});
}
},
).expanded,
],
),
8.height,
AppTextFormField(
labelText: context.translation.workingHours,
backgroundColor: AppColor.neutral80,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth),
initialValue: _serviceReport?.workingHours.toString(),
textAlign: TextAlign.center,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
//TODO need to be selected when submit...
// SingleItemDropDownMenu<Lookup, ServiceTypeProvider>(
// context: context,
// title: context.translation.serviceType,
// initialValue: _serviceReport.serviceType,
// onSelect: (value) {
// _serviceReport.serviceType = value;
// },
// ),
//Provider.of<ServiceReportLastCallsProvider>(context)
8.height,
AppTextFormField(
labelText: context.translation.travelingHours,
backgroundColor: AppColor.neutral100,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue: _serviceReport?.travelingHours?.toString(),
textInputType: TextInputType.number,
contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth),
showShadow: false,
onSaved: (value) {
_serviceReport.travelingHours = double.tryParse(value) ?? 0.0;
},
),
16.height,
context.translation.repairLocation.bodyText(context).custom(color: AppColor.black20, fontWeight: FontWeight.w500),
8.height,
repairLocationWidget(context),
16.height,
AppTextFormField(
labelText: context.translation.assignedEmployee,
backgroundColor: AppColor.neutral80,
contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth),
initialValue: _serviceReport?.workingHours.toString(),
textAlign: TextAlign.center,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
initialValue: _serviceReport?.comment,
labelText: context.translation.technicalComment,
backgroundColor: AppColor.neutral100,
showShadow: false,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onSaved: (value) {
_serviceReport.comment = value;
},
),
],
),
),
).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12),
FooterActionButton.footerContainer(
child: AppFilledButton(
label:context.translation.addInternalActivity, // Use the dynamic label
buttonColor: AppColor.primary10,
onPressed: () async {
// Handle button press
},
),
),
],
),
);
}
Widget repairLocationWidget(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
radioButtonWidget(label: context.translation.remotely, value: 1),
radioButtonWidget(label: context.translation.workshop, value: 2),
radioButtonWidget(label: context.translation.abroad, value: 3),
],
);
}
Widget radioButtonWidget({@required String label, @required dynamic value}) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 20.toScreenWidth,
height: 40.toScreenHeight,
//TODO use the type required according data..
child: Radio<int>(
activeColor: AppColor.primary10,
value: value,
groupValue: _selectedValue,
onChanged: (int value) {
setState(() {
_selectedValue = value;
});
},
),
),
8.width,
Text(
label,
style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120),
),
13.width,
],
);
}
}

@ -0,0 +1,94 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/external_request.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/internal_request.dart';
class MaintenanceRequestForm extends StatefulWidget {
const MaintenanceRequestForm({Key key}) : super(key: key);
@override
_MaintenanceRequestFormState createState() => _MaintenanceRequestFormState();
}
class _MaintenanceRequestFormState extends State<MaintenanceRequestForm> with SingleTickerProviderStateMixin {
TabController _tabController;
int initialIndex = 0;
@override
void initState() {
super.initState();
// _tabController = TabController(length: 2, vsync: this);
// print('tab controller i got is ${_tabController.length}');
// _tabController.addListener(() {
// print('add listner called..');
// setState(() {
// print('index i got is ${_tabController.index}');
// if (_tabController.index == 0) {
// _buttonLabel = 'abc';
// } else if (_tabController.index == 1) {
// _buttonLabel = 'def';
// }
// });
// });
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.neutral100,
appBar: DefaultAppBar(title: context.translation.maintenanceRequest),
body: DefaultTabController(
length: 2,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 16.toScreenWidth, right: 16.toScreenWidth, top: 12.toScreenHeight),
decoration: BoxDecoration(
color: context.isDark ? AppColor.neutral50 : AppColor.white10,
borderRadius: BorderRadius.circular(10),
),
child: TabBar(
padding: EdgeInsets.symmetric(vertical: 4.toScreenHeight, horizontal: 4.toScreenWidth),
labelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
unselectedLabelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
unselectedLabelStyle: AppTextStyles.bodyText,
labelStyle: AppTextStyles.bodyText,
indicatorPadding: EdgeInsets.zero,
indicator: BoxDecoration(
color: context.isDark ? AppColor.neutral60 : AppColor.neutral110,
borderRadius: BorderRadius.circular(7),
),
tabs: [
Tab(text: context.translation.internal, height: 57.toScreenHeight),
Tab(text: context.translation.external, height: 57.toScreenHeight),
],
),
),
// 12.height,
const TabBarView(
children: [
InternalMaintenanceRequest(),
ExternalMaintenanceRequest(),
],
).expanded,
],
),
),
);
}
}

@ -0,0 +1,244 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../../../models/lookup.dart';
import '../../../../../../models/service_request/spare_parts.dart';
import '../../../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
import '../../../../controllers/validator/validator.dart';
class SparePartRequest extends StatefulWidget {
static const String id = "/spare-part-request";
const SparePartRequest({Key key}) : super(key: key);
@override
_SparePartRequestState createState() => _SparePartRequestState();
}
class _SparePartRequestState extends State<SparePartRequest> with TickerProviderStateMixin {
UserProvider _userProvider;
SettingProvider _settingProvider;
ServiceRequestsProvider _serviceRequestsProvider;
ServiceStatusProvider _assetTypeProvider;
PartsProvider _partsProvider;
ServiceReport _serviceReport;
bool _isLoading = false;
List<SparePart> _spareParts = [];
final List<File> _files = [];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _partQtyController = TextEditingController();
final TextEditingController _oracleNoController = TextEditingController();
@override
void initState() {
_serviceReport = ServiceReport(
// returnToService: DateTime.now(),
// //type: const Lookup(value: 2),
// device: widget.request.device,
sparePartsWorkOrders: [],
);
super.initState();
if (context.mounted) {
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest.id;
}
// _isLoading = true;
}
Asset loanAvailabilityAsset;
@override
void dispose() {
_partQtyController.dispose();
_oracleNoController.dispose();
super.dispose();
}
void getRequestForWorkOrder() async {
_isLoading = true;
setState(() {});
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
_serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: serviceRequestsProvider.currentSelectedRequest.id);
await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host);
_serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee;
_serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType;
_serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web
_spareParts = await _partsProvider.getPartsList(assetId: serviceRequestsProvider.currentSelectedRequest.deviceId);
_isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_assetTypeProvider = Provider.of<ServiceStatusProvider>(context);
_partsProvider = Provider.of<PartsProvider>(context);
if (_serviceReport.callRequest == null) {
getRequestForWorkOrder();
}
_serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere(
(element) => element.value == _serviceReport.callRequest?.assetType,
orElse: () => null,
);
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.sparePartRequest),
body: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
context.translation.sparePartDetails.heading5(context),
12.height,
SingleItemDropDownMenu<SparePart, NullableLoadingProvider>(
context: context,
title: context.translation.partNo,
staticData: _spareParts,
height: 80.toScreenHeight,
showShadow: false,
initialValue: serviceRequestProvider.initialSelectedSparePart.sparePart,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
onSelect: (part) {
print('part i got is ${part.id}');
serviceRequestProvider.initialSelectedSparePart = SparePartsWorkOrders(id: 0, sparePart: part, qty: 0);
},
),
15.height,
AppTextFormField(
controller: _partQtyController,
labelText: context.translation.quantity,
textInputType: TextInputType.number,
contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight),
showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
enable: serviceRequestProvider.initialSelectedSparePart != null && serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null,
validator: (value) => value == null || value.isEmpty
? context.translation.requiredField
: Validator.isNumeric(value)
? null
: context.translation.onlyNumbers,
onSaved: (text) {
serviceRequestProvider.initialSelectedSparePart.qty = num.tryParse(text ?? "");
},
),
15.height,
AppTextFormField(
controller: _oracleNoController,
labelText: context.translation.oracleNo,
textInputType: TextInputType.number,
contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight),
showWithoutDecoration: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
enable: serviceRequestProvider.initialSelectedSparePart != null && serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null,
validator: (value) => value == null || value.isEmpty
? context.translation.requiredField
: Validator.isNumeric(value)
? null
: context.translation.onlyNumbers,
onSaved: (text) {
//TODO set the values...
// serviceRequestProvider.initialSelectedSparePart. = num.tryParse(text ?? "");
},
),
15.height,
AppTextFormField(
initialValue: _serviceReport?.comment,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
labelText: context.translation.description,
alignLabelWithHint: true,
showWithoutDecoration: true,
textInputType: TextInputType.multiline,
onSaved: (value) {
_serviceReport.comment = value;
},
),
15.height,
MultiFilesPicker(label: context.translation.attachQuotation, files: _files),
],
).paddingAll(16),
),
8.height,
],
),
).expanded,
AppFilledButton(
label: context.translation.addSparePartActivity,
buttonColor: AppColor.green70,
onPressed: () async {
ServiceRequestBottomSheet.actionBottomSheet(context: context, title: context.translation.addSparePartActionHeading);
// bool shouldReloadData = (await showModalBottomSheet(
// context: context,
// useSafeArea: true,
// isScrollControlled: true,
// backgroundColor: Colors.transparent,
// builder: (context) => ActionBottomSheet(title: context.translation.addSparePartActionHeading),
// )) as bool;
// if (shouldReloadData ?? false) {}
//TODO write add sparepart logic
// if ((!_formKey.currentState.validate()) || (!(await _serviceReport.validate(context)))) {
// setState(() {});
// return;
// }
// _formKey.currentState.save();
// _serviceReport.attachmentsWorkOrder ??= [];
// if (_files.isEmpty) _serviceReport.attachmentsWorkOrder = [];
// for (var file in _files) {
// _serviceReport.attachmentsWorkOrder.add(Attachment(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
// }
// final user = Provider.of<UserProvider>(context, listen: false).user;
// await _serviceRequestsProvider.createServiceReport(context, report: _serviceReport, request: serviceRequestProvider.serviceRequest, user: user);
},
),
],
).paddingAll(16),
),
),
);
}),
);
}
}

@ -0,0 +1,263 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/validator/validator.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/search_work_order.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/models/service_request/wo_call_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
class AssetConditionView extends StatefulWidget {
static const id = "/CreateSubWorkOrder";
final SearchWorkOrder workOrder;
const AssetConditionView({this.workOrder, Key key}) : super(key: key);
@override
State<AssetConditionView> createState() => _AssetConditionViewState();
}
class _AssetConditionViewState extends State<AssetConditionView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
SearchWorkOrder _subWorkOrders;
ServiceReport _serviceReport;
PartsProvider _partsProvider;
List<SparePart> _spareParts = [];
bool _isLoading = false;
bool _showVendorFields = false;
SuppEngineerWorkOrders engineer;
SupplierDetails initialSupplier;
final TextEditingController _workPreformedController = TextEditingController();
final TextEditingController _partQtyController = TextEditingController();
@override
void initState() {
_subWorkOrders = SearchWorkOrder(
assignedEmployee: widget?.workOrder?.callRequest?.assignedEmployee,
callRequest: CallRequest(id: widget?.workOrder?.callRequest?.id),
currentSituation: null,
supplier: null,
// parentWOId: widget.workOrder.id,
);
getData();
_serviceReport = ServiceReport();
// _isLoading = true;
super.initState();
// if (context.mounted) {
// Provider.of<ServiceReportAssistantsEmployeeProvider>(context, listen: false).reset();
// Provider.of<ReasonProvider>(context, listen: false).reset();
// Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = widget.workOrder.callRequest.id.toString();
// }
}
ServiceStatusProvider assetTypesProvider;
CallRequest _callRequestForWorkOrder;
void getData() async {
ReasonProvider reasonProvider = Provider.of<ReasonProvider>(context,listen: false);
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context,listen: false);
_spareParts = await Provider.of<PartsProvider>(context,listen: false).getPartsList(assetId: serviceRequestsProvider.currentSelectedRequest.deviceId);
// _serviceReport = serviceRequestsProvider.currentSelectedRequest;
// Provider.of<RequestedThroughProvider>(context).getDate();
// Provider.of<TypeOfRequestProvider>(context).getDate();
reasonProvider.serviceRequestId = serviceRequestsProvider.currentSelectedRequest.id;
reasonProvider.getDate();
// Provider.of<PriorityProvider>(context).getDate();
// Provider.of<EquipmentStatusProvider>(context).getDate();
}
Future getAssetType() async {
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
final serviceRequestProvider = Provider.of<ServiceRequestsProvider>(context);
Provider.of<ServiceRequestFaultDescriptionProvider>(context, listen: false).reset();
assetTypesProvider = Provider.of<ServiceStatusProvider>(context, listen: false);
_callRequestForWorkOrder = await serviceRequestProvider.getCallRequestForWorkOrder(callId: widget.workOrder?.callRequest?.id?.toString());
if (_subWorkOrders?.parentWOId != null) {
final subWoDetails = await serviceRequestProvider.getSubWorkOrderDetails(parentId: _subWorkOrders?.parentWOId.toString());
_subWorkOrders.copyDetails(subWoDetails);
_serviceReport.equipmentStatus = subWoDetails.equipmentStatus;
_serviceReport.reason = subWoDetails.reason;
initialSupplier = subWoDetails.supplier;
_serviceReport.faultDescription = subWoDetails.faultDescription;
_subWorkOrders.visitDate = subWoDetails.visitDate;
_subWorkOrders.sparePartsWorkOrders = subWoDetails.sparePartsWorkOrders;
}
await assetTypesProvider.getTypes();
_subWorkOrders?.assetType = assetTypesProvider.statuses?.firstWhere(
(element) => element.value == _callRequestForWorkOrder?.assetType,
orElse: () => null,
);
if (checkVendorFieldsVisibility(_subWorkOrders.calllastSituation)) {
if (_subWorkOrders.suppEngineerWorkOrders?.isNotEmpty ?? false) {
engineer = _subWorkOrders.suppEngineerWorkOrders?.last;
engineer?.id = engineer?.supplierContactId;
}
_subWorkOrders.supplier ??= SupplierDetails(id: _subWorkOrders?.supplier?.id);
}
_spareParts = await _partsProvider.getPartsList(assetId: widget.workOrder?.callRequest?.asset?.id);
setState(() {
_isLoading = false;
});
}
Asset loanAvailabilityAsset;
@override
void dispose() {
_workPreformedController?.dispose();
_partQtyController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final user = Provider.of<UserProvider>(context).user;
// final isCurrentUserIsAssistantEmp = (user.userID != widget.workOrder.assignedEmployee?.id);
// if (isCurrentUserIsAssistantEmp) {
// // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)];
// _subWorkOrders.assistantEmployees = [AssistantEmployees(id: 0, user: AssignedEmployee(id: user.userID, name: user.username))];
// } else {}
// if (_callRequestForWorkOrder == null) {
// _partsProvider = Provider.of<PartsProvider>(context);
// // getAssetType();
// }
bool disablePart = _subWorkOrders.calllastSituation?.value == 12;
return Consumer<ServiceRequestsProvider>(
builder: (context, serviceRequestProvider,child) {
return SafeArea(
child: _isLoading
? const ALoading()
: Container(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
child: Column(
children: [
SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SingleItemDropDownMenu<Lookup, ReasonProvider>(
context: context,
title: context.translation.reason,
initialValue: _subWorkOrders.reason,
onSelect: (value) {
if (value != null) {
_subWorkOrders.reason = value;
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, EquipmentStatusProvider>(
context: context,
title: context.translation.equipmentStatus,
initialValue: _subWorkOrders.equipmentStatus,
onSelect: (value) {
if (value != null) {
_subWorkOrders.equipmentStatus = value;
}
},
),
8.height,
SingleItemDropDownMenu<SparePart, NullableLoadingProvider>(
context: context,
title: context.translation.partNo,
staticData: _spareParts,
showShadow: true,
initialValue: serviceRequestProvider.initialSelectedSparePart.sparePart,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.white10,
onSelect: (part) {
serviceRequestProvider.initialSelectedSparePart = SparePartsWorkOrders(id: 0, sparePart: part, qty: 0);
},
),
// AppTextFormField(
// controller: _partQtyController,
// labelText: context.translation.quantity,
// textInputType: TextInputType.number,
// contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight),
// showWithoutDecoration: true,
// backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
// enable: serviceRequestProvider.initialSelectedSparePart != null && serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null,
// validator: (value) => value == null || value.isEmpty
// ? context.translation.requiredField
// : Validator.isNumeric(value)
// ? null
// : context.translation.onlyNumbers,
// onSaved: (text) {
// serviceRequestProvider.initialSelectedSparePart.qty = num.tryParse(text ?? "");
// },
// ),
15.height,
],
),
),),]),
));
}
);
// ),
// );
}
bool checkVendorFieldsVisibility(Lookup callsLastSituation) {
bool result = (initialSupplier?.suppliername?.isNotEmpty ?? false) ||
(callsLastSituation?.name?.toLowerCase()?.contains("under repair-vendor") ?? false) ||
(callsLastSituation?.name?.toLowerCase()?.contains("waiting for vendor") ?? false);
setState(() {
_showVendorFields = result;
});
return result;
}
Future<bool> validate() async {
if (_subWorkOrders.reason == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.reason}");
return false;
} else if (_subWorkOrders.equipmentStatus == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.equipmentStatus}");
return false;
} else if (_subWorkOrders.calllastSituation == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.callLastSituation}");
return false;
} else if (_showVendorFields && _subWorkOrders.suppEngineerWorkOrders == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.supplierEngineer}");
return false;
} else if (_showVendorFields && (_subWorkOrders.supplier.suppliername == null || _subWorkOrders.supplier.suppliername.isEmpty)) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.supplier}");
return false;
} else if (_subWorkOrders.calllastSituation.value == 12 && (_subWorkOrders.sparePartsWorkOrders == null || _subWorkOrders.sparePartsWorkOrders.isEmpty)) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNo}");
return false;
} else if (_subWorkOrders?.timer?.startAt == null) {
await Fluttertoast.showToast(msg: "Working Hours Required");
return false;
} else if (_subWorkOrders?.timer?.endAt == null) {
await Fluttertoast.showToast(msg: "Please Stop The Timer");
return false;
}
return true;
}
}

@ -0,0 +1,39 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
class AttachmentView extends StatelessWidget {
const AttachmentView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
//TODO user the same form key everywhere....
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final List<File> _files = [];
return Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
serviceRequestProvider.currentSelectedRequest.visitDate = '';
return Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: [
MultiFilesPicker(
label: context.translation.attachImage,
buttonHeight: 108.toScreenHeight,
buttonIcon: 'image_icon'?.toSvgAsset(),
files: _files,
onlyImages: true,
),
16.height,
],
),
),
);
});
}
}

@ -0,0 +1,120 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/date_and_time/time_picker.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart';
class TimeDurationView extends StatelessWidget {
const TimeDurationView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
//TODO user the same form key everywhere....
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
return Consumer<ServiceRequestsProvider>(
builder: (context, serviceRequestProvider,child) {
serviceRequestProvider.currentSelectedRequest.visitDate = '';
return Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: [
ADatePicker(
label: context.translation.visitDate,
hideShadow: true,
withIcon: false,
hint: context.translation.select,
height: 70.toScreenHeight,
date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.visitDate ?? ""),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
if (selectedDate != null) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (selectedDateTime != null) {
serviceRequestProvider.currentSelectedRequest.visitDate = selectedDateTime?.toIso8601String();
}
}
});
}
},
),
8.height,
ATimePicker(
label: context.translation.startTime,
hint: context.translation.select,
withIcon: false,
withBorder: false,
height: 70.toScreenHeight,
time: serviceRequestProvider.selectedTime,
onTimePicker: (selectedTime) {
if (selectedTime != null) {
print('time selected $selectedTime');
serviceRequestProvider.selectedTime = selectedTime;
}
},
),
8.height,
ATimePicker(
label: context.translation.endTime,
hint: context.translation.select,
withIcon: false,
withBorder: false,
height: 70.toScreenHeight,
time: serviceRequestProvider.selectedTime,
onTimePicker: (selectedTime) {
if (selectedTime != null) {
print('time selected $selectedTime');
serviceRequestProvider.selectedTime = selectedTime;
}
},
),
8.height,
SizedBox(
width: double.infinity,
height: 70.toScreenHeight,
child: AppTimer(
label: context.translation.workingHours,
timer: TimerModel(),
decoration: BoxDecoration(
color: AppColor.background(context),
borderRadius: BorderRadius.circular(10),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
// enabled: serviceRequestProvider.currentSelectedRequest.date == null,
enabled: true,
onChange: (timer) async {
print('timer i got is ${timer.toString()}');
return true;
},
),
),
16.height,
],
),
),
);
}
);
}
}

@ -0,0 +1,242 @@
import 'package:flutter/material.dart';
import 'package:test_sa/common_widgets/stapper_widget/components/base_step.dart';
import 'package:test_sa/common_widgets/stapper_widget/components/custom_line.dart';
import 'package:test_sa/common_widgets/stapper_widget/custom_stepper.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/service_request_latest/views/forms/work_order/components/asset_conditon_view.dart';
import 'package:test_sa/service_request_latest/views/forms/work_order/components/attachments_view.dart';
import 'package:test_sa/service_request_latest/views/forms/work_order/components/time_duration_view.dart';
class WorkOrderFormView extends StatefulWidget {
const WorkOrderFormView({Key key}) : super(key: key);
@override
_WorkOrderFormViewState createState() => _WorkOrderFormViewState();
}
class _WorkOrderFormViewState extends State<WorkOrderFormView> {
int currentStep = 0;
int activeStep = 0;
int reachedStep = 0;
int upperBound = 2;
final formKey = GlobalKey<FormState>();
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
Future<void> getInitialData() async {
// ListingVm listingVm = Provider.of<ListingVm>(context, listen: false);
// listingVm.listingPropertyType = widget.arguments['listingType'];
// if (widget.arguments['formType'] == AppConstants.addListing) {
// listingVm.landLordModel = LandLordModel();
// listingVm.listing['propertyType'] = widget.arguments['listingType'];
// if (listingVm.listing['propertyType'] == AppConstants.sell) {
// listingVm.listingParameter = 'sellParameter';
// listingVm.listing[listingVm.listingParameter] =
// SellParameter().toJson();
// listingVm.listing[listingVm.listingParameter]?['ownerDocs'] = [];
// }
// if (listingVm.listing['propertyType'] == AppConstants.rent) {
// listingVm.listingParameter = 'rentParameter';
// listingVm.listing[listingVm.listingParameter] =
// RentParameter().toJson();
// listingVm.listing[listingVm.listingParameter]?['ownerDocs'] = [];
// }
// } else if (widget.arguments['formType'] == AppConstants.editListing) {
// if (listingVm.listing['propertyType'] == AppConstants.sell) {
// listingVm.listingParameter = 'sellParameter';
// }
// if (listingVm.listing['propertyType'] == AppConstants.rent) {
// listingVm.listingParameter = 'rentParameter';
// }
// if (widget.arguments['isDuplicate'] == true) {
// FormUtils.setDuplicateValues(
// listingVm: listingVm, listType: widget.arguments['listingType']);
// }
// listingVm.formLocationController.clear();
// listingVm.formCommunityInitialValue =
// await FormUtils.setLocation(listingVm.listing, context);
// listingVm.formLocationController.text =
// listingVm.formCommunityInitialValue ?? '';
//
// listingVm.formAvailabilityDate =
// listingVm.listing[listingVm.listingParameter]['availabilityDate'] ??
// '';
// listingVm.formBuildYearDate =
// listingVm.listing[listingVm.listingParameter]['buildYear'] ?? '';
//
// listingVm.listing['photos'] ??= [];
// listingVm.listing[listingVm.listingParameter]['ownerDocs'] ??= [];
// }
// GeneralUtil.initilizePortalsSwitch(listingVm: listingVm);
// listingVm.getTenantExtent();
// await listingVm.getRegion();
// if (listingVm.listing[listingVm.listingParameter]
// ['propertyFinderLocation'] !=
// null) {
// await listingVm.getPropertyFinderLocationList(
// searchQuery: listingVm.listing[listingVm.listingParameter]
// ['propertyFinderLocation']);
// }
// await listingVm.getWaterMarkImage();
// await listingVm.getDeveloper();
// await GeneralUtil.loadPortalsLocationsData(listingVm);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.neutral100,
appBar: DefaultAppBar(title: context.translation.createWorkOrder),
body: Column(
children: [
16.height,
CustomStepper(
activeStep: activeStep,
lineStyle: LineStyle(
activeLineColor: AppColor.primary10,
finishedLineColor: AppColor.primary10,
defaultLineColor: AppColor.white40,
lineThickness: 1,
lineLength: 93.toScreenWidth,
lineType: LineType.normal,
),
internalPadding: 2.toScreenWidth,
steps: [
StepModel(customStep: customStepWidget(index: 0, stepIndex: 1), customTitle: customStepLabel(index: 1, label: context.translation.timeAndDuration)),
StepModel(customStep: customStepWidget(index: 1, stepIndex: 2), customTitle: customStepLabel(index: 1, label: context.translation.assetsCondition)),
StepModel(customStep: customStepWidget(index: 2, stepIndex: 3), customTitle: customStepLabel(index: 1, label: context.translation.attachmentsAcknowledge)),
],
onStepReached: (index) => setState(() => activeStep = index),
),
Expanded(
child: Padding(
padding: EdgeInsetsDirectional.symmetric(horizontal: 16.toScreenWidth, vertical: 25.toScreenHeight),
child: getStepWidget(),
)),
bottomContainerWidget(),
],
),
);
}
Widget bottomContainerWidget() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth,vertical: 16.toScreenHeight),
color: AppColor.white10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppFilledButton(
label: context.translation.cancel,
loading: false,
buttonColor: AppColor.white60,
textColor: AppColor.black10,
onPressed: () async {
Navigator.pop(context);
// await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest);
// Navigator.pop(context, true);
},
).expanded,
12.width,
AppFilledButton(
label: context.translation.next,
buttonColor: AppColor.primary10,
loading: false,
onPressed: () {
_incrementActiveStep();
//TODO move to next step..
},
).expanded,
],
));
}
void _incrementActiveStep() {
setState(() {
++activeStep;
if (reachedStep < activeStep) {
reachedStep = activeStep;
}
});
}
Future<void> _navigateNext(ServiceRequestsProvider serviceRequestsProvider) async {
if (activeStep < upperBound) {
switch (activeStep) {
case 0:
// await _navigateNextStep(listingVm);
break;
case 1:
break;
case 2:
_incrementActiveStep();
break;
}
}
}
// Your onPressed code
Widget customStepWidget({@required int index, @required int stepIndex}) {
return CircleAvatar(
backgroundColor: activeStep >= index ? AppColor.primary10 : AppColor.background(context),
child: activeStep > index
? Icon(
Icons.done,
color: AppColor.white10,
size: 26.toScreenHeight,
)
: activeStep == index
? Text(
'0$stepIndex',
style: const TextStyle(fontWeight: FontWeight.w500, color: AppColor.white10),
textAlign: TextAlign.center,
)
: Text(
'0$stepIndex',
style: const TextStyle(color: AppColor.black20),
),
);
}
Widget customStepLabel({@required String label, @required int index}) {
return Column(
children: [
Text(
label,
textAlign: TextAlign.center,
style: AppTextStyles.bodyText2.copyWith(color: AppColor.black20),
),
],
);
}
/// Returns the previous button.
Widget getStepWidget() {
switch (activeStep) {
case 0:
return const TimeDurationView();
case 1:
return const AssetConditionView();
case 2:
return const AttachmentView();
default:
return const SizedBox();
}
}
}

@ -0,0 +1,215 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/devices_provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/validator/validator.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/device/asset_search.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/qr/scan_qr.dart';
import '../../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
class CreateNewRequest extends StatefulWidget {
static const String id = "/create-new-request";
const CreateNewRequest({Key key}) : super(key: key);
@override
_CreateNewRequestState createState() => _CreateNewRequestState();
}
class _CreateNewRequestState extends State<CreateNewRequest> with TickerProviderStateMixin {
AssetProvider _devicesProvider;
bool _isLoading = false;
int _selectedEStatus = 1;
bool _isHighPrority = false;
String text;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
if (context.mounted) {
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
Provider.of<ServiceReportLastCallsProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).reset();
Provider.of<ReasonProvider>(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest.id;
}
// _isLoading = true;
}
_getDevice(String result, {bool isQr = false}) async {
if (result == null) return;
_devicesProvider.reset();
await _devicesProvider.getAssets(
search: AssetSearch(assetNo: result, assetSerialNumber: ""),
isQr: isQr,
);
}
Asset loanAvailabilityAsset;
@override
Widget build(BuildContext context) {
final List<File> _files = [];
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.createNewRequest),
body: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestProvider, child) {
return SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppFilledButton(
label: context.translation.scanOrPickAsset,
showIcon: true,
icon: "scan_asset".toSvgAsset(height: 20, fit: BoxFit.contain, color: Theme.of(context).scaffoldBackgroundColor),
buttonColor: AppColor.neutral50,
onPressed: () async {
String result = await Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const ScanQr()),
) as String;
_getDevice(result, isQr: true);
} ,
),
21.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
context.translation.highPriority.bodyText(context).custom(color: AppColor.black20),
CupertinoSwitch(
value: _isHighPrority,
onChanged: (value) {
setState(() {
// listingVm.listing[listingVm.listingParameter]['bayut'] = value;
_isHighPrority = value;
});
},
thumbColor: AppColor.red70,
activeColor: AppColor.red30.withOpacity(0.4),
),
],
),
20.height,
context.translation.equipmentStatus.bodyText(context).custom(color: AppColor.black20),
12.height,
assetStatusWidget(context),
8.height,
23.height,
MultiFilesPicker(label: context.translation.attachImage,
files: _files,
buttonColor: AppColor.primary10,
onlyImages: true,
buttonIcon: 'image-plus'?.toSvgAsset(color: AppColor.primary10),
),
AppTextFormField(
labelText: "Type any comment",
backgroundColor: AppColor.neutral30,
alignLabelWithHint: true,
showShadow: false,
validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField,
textInputType: TextInputType.multiline,
suffixIcon: "comment_send".toSvgAsset().paddingOnly(end: 16).onPress(() {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
// final comment = Comment(id: 0, callRequestId: num.tryParse(widget.requestId ?? ""), comment: text);
// commentsProvider.addComment(context, comment: comment);
}
}),
onSaved: (value) {
text = value;
},
),
],
).paddingOnly(start:13,end: 13,top: 15,bottom: 16),
).paddingAll(16),
).expanded,
FooterActionButton.footerContainer(
child: AppFilledButton(
label: context.translation.submitRequest,
buttonColor: AppColor.primary10,
onPressed: (){},
),
),
],
),
),
),
);
}),
);
}
Widget assetStatusWidget(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
radioButtonWidget(label: context.translation.up_and_running, value: 1),
radioButtonWidget(label: context.translation.partially_down, value: 2),
radioButtonWidget(label: context.translation.fully_down, value: 3),
],
);
}
Widget radioButtonWidget({@required String label, @required dynamic value}) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 20.toScreenWidth,
height: 40.toScreenHeight,
//TODO use the type required according data..
child: Radio<int>(
activeColor: AppColor.primary10,
value: value,
groupValue: _selectedEStatus,
onChanged: (int value) {
setState(() {
_selectedEStatus = value;
});
},
),
),
8.width,
Text(
label,
style: AppTextStyles.tinyFont,
),
13.width,
],
);
}
}

@ -7,6 +7,7 @@ import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/service_request_latest/views/components/history_log_view.dart'; import 'package:test_sa/service_request_latest/views/components/history_log_view.dart';
import 'package:test_sa/service_request_latest/views/components/initial_visit_card.dart';
import 'components/request_detail_view.dart'; import 'components/request_detail_view.dart';
@ -52,7 +53,6 @@ class RequestDetailMain extends StatelessWidget {
serviceRequest: ServiceRequest(id: requestId.toString()), serviceRequest: ServiceRequest(id: requestId.toString()),
fromTabView: true, fromTabView: true,
), ),
// HistoryLogView(),
const HistoryLogView(), const HistoryLogView(),
], ],
).expanded, ).expanded,

@ -1,47 +0,0 @@
// import 'package:another_flushbar/flushbar.dart';
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:test_sa/new_views/app_style/app_color.dart';
// todo delete
// class GeneralUtils {
// static Duration parseTimeString(String timeString) {
// try {
// print('time string i got is ${timeString}');
// List<String> timeParts = timeString.split(':');
//
// int hours = int.parse(timeParts[0]);
// int minutes = int.parse(timeParts[1]);
// int seconds = int.parse(timeParts[2]);
//
// print('');
//
// return Duration(hours: hours, minutes: minutes, seconds: seconds);
// } catch (e) {
// if (kDebugMode) {
// print("Error parsing time string: $e");
// }
// return Duration.zero; // Return zero duration in case of an error
// }
// }
//
// static Widget showFlushBar({required BuildContext context, String? title, String? message, double? duration}) {
// return Flushbar(
// flushbarPosition: FlushbarPosition.TOP,
// backgroundColor: AppColor.green70,
// title: title ?? "Hey Ninja",
// message: message ?? "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
// duration: Duration(seconds: duration?.toInt() ?? 3),
// flushbarStyle: FlushbarStyle.GROUNDED,
// reverseAnimationCurve: Curves.easeInOut,
// mainButton: IconButton(
// onPressed: () {
// Navigator.pop(context);
// },
// icon: const Icon(
// Icons.close,
// color: AppColor.white20,
// ),
// ),
// )..show(context);
// }
// }

@ -7,26 +7,26 @@ import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
class ADatePicker extends StatelessWidget { class ADatePicker extends StatelessWidget {
final DateTime? date; // Nullable final DateTime date;
final DateTime? from; // Nullable final DateTime from;
final DateTime? to; // Nullable final DateTime to;
final String label; final String label;
final bool hideShadow; final bool hideShadow;
final String? hint; // Nullable final String hint;
final Function(DateTime)? onDatePicker; // Nullable final Function(DateTime) onDatePicker;
final bool enable; final bool enable, withBorder, withIcon;
final bool withBorder; final Color backgroundColor;
final Color? backgroundColor; // Nullable
final bool formatDateWithTime; final bool formatDateWithTime;
final double? height; // Nullable final double height;
const ADatePicker({ const ADatePicker({
Key? key, Key key,
required this.label, @required this.label,
this.withBorder = true, this.withBorder = true,
this.height, this.height,
this.backgroundColor, this.backgroundColor,
this.hideShadow = false, this.hideShadow = false,
this.withIcon = true,
this.hint, this.hint,
this.date, this.date,
this.formatDateWithTime = false, this.formatDateWithTime = false,
@ -42,9 +42,9 @@ class ADatePicker extends StatelessWidget {
height: height, height: height,
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor ?? color: backgroundColor ??
(context.isDark && !enable (context.isDark && (enable == false)
? AppColor.neutral50 ? AppColor.neutral50
: !enable : (enable == false)
? AppColor.neutral40 ? AppColor.neutral40
: AppColor.background(context)), : AppColor.background(context)),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
@ -54,36 +54,34 @@ class ADatePicker extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Row( child: Row(
children: [ children: [
// enable
// ?
Column( Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
label.tinyFont(context), label.tinyFont(context),
(date == null (date?.toIso8601String == null
? hint ?? context.translation.pickADate ? hint ?? context.translation.pickADate
: (formatDateWithTime : (formatDateWithTime ? date?.toIso8601String()?.toFirstActionFormat : (date?.toIso8601String()?.split("T")?.first ?? context.translation.pickADate)))
? date?.toIso8601String().toFirstActionFormat // Use null-aware operator
: (date?.toIso8601String().split("T").first ?? context.translation.pickADate)))!
.bodyText(context) .bodyText(context)
.custom(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), .custom(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
], ],
).expanded, ).expanded,
//: label.bodyText(context).paddingOnly(top: 8, bottom: 8),
enable ? 16.width : const Spacer(), enable ? 16.width : const Spacer(),
"calender".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null), withIcon ? "calender".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null) : const SizedBox(),
], ],
), ),
).onPress(enable ).onPress(enable
? () async { ? () async {
final DateTime? picked = await showDatePicker( DateTime picked = await showDatePicker(
// Nullable DateTime
context: context, context: context,
initialDate: DateTime.now(), initialDate: DateTime.now(),
firstDate: from ?? DateTime.now(), firstDate: from ?? DateTime.now(),
lastDate: to ?? DateTime.now().add(const Duration(days: 365)), lastDate: to ?? DateTime.now().add(const Duration(days: 365)),
); );
if (picked != null && onDatePicker != null) { if (onDatePicker != null) onDatePicker(picked);
onDatePicker!(picked); // Use null-aware operator
}
} }
: null); : null);
} }

@ -1,24 +1,27 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
class ATimePicker extends StatelessWidget { class ATimePicker extends StatelessWidget {
final TimeOfDay? time; // Nullable final TimeOfDay time;
final String label; final String label;
final String? hint; // Nullable final String icon;
final Function(TimeOfDay)? onTimePicker; // Nullable final String hint;
final bool enable; final Function(TimeOfDay) onTimePicker;
final bool withBorder; final bool enable, withBorder, withIcon;
final Color? backgroundColor; // Nullable final Color backgroundColor;
final double? height; // Nullable final double height;
const ATimePicker({ const ATimePicker({
Key? key, Key key,
required this.label, @required this.label,
this.withBorder = true, this.withBorder = true,
this.icon,
this.withIcon = true,
this.height, this.height,
this.backgroundColor, this.backgroundColor,
this.hint, this.hint,
@ -33,9 +36,9 @@ class ATimePicker extends StatelessWidget {
height: height, height: height,
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor ?? color: backgroundColor ??
(context.isDark && !enable (context.isDark && (enable == false)
? AppColor.neutral50 ? AppColor.neutral50
: !enable : (enable == false)
? AppColor.neutral40 ? AppColor.neutral40
: AppColor.background(context)), : AppColor.background(context)),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
@ -45,32 +48,42 @@ class ATimePicker extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Row( child: Row(
children: [ children: [
// enable
// ?
Column( Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
label.tinyFont(context), label.tinyFont(context),
(time == null (time == null ? hint ?? context.translation.pickTime : (time.format(context) ?? context.translation.pickADate))
? hint ?? context.translation.pickTime
: (time!.format(context) ?? // Use null assertion operator
context.translation.pickADate))
.bodyText(context) .bodyText(context)
.custom(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), .custom(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
], ],
).expanded, ).expanded,
//: label.bodyText(context).paddingOnly(top: 8, bottom: 8),
enable ? 16.width : const Spacer(), enable ? 16.width : const Spacer(),
"calender".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null), withIcon
? icon != null
? icon.toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null)
: "calender".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null)
: const SizedBox(),
], ],
), ),
).onPress(enable ).onPress(enable
? () async { ? () async {
final TimeOfDay? pickedTime = await showTimePicker( // Define the initial time
// Nullable TimeOfDay TimeOfDay initialTime = TimeOfDay.now();
// Show the time picker with the initial time set
TimeOfDay pickedTime = await showTimePicker(
context: context, context: context,
initialTime: TimeOfDay.now(), initialTime: initialTime,
); );
if (pickedTime != null && onTimePicker != null) {
onTimePicker!(pickedTime); // Use null-aware operator // Handle the selected time (if user didn't cancel)
if (pickedTime != null) {
if (onTimePicker != null) onTimePicker(pickedTime);
print("Selected time: ${pickedTime.format(context)}");
} }
} }
: null); : null);

@ -11,13 +11,15 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
import '../loaders/image_loader.dart'; import '../loaders/image_loader.dart';
class ESignature extends StatefulWidget { class ESignature extends StatefulWidget {
final String? oldSignature; final String oldSignature;
final Uint8List? newSignature; final Uint8List newSignature;
final Function(Uint8List?)? onSaved; Color backgroundColor;
final Function(Uint8List)? onChange; bool showShadow=true;
final Function(Uint8List) onSaved;
final Function(Uint8List) onChange;
final String title; final String title;
const ESignature({Key? key, required this.title, required this.oldSignature, this.onSaved, this.onChange, required this.newSignature}) : super(key: key); ESignature({Key key, this.title, this.oldSignature, this.onSaved, this.onChange, this.newSignature,this.backgroundColor,this.showShadow=true}) : super(key: key);
@override @override
State<ESignature> createState() => _ESignatureState(); State<ESignature> createState() => _ESignatureState();
@ -25,9 +27,9 @@ class ESignature extends StatefulWidget {
class _ESignatureState extends State<ESignature> { class _ESignatureState extends State<ESignature> {
// Initialise a controller. It will contains signature points, stroke width and pen color. // Initialise a controller. It will contains signature points, stroke width and pen color.
SignatureController? _controller; SignatureController _controller;
Uint8List? signature; Uint8List signature;
bool _editable = false; bool _editable = false;
@ -42,7 +44,7 @@ class _ESignatureState extends State<ESignature> {
@override @override
void dispose() { void dispose() {
_controller?.dispose(); _controller.dispose();
super.dispose(); super.dispose();
} }
@ -55,7 +57,7 @@ class _ESignatureState extends State<ESignature> {
); );
print(widget.oldSignature); print(widget.oldSignature);
return FormField<String>(onSaved: (_) async { return FormField<String>(onSaved: (_) async {
if (widget.onSaved != null) widget.onSaved!(signature); widget.onSaved(signature);
}, builder: (FormFieldState<String> state) { }, builder: (FormFieldState<String> state) {
return Column( return Column(
children: [ children: [
@ -63,9 +65,9 @@ class _ESignatureState extends State<ESignature> {
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
decoration: BoxDecoration( decoration: BoxDecoration(
color: context.isDark ? AppColor.background(context) : Colors.white, color:widget.backgroundColor ?? (context.isDark ? AppColor.background(context) : Colors.white),
borderRadius: _editable ? const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)) : BorderRadius.circular(10), borderRadius: _editable ? const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)) : BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], boxShadow:widget.showShadow? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)]:[],
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
@ -87,9 +89,9 @@ class _ESignatureState extends State<ESignature> {
)) ))
.onPress(() async { .onPress(() async {
if (_editable) { if (_editable) {
signature = await _controller!.toPngBytes(); signature = await _controller.toPngBytes();
if (widget.onChange != null) { if (widget.onChange != null) {
widget.onChange!(signature!); widget.onChange(signature);
} }
} }
_editable = !_editable; _editable = !_editable;
@ -102,12 +104,12 @@ class _ESignatureState extends State<ESignature> {
height: 135.toScreenHeight, height: 135.toScreenHeight,
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.only(bottom: 8),
child: signature != null ? Image.memory(signature!) : ImageLoader(boxFit: BoxFit.contain, url: URLs.getFileUrl(widget.oldSignature)!), child: signature != null ? Image.memory(signature) : ImageLoader(boxFit: BoxFit.contain, url: URLs.getFileUrl(widget.oldSignature)),
) )
: AbsorbPointer( : AbsorbPointer(
absorbing: !_editable, absorbing: !_editable,
child: Signature( child: Signature(
controller: _controller!, controller: _controller,
height: 135.toScreenHeight, height: 135.toScreenHeight,
width: MediaQuery.of(context).size.width - 64.toScreenWidth, width: MediaQuery.of(context).size.width - 64.toScreenWidth,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
@ -125,15 +127,15 @@ class _ESignatureState extends State<ESignature> {
child: Row( child: Row(
children: [ children: [
"clear".toSvgAsset(width: 14).paddingOnly(start: 16).onPress(() { "clear".toSvgAsset(width: 14).paddingOnly(start: 16).onPress(() {
_controller!.clear(); _controller.clear();
}), }),
35.width, 35.width,
"back".toSvgAsset(width: 17).onPress(() { "back".toSvgAsset(width: 17).onPress(() {
_controller!.undo(); _controller.undo();
}), }),
27.width, 27.width,
"redo".toSvgAsset(width: 17).onPress(() { "redo".toSvgAsset(width: 17).onPress(() {
_controller!.redo(); _controller.redo();
}), }),
// IconButton( // IconButton(
// onPressed: () { // onPressed: () {

@ -18,10 +18,13 @@ class MultiFilesPicker extends StatefulWidget {
final bool error; final bool error;
final List<File> files; final List<File> files;
final bool enabled, onlyImages; final bool enabled, onlyImages;
final Function(List<File>)? onChange; double buttonHeight;
Widget buttonIcon;
Color buttonColor;
final Function(List<File>) onChange;
final bool showAsGrid; final bool showAsGrid;
const MultiFilesPicker({Key? key, this.files = const <File>[], required this.label, this.error = false, this.enabled = true, this.onlyImages = false, this.onChange, this.showAsGrid = false}) MultiFilesPicker({Key key, this.files, this.label, this.error = false, this.buttonHeight, this.buttonIcon, this.enabled = true, this.onlyImages = false, this.onChange, this.showAsGrid = false,this.buttonColor})
: super(key: key); : super(key: key);
@override @override
@ -36,13 +39,16 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
children: [ children: [
AppDashedButton( AppDashedButton(
title: widget.label, title: widget.label,
height: widget.buttonHeight,
buttonColor: widget.buttonColor,
icon: widget.buttonIcon,
onPressed: (widget.enabled == false) onPressed: (widget.enabled == false)
? () {} ? () {}
: widget.showAsGrid : widget.showAsGrid
? showFileSourceSheet ? showFileSourceSheet
: onFilePicker), : onFilePicker),
16.height, 16.height,
if (widget.files.isNotEmpty ?? false) if (widget.files?.isNotEmpty ?? false)
Wrap( Wrap(
spacing: 8.toScreenWidth, spacing: 8.toScreenWidth,
children: List.generate( children: List.generate(
@ -58,7 +64,7 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
} }
widget.files.remove(image); widget.files.remove(image);
if (widget.onChange != null) { if (widget.onChange != null) {
widget.onChange!(widget.files); widget.onChange(widget.files);
} }
setState(() {}); setState(() {});
}, },
@ -71,14 +77,14 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
} }
fromFilePicker() async { fromFilePicker() async {
FilePickerResult? result = await FilePicker.platform.pickFiles( FilePickerResult result = await FilePicker.platform.pickFiles(
type: FileType.custom, type: FileType.custom,
allowMultiple: true, allowMultiple: true,
allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'],
); );
if (result != null) { if (result != null) {
for (var path in result.paths) { for (var path in result.paths) {
widget.files.add(File(path!)); widget.files.add(File(path));
} }
setState(() {}); setState(() {});
} }
@ -90,7 +96,7 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
return; return;
} }
ImageSource? source = (await showModalBottomSheet( ImageSource source = (await showModalBottomSheet(
context: context, context: context,
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical( borderRadius: BorderRadius.vertical(
@ -105,10 +111,10 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
"Attach File".heading4(context), "Attach File".heading4(context),
12.height, 12.height,
GridView( GridView(
padding: const EdgeInsets.all(0), padding: EdgeInsets.all(0),
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
children: <Widget>[ children: <Widget>[
gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)),
gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)), gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)),
@ -121,7 +127,7 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
12.height, 12.height,
], ],
).paddingAll(21), ).paddingAll(21),
)) as ImageSource?; )) as ImageSource;
if (source == null) return; if (source == null) return;
@ -129,30 +135,32 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
if (pickedFile != null) { if (pickedFile != null) {
File fileImage = File(pickedFile.path); File fileImage = File(pickedFile.path);
if (fileImage != null) {
widget.files.add(fileImage); widget.files.add(fileImage);
if (widget.onChange != null) { if (widget.onChange != null) {
widget.onChange!(widget.files); widget.onChange(widget.files);
} }
setState(() {}); setState(() {});
} }
} }
}
Widget gridItem(IconData iconData, String title) { Widget gridItem(IconData iconData, String title) {
return Container( return Container(
padding: const EdgeInsets.all(12), padding: EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xffF1F1F1), width: 1), border: Border.all(color: Color(0xffF1F1F1), width: 1),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Icon(iconData, color: const Color(0xff7D859A), size: 36), Icon(iconData, color: Color(0xff7D859A), size: 36),
Text( Text(
title, title,
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
), ),
], ],
), ),
@ -164,7 +172,7 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
return; return;
} }
ImageSource? source = await showDialog( ImageSource source = await showDialog(
context: context, context: context,
builder: (dialogContext) => CupertinoAlertDialog( builder: (dialogContext) => CupertinoAlertDialog(
actions: <Widget>[ actions: <Widget>[
@ -196,12 +204,14 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
if (pickedFile != null) { if (pickedFile != null) {
File fileImage = File(pickedFile.path); File fileImage = File(pickedFile.path);
if (fileImage != null) {
widget.files.add(fileImage); widget.files.add(fileImage);
if (widget.onChange != null) { if (widget.onChange != null) {
widget.onChange!(widget.files); widget.onChange(widget.files);
} }
setState(() {}); setState(() {});
} }
}
setState(() {}); setState(() {});
} }

@ -35,6 +35,7 @@ class MultiFilesPickerItem extends StatelessWidget {
Container( Container(
margin: EdgeInsetsDirectional.only(top: 4.toScreenHeight, end: 6.toScreenWidth), margin: EdgeInsetsDirectional.only(top: 4.toScreenHeight, end: 6.toScreenWidth),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.red,
border: Border.all(width: 1, color: context.isDark ? AppColor.neutral30 : AppColor.neutral30), border: Border.all(width: 1, color: context.isDark ? AppColor.neutral30 : AppColor.neutral30),
image: DecorationImage( image: DecorationImage(
image: getImage(isImage, isPdf, isExcel, file), image: getImage(isImage, isPdf, isExcel, file),

@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.2.2+9 version: 1.2.2+9
environment: environment:
sdk: ">=3.5.0 <4.0.0" sdk: ">=2.7.0 <3.0.0"
localization_dir: assets\translations localization_dir: assets\translations
@ -38,57 +38,54 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.5 cupertino_icons: ^1.0.5
font_awesome_flutter: ^10.2.1 font_awesome_flutter: ^10.2.1
http: ^1.2.2 http: ^0.13.5
provider: ^6.0.3 provider: ^6.0.3
shared_preferences: ^2.0.15 shared_preferences: ^2.0.15
fluttertoast: ^8.0.9 fluttertoast: ^8.0.9
image_picker: ^1.1.2 image_picker: ^0.8.6
url_launcher: ^6.1.6 url_launcher: ^6.1.6
flutter_launcher_icons: ^0.13.1 flutter_launcher_icons: ^0.10.0
package_info: ^2.0.2 package_info: ^2.0.2
share: ^2.0.4 share: ^2.0.4
flutter_local_notifications: ^17.2.2 flutter_local_notifications: ^12.0.1+1
cached_network_image: ^3.2.2 cached_network_image: ^3.2.2
carousel_slider: ^5.0.0 carousel_slider: ^4.1.1
intl: ^0.19.0 intl: ^0.17.0
flutter_typeahead: ^5.2.0 flutter_typeahead: ^4.1.1
speech_to_text: ^7.0.0 speech_to_text: ^6.1.1
firebase_core: ^3.4.1 firebase_core: ^2.4.0
firebase_messaging: ^15.1.1 firebase_messaging: ^14.2.0
qr_code_scanner: ^1.0.1 qr_code_scanner: ^1.0.1
flutter_sound: ^9.2.13 flutter_sound: ^9.2.13
permission_handler: ^11.3.1 permission_handler: ^10.2.0
rive: ^0.13.13 rive: ^0.9.1
another_flushbar: another_flushbar:
pinput: pinput:
audioplayers: ^6.1.0 audioplayers: ^1.1.1
flare_flutter: ^3.0.2 flare_flutter: ^3.0.2
signature: ^5.3.0 signature: ^5.3.0
flutter_svg: ^2.0.10+1 flutter_svg: ^1.1.6
file_picker: ^8.1.2 file_picker: ^5.2.5
record_mp3_plus: any record_mp3: ^2.1.0
path_provider: ^2.1.0 path_provider: ^2.1.0
open_file: ^3.3.2 open_file: ^3.3.2
localization: ^2.1.0 localization: ^2.1.0
dotted_border: ^2.1.0 dotted_border: ^2.1.0
lottie: ^3.1.2 lottie: ^2.3.0
shimmer: ^3.0.0 shimmer: ^2.0.0
flutter_advanced_switch: ^3.0.1 flutter_advanced_switch: ^3.0.1
table_calendar: ^3.0.8 table_calendar: ^3.0.8
image_cropper: ^8.0.2 image_cropper: ^3.0.3
touchable: ^0.2.1
badges: ^3.1.1 badges: ^3.1.1
# buttons_tabbar: ^1.1.2 flutter_month_picker: ^0.0.2
flutter_custom_month_picker: ^0.1.3 syncfusion_flutter_charts: ^21.2.3
syncfusion_flutter_charts: ^26.2.14 local_auth: ^2.1.6
local_auth: ^2.3.0
local_auth_darwin: any
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
dependency_overrides:
win32: ^5.5.4
# The "flutter_lints" package below contains a set of recommended lints to # The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is # encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your

Loading…
Cancel
Save