Merge branch 'refs/heads/master' into dev_sikander

# Conflicts:
#	assets/images/svg/bell.svg
#	lib/widgets/common_bottom_sheet.dart
pull/19/head
Sikander Saleem 2 months ago
commit 0ce43fde5f

@ -247,7 +247,7 @@
<!-- </receiver> &lt;!&ndash; Huawei Push Notifications &ndash;&gt;-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCyDbWUM9d_sBUGIE8PcuShzPaqO08NSC8" />
android:value="AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng" />
<!--
Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

@ -0,0 +1,3 @@
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.5 0.0839844C3.82217 0.0839844 4.08333 0.345152 4.08333 0.667318V0.720827C4.72328 0.667291 5.49135 0.667304 6.39988 0.667318L7.60012 0.667318C8.50865 0.667304 9.27672 0.667291 9.91667 0.720827V0.667318C9.91667 0.345152 10.1778 0.0839844 10.5 0.0839844C10.8222 0.0839844 11.0833 0.345152 11.0833 0.667318V0.929147C11.5274 1.06999 11.9132 1.29145 12.2395 1.64417C12.7228 2.16666 12.9309 2.8214 13.0292 3.61237C13.125 4.38254 13.125 5.36553 13.125 6.6021V6.98254C13.125 8.21911 13.125 9.2021 13.0292 9.97227C12.9309 10.7632 12.7228 11.418 12.2395 11.9405C11.7502 12.4694 11.1269 12.7032 10.3744 12.8126C9.65334 12.9174 8.73662 12.9173 7.60012 12.9173H6.39988C5.26338 12.9173 4.34666 12.9174 3.62561 12.8126C2.87312 12.7032 2.2498 12.4694 1.76051 11.9405C1.2772 11.418 1.06913 10.7632 0.970761 9.97227C0.874981 9.20211 0.874989 8.21911 0.875 6.98256L0.875 6.60208C0.874989 5.36553 0.874981 4.38253 0.970761 3.61237C1.06913 2.8214 1.2772 2.16666 1.76051 1.64417C2.08678 1.29145 2.47265 1.06999 2.91667 0.929148V0.667318C2.91667 0.345152 3.17783 0.0839844 3.5 0.0839844ZM2.13725 4.83475C2.22244 4.75065 2.3562 4.75065 2.62373 4.75065L11.3763 4.75065C11.6438 4.75065 11.7776 4.75065 11.8628 4.83475C11.9479 4.91884 11.9497 5.05091 11.9531 5.31503C11.9582 5.70771 11.9583 6.14726 11.9583 6.64255V6.94209C11.9583 8.22826 11.9573 9.13855 11.8715 9.82829C11.7873 10.5056 11.6301 10.8811 11.383 11.1483C11.1419 11.4089 10.8123 11.57 10.2066 11.658C9.57916 11.7492 8.74752 11.7507 7.55417 11.7507H6.44583C5.25248 11.7507 4.42084 11.7492 3.79342 11.658C3.18774 11.57 2.85808 11.4089 2.61696 11.1483C2.36987 10.8811 2.21274 10.5056 2.12851 9.82829C2.04273 9.13855 2.04167 8.22826 2.04167 6.94209V6.64255C2.04167 6.14726 2.04183 5.70771 2.04692 5.31503C2.05034 5.05091 2.05206 4.91884 2.13725 4.83475Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -0,0 +1,4 @@
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.5 0.75C3.91421 0.75 4.25 1.08579 4.25 1.5V1.5688C5.07278 1.49997 6.06031 1.49998 7.22842 1.5L8.77158 1.5C9.93969 1.49998 10.9272 1.49997 11.75 1.5688V1.5C11.75 1.08579 12.0858 0.75 12.5 0.75C12.9142 0.75 13.25 1.08579 13.25 1.5V1.83664C13.8209 2.01772 14.317 2.30245 14.7365 2.75595C15.3213 3.3882 15.5927 4.1711 15.7281 5.10899C15.861 6.03001 15.8733 7.1875 15.8748 8.62422V9.75C15.8748 10.1642 15.539 10.5 15.1248 10.5C14.7106 10.5 14.3748 10.1642 14.3748 9.75V8.62579C14.3742 8.06266 14.3716 7.56155 14.3621 7.1128C14.3578 6.91051 14.1918 6.75 13.9895 6.75L2.01043 6.75C1.80809 6.75 1.64212 6.91043 1.63785 7.11272C1.62532 7.70596 1.625 8.3885 1.625 9.18243L1.625 9.56757C1.625 11.2212 1.62637 12.3916 1.73665 13.2784C1.84496 14.1492 2.04697 14.632 2.36467 14.9755C2.67467 15.3106 3.09852 15.5177 3.87725 15.6309C4.68393 15.7481 5.75319 15.75 7.2875 15.75C7.70171 15.75 8.0375 16.0858 8.0375 16.5C8.0375 16.9142 7.70171 17.25 7.2875 17.25H7.22842C5.76721 17.25 4.58856 17.25 3.6615 17.1153C2.69401 16.9747 1.8926 16.6741 1.26352 15.9941C0.64212 15.3223 0.374593 14.4805 0.248121 13.4635C0.124976 12.4733 0.124987 11.2094 0.125 9.6196L0.125 9.1304C0.124987 7.54055 0.124976 6.2767 0.248121 5.28649C0.374593 4.26954 0.64212 3.42773 1.26352 2.75595C1.683 2.30245 2.17912 2.01772 2.75 1.83664L2.75 1.5C2.75 1.08579 3.08579 0.75 3.5 0.75Z" fill="#D48D05"/>
<path d="M14.7502 13.8794C15.1644 13.8794 15.5002 13.5436 15.5002 13.1294C15.5002 12.7152 15.1644 12.3794 14.7502 12.3794H11.3751L11.3752 11.9337C11.3752 11.802 11.3754 11.6402 11.3588 11.5079L11.3585 11.5054C11.3467 11.4106 11.2928 10.9785 10.8686 10.7728C10.4435 10.5665 10.0684 10.793 9.98722 10.842L9.63585 11.0963C9.35398 11.3173 8.96814 11.6216 8.67488 11.9069C8.52855 12.0493 8.37762 12.2122 8.25849 12.3854C8.15259 12.5394 8.00014 12.802 8.00014 13.125C8.00014 13.448 8.15259 13.7106 8.25849 13.8646C8.37762 14.0378 8.52855 14.2007 8.67488 14.3431C8.96814 14.6284 9.35398 14.9327 9.63585 15.1537L9.98722 15.408C10.0684 15.457 10.4435 15.6835 10.8686 15.4772C11.2928 15.2715 11.3467 14.8394 11.3585 14.7446L11.3588 14.7421C11.3754 14.6098 11.3752 14.448 11.3752 14.3163L11.3751 13.8794H14.7502Z" fill="#D48D05"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

@ -0,0 +1,4 @@
<svg width="17" height="14" viewBox="0 0 17 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.66067 0.4375C11.0399 0.437493 12.1231 0.437487 12.9771 0.533949C13.8487 0.632408 14.5555 0.837715 15.143 1.30171C15.3189 1.44062 15.482 1.59404 15.6303 1.76035C16.1299 2.32076 16.353 3.00002 16.4593 3.83339C16.4715 3.92927 16.4776 3.97722 16.4666 4.01934C16.4491 4.08665 16.3974 4.14531 16.3329 4.17126C16.2925 4.1875 16.2419 4.1875 16.1408 4.1875L0.859177 4.1875C0.758099 4.1875 0.707553 4.1875 0.667164 4.17126C0.602615 4.14532 0.550957 4.08665 0.533383 4.01934C0.522386 3.97722 0.5285 3.92927 0.540728 3.83338C0.647 3.00002 0.870114 2.32076 1.36975 1.76035C1.51802 1.59404 1.68109 1.44062 1.85698 1.30171C2.44451 0.837715 3.15132 0.632408 4.02294 0.533949C4.87689 0.437487 5.9601 0.437493 7.33936 0.4375L9.66067 0.4375Z" fill="#0B85F7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.5625 7.03956C16.5625 8.33257 16.5625 9.35705 16.4593 10.1666C16.353 11 16.1299 11.6792 15.6303 12.2397C15.482 12.406 15.3189 12.5594 15.143 12.6983C14.5555 13.1623 13.8487 13.3676 12.9771 13.4661C12.1231 13.5625 11.0399 13.5625 9.66066 13.5625H7.33934C5.96009 13.5625 4.87688 13.5625 4.02294 13.4661C3.15131 13.3676 2.4445 13.1623 1.85697 12.6983C1.68108 12.5594 1.51801 12.406 1.36974 12.2397C0.870106 11.6792 0.646992 11 0.540719 10.1666C0.437482 9.35705 0.43749 8.33255 0.4375 7.03955V6.96044C0.437497 6.52863 0.437494 6.12674 0.441337 5.75281C0.443461 5.54605 0.444524 5.44267 0.510282 5.37758C0.57604 5.3125 0.680207 5.3125 0.888543 5.3125L16.1115 5.3125C16.3198 5.3125 16.424 5.3125 16.4897 5.37758C16.5555 5.44267 16.5565 5.54605 16.5587 5.75281C16.5625 6.12662 16.5625 6.52836 16.5625 6.96003V7.03956ZM7.18749 10C7.18749 9.68934 7.43933 9.4375 7.74999 9.4375H8.87499C9.18565 9.4375 9.43749 9.68934 9.43749 10C9.43749 10.3107 9.18565 10.5625 8.87499 10.5625H7.74999C7.43933 10.5625 7.18749 10.3107 7.18749 10ZM11.125 9.4375C10.8143 9.4375 10.5625 9.68934 10.5625 10C10.5625 10.3107 10.8143 10.5625 11.125 10.5625L13.75 10.5625C14.0607 10.5625 14.3125 10.3107 14.3125 10C14.3125 9.68934 14.0607 9.4375 13.75 9.4375L11.125 9.4375Z" fill="#0B85F7"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -0,0 +1,3 @@
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.00008 0.228516C3.5368 0.228516 0.729248 3.03606 0.729248 6.49935C0.729248 9.96263 3.5368 12.7702 7.00008 12.7702C10.4634 12.7702 13.2709 9.96263 13.2709 6.49935C13.2709 3.03606 10.4634 0.228516 7.00008 0.228516ZM9.74589 4.57849C9.9737 4.35069 9.9737 3.98134 9.74589 3.75354C9.51809 3.52573 9.14874 3.52573 8.92094 3.75354L7.00012 5.67435L5.95421 4.62852C5.7264 4.40072 5.35705 4.40074 5.12925 4.62855C4.90146 4.85636 4.90147 5.22571 5.12928 5.45351L6.17516 6.49931L6.00427 6.6702C5.77646 6.89801 5.77646 7.26736 6.00427 7.49516C6.23207 7.72297 6.60142 7.72297 6.82923 7.49516L7.00015 7.32424L7.17088 7.49496C7.39869 7.72276 7.76804 7.72275 7.99584 7.49493C8.22363 7.26712 8.22362 6.89777 7.99581 6.66998L7.8251 6.49928L9.74589 4.57849Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 913 B

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.9375 8.67504C0.9375 4.37879 4.57142 0.9375 9 0.9375C13.4286 0.9375 17.0625 4.37879 17.0625 8.67504C17.0625 12.9713 13.4286 16.4126 9 16.4126C8.4781 16.4132 7.95776 16.3649 7.44524 16.2687C7.26734 16.2353 7.15432 16.2142 7.07022 16.2027C7.0075 16.1931 6.94448 16.2164 6.92081 16.2293C6.83492 16.2701 6.72051 16.3308 6.54535 16.4239C5.47156 16.995 4.21878 17.1975 3.01047 16.9727C2.81535 16.9365 2.6538 16.8 2.58535 16.6137C2.5169 16.4275 2.55168 16.2189 2.67688 16.0649C3.02773 15.6333 3.26897 15.1135 3.37566 14.5539C3.40453 14.4 3.3392 14.191 3.13838 13.987C1.77729 12.6049 0.9375 10.7358 0.9375 8.67504ZM8.25 6.94368C8.25 6.71747 8.49208 6.375 9 6.375C9.50792 6.375 9.75 6.71747 9.75 6.94368C9.75 7.03521 9.72061 7.12658 9.65713 7.21331C9.57168 7.33005 9.46169 7.45479 9.32273 7.60662L9.25602 7.67927C9.13971 7.80573 9.00656 7.9505 8.88529 8.09703C8.60705 8.4332 8.25 8.93789 8.25 9.58104V9.91071C8.25 10.3249 8.58579 10.6607 9 10.6607C9.41421 10.6607 9.75 10.3249 9.75 9.91071V9.58104C9.75 9.49591 9.79997 9.34445 10.0408 9.05343C10.1348 8.93985 10.2363 8.82947 10.352 8.70347L10.4292 8.61937C10.569 8.46668 10.7288 8.28875 10.8675 8.09927C11.1049 7.77502 11.25 7.37719 11.25 6.94368C11.25 5.71331 10.1489 4.875 9 4.875C7.85106 4.875 6.75 5.71331 6.75 6.94368C6.75 7.35789 7.08579 7.69368 7.5 7.69368C7.91421 7.69368 8.25 7.35789 8.25 6.94368ZM9 11.625C8.58579 11.625 8.25 11.9608 8.25 12.375C8.25 12.7892 8.58579 13.125 9 13.125H9.00898C9.42319 13.125 9.75898 12.7892 9.75898 12.375C9.75898 11.9608 9.42319 11.625 9.00898 11.625H9Z" fill="#F43333"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -1,4 +1,4 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.5 1.25C8.04419 1.25 4.42789 4.84151 4.42786 9.27697C4.42776 10.3087 4.35838 11.0873 3.88271 11.7872C3.81656 11.8831 3.72879 12.0032 3.63289 12.1345C3.46634 12.3625 3.27527 12.624 3.13033 12.8505C2.87452 13.2503 2.62459 13.7324 2.53868 14.2942C2.25836 16.127 3.55056 17.3136 4.83746 17.8454C9.37016 19.7182 15.6298 19.7182 20.1625 17.8454C21.4494 17.3136 22.7416 16.127 22.4613 14.2942C22.3754 13.7324 22.1255 13.2503 21.8697 12.8505C21.7247 12.624 21.5337 12.3625 21.3671 12.1345C21.2712 12.0033 21.1835 11.8832 21.1173 11.7873C20.6416 11.0874 20.5722 10.3088 20.5721 9.27703C20.5721 4.84155 16.9558 1.25 12.5 1.25Z" fill="white"/>
<path d="M12.4985 22.7477C13.5187 22.7477 14.4742 22.4563 15.2776 21.9511C15.9906 21.5027 16.3472 21.2785 16.2224 20.9057C16.0976 20.533 15.6057 20.5747 14.6217 20.6582C13.2146 20.7776 11.7824 20.7776 10.3752 20.6582C9.39126 20.5747 8.8993 20.533 8.77454 20.9057C8.64977 21.2784 9.0063 21.5027 9.71934 21.9511C10.5227 22.4563 11.4782 22.7477 12.4985 22.7477Z" fill="white"/>
<svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 0.25C5.54419 0.25 1.92789 3.84151 1.92786 8.27697C1.92776 9.30865 1.85838 10.0873 1.38271 10.7872C1.31656 10.8831 1.22879 11.0032 1.13289 11.1345C0.966345 11.3625 0.775273 11.624 0.630335 11.8505C0.374521 12.2503 0.124594 12.7324 0.0386759 13.2942C-0.241638 15.127 1.05056 16.3136 2.33746 16.8454C6.87016 18.7182 13.1298 18.7182 17.6625 16.8454C18.9494 16.3136 20.2416 15.127 19.9613 13.2942C19.8754 12.7324 19.6255 12.2503 19.3697 11.8505C19.2247 11.624 19.0337 11.3625 18.8671 11.1345C18.7712 11.0033 18.6835 10.8832 18.6173 10.7873C18.1416 10.0874 18.0722 9.30878 18.0721 8.27703C18.0721 3.84155 14.4558 0.25 10 0.25Z" fill="#2E3039"/>
<path d="M9.99846 21.7477C11.0187 21.7477 11.9742 21.4563 12.7776 20.9511C13.4906 20.5027 13.8472 20.2785 13.7224 19.9057C13.5976 19.533 13.1057 19.5747 12.1217 19.6582C10.7146 19.7776 9.28236 19.7776 7.87518 19.6582C6.89126 19.5747 6.3993 19.533 6.27454 19.9057C6.14977 20.2784 6.5063 20.5027 7.21934 20.9511C8.02272 21.4563 8.9782 21.7477 9.99846 21.7477Z" fill="#2E3039"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="32" height="32" rx="11" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.46967 9.46967C9.76256 9.17678 10.2374 9.17678 10.5303 9.46967L16 14.9393L21.4697 9.46967C21.7626 9.17678 22.2374 9.17678 22.5303 9.46967C22.8232 9.76256 22.8232 10.2374 22.5303 10.5303L17.0607 16L22.5303 21.4697C22.8232 21.7626 22.8232 22.2374 22.5303 22.5303C22.2374 22.8232 21.7626 22.8232 21.4697 22.5303L16 17.0607L10.5303 22.5303C10.2374 22.8232 9.76256 22.8232 9.46967 22.5303C9.17678 22.2374 9.17678 21.7626 9.46967 21.4697L14.9393 16L9.46967 10.5303C9.17678 10.2374 9.17678 9.76256 9.46967 9.46967Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 732 B

@ -0,0 +1,4 @@
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.25 1.5C4.25 1.08579 3.91421 0.75 3.5 0.75C3.08579 0.75 2.75 1.08579 2.75 1.5L2.75 1.83664C2.17912 2.01772 1.683 2.30245 1.26352 2.75595C0.64212 3.42773 0.374593 4.26954 0.248121 5.28649C0.124976 6.2767 0.124987 7.54054 0.125 9.13039L0.125 9.61959C0.124987 11.2094 0.124976 12.4733 0.248121 13.4635C0.374593 14.4805 0.64212 15.3223 1.26352 15.9941C1.86304 16.6422 2.61224 16.9476 3.52132 17.0965C4.39992 17.2403 5.507 17.2491 6.87495 17.2499L7.62495 17.25C8.03916 17.25 8.37497 16.9142 8.375 16.5C8.37503 16.0858 8.03927 15.75 7.62505 15.75L6.87547 15.7499C5.47193 15.749 4.49783 15.7364 3.7637 15.6162C3.06006 15.501 2.66455 15.2997 2.36467 14.9755C2.04697 14.632 1.84496 14.1492 1.73665 13.2784C1.62637 12.3916 1.625 11.2212 1.625 9.56757L1.625 9.18243C1.625 8.54564 1.6252 7.98051 1.63175 7.47564C1.63616 7.13604 1.63836 6.96625 1.74789 6.85813C1.85742 6.75 2.02941 6.75 2.37337 6.75L13.6266 6.75C13.9705 6.75 14.1425 6.75 14.252 6.8581C14.3616 6.9662 14.3638 7.136 14.3683 7.4756C14.3715 7.71952 14.3732 7.97803 14.3741 8.25239C14.3754 8.6666 14.7122 9.00132 15.1264 9C15.5407 8.99868 15.8754 8.66183 15.8741 8.24762C15.8699 6.92805 15.8479 5.85257 15.7094 4.98584C15.5681 4.10202 15.2953 3.36008 14.7365 2.75595C14.317 2.30245 13.8209 2.01772 13.25 1.83664V1.5C13.25 1.08579 12.9142 0.75 12.5 0.75C12.0858 0.75 11.75 1.08579 11.75 1.5V1.5688C10.9272 1.49997 9.93969 1.49998 8.77159 1.5L7.22842 1.5C6.06032 1.49998 5.07278 1.49997 4.25 1.5688V1.5Z" fill="#18C273"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.3754 11.8119L14.3754 11.0156C14.3754 9.98687 13.5164 9.1875 12.5004 9.1875C11.4843 9.1875 10.6254 9.98687 10.6254 11.0156L10.6254 11.8119C10.569 11.829 10.513 11.8495 10.4574 11.8742C9.99227 12.0806 9.63454 12.4707 9.4506 12.9465C9.37118 13.152 9.34065 13.3629 9.32648 13.5854C9.31284 13.7995 9.31285 14.0604 9.31285 14.3729L9.31268 14.4979C9.31219 14.7306 9.31169 14.9637 9.32648 15.1958C9.34065 15.4183 9.37118 15.6293 9.4506 15.8347C9.63454 16.3105 9.99227 16.7007 10.4574 16.9071C10.8265 17.0709 11.2497 17.0671 11.6516 17.0635C11.7097 17.063 11.7675 17.0625 11.8245 17.0625H13.1762C13.2332 17.0625 13.291 17.063 13.3491 17.0635C13.751 17.0671 14.1742 17.0709 14.5433 16.9071C15.0084 16.7007 15.3662 16.3105 15.5501 15.8347C15.6295 15.6293 15.6601 15.4183 15.6742 15.1958C15.689 14.9637 15.6885 14.7306 15.688 14.4979L15.6879 14.3729C15.6879 14.0604 15.6879 13.7995 15.6742 13.5854C15.6601 13.3629 15.6295 13.152 15.5501 12.9465C15.3662 12.4707 15.0084 12.0806 14.5433 11.8742C14.4877 11.8495 14.4317 11.829 14.3754 11.8119ZM11.7504 11.0156C11.7504 10.6464 12.0667 10.3125 12.5004 10.3125C12.934 10.3125 13.2504 10.6464 13.2504 11.0156L13.2504 11.7188H11.7504L11.7504 11.0156Z" fill="#18C273"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -0,0 +1,3 @@
<svg width="15" height="14" viewBox="0 0 15 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.8115 0.745822C15.2258 2.14723 12.963 13.5442 10.6411 13.745C8.69325 13.9135 8.08629 10.0718 7.67603 8.8541C7.27114 7.65237 6.82058 7.21973 5.62874 6.82545C2.60098 5.82381 1.0871 5.32299 0.787367 4.52997C-0.00632346 2.43005 12.0052 -1.04403 13.8115 0.745822Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 394 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.4 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.5 MiB

@ -0,0 +1,6 @@
<svg width="343" height="51" viewBox="0 0 343 51" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.818115" width="343" height="50" rx="8" fill="black"/>
<rect y="0.818115" width="343" height="50" rx="8" stroke="black"/>
<path d="M105.44 32.8181V18.7263H110.684C113.448 18.7263 115.362 20.5818 115.362 23.3455V23.365C115.362 26.1189 113.448 28.0037 110.684 28.0037H107.628V32.8181H105.44ZM110.138 20.572H107.628V26.1677H110.138C112.042 26.1677 113.136 25.1423 113.136 23.3748V23.3552C113.136 21.5974 112.042 20.572 110.138 20.572ZM119.27 33.0037C117.219 33.0037 115.842 31.7439 115.842 29.8982V29.8787C115.842 28.0916 117.229 26.9978 119.66 26.8513L122.453 26.6853V25.9138C122.453 24.781 121.721 24.0974 120.412 24.0974C119.191 24.0974 118.439 24.6736 118.264 25.4939L118.244 25.5818H116.252L116.262 25.4744C116.408 23.7068 117.941 22.3494 120.471 22.3494C122.98 22.3494 124.572 23.6775 124.572 25.738V32.8181H122.453V31.197H122.414C121.818 32.3005 120.627 33.0037 119.27 33.0037ZM117.971 29.8494C117.971 30.7478 118.713 31.3142 119.846 31.3142C121.33 31.3142 122.453 30.3083 122.453 28.9705V28.1697L119.943 28.3259C118.674 28.4041 117.971 28.9607 117.971 29.8298V29.8494ZM127.864 36.2458C127.454 36.2458 127.015 36.197 126.761 36.1482V34.4978C126.927 34.5369 127.171 34.5759 127.454 34.5759C128.45 34.5759 128.997 34.3123 129.349 33.3162L129.525 32.8279L125.784 22.5447H128.07L130.657 30.9041H130.726L133.314 22.5447H135.54L131.712 33.2966C130.95 35.4255 129.876 36.2458 127.864 36.2458ZM142.955 32.8181L140.132 22.5447H142.242L144.117 30.6306H144.156L146.295 22.5447H148.326L150.474 30.6306H150.523L152.398 22.5447H154.488L151.675 32.8181H149.478L147.32 25.1228H147.271L145.132 32.8181H142.955ZM156.97 20.9626C156.286 20.9626 155.739 20.4158 155.739 19.7517C155.739 19.0779 156.286 18.531 156.97 18.531C157.663 18.531 158.2 19.0779 158.2 19.7517C158.2 20.4158 157.663 20.9626 156.97 20.9626ZM155.915 32.8181V22.5447H158.024V32.8181H155.915ZM163.855 33.0232C161.824 33.0232 160.848 32.1638 160.848 30.113V24.2244H159.373V22.5447H160.848V19.8689H163.006V22.5447H164.93V24.2244H163.006V29.9861C163.006 31.031 163.475 31.3435 164.363 31.3435C164.588 31.3435 164.773 31.324 164.93 31.3044V32.9353C164.686 32.9744 164.285 33.0232 163.855 33.0232ZM166.806 32.8181V18.7263H168.915V24.2341H168.964C169.511 23.0427 170.614 22.3494 172.148 22.3494C174.345 22.3494 175.79 23.99 175.79 26.4705V32.8181H173.681V26.8708C173.681 25.1716 172.821 24.156 171.337 24.156C169.882 24.156 168.915 25.2693 168.915 26.8708V32.8181H166.806Z" fill="white"/>
<path d="M193.748 20.6455C194.253 20.6455 196.061 20.6904 197.241 22.4087C197.139 22.4873 195.343 23.498 195.343 25.7666C195.343 28.3945 197.634 29.3267 197.701 29.3491C197.69 29.4053 197.33 30.6182 196.499 31.8647C195.747 32.9429 194.95 34.0322 193.748 34.0322C192.546 34.0322 192.232 33.3359 190.862 33.3359C189.503 33.3359 189.02 34.0547 187.93 34.0547C186.83 34.0547 186.055 33.0439 185.19 31.8198C184.168 30.3486 183.337 28.0913 183.337 25.9463C183.337 22.521 185.572 20.6904 187.773 20.6904C188.93 20.6904 189.907 21.4541 190.637 21.4541C191.333 21.4541 192.411 20.6455 193.748 20.6455ZM193.13 19.1968C192.535 19.9155 191.524 20.4546 190.727 20.4546C190.637 20.4546 190.547 20.4434 190.491 20.4321C190.48 20.3872 190.457 20.2412 190.457 20.1064C190.457 19.1968 190.929 18.2871 191.423 17.7144C192.063 16.9619 193.141 16.4116 194.017 16.3779C194.04 16.479 194.051 16.6025 194.051 16.7261C194.051 17.6357 193.669 18.5342 193.13 19.1968ZM202.115 17.647H208.652C211.886 17.647 214.098 19.8594 214.098 23.1274C214.098 26.3394 211.807 28.5405 208.528 28.5405H205.013V33.8525H202.115V17.647ZM205.013 20.0728V26.1372H207.877C209.943 26.1372 211.156 25.0591 211.156 23.1274C211.156 21.1396 209.977 20.0728 207.888 20.0728H205.013ZM219.535 31.8647C221.219 31.8647 222.477 30.7754 222.477 29.3491V28.3721L219.703 28.5518C218.142 28.6528 217.412 29.2144 217.412 30.2139C217.412 31.2471 218.3 31.8647 219.535 31.8647ZM218.715 34.0547C216.345 34.0547 214.65 32.6172 214.65 30.3711C214.65 28.1475 216.323 26.8672 219.31 26.6875L222.477 26.4966V25.4634C222.477 24.2617 221.669 23.5879 220.164 23.5879C218.884 23.5879 218.008 24.0371 217.749 24.8682H215.121C215.346 22.7007 217.379 21.3193 220.299 21.3193C223.454 21.3193 225.229 22.8579 225.229 25.4634V33.8525H222.545V32.168H222.354C221.669 33.3584 220.321 34.0547 218.715 34.0547ZM228.329 38.311C228.161 38.311 227.408 38.2998 227.229 38.2661V35.9863C227.386 36.02 227.801 36.0312 227.992 36.0312C229.172 36.0312 229.834 35.582 230.194 34.4478L230.34 33.9087L225.948 21.5664H229.003L231.878 31.1572H232.069L234.933 21.5664H237.875L233.439 34.2456C232.395 37.3003 231.081 38.311 228.329 38.311Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

@ -0,0 +1,7 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 870" width="1000" height="870">
<title>Layer copy</title>
<style>
.s0 { fill: #000000 }
</style>
<path id="Layer copy" class="s0" d="m88.3 1c0.4 0.6 2.6 3.3 4.7 5.9 15.3 18.2 26.8 47.8 33 85.1 4.1 24.5 4.3 32.2 4.3 125.6v87h-41.8c-38.2 0-42.6-0.2-50.1-1.7-11.8-2.5-24-9.2-32.2-17.8-6.5-6.9-6.3-7.3-5.9 13.6 0.5 17.3 0.7 19.2 3.2 28.6 4 14.9 9.5 26 17.8 35.9 11.3 13.6 22.8 21.2 39.2 26.3 3.5 1 10.9 1.4 37.1 1.6l32.7 0.5v43.3 43.4l-46.1-0.3-46.3-0.3-8-3.2c-9.5-3.8-13.8-6.6-23.1-14.9l-6.8-6.1 0.4 19.1c0.5 17.7 0.6 19.7 3.1 28.7 8.7 31.8 29.7 54.5 57.4 61.9 6.9 1.9 9.6 2 38.5 2.4l30.9 0.4v89.6c0 54.1-0.3 94-0.8 100.8-0.5 6.2-2.1 17.8-3.5 25.9-6.5 37.3-18.2 65.4-35 83.6l-3.4 3.7h169.1c101.1 0 176.7-0.4 187.8-0.9 19.5-1 63-5.3 72.8-7.4 3.1-0.6 8.9-1.5 12.7-2.1 8.1-1.2 21.5-4 40.8-8.9 27.2-6.8 52-15.3 76.3-26.1 7.6-3.4 29.4-14.5 35.2-18 3.1-1.8 6.8-4 8.2-4.7 3.9-2.1 10.4-6.3 19.9-13.1 4.7-3.4 9.4-6.7 10.4-7.4 4.2-2.8 18.7-14.9 25.3-21 25.1-23.1 46.1-48.8 62.4-76.3 2.3-4 5.3-9 6.6-11.1 3.3-5.6 16.9-33.6 18.2-37.8 0.6-1.9 1.4-3.9 1.8-4.3 2.6-3.4 17.6-50.6 19.4-60.9 0.6-3.3 0.9-3.8 3.4-4.3 1.6-0.3 24.9-0.3 51.8-0.1 53.8 0.4 53.8 0.4 65.7 5.9 6.7 3.1 8.7 4.5 16.1 11.2 9.7 8.7 8.8 10.1 8.2-11.7-0.4-12.8-0.9-20.7-1.8-23.9-3.4-12.3-4.2-14.9-7.2-21.1-9.8-21.4-26.2-36.7-47.2-44l-8.2-3-33.4-0.4-33.3-0.5 0.4-11.7c0.4-15.4 0.4-45.9-0.1-61.6l-0.4-12.6 44.6-0.2c38.2-0.2 45.3 0 49.5 1.1 12.6 3.5 21.1 8.3 31.5 17.8l5.8 5.4v-14.8c0-17.6-0.9-25.4-4.5-37-7.1-23.5-21.1-41-41.1-51.8-13-7-13.8-7.2-58.5-7.5-26.2-0.2-39.9-0.6-40.6-1.2-0.6-0.6-1.1-1.6-1.1-2.4 0-0.8-1.5-7.1-3.5-13.9-23.4-82.7-67.1-148.4-131-197.1-8.7-6.7-30-20.8-38.6-25.6-3.3-1.9-6.9-3.9-7.8-4.5-4.2-2.3-28.3-14.1-34.3-16.6-3.6-1.6-8.3-3.6-10.4-4.4-35.3-15.3-94.5-29.8-139.7-34.3-7.4-0.7-17.2-1.8-21.7-2.2-20.4-2.3-48.7-2.6-209.4-2.6-135.8 0-169.9 0.3-169.4 1zm330.7 43.3c33.8 2 54.6 4.6 78.9 10.5 74.2 17.6 126.4 54.8 164.3 117 3.5 5.8 18.3 36 20.5 42.1 10.5 28.3 15.6 45.1 20.1 67.3 1.1 5.4 2.6 12.6 3.3 16 0.7 3.3 1 6.4 0.7 6.7-0.5 0.4-100.9 0.6-223.3 0.5l-222.5-0.2-0.3-128.5c-0.1-70.6 0-129.3 0.3-130.4l0.4-1.9h71.1c39 0 78 0.4 86.5 0.9zm297.5 350.3c0.7 4.3 0.7 77.3 0 80.9l-0.6 2.7-227.5-0.2-227.4-0.3-0.2-42.4c-0.2-23.3 0-42.7 0.2-43.1 0.3-0.5 97.2-0.8 227.7-0.8h227.2zm-10.2 171.7c0.5 1.5-1.9 13.8-6.8 33.8-5.6 22.5-13.2 45.2-20.9 62-3.8 8.6-13.3 27.2-15.6 30.7-1.1 1.6-4.3 6.7-7.1 11.2-18 28.2-43.7 53.9-73 72.9-10.7 6.8-32.7 18.4-38.6 20.2-1.2 0.3-2.5 0.9-3 1.3-0.7 0.6-9.8 4-20.4 7.8-19.5 6.9-56.6 14.4-86.4 17.5-19.3 1.9-22.4 2-96.7 2h-76.9v-129.7-129.8l220.9-0.4c121.5-0.2 221.6-0.5 222.4-0.7 0.9-0.1 1.8 0.5 2.1 1.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -806,5 +806,10 @@
"loginBy": "تسجيل الدخول بواسطة",
"loginByOTP": "تسجيل الدخول بواسطة OTP",
"guest": "زائر",
"switchAccount": "تبديل الحساب"
"switchAccount": "تبديل الحساب",
"lastLoginBy":"آخر تسجيل دخول بواسطة",
"allSet": "جاهز! الآن يمكنك تسجيل الدخول باستخدام Face ID / Biometric أو البصمة",
"enableQuickLogin":"تمكين تسجيل الدخول السريع",
"enableMsg":"تمكين تسجيل الدخول السريع سيسمح بالتحقق من خلال Face ID / Biometric الخاص بجهازك الحالي",
"notNow": "ليس الآن"
}

@ -802,5 +802,10 @@
"loginBy": "Login By",
"loginByOTP": "Login By OTP",
"guest": "Guest",
"switchAccount": "Switch Account"
"switchAccount": "Switch Account",
"lastloginBy": "Last login by",
"allSet": "All Set! Now you can login with Face ID or Biometric",
"enableQuickLogin": "Enable Quick Login",
"enableMsg": "Enabling the quick login will verify through your existing device Face ID / Biometric",
"notNow": "Not Now"
}

@ -48,6 +48,7 @@
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
478CFA952E6E20A60064F3D7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7595037DD52211B91157B0F3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
@ -129,6 +130,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
478CFA952E6E20A60064F3D7 /* Runner.entitlements */,
478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
@ -450,8 +452,9 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = ZB3P5B74MA;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
@ -632,8 +635,9 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = ZB3P5B74MA;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
@ -657,8 +661,9 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = ZB3P5B74MA;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;

@ -102,11 +102,11 @@ class ApiClientImp implements ApiClient {
if (isRCService) {
url = RC_BASE_URL + endPoint;
} else {
url = BASE_URL + endPoint;
url = ApiConsts.baseUrl + endPoint;
}
}
try {
var user = _appState.getAuthenticatedUser;
var user = _appState.getAuthenticatedUser();
Map<String, String> headers = {'Content-Type': 'application/json', 'Accept': 'application/json'};
if (!isExternal) {
String? token = _appState.appAuthToken;
@ -136,11 +136,15 @@ class ApiClientImp implements ApiClient {
// TODO : These should be from the appState
if (user != null) {
body['TokenID'] = body['TokenID'] ?? token;
body['PatientID'] = body['PatientID'] ?? user.patientID;
body['PatientID'] = body['PatientID'] ?? user.patientId;
body['PatientOutSA'] = body.containsKey('PatientOutSA') ? body['PatientOutSA'] ?? user.outSA : user.outSA;
body['SessionID'] = getSessionId(body['TokenID'] ?? ""); //getSe
body['PatientOutSA'] = body.containsKey('PatientOutSA') ? body['PatientOutSA'] ?? user.outSa : user.outSa;
body['SessionID'] = body['TokenID'] == null ? ApiConsts.sessionID : getSessionId(body['TokenID'] ?? ""); //getSe
}
// else {
// body['SessionID'] = body['TokenID'] == null ? ApiConsts.sessionID : getSessionId(body['TokenID'] ?? ""); //getSe
//
// }
}
}
@ -151,17 +155,23 @@ class ApiClientImp implements ApiClient {
// request.languageID = (languageID == 'ar' ? 1 : 2);
// request.patientOutSA = (request.zipCode == '966' || request.zipCode == '+966') ? 0 : 1;
body['VersionID'] = ApiConsts.appVersionID.toString();
body['Channel'] = ApiConsts.appChannelId.toString();
body['IPAdress'] = ApiConsts.appIpAddress;
body['generalid'] = ApiConsts.appGeneralId;
body['LanguageID'] = _appState.getLanguageID().toString();
body['Latitude'] = _appState.userLat.toString();
body['Longitude'] = _appState.userLong.toString();
body['DeviceTypeID'] = _appState.deviceTypeID;
if (_appState.appLoginTokenID.isNotEmpty) {
body['LogInTokenID'] = _appState.appLoginTokenID;
// body['VersionID'] = ApiConsts.appVersionID.toString();
if (!isExternal) {
body['VersionID'] = "50.0";
body['Channel'] = ApiConsts.appChannelId.toString();
body['IPAdress'] = ApiConsts.appIpAddress;
body['generalid'] = ApiConsts.appGeneralId;
body['LanguageID'] = _appState.getLanguageID().toString();
body['Latitude'] = _appState.userLat.toString();
body['Longitude'] = _appState.userLong.toString();
body['DeviceTypeID'] = _appState.deviceTypeID;
if (_appState.appLoginTokenID.isNotEmpty) {
body['LogInTokenID'] = _appState.appLoginTokenID;
}
// body['TokenID'] = "@dm!n";
// body['PatientID'] = "4767477";
}
body.removeWhere((key, value) => value == null);
@ -190,7 +200,7 @@ class ApiClientImp implements ApiClient {
} else {
var parsed = json.decode(utf8.decode(response.bodyBytes));
if (isAllowAny) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
onSuccess(parsed, statusCode, messageStatus: 1, errorMessage: "");
} else {
if (parsed['Response_Message'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);

@ -1,4 +1,5 @@
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:amazon_payfort/amazon_payfort.dart';
var MAX_SMALL_SCREEN = 660;
final OPENTOK_API_KEY = '46209962';
@ -697,7 +698,7 @@ var IS_DOCTOR_AVAILABLE_BY_CALENDAR_SCHEDULE = 'Services/OUTPs.svc/REST/HIS_IsDo
var getPayFortProjectDetails = "Services/PayFort_Serv.svc/REST/GetPayFortProjectDetails";
var addPayFortApplePayResponse = "Services/PayFort_Serv.svc/REST/AddResponse";
// var payFortEnvironment = FortEnvironment.production;
var applePayMerchantId = "merchant.com.hmgwebservices";
// var applePayMerchantId = "merchant.com.hmgwebservices";
// var payFortEnvironment = FortEnvironment.test;
// var applePayMerchantId = "merchant.com.hmgwebservices.uat";
@ -735,25 +736,52 @@ class ApiConsts {
static num VERSION_ID = 18.9;
static var payFortEnvironment = FortEnvironment.production;
static var applePayMerchantId = "merchant.com.hmgwebservices";
static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT
// var payFortEnvironment = FortEnvironment.test;
// var applePayMerchantId = "merchant.com.hmgwebservices.uat";
static setBackendURLs() {
switch (appEnvironmentType) {
case AppEnvironmentTypeEnum.prod:
baseUrl = "https://hmgwebservices.com/";
payFortEnvironment = FortEnvironment.production;
applePayMerchantId = "merchant.com.hmgwebservices";
SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx";
break;
case AppEnvironmentTypeEnum.dev:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
case AppEnvironmentTypeEnum.uat:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
case AppEnvironmentTypeEnum.preProd:
baseUrl = "https://webservices.hmg.com/";
payFortEnvironment = FortEnvironment.production;
applePayMerchantId = "merchant.com.hmgwebservices";
SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx";
break;
case AppEnvironmentTypeEnum.qa:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
case AppEnvironmentTypeEnum.staging:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
}
}
@ -765,10 +793,16 @@ class ApiConsts {
static final String sendActivationCodeRegister = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration';
static final String checkActivationCode = 'Services/Authentication.svc/REST/CheckActivationCode';
static final String checkActivationCodeRegister = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration';
static final String checkUsageAgreement = 'Services/Patients.svc/REST/CheckForUsageAgreement';
static final String getUserAgreementContent = 'Services/Patients.svc/REST/GetUsageAgreementText';
static final String checkPatientForRegistration = 'Services/Authentication.svc/REST/CheckPatientForRegisteration';
static final String checkUserStatus= 'Services/NHIC.svc/REST/GetPatientInfo';
// static values for Api
static final double appVersionID = 18.7;
static final int appChannelId = 3;
static final String appIpAddress = "10.20.10.20";
static final String appGeneralId = "Cs2020@2016\$2958";
static final String sessionID = 'TMRhVmkGhOsvamErw';
}

@ -76,6 +76,17 @@ class AppAssets {
static const String insurance = '$svgBasePath/insurance.svg';
static const String requests = '$svgBasePath/requests.svg';
static const String more = '$svgBasePath/more.svg';
static const String appointment_calendar_icon = '$svgBasePath/appointment_calendar_icon.svg';
static const String appointment_time_icon = '$svgBasePath/appointment_time_icon.svg';
static const String confirm_appointment_icon = '$svgBasePath/confirm_appointment_icon.svg';
static const String appointment_pay_icon = '$svgBasePath/appointment_pay_icon.svg';
static const String appointment_checkin_icon = '$svgBasePath/appointment_checkin_icon.svg';
static const String ask_doctor_icon = '$svgBasePath/ask_doctor_icon.svg';
static const String uae_dirham_symbol = '$svgBasePath/uae_dirham_symbol.svg';
static const String directions_icon = '$svgBasePath/directions_icon.svg';
static const String apple_pay_button = '$svgBasePath/pay_with_apple_pay.svg';
static const String bell = '$svgBasePath/bell.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';
@ -89,12 +100,13 @@ class AppAssets {
static const String hmg_logo = '$pngBasePath/hmg_logo.png';
static const String livecare_service = '$pngBasePath/livecare_service.png';
static const String male_img = '$pngBasePath/male_img.png';
static const String femaleImg = '$pngBasePath/female_img.png';
static const String apple_pay = '$pngBasePath/Apple_Pay.png';
static const String mada = '$pngBasePath/Mada.png';
static const String Mastercard = '$pngBasePath/Mastercard.png';
static const String tamara_en = '$pngBasePath/tamara_en.png';
static const String visa = '$pngBasePath/visa.png';
static const String lockIcon = '$pngBasePath/lock-icon.png';
}
class AppAnimations {
@ -102,4 +114,5 @@ class AppAnimations {
static const String login = '$lottieBasePath/login.json';
static const String register = '$lottieBasePath/register.json';
static const String checkmark = '$lottieBasePath/checkmark.json';
static const String loadingAnimation = '$lottieBasePath/Loader.json';
}

@ -1,5 +1,9 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/common_models/VidaPlusProjectListModel.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
@ -20,15 +24,35 @@ class AppState {
int getLanguageID() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode == "ar" ? 1 : 2;
int getDeviceTypeID() => Platform.isIOS ? 1 : 2;
String? getLanguageCode() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode;
AuthenticatedUser? _authenticatedUser;
AuthenticatedUser? _authenticatedRootUser;
AuthenticatedUser? _authenticatedChildUser;
void setAuthenticatedUser(AuthenticatedUser authenticatedUser, {bool isFamily = false}) {
if (isFamily) {
_authenticatedChildUser = authenticatedUser;
} else {
setIsAuthenticated = true;
_authenticatedRootUser = authenticatedUser;
}
}
void setAuthenticatedUser(AuthenticatedUser authenticatedUser) {
_authenticatedUser = authenticatedUser;
AuthenticatedUser? getAuthenticatedUser({bool isFamily = false}) {
if (isFamily) {
return _authenticatedChildUser;
} else {
return _authenticatedRootUser;
}
}
AuthenticatedUser? get getAuthenticatedUser => _authenticatedUser;
String _userBloodGroup = "";
String get getUserBloodGroup => _userBloodGroup;
set setUserBloodGroup(String value) => _userBloodGroup = value;
SelectDeviceByImeiRespModelElement? _selectDeviceByImeiRespModelElement;
@ -46,6 +70,10 @@ class AppState {
set setDeviceToken(v) => deviceToken = v;
String voipToken = "";
set setVoipToken(v) => voipToken = v;
String appAuthToken = "";
set setAppAuthToken(v) => appAuthToken = v;
@ -54,11 +82,25 @@ class AppState {
set setSessionId(v) => sessionId = v;
bool isAuthenticated = true;
bool isAuthenticated = false;
set setIsAuthenticated(v) => isAuthenticated = v;
String deviceTypeID = "";
set setDeviceTypeID(v) => deviceTypeID = v;
List<VidaPlusProjectListModel> vidaPlusProjectList = [];
setVidaPlusProjectList(List<VidaPlusProjectListModel> vidaPlusProjectListModelInput) {
vidaPlusProjectList = vidaPlusProjectListModelInput;
}
CheckUserStatusResponseNHIC? _nHICUserData;
CheckUserStatusResponseNHIC get getNHICUserData => _nHICUserData!;
set setNHICUserData(CheckUserStatusResponseNHIC value) {
_nHICUserData = value;
}
}

@ -0,0 +1,15 @@
class VidaPlusProjectListModel {
int? projectID;
VidaPlusProjectListModel({this.projectID});
VidaPlusProjectListModel.fromJson(Map<String, dynamic> json) {
projectID = json['ProjectID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ProjectID'] = this.projectID;
return data;
}
}

@ -0,0 +1,120 @@
class TamaraRequestModel {
String? merchantReference;
String? merchantIdentifier;
String? clientRequestID;
num? amount;
String? currency;
String? language;
String? commandType;
String? signature;
String? customerEmail;
String? orderDescription;
bool? isInstallment;
num? projectID;
String? accessCode;
String? sHARequestPhase;
String? sHAResponsePhase;
String? customerName;
String? fileNumber;
bool? patientOutSA;
String? deviceToken;
String? longitude;
String? latitude;
String? appointmentNo;
var serviceID;
var liveServiceID;
String? doctorID;
var appointmentDate;
bool? isSchedule;
TamaraRequestModel(
{this.merchantReference,
this.merchantIdentifier,
this.clientRequestID,
this.amount,
this.currency,
this.language,
this.commandType,
this.signature,
this.customerEmail,
this.orderDescription,
this.isInstallment,
this.projectID,
this.accessCode,
this.sHARequestPhase,
this.sHAResponsePhase,
this.customerName,
this.fileNumber,
this.patientOutSA,
this.deviceToken,
this.longitude,
this.latitude,
this.appointmentNo,
this.serviceID,
this.liveServiceID,
this.appointmentDate,
this.doctorID,
this.isSchedule});
TamaraRequestModel.fromJson(Map<String, dynamic> json) {
merchantReference = json['Merchant_Reference'];
merchantIdentifier = json['Merchant_Identifier'];
clientRequestID = json['ClientRequestID'];
amount = json['Amount'];
currency = json['Currency'];
language = json['Language'];
commandType = json['CommandType'];
signature = json['Signature'];
customerEmail = json['CustomerEmail'];
orderDescription = json['OrderDescription'];
isInstallment = json['IsInstallment'];
projectID = json['ProjectID'];
accessCode = json['Access_code'];
sHARequestPhase = json['SHA_RequestPhase'];
sHAResponsePhase = json['SHA_ResponsePhase'];
customerName = json['CustomerName'];
fileNumber = json['FileNumber'];
patientOutSA = json['PatientOutSA'];
deviceToken = json['DeviceToken'];
longitude = json['Longitude'];
latitude = json['Latitude'];
appointmentNo = json['AppointmentNo'];
serviceID = json['Service_ID'];
liveServiceID = json['Live_ServiceID'];
doctorID = json['DoctorID'];
appointmentDate = json['AppointmentDate'];
isSchedule = json['IsSchedule'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Merchant_Reference'] = this.merchantReference;
data['Merchant_Identifier'] = this.merchantIdentifier;
data['ClientRequestID'] = this.clientRequestID;
data['Amount'] = this.amount;
data['Currency'] = this.currency;
data['Language'] = this.language;
data['CommandType'] = this.commandType;
data['Signature'] = this.signature;
data['CustomerEmail'] = this.customerEmail;
data['OrderDescription'] = this.orderDescription;
data['IsInstallment'] = this.isInstallment;
data['ProjectID'] = this.projectID;
data['Access_code'] = this.accessCode;
data['SHA_RequestPhase'] = this.sHARequestPhase;
data['SHA_ResponsePhase'] = this.sHAResponsePhase;
data['CustomerName'] = this.customerName;
data['FileNumber'] = this.fileNumber;
data['PatientOutSA'] = this.patientOutSA;
data['DeviceToken'] = this.deviceToken;
data['Longitude'] = this.longitude;
data['Latitude'] = this.latitude;
data['AppointmentNo'] = this.appointmentNo;
data['Service_ID'] = this.serviceID;
data['Live_ServiceID'] = this.liveServiceID;
data['DoctorID'] = this.doctorID;
data['AppointmentDate'] = this.appointmentDate;
data['IsSchedule'] = this.isSchedule;
return data;
}
}

@ -12,6 +12,9 @@ import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart
import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
@ -21,8 +24,10 @@ import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/firebase_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:local_auth/local_auth.dart';
import 'package:logger/web.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -49,6 +54,8 @@ class AppDependencies {
));
getIt.registerLazySingleton<NavigationService>(() => NavigationService());
getIt.registerLazySingleton<LocalAuthentication>(() => LocalAuthentication());
getIt.registerLazySingleton<GAnalytics>(() => GAnalytics());
getIt.registerLazySingleton<AppState>(() => AppState(navigationService: getIt()));
getIt.registerLazySingleton<LocationUtils>(() => LocationUtils(
@ -76,6 +83,8 @@ class AppDependencies {
getIt.registerLazySingleton<RadiologyRepo>(() => RadiologyRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<PrescriptionsRepo>(() => PrescriptionsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<InsuranceRepo>(() => InsuranceRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<PayfortRepo>(() => PayfortRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<LocalAuthService>(() => LocalAuthService(loggerService: getIt<LoggerService>(), localAuth: getIt<LocalAuthentication>()));
// ViewModels
// Global/shared VMs LazySingleton
@ -102,12 +111,26 @@ class AppDependencies {
);
getIt.registerLazySingleton<InsuranceViewModel>(
() => InsuranceViewModel(
() => InsuranceViewModel(
insuranceRepo: getIt(),
errorHandlerService: getIt(),
),
);
getIt.registerLazySingleton<MyAppointmentsViewModel>(
() => MyAppointmentsViewModel(
myAppointmentsRepo: getIt(),
errorHandlerService: getIt(),
),
);
getIt.registerLazySingleton<PayfortViewModel>(
() => PayfortViewModel(
payfortRepo: getIt(),
errorHandlerService: getIt(),
),
);
getIt.registerLazySingleton<AuthenticationViewModel>(
() => AuthenticationViewModel(
authenticationRepo: getIt(),
@ -116,6 +139,7 @@ class AppDependencies {
dialogService: getIt(),
appState: getIt(),
errorHandlerService: getIt(),
localAuthService: getIt()
),
);

@ -24,6 +24,8 @@ enum ViewStateEnum {
enum CountryEnum { saudiArabia, unitedArabEmirates }
enum CalenderEnum { gregorian, hijri }
enum SelectionTypeEnum { dropdown, calendar }
enum GenderTypeEnum { male, female }
@ -32,12 +34,47 @@ enum MaritalStatusTypeEnum { single, married, divorced, widowed }
enum ChipTypeEnum { success, error, alert, info, warning }
enum OTPTypeEnum { sms, whatsapp }
enum OTPTypeEnum { sms, whatsapp, faceIDFingerprint }
enum LoginTypeEnum { sms, whatsapp, face, fingerprint }
enum AppEnvironmentTypeEnum { dev, uat, preProd, qa, staging, prod }
extension CalenderExtension on CalenderEnum {
int get toInt {
switch (this) {
case CalenderEnum.hijri:
return 1;
case CalenderEnum.gregorian:
return 0;
}
}
String get displayName {
switch (this) {
case CalenderEnum.hijri:
return 'Hijri';
case CalenderEnum.gregorian:
return 'Gregorian';
}
}
static LoginTypeEnum? fromValue(int value) {
switch (value) {
case 1:
return LoginTypeEnum.sms;
case 2:
return LoginTypeEnum.fingerprint;
case 3:
return LoginTypeEnum.face;
case 4:
return LoginTypeEnum.whatsapp;
default:
return null;
}
}
}
extension LoginTypeExtension on LoginTypeEnum {
int get toInt {
switch (this) {
@ -89,6 +126,8 @@ extension OTPTypeEnumExtension on OTPTypeEnum {
return 1;
case OTPTypeEnum.whatsapp:
return 2;
case OTPTypeEnum.faceIDFingerprint:
return 0;
}
}
@ -104,3 +143,49 @@ extension OTPTypeEnumExtension on OTPTypeEnum {
}
}
}
enum ServiceTypeEnum {
advancePayment, //3
ancillaryOrder, //3
appointmentPayment, //2
covidPayment, //2
erOnlineCheckIn, //3
liveCareAppointment //4
}
extension ServiceTypeEnumExt on ServiceTypeEnum {
String value() {
switch (this) {
case ServiceTypeEnum.advancePayment:
return "Advance Payment";
case ServiceTypeEnum.ancillaryOrder:
return "Ancillary Order";
case ServiceTypeEnum.appointmentPayment:
return "Appointment Payment";
case ServiceTypeEnum.covidPayment:
return "Covid Payment";
case ServiceTypeEnum.erOnlineCheckIn:
return "ER Online Check In";
case ServiceTypeEnum.liveCareAppointment:
return "LiveCare Appointment";
}
}
int getIdFromServiceEnum() {
switch (this) {
case ServiceTypeEnum.advancePayment:
return 3;
case ServiceTypeEnum.ancillaryOrder:
return 3;
case ServiceTypeEnum.appointmentPayment:
return 2;
case ServiceTypeEnum.covidPayment:
return 2;
case ServiceTypeEnum.erOnlineCheckIn:
return 3;
case ServiceTypeEnum.liveCareAppointment:
return 4;
}
}
}

@ -1,5 +1,9 @@
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/send_activation_request_model.dart';
import 'package:hmg_patient_app_new/features/common/models/commong_authanticated_req_model.dart';
class RequestUtils {
static dynamic getPatientAuthenticationRequest({
@ -10,6 +14,8 @@ class RequestUtils {
required bool isForRegister,
required int? patientId,
required String zipCode,
required CalenderEnum calenderType,
String? dob,
}) {
bool fileNo = false;
if (nationId.isNotEmpty) {
@ -23,20 +29,22 @@ class RequestUtils {
request.zipCode = zipCode; // or countryCode if defined elsewhere
if (isForRegister) {
// request.searchType = registeredData.searchType ?? 1;
// request.patientID = registeredData.patientID ?? 0;
// request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0';
// request.dob = registeredData.dob;
// request.isRegister = registeredData.isRegister;
request.patientIdentificationID = int.parse(nationId);
request.searchType = 1;
request.isHijri = calenderType.toInt;
request.patientID = patientId;
request.dob = dob;
request.patientOutSA = patientOutSA ? 1 : 0;
request.isDentalAllowedBackend = false;
} else {
if (fileNo) {
request.patientID = patientId ?? int.parse(nationId);
request.patientIdentificationID = request.nationalID = "";
request.patientIdentificationID = request.nationalID;
request.searchType = 2;
} else {
request.patientID = 0;
request.searchType = 1;
request.patientIdentificationID = request.nationalID = nationId.isNotEmpty ? nationId : '0';
request.patientIdentificationID = request.nationalID = nationId.isNotEmpty ? int.parse(nationId) : 0;
}
request.isRegister = false;
}
@ -50,7 +58,7 @@ class RequestUtils {
required bool patientOutSA,
required String? loginTokenID,
required var registeredData,
required int? patientId,
int? patientId,
required String nationIdText,
required String countryCode,
}) {
@ -77,12 +85,12 @@ class RequestUtils {
} else {
if (fileNo) {
request.patientID = patientId ?? int.parse(nationIdText);
request.patientIdentificationID = request.nationalID = "";
request.patientIdentificationID = request.nationalID = "" as int?;
request.searchType = 2;
} else {
request.patientID = 0;
request.searchType = 1;
request.patientIdentificationID = request.nationalID = nationIdText.isNotEmpty ? nationIdText : '0';
request.patientIdentificationID = request.nationalID = (nationIdText.isNotEmpty ? nationIdText : '0') as int?;
}
request.isRegister = false;
}
@ -96,12 +104,14 @@ class RequestUtils {
required String mobileNumber,
required String zipCode,
required int? patientId,
required String? nationalId,
required int? nationalId,
required bool patientOutSA,
required int selectedLoginType,
required bool isForRegister,
required bool isFileNo,
dynamic payload,
}) {
AppState _appState = getIt.get<AppState>();
var request = SendActivationRequest();
if (mobileNumber.isNotEmpty) {
request.patientMobileNumber = int.parse(mobileNumber);
@ -112,20 +122,51 @@ class RequestUtils {
request.oTPSendType = otpTypeEnum.toInt(); //this.selectedOption == 1 ? 1 : 2;
request.zipCode = zipCode;
if (isForRegister) {
// request.searchType = registeredData.searchType ?? 1;
// request.patientID = registeredData.patientID ?? 0;
// request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0';
// request.dob = registeredData.dob;
// request.isRegister = registeredData.isRegister;
if (isForRegister && payload != null) {
request.searchType = isFileNo ? 2 : 1;
// request.searchType = payload["SearchType"];
request.patientID = payload["PatientID"];
request.patientIdentificationID = request.nationalID = payload["PatientIdentificationID"] ?? '0';
request.dob = payload["DOB"];
request.isRegister = payload["isRegister"];
request.healthId = _appState.getNHICUserData.healthId;
request.isHijri = payload["IsHijri"];
request.deviceToken = _appState.deviceToken;
} else {
request.searchType = isFileNo ? 2 : 1;
request.patientID = patientId ?? 0;
request.nationalID = nationalId ?? '0';
request.patientIdentificationID = nationalId ?? '0';
request.nationalID = nationalId ?? 0;
request.patientIdentificationID = (nationalId ?? '0') as int?;
request.isRegister = false;
}
request.deviceTypeID = request.searchType;
return request;
}
//DeviceToken":""
//
//{"PatientMobileNumber":530896018,"MobileNo":"0530896018","DeviceToken":"","ProjectOutSA":false,"LoginType":1,"ZipCode":"966","isRegister":true,"LogInTokenID":"","SearchType":2,"PatientID":0,"NationalID":"2599865082","PatientIdentificationID":"2599865082","OTP_SendType":1,"LanguageID":2,"VersionID":18.7,"Channel":3,"IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","PatientOutSA":0,"isDentalAllowedBackend":false,"DeviceTypeID":1,"DOB":"19/07/1997","IsHijri":0,"HealthId":"30000541803510","Latitude":0.0,"Longitude":0.0,"PatientType":1}
//{"PatientMobileNumber":530896018,"MobileNo":"0530896018","DeviceToken":"","ProjectOutSA":false,"LoginType":1,"ZipCode":"966","isRegister":true,"LogInTokenID":"","SearchType":1,"PatientID":0,"NationalID":"2599865082","PatientIdentificationID":"2599865082","OTP_SendType":1,"LanguageID":"2","VersionID":"18.7","Channel":"3","IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","PatientOutSA":0,"SessionID":"TMRhVmkGhOsvamErw","isDentalAllowedBackend":false,"DeviceTypeID":"1","SMSSignature":"enKTDcqbOVd","DOB":"19/07/1997","PatientType":"1","Latitude":"0.0","Longitude":"0.0"}
static getAuthanticatedCommonRequest() {
AppState _appState = getIt.get<AppState>();
var request = CommonAuthanticatedRequest();
request.sessionId = ApiConsts.sessionID;
request.latitude = _appState.userLat;
request.longitude = _appState.userLong;
request.languageId = _appState.getLanguageID();
request.versionId = ApiConsts.appVersionID;
request.ipAdress = ApiConsts.appIpAddress;
request.deviceTypeId = _appState.getDeviceTypeID();
request.patientTypeId = _appState.getAuthenticatedUser()?.patientType;
request.patientType = _appState.getAuthenticatedUser()?.patientType;
request.generalid = ApiConsts.appGeneralId;
request.channel = ApiConsts.appChannelId;
request.patientId = _appState.getAuthenticatedUser()!.patientId;
request.patientOutSa = _appState.getAuthenticatedUser()!.outSa;
request.tokenId = null;
return request;
}
}

@ -11,6 +11,7 @@ import 'package:google_api_availability/google_api_availability.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@ -296,6 +297,29 @@ class Utils {
).center;
}
static Widget getLoadingWidget({String? loadingText}) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Lottie.asset(AppAnimations.loadingAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor),
SizedBox(height: 8.h),
],
).center;
}
static bool isVidaPlusProject(AppState appState, int projectID) {
bool isVidaPlus = false;
for (var element in appState.vidaPlusProjectList) {
if (element.projectID == projectID) {
isVidaPlus = true;
}
}
return isVidaPlus;
}
static getPhoneNumberWithoutZero(String number) {
String newNumber = "";
if (number.startsWith('0')) {
@ -367,6 +391,19 @@ class Utils {
}
}
static String formatDateForApi(String isoDateString) {
try {
final dateTime = DateTime.parse(isoDateString);
final year = dateTime.year.toString();
final month = dateTime.month.toString().padLeft(2, '0');
final day = dateTime.day.toString().padLeft(2, '0');
return '$day/$month/$year';
} catch (e) {
log("Error formatting date for API: $e");
return "";
}
}
static String formatHijriDateToDisplay(String hijriDateString) {
try {
// Assuming hijriDateString is in the format yyyy-MM-dd
@ -474,6 +511,35 @@ class Utils {
);
}
static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize, {bool isSaudiCurrency = true}) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
appState.isArabic()
? Container()
: Utils.buildSvgWithAssets(
icon: isSaudiCurrency ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol,
iconColor: iconColor,
width: iconSize.h,
height: iconSize.h,
fit: BoxFit.contain,
),
SizedBox(width: 5.h),
paymentAmountWidget,
SizedBox(width: 5.h),
!appState.isArabic()
? Container()
: Utils.buildSvgWithAssets(
icon: isSaudiCurrency ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol,
iconColor: iconColor,
width: iconSize.h,
height: iconSize.h,
fit: BoxFit.contain,
),
],
);
}
static Future<bool> isGoogleServicesAvailable() async {
GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
String status = availability.toString().split('.').last;
@ -496,4 +562,13 @@ class Utils {
static String generateMd5Hash(String input) {
return crypto.md5.convert(utf8.encode(input)).toString();
}
static String getAppointmentTransID(int projectID, int clinicID, int appoNo, {bool isAddMilliseconds = true}) {
String currentMillis = DateTime.now().millisecondsSinceEpoch.toString();
return '$projectID-$clinicID-$appoNo${isAddMilliseconds ? '-${currentMillis.substring(currentMillis.length - 5, currentMillis.length)}' : ""}';
}
static String getAdvancePaymentTransID(int projectID, int fileNumber) {
return '$projectID-$fileNumber-${DateTime.now().millisecondsSinceEpoch}';
}
}

@ -5,6 +5,11 @@ extension ContextUtils on BuildContext {
double get screenWidth => MediaQuery.of(this).size.width;
EdgeInsets get padding => MediaQuery.of(this).padding;
bool get safeInsets => padding.top > 0 || padding.bottom > 0 || padding.left > 0 || padding.right > 0;
ThemeData get theme => Theme.of(this);
TextTheme get textTheme => theme.textTheme;

@ -150,14 +150,14 @@ extension EmailValidator on String {
decoration: isUnderLine ? TextDecoration.underline : null),
);
Widget toText15({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, FontWeight? weight, int? maxlines}) => Text(
Widget toText15({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, FontWeight? weight, int? maxlines, double? letterSpacing = -0.4,}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
maxLines: maxlines,
style: TextStyle(
color: color ?? AppColors.blackColor,
fontSize: 15.fSize,
letterSpacing: -1,
letterSpacing: letterSpacing,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null),
);

@ -5,27 +5,29 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_activation_code_register_request_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class AuthenticationRepo {
Future<Either<Failure, GenericApiModel<SelectDeviceByImeiRespModelElement>>> selectDeviceByImei({
required String firebaseToken,
});
Future<Either<Failure, GenericApiModel<SelectDeviceByImeiRespModelElement>>> selectDeviceByImei({required String firebaseToken});
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq});
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({
required dynamic sendActivationCodeReq,
String? languageID,
bool isRegister = false,
});
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({required dynamic sendActivationCodeReq, String? languageID, bool isRegister = false});
Future<Either<Failure, GenericApiModel<dynamic>>> checkActivationCodeRepo({
required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
required String? activationCode,
required bool isRegister,
});
Future<Either<Failure, GenericApiModel<dynamic>>> checkActivationCodeRepo(
{required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
required String? activationCode,
required bool isRegister});
Future<Either<Failure, GenericApiModel<dynamic>>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest});
Future<Either<Failure, GenericApiModel<dynamic>>> getUserAgreementContent({required dynamic commonAuthanticatedRequest});
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientForRegistration({required dynamic commonAuthanticatedRequest});
Future<Either<Failure, GenericApiModel<dynamic>>> checkUserStatus({required dynamic commonAuthanticatedRequest});
}
class AuthenticationRepoImp implements AuthenticationRepo {
@ -198,4 +200,141 @@ class AuthenticationRepoImp implements AuthenticationRepo {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest}) async {
commonAuthanticatedRequest['Region'] = 1;
print("dsfsdd");
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.checkUsageAgreement,
body: commonAuthanticatedRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> getUserAgreementContent({required dynamic commonAuthanticatedRequest}) async {
commonAuthanticatedRequest['Region'] = 1;
print("dsfsdd");
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.getUserAgreementContent,
body: commonAuthanticatedRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientForRegistration({required dynamic commonAuthanticatedRequest}) async {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.checkPatientForRegistration,
body: commonAuthanticatedRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> checkUserStatus({required dynamic commonAuthanticatedRequest}) async {
commonAuthanticatedRequest['Region'] = 1;
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.checkUserStatus,
body: commonAuthanticatedRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
}

@ -2,21 +2,28 @@ import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
import 'package:hmg_patient_app_new/core/utils/request_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/core/utils/validation_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_activation_code_register_request_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/presentation/authentication/saved_login_screen.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
class AuthenticationViewModel extends ChangeNotifier {
@ -25,6 +32,7 @@ class AuthenticationViewModel extends ChangeNotifier {
final ErrorHandlerService _errorHandlerService;
final DialogService _dialogService;
final NavigationService _navigationService;
final LocalAuthService _localAuthService;
AuthenticationViewModel({
required AppState appState,
@ -33,11 +41,13 @@ class AuthenticationViewModel extends ChangeNotifier {
required DialogService dialogService,
required NavigationService navigationService,
required CacheService cacheService,
required LocalAuthService localAuthService,
}) : _navigationService = navigationService,
_dialogService = dialogService,
_errorHandlerService = errorHandlerService,
_appState = appState,
_authenticationRepo = authenticationRepo;
_authenticationRepo = authenticationRepo,
_localAuthService = localAuthService;
final TextEditingController nationalIdController = TextEditingController(), phoneNumberController = TextEditingController(), dobController = TextEditingController();
CountryEnum selectedCountrySignup = CountryEnum.saudiArabia;
@ -45,8 +55,12 @@ class AuthenticationViewModel extends ChangeNotifier {
GenderTypeEnum? genderType;
bool isTermsAccepted = false;
List<NationalityCountries>? countriesList;
String? dob = "";
NationalityCountries? pickedCountryByUAEUser;
CalenderEnum calenderType = CalenderEnum.gregorian;
//==================
bool isDubai = false;
bool authenticated = false;
@ -64,15 +78,14 @@ class AuthenticationViewModel extends ChangeNotifier {
late int selectedOption = 1;
bool onlySMSBox = false;
int fingrePrintBefore = 0;
var dob;
late int isHijri;
var healthId;
Future<void> onLoginPressed() async {
try {
LoadingUtils.showFullScreenLoader();
//TODO: We will remove this delay
await Future.delayed(Duration(seconds: 3));
// await Future.delayed(Duration(seconds: 3));
var data = _appState.getSelectDeviceByImeiRespModelElement;
log("Cached IMEI data: ${data?.toJson()}");
if (data != null) {
@ -87,7 +100,7 @@ class AuthenticationViewModel extends ChangeNotifier {
}
}
void clearDefaults() {
void clearDefaultInputValues() {
nationalIdController.clear();
phoneNumberController.clear();
dobController.clear();
@ -103,6 +116,24 @@ class AuthenticationViewModel extends ChangeNotifier {
notifyListeners();
}
void onCalenderTypeChange(bool isGregorian) {
calenderType = isGregorian ? CalenderEnum.gregorian : CalenderEnum.hijri;
notifyListeners();
}
void onDobChange(String? date) {
if (calenderType == CalenderEnum.hijri) {
var hijriDate = HijriGregConverter.gregorianToHijri(DateTime.parse(date!));
DateTime hijriDateTimeForController = DateTime(hijriDate.year, hijriDate.month, hijriDate.day);
dob = Utils.formatDateForApi(date);
dobController.text = Utils.formatHijriDateToDisplay(hijriDateTimeForController.toIso8601String()); // Or directly hijriDate.toString() if that's what your formatter expects
} else {
dobController.text = Utils.formatDateToDisplay(date!);
dob = Utils.formatDateForApi(date);
}
notifyListeners();
}
void loadCountriesData({required BuildContext context}) async {
final String response = await DefaultAssetBundle.of(context).loadString('assets/json/countriesList.json');
final List<dynamic> data = json.decode(response);
@ -135,9 +166,11 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> selectDeviceImei({required Function(dynamic data) onSuccess, Function(String)? onError}) async {
// LoadingUtils.showFullScreenLoading();
String firebaseToken = _appState.deviceToken == ""
? "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc"
: _appState.deviceToken;
// String firebaseToken = _appState.deviceToken;
String firebaseToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
// == ""
// ? "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc"
// : _appState.deviceToken;
final result = await _authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken);
result.fold(
@ -165,8 +198,8 @@ class AuthenticationViewModel extends ChangeNotifier {
if (savedData != null) {
// TODO: Navigate to SavedLogin when available
_navigationService.pushPage(page: LoginScreen());
// navigationService.pushPage(page: SavedLogin(savedData));
//_navigationService.pushPage(page: LoginScreen());
_navigationService.pushPage(page: SavedLogin());
}
} catch (e) {
log("Error handling existing IMEI data: $e");
@ -186,8 +219,8 @@ class AuthenticationViewModel extends ChangeNotifier {
// TODO: Navigate to SavedLogin when available
// SelectDeviceByImeiRespModelElement savedData =
// SelectDeviceByImeiRespModelElement.fromJson(respData);
// navigationService.pushPage(page: SavedLogin(savedData));
_navigationService.pushPage(page: LoginScreen());
_navigationService.pushPage(page: SavedLogin());
// _navigationService.pushPage(page: LoginScreen());
} else {
LoadingUtils.hideFullScreenLoader();
_navigationService.pushPage(page: LoginScreen());
@ -221,14 +254,14 @@ class AuthenticationViewModel extends ChangeNotifier {
LoadingUtils.showFullScreenLoader();
dynamic checkPatientAuthenticationReq = RequestUtils.getPatientAuthenticationRequest(
phoneNumber: phoneNumberController.text,
nationId: nationalIdController.text,
isForRegister: false,
patientOutSA: false,
otpTypeEnum: otpTypeEnum,
patientId: 0,
zipCode: '966',
);
phoneNumber: phoneNumberController.text,
nationId: nationalIdController.text,
isForRegister: false,
patientOutSA: false,
otpTypeEnum: otpTypeEnum,
patientId: 0,
zipCode: selectedCountrySignup.countryCode,
calenderType: calenderType);
final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq);
LoadingUtils.hideFullScreenLoader();
@ -248,6 +281,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} else {
if (apiResponse.data['IsAuthenticated']) {
await checkActivationCode(
otpTypeEnum: otpTypeEnum,
onWrongActivationCode: (String? message) {},
activationCode: 0000,
);
@ -258,45 +292,41 @@ class AuthenticationViewModel extends ChangeNotifier {
);
}
Future<void> sendActivationCode({
required OTPTypeEnum otpTypeEnum,
required String nationalIdOrFileNumber,
required String phoneNumber,
}) async {
Future<void> sendActivationCode({required OTPTypeEnum otpTypeEnum, required String nationalIdOrFileNumber, required String phoneNumber, dynamic payload}) async {
bool isForRegister = await checkIsUserComingForRegister(request: payload);
bool isPatientOutSA = await isPatientOutsideSA(request: payload);
bool isFileNo = await isPatientHasFile(request: payload);
var request = RequestUtils.getCommonRequestSendActivationCode(
otpTypeEnum: otpTypeEnum,
mobileNumber: phoneNumber,
selectedLoginType: otpTypeEnum.toInt(),
zipCode: "966",
nationalId: nationalIdOrFileNumber,
isFileNo: false,
patientId: 0,
isForRegister: false,
patientOutSA: false,
);
otpTypeEnum: otpTypeEnum,
mobileNumber: phoneNumber,
selectedLoginType: otpTypeEnum.toInt(),
zipCode: selectedCountrySignup.countryCode,
nationalId: int.parse(nationalIdOrFileNumber),
isFileNo: isFileNo,
patientId: 0,
isForRegister: isForRegister,
patientOutSA: isPatientOutSA,
payload: payload);
// TODO: GET APP SMS SIGNATURE HERE
request.sMSSignature = "enKTDcqbOVd";
// GifLoaderDialogUtils.showMyDialog(context);
bool isForRegister = healthId != null || isDubai;
if (isForRegister) {
if (!isDubai) {
request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob));
}
request.healthId = healthId;
request.isHijri = isHijri;
} else {
// request.dob = "";
// request.healthId = "";
// request.isHijri = 0;
}
final resultEither = await _authenticationRepo.sendActivationCodeRepo(
sendActivationCodeReq: request,
isRegister: isForRegister,
languageID: 'er',
);
// bool isForRegister = healthId != null || isDubai;
// if (isForRegister) {
// if (!isDubai) {
// request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob));
// }
// request.healthId = healthId;
// request.isHijri = calenderType.toInt;
// } else {
// // request.dob = "";
// // request.healthId = "";
// // request.isHijri = 0;
// }
final resultEither = await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: isForRegister, languageID: 'er');
resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure),
@ -315,33 +345,38 @@ class AuthenticationViewModel extends ChangeNotifier {
);
}
Future<bool> checkIsUserComingForRegister({required dynamic request}) async {
bool isUserComingForRegister = false;
print(request);
if (request != null && request['isRegister']) {
isUserComingForRegister = true;
}
return isUserComingForRegister;
}
Future<void> checkActivationCode({
required int activationCode,
required OTPTypeEnum otpTypeEnum,
required Function(String? message) onWrongActivationCode,
}) async {
final request = RequestUtils.getCommonRequestWelcome(
phoneNumber: '0567184134',
otpTypeEnum: OTPTypeEnum.sms,
deviceToken: 'dummyDeviceToken123',
phoneNumber: phoneNumberController.text,
otpTypeEnum: otpTypeEnum,
deviceToken: _appState.deviceToken,
patientOutSA: true,
loginTokenID: 'dummyLoginToken456',
loginTokenID: _appState.appLoginTokenID,
registeredData: null,
patientId: 12345,
nationIdText: '1234567890',
countryCode: 'SA',
nationIdText: nationalIdController.text,
countryCode: selectedCountrySignup.countryCode,
).toJson();
bool isForRegister = healthId != null || isDubai;
if (isForRegister) {
if (isDubai) request['DOB'] = dob;
request['HealthId'] = healthId;
request['IsHijri'] = isHijri;
request['IsHijri'] = calenderType.toInt;
final resultEither = await _authenticationRepo.checkActivationCodeRepo(
newRequest: request,
activationCode: activationCode.toString(),
isRegister: true,
);
final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: request, activationCode: activationCode.toString(), isRegister: true);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
@ -353,23 +388,41 @@ class AuthenticationViewModel extends ChangeNotifier {
});
} else {
final resultEither = await _authenticationRepo.checkActivationCodeRepo(
newRequest: request,
newRequest: CheckActivationCodeRegisterReq.fromJson(request),
activationCode: activationCode.toString(),
isRegister: false,
);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(resultEither as Map<String, dynamic>);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
if (activation.errorCode == '699') {
// Todo: Hide Loader
// GifLoaderDialogUtils.hideDialog(context);
onWrongActivationCode(activation.errorEndUserMessage);
return;
} else if (activation.messageStatus == 2) {
onWrongActivationCode(activation.errorEndUserMessage);
return;
} else if (registerd_data?.isRegister == true) {
_navigationService.popUntilNamed(AppRoutes.registerNewScreen);
// Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew));
return;
} else {
if (activation.list != null && activation.list!.isNotEmpty) {
_appState.setAuthenticatedUser(activation.list!.first);
}
_appState.setUserBloodGroup = (activation.patientBlodType ?? "");
_appState.setAppLoginTokenID = activation.authenticationTokenId;
final request = RequestUtils.getAuthanticatedCommonRequest().toJson();
bool isUserAgreedBefore = await checkIfUserAgreedBefore(request: request);
clearDefaultInputValues();
if (isUserAgreedBefore) {
navigateToHomeScreen();
} else {
navigateToHomeScreen();
//Agreement page not designed yet so we are navigating to home screen directly
// getUserAgreementContent(request: request);
}
// TODO: setPreferences and stuff
// sharedPref.remove(FAMILY_FILE);
// activation.list!.isFamily = false;
@ -382,29 +435,230 @@ class AuthenticationViewModel extends ChangeNotifier {
// loginTokenID = activation.logInTokenID;
// await sharedPref.setObject(LOGIN_TOKEN_ID, activation.logInTokenID);
// await sharedPref.setString(TOKEN, activation.authenticationTokenID!);
// checkIfUserAgreedBefore(activation);
// projectViewModel.analytics.loginRegistration.login_successful();
}
});
}
}
Future<bool> checkIfUserAgreedBefore({required dynamic request}) async {
bool isAgreed = false;
if (havePrivilege(109)) {
final resultEither = await _authenticationRepo.checkIfUserAgreed(commonAuthanticatedRequest: request);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
if (apiResponse.data['IsPatientAlreadyAgreed']) {
return true;
}
});
}
return isAgreed;
}
Future<void> getUserAgreementContent({required dynamic request}) async {
final resultEither = await _authenticationRepo.getUserAgreementContent(commonAuthanticatedRequest: request);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
// _navigationService.pushAndReplace(routeName)
//TODO: Add User Agreement Page Here
});
}
bool havePrivilege(int id) {
bool isHavePrivilege = false;
try {
for (var element in _appState.getAuthenticatedUser()!.listPrivilege!) {
if (element.id == id) isHavePrivilege = element.previlege!;
}
} catch (e) {
print(e);
}
return isHavePrivilege;
}
Future<void> navigateToHomeScreen() async {
_navigationService.pushAndReplace(AppRoutes.landingScreen);
}
Future<void> navigateToOTPScreen({required OTPTypeEnum otpTypeEnum, required String phoneNumber}) async {
_navigationService.pushToOtpScreen(
phoneNumber: phoneNumber,
checkActivationCode: (int activationCode) async {
await checkActivationCode(
activationCode: activationCode,
otpTypeEnum: otpTypeEnum,
onWrongActivationCode: (String? value) {
onWrongActivationCode(message: value);
});
// Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => RegisterNewStep2(null, {"nationalID": "12345678654321"})));
},
onResendOTPPressed: (String phoneNumber) {},
);
}
Future<void> onWrongActivationCode({String? message}) async {
// TODO: HANDLE THIS VIA BOTTOM SHEET
await _dialogService.showErrorBottomSheet(message: message ?? "Something went wrong. ", onOkPressed: () {});
}
loginWithFingerPrintFace(int selectedOption) async {
_localAuthService.authenticate().then((value) {
if (value) {
// we have to handle this if verification true;
checkActivationCode(otpTypeEnum: OTPTypeEnum.faceIDFingerprint, activationCode: 0000, onWrongActivationCode: (String? message) {});
// authenticated = true;
notifyListeners();
// navigateToHomeScreen();
} else {
//authenticated = false;
notifyListeners();
}
});
this.selectedOption = selectedOption;
notifyListeners();
}
checkLastLoginStatus(Function() onSuccess) async {
if (_appState.getSelectDeviceByImeiRespModelElement != null &&
(_appState.getSelectDeviceByImeiRespModelElement!.logInType == 1 || _appState.getSelectDeviceByImeiRespModelElement!.logInType == 4)) {
Future.delayed(Duration(seconds: 1), () {
onSuccess();
});
}
}
Future<void> onRegisterPress({required OTPTypeEnum otpTypeEnum}) async {
bool isOutSidePatient = selectedCountrySignup.countryCode == CountryEnum.unitedArabEmirates.countryCode ? true : false;
final request = await RequestUtils.getPatientAuthenticationRequest(
phoneNumber: phoneNumberController.text,
nationId: nationalIdController.text,
patientOutSA: isOutSidePatient,
otpTypeEnum: otpTypeEnum,
isForRegister: true,
patientId: 0,
zipCode: selectedCountrySignup.countryCode,
calenderType: calenderType,
dob: dob)
.toJson();
var nRequest = Map<String, dynamic>.from(request);
if (true) {
request.removeWhere((key, value) => value == null);
nRequest.removeWhere((key, value) => value == null);
nRequest.removeWhere((key, value) => key == "SearchType");
nRequest.removeWhere((key, value) => key == "PatientID");
nRequest.removeWhere((key, value) => key == "OTP_SendType");
nRequest.removeWhere((key, value) => key == "LanguageID");
}
final resultEither = await _authenticationRepo.checkPatientForRegistration(commonAuthanticatedRequest: nRequest);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
checkUserStatusForRegistration(response: apiResponse.data, request: request);
});
}
Future<void> checkUserStatusForRegistration({required dynamic response, required dynamic request}) async {
if (response is Map) {
_appState.setAppAuthToken = response["LogInTokenID"];
if (response["MessageStatus"] == 2) {
print(response["ErrorEndUserMessage"]);
return;
}
if (response['hasFile'] == true) {
//TODO: Show Here Ok And Cancel Dialog and On OKPress it will go for sendActivationCode
} else {
request['forRegister'] = true;
request['isRegister'] = true;
if (await isPatientOutsideSA(request: response)) {
print("=======IN SA=======");
chekUserNHICData(request: request);
} else {
print("=======OUT SA=======");
_appState.setAppLoginTokenID = response['LogInTokenID'];
sendActivationCode(
otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
phoneNumber: request["PatientMobileNumber"].toString());
}
}
} else {
//TODO: Here Hide Loader And Show TOAST
//TODO: if (response['ErrorCode'] == '-986') Toast With OK, And Show response as Output.
}
}
Future<bool> isPatientOutsideSA({required dynamic request}) {
try {
if (request is Map<String, dynamic> && request.containsKey("PatientOutSA")) {
if (!request["PatientOutSA"]) {
return Future.value(true);
} else {
return Future.value(false);
}
} else {
return Future.value(false);
}
} catch (e) {
return Future.value(false);
}
}
Future<bool> isPatientHasFile({required dynamic request}) async {
bool isFile = false;
if (request != null && request["NationalID"] != null) {
isFile = request["NationalID"].length < 10;
}
return isFile;
}
Future<void> chekUserNHICData({required dynamic request}) async {
final resultEither = await _authenticationRepo.checkUserStatus(commonAuthanticatedRequest: request);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse.data is Map) {
_appState.setNHICUserData = CheckUserStatusResponseNHIC.fromJson(apiResponse.data as Map<String, dynamic>);
sendActivationCode(
otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
phoneNumber: request["PatientMobileNumber"].toString(),
payload: request,
);
}
});
// this.authService.checkUserStatus(request).then((result) {
// // Keep loader active, continue to next step
// if (result is Map) {
// RegisterInfoResponse? resultSet;
// CheckUserStatusResponse res = CheckUserStatusResponse.fromJson(result as Map<String, dynamic>);
// nHICData = res;
// sharedPref.setObject(NHIC_DATA, res.toJson());
// resultSet = RegisterInfoResponse.fromJson(res.toJson());
//
// sendActivationCode(type, loginToken, resultSet, isSkipRegistration);
// } else {
// GifLoaderDialogUtils.hideDialog(context);
// context.showBottomSheet(
// child: ExceptionBottomSheet(
// message: result != null ? result : TranslationBase.of(context).somethingWentWrong,
// showCancel: false,
// onOkPressed: () {
// Navigator.of(context).pop();
// },
// ),
// );
// }
// }).catchError((err) {
// GifLoaderDialogUtils.hideDialog(context);
// context.showBottomSheet(
// child: ExceptionBottomSheet(
// message: err.toString(),
// showCancel: false,
// onOkPressed: () {
// Navigator.of(context).pop();
// },
// ),
// );
// });
}
@override

@ -9,8 +9,8 @@ class SendActivationRequest {
String? logInTokenID;
int? searchType;
int? patientID;
String? nationalID;
String? patientIdentificationID;
int? nationalID;
int? patientIdentificationID;
int? oTPSendType;
int? languageID;
double? versionID;

@ -1,292 +1,321 @@
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'dart:convert';
class AuthenticatedUser {
String? setupID;
String? setupId;
int? patientType;
int? patientID;
int? patientId;
String? firstName;
String? middleName;
String? lastName;
String? firstNameN;
String? middleNameN;
String? lastNameN;
int? relationshipID;
int? relationshipId;
int? gender;
String? dateofBirth;
DateTime? dateofBirthDataTime;
dynamic dateofBirthN;
String? nationalityID;
dynamic phoneResi;
dynamic phoneOffice;
String? nationalityId;
String? phoneResi;
String? phoneOffice;
String? mobileNumber;
dynamic faxNumber;
String? faxNumber;
String? emailAddress;
dynamic bloodGroup;
dynamic rHFactor;
dynamic rhFactor;
bool? isEmailAlertRequired;
bool? isSMSAlertRequired;
bool? isSmsAlertRequired;
String? preferredLanguage;
bool? isPrivilegedMember;
dynamic memberID;
dynamic memberId;
dynamic expiryDate;
dynamic isHmgEmployee;
dynamic employeeID;
dynamic emergencyContactName;
dynamic emergencyContactNo;
dynamic employeeId;
String? emergencyContactName;
String? emergencyContactNo;
int? patientPayType;
dynamic dHCCPatientRefID;
dynamic dhccPatientRefId;
bool? isPatientDummy;
int? status;
dynamic isStatusCleared;
int? patientIdentificationType;
String? patientIdentificationNo;
int? projectID;
int? infoSourceID;
int? projectId;
int? infoSourceId;
dynamic address;
int? age;
String? ageDesc;
int? areaID;
int? areaId;
int? crsVerificationStatus;
String? crsVerificationStatusDesc;
String? crsVerificationStatusDescN;
int? createdBy;
String? genderDescription;
dynamic iR;
dynamic iSOCityID;
dynamic iSOCountryID;
String? healthIdFromNhicViaVida;
dynamic ir;
dynamic isoCityId;
dynamic isoCountryId;
bool? isVerfiedFromNhic;
List<ListPrivilege>? listPrivilege;
dynamic marital;
int? outSA;
dynamic pOBox;
dynamic occupationId;
int? outSa;
dynamic poBox;
bool? receiveHealthSummaryReport;
int? sourceType;
dynamic strDateofBirth;
dynamic tempAddress;
dynamic zipCode;
dynamic isFamily;
dynamic cRSVerificationStatus;
// dynamic patientPayType;
// dynamic patientType;
// dynamic status;
dynamic eHealthIdField;
dynamic authenticatedUserPatientPayType;
dynamic authenticatedUserPatientType;
dynamic authenticatedUserStatus;
AuthenticatedUser(
{this.setupID,
this.patientType,
this.patientID,
this.firstName,
this.middleName,
this.lastName,
this.firstNameN,
this.middleNameN,
this.lastNameN,
this.relationshipID,
this.gender,
this.dateofBirth,
this.dateofBirthN,
this.nationalityID,
this.phoneResi,
this.phoneOffice,
this.mobileNumber,
this.faxNumber,
this.emailAddress,
this.bloodGroup,
this.rHFactor,
this.isEmailAlertRequired,
this.isSMSAlertRequired,
this.preferredLanguage,
this.isPrivilegedMember,
this.memberID,
this.expiryDate,
this.isHmgEmployee,
this.employeeID,
this.emergencyContactName,
this.emergencyContactNo,
this.patientPayType,
this.dHCCPatientRefID,
this.isPatientDummy,
this.status,
this.isStatusCleared,
this.patientIdentificationType,
this.patientIdentificationNo,
this.projectID,
this.infoSourceID,
this.address,
this.age,
this.ageDesc,
this.areaID,
this.createdBy,
this.genderDescription,
this.iR,
this.iSOCityID,
this.iSOCountryID,
this.listPrivilege,
this.marital,
this.outSA,
this.pOBox,
this.receiveHealthSummaryReport,
this.sourceType,
this.strDateofBirth,
this.tempAddress,
this.zipCode,
this.isFamily,
this.cRSVerificationStatus});
AuthenticatedUser({
this.setupId,
this.patientType,
this.patientId,
this.firstName,
this.middleName,
this.lastName,
this.firstNameN,
this.middleNameN,
this.lastNameN,
this.relationshipId,
this.gender,
this.dateofBirth,
this.dateofBirthN,
this.nationalityId,
this.phoneResi,
this.phoneOffice,
this.mobileNumber,
this.faxNumber,
this.emailAddress,
this.bloodGroup,
this.rhFactor,
this.isEmailAlertRequired,
this.isSmsAlertRequired,
this.preferredLanguage,
this.isPrivilegedMember,
this.memberId,
this.expiryDate,
this.isHmgEmployee,
this.employeeId,
this.emergencyContactName,
this.emergencyContactNo,
this.patientPayType,
this.dhccPatientRefId,
this.isPatientDummy,
this.status,
this.isStatusCleared,
this.patientIdentificationType,
this.patientIdentificationNo,
this.projectId,
this.infoSourceId,
this.address,
this.age,
this.ageDesc,
this.areaId,
this.crsVerificationStatus,
this.crsVerificationStatusDesc,
this.crsVerificationStatusDescN,
this.createdBy,
this.genderDescription,
this.healthIdFromNhicViaVida,
this.ir,
this.isoCityId,
this.isoCountryId,
this.isVerfiedFromNhic,
this.listPrivilege,
this.marital,
this.occupationId,
this.outSa,
this.poBox,
this.receiveHealthSummaryReport,
this.sourceType,
this.strDateofBirth,
this.tempAddress,
this.zipCode,
this.eHealthIdField,
this.authenticatedUserPatientPayType,
this.authenticatedUserPatientType,
this.authenticatedUserStatus,
});
AuthenticatedUser.fromJson(Map<String, dynamic> json) {
setupID = json['SetupID'];
patientType = json['PatientType'];
patientID = json['PatientID'];
firstName = json['FirstName'];
middleName = json['MiddleName'];
lastName = json['LastName'];
firstNameN = json['FirstNameN'];
middleNameN = json['MiddleNameN'];
lastNameN = json['LastNameN'];
relationshipID = json['RelationshipID'];
gender = json['Gender'];
dateofBirth = json['DateofBirth'];
dateofBirthDataTime = DateUtil.convertStringToDate(json['DateofBirth']);
dateofBirthN = json['DateofBirthN'];
nationalityID = json['NationalityID'];
phoneResi = json['PhoneResi'];
phoneOffice = json['PhoneOffice'];
mobileNumber = json['MobileNumber'];
faxNumber = json['FaxNumber'];
emailAddress = json['EmailAddress'];
bloodGroup = json['BloodGroup'];
rHFactor = json['RHFactor'];
isEmailAlertRequired = json['IsEmailAlertRequired'];
isSMSAlertRequired = json['IsSMSAlertRequired'];
preferredLanguage = json['PreferredLanguage'];
isPrivilegedMember = json['IsPrivilegedMember'];
memberID = json['MemberID'];
expiryDate = json['ExpiryDate'];
isHmgEmployee = json['IsHmgEmployee'];
employeeID = json['EmployeeID'];
emergencyContactName = json['EmergencyContactName'];
emergencyContactNo = json['EmergencyContactNo'];
patientPayType = json['PatientPayType'];
dHCCPatientRefID = json['DHCCPatientRefID'];
isPatientDummy = json['IsPatientDummy'];
status = json['Status'];
isStatusCleared = json['IsStatusCleared'];
patientIdentificationType = json['PatientIdentificationType'];
patientIdentificationNo = json['PatientIdentificationNo'];
projectID = json['ProjectID'];
infoSourceID = json['InfoSourceID'];
address = json['Address'];
age = json['Age'];
ageDesc = json['AgeDesc'];
areaID = json['AreaID'];
createdBy = json['CreatedBy'];
genderDescription = json['GenderDescription'];
iR = json['IR'];
iSOCityID = json['ISOCityID'];
iSOCountryID = json['ISOCountryID'];
if (json['ListPrivilege'] != null) {
listPrivilege = [];
json['ListPrivilege'].forEach((v) {
listPrivilege!.add(new ListPrivilege.fromJson(v));
});
}
marital = json['Marital'];
outSA = json['OutSA'];
pOBox = json['POBox'];
receiveHealthSummaryReport = json['ReceiveHealthSummaryReport'];
sourceType = json['SourceType'];
strDateofBirth = json['StrDateofBirth'];
tempAddress = json['TempAddress'];
zipCode = json['ZipCode'];
isFamily = json['IsFamily'];
cRSVerificationStatus = json['CRSVerificationStatus'];
}
factory AuthenticatedUser.fromRawJson(String str) => AuthenticatedUser.fromJson(json.decode(str));
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['SetupID'] = this.setupID;
data['PatientType'] = this.patientType;
data['PatientID'] = this.patientID;
data['FirstName'] = this.firstName;
data['MiddleName'] = this.middleName;
data['LastName'] = this.lastName;
data['FirstNameN'] = this.firstNameN;
data['MiddleNameN'] = this.middleNameN;
data['LastNameN'] = this.lastNameN;
data['RelationshipID'] = this.relationshipID;
data['Gender'] = this.gender;
data['DateofBirth'] = this.dateofBirth;
data['DateofBirthN'] = this.dateofBirthN;
data['NationalityID'] = this.nationalityID;
data['PhoneResi'] = this.phoneResi;
data['PhoneOffice'] = this.phoneOffice;
data['MobileNumber'] = this.mobileNumber;
data['FaxNumber'] = this.faxNumber;
data['EmailAddress'] = this.emailAddress;
data['BloodGroup'] = this.bloodGroup;
data['RHFactor'] = this.rHFactor;
data['IsEmailAlertRequired'] = this.isEmailAlertRequired;
data['IsSMSAlertRequired'] = this.isSMSAlertRequired;
data['PreferredLanguage'] = this.preferredLanguage;
data['IsPrivilegedMember'] = this.isPrivilegedMember;
data['MemberID'] = this.memberID;
data['ExpiryDate'] = this.expiryDate;
data['IsHmgEmployee'] = this.isHmgEmployee;
data['EmployeeID'] = this.employeeID;
data['EmergencyContactName'] = this.emergencyContactName;
data['EmergencyContactNo'] = this.emergencyContactNo;
data['PatientPayType'] = this.patientPayType;
data['DHCCPatientRefID'] = this.dHCCPatientRefID;
data['IsPatientDummy'] = this.isPatientDummy;
data['Status'] = this.status;
data['IsStatusCleared'] = this.isStatusCleared;
data['PatientIdentificationType'] = this.patientIdentificationType;
data['PatientIdentificationNo'] = this.patientIdentificationNo;
data['ProjectID'] = this.projectID;
data['InfoSourceID'] = this.infoSourceID;
data['Address'] = this.address;
data['Age'] = this.age;
data['AgeDesc'] = this.ageDesc;
data['AreaID'] = this.areaID;
data['CreatedBy'] = this.createdBy;
data['GenderDescription'] = this.genderDescription;
data['IR'] = this.iR;
data['ISOCityID'] = this.iSOCityID;
data['ISOCountryID'] = this.iSOCountryID;
if (this.listPrivilege != null) {
data['ListPrivilege'] =
this.listPrivilege!.map((v) => v.toJson()).toList();
}
data['Marital'] = this.marital;
data['OutSA'] = this.outSA;
data['POBox'] = this.pOBox;
data['ReceiveHealthSummaryReport'] = this.receiveHealthSummaryReport;
data['SourceType'] = this.sourceType;
data['StrDateofBirth'] = this.strDateofBirth;
data['TempAddress'] = this.tempAddress;
data['ZipCode'] = this.zipCode;
data['IsFamily'] = this.isFamily;
data['CRSVerificationStatus'] = this.cRSVerificationStatus;
return data;
}
String toRawJson() => json.encode(toJson());
factory AuthenticatedUser.fromJson(Map<String, dynamic> json) => AuthenticatedUser(
setupId: json["SetupID"],
patientType: json["PatientType"],
patientId: json["PatientID"],
firstName: json["FirstName"],
middleName: json["MiddleName"],
lastName: json["LastName"],
firstNameN: json["FirstNameN"],
middleNameN: json["MiddleNameN"],
lastNameN: json["LastNameN"],
relationshipId: json["RelationshipID"],
gender: json["Gender"],
dateofBirth: json["DateofBirth"],
dateofBirthN: json["DateofBirthN"],
nationalityId: json["NationalityID"],
phoneResi: json["PhoneResi"],
phoneOffice: json["PhoneOffice"],
mobileNumber: json["MobileNumber"],
faxNumber: json["FaxNumber"],
emailAddress: json["EmailAddress"],
bloodGroup: json["BloodGroup"],
rhFactor: json["RHFactor"],
isEmailAlertRequired: json["IsEmailAlertRequired"],
isSmsAlertRequired: json["IsSMSAlertRequired"],
preferredLanguage: json["PreferredLanguage"],
isPrivilegedMember: json["IsPrivilegedMember"],
memberId: json["MemberID"],
expiryDate: json["ExpiryDate"],
isHmgEmployee: json["IsHmgEmployee"],
employeeId: json["EmployeeID"],
emergencyContactName: json["EmergencyContactName"],
emergencyContactNo: json["EmergencyContactNo"],
patientPayType: json["PatientPayType"],
dhccPatientRefId: json["DHCCPatientRefID"],
isPatientDummy: json["IsPatientDummy"],
status: json["Status"],
isStatusCleared: json["IsStatusCleared"],
patientIdentificationType: json["PatientIdentificationType"],
patientIdentificationNo: json["PatientIdentificationNo"],
projectId: json["ProjectID"],
infoSourceId: json["InfoSourceID"],
address: json["Address"],
age: json["Age"],
ageDesc: json["AgeDesc"],
areaId: json["AreaID"],
crsVerificationStatus: json["CRSVerificationStatus"],
crsVerificationStatusDesc: json["CRSVerificationStatusDesc"],
crsVerificationStatusDescN: json["CRSVerificationStatusDescN"],
createdBy: json["CreatedBy"],
genderDescription: json["GenderDescription"],
healthIdFromNhicViaVida: json["HealthIDFromNHICViaVida"],
ir: json["IR"],
isoCityId: json["ISOCityID"],
isoCountryId: json["ISOCountryID"],
isVerfiedFromNhic: json["IsVerfiedFromNHIC"],
listPrivilege: json["ListPrivilege"] == null ? [] : List<ListPrivilege>.from(json["ListPrivilege"]!.map((x) => ListPrivilege.fromJson(x))),
marital: json["Marital"],
occupationId: json["OccupationID"],
outSa: json["OutSA"],
poBox: json["POBox"],
receiveHealthSummaryReport: json["ReceiveHealthSummaryReport"],
sourceType: json["SourceType"],
strDateofBirth: json["StrDateofBirth"],
tempAddress: json["TempAddress"],
zipCode: json["ZipCode"],
eHealthIdField: json["eHealthIDField"],
authenticatedUserPatientPayType: json["patientPayType"],
authenticatedUserPatientType: json["patientType"],
authenticatedUserStatus: json["status"],
);
Map<String, dynamic> toJson() => {
"SetupID": setupId,
"PatientType": patientType,
"PatientID": patientId,
"FirstName": firstName,
"MiddleName": middleName,
"LastName": lastName,
"FirstNameN": firstNameN,
"MiddleNameN": middleNameN,
"LastNameN": lastNameN,
"RelationshipID": relationshipId,
"Gender": gender,
"DateofBirth": dateofBirth,
"DateofBirthN": dateofBirthN,
"NationalityID": nationalityId,
"PhoneResi": phoneResi,
"PhoneOffice": phoneOffice,
"MobileNumber": mobileNumber,
"FaxNumber": faxNumber,
"EmailAddress": emailAddress,
"BloodGroup": bloodGroup,
"RHFactor": rhFactor,
"IsEmailAlertRequired": isEmailAlertRequired,
"IsSMSAlertRequired": isSmsAlertRequired,
"PreferredLanguage": preferredLanguage,
"IsPrivilegedMember": isPrivilegedMember,
"MemberID": memberId,
"ExpiryDate": expiryDate,
"IsHmgEmployee": isHmgEmployee,
"EmployeeID": employeeId,
"EmergencyContactName": emergencyContactName,
"EmergencyContactNo": emergencyContactNo,
"PatientPayType": patientPayType,
"DHCCPatientRefID": dhccPatientRefId,
"IsPatientDummy": isPatientDummy,
"Status": status,
"IsStatusCleared": isStatusCleared,
"PatientIdentificationType": patientIdentificationType,
"PatientIdentificationNo": patientIdentificationNo,
"ProjectID": projectId,
"InfoSourceID": infoSourceId,
"Address": address,
"Age": age,
"AgeDesc": ageDesc,
"AreaID": areaId,
"CRSVerificationStatus": crsVerificationStatus,
"CRSVerificationStatusDesc": crsVerificationStatusDesc,
"CRSVerificationStatusDescN": crsVerificationStatusDescN,
"CreatedBy": createdBy,
"GenderDescription": genderDescription,
"HealthIDFromNHICViaVida": healthIdFromNhicViaVida,
"IR": ir,
"ISOCityID": isoCityId,
"ISOCountryID": isoCountryId,
"IsVerfiedFromNHIC": isVerfiedFromNhic,
"ListPrivilege": listPrivilege == null ? [] : List<dynamic>.from(listPrivilege!.map((x) => x.toJson())),
"Marital": marital,
"OccupationID": occupationId,
"OutSA": outSa,
"POBox": poBox,
"ReceiveHealthSummaryReport": receiveHealthSummaryReport,
"SourceType": sourceType,
"StrDateofBirth": strDateofBirth,
"TempAddress": tempAddress,
"ZipCode": zipCode,
"eHealthIDField": eHealthIdField,
"patientPayType": authenticatedUserPatientPayType,
"patientType": authenticatedUserPatientType,
"status": authenticatedUserStatus,
};
}
class ListPrivilege {
int? iD;
int? id;
String? serviceName;
bool? previlege;
dynamic region;
ListPrivilege({this.iD, this.serviceName, this.previlege, this.region});
ListPrivilege({
this.id,
this.serviceName,
this.previlege,
this.region,
});
factory ListPrivilege.fromRawJson(String str) => ListPrivilege.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
ListPrivilege.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
serviceName = json['ServiceName'];
previlege = json['Previlege'];
region = json['Region'];
}
factory ListPrivilege.fromJson(Map<String, dynamic> json) => ListPrivilege(
id: json["ID"],
serviceName: json["ServiceName"],
previlege: json["Previlege"],
region: json["Region"],
);
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['ServiceName'] = this.serviceName;
data['Previlege'] = this.previlege;
data['Region'] = this.region;
return data;
}
Map<String, dynamic> toJson() => {
"ID": id,
"ServiceName": serviceName,
"Previlege": previlege,
"Region": region,
};
}

@ -1,22 +1,26 @@
import 'dart:convert';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
class CheckActivationCode {
dynamic date;
int? languageID;
int? languageId;
int? serviceName;
dynamic time;
dynamic androidLink;
String? authenticationTokenID;
String? authenticationTokenId;
dynamic data;
bool? dataw;
int? dietType;
int? dietTypeId;
dynamic errorCode;
dynamic errorEndUserMessage;
dynamic errorEndUserMessageN;
dynamic errorMessage;
int? errorStatusCode;
int? errorType;
int? foodCategory;
dynamic iOSLink;
dynamic iosLink;
bool? isAuthenticated;
int? mealOrderStatus;
int? mealType;
@ -25,34 +29,46 @@ class CheckActivationCode {
dynamic patientBlodType;
dynamic successMsg;
dynamic successMsgN;
dynamic vidaUpdatedResponse;
dynamic doctorInformationList;
dynamic getAllPendingRecordsList;
dynamic getAllSharedRecordsByStatusList;
dynamic getMaritalstatusLst;
dynamic getOccupationLst;
dynamic getResponseFileList;
bool? isHMGPatient;
dynamic hisPatientModelVpPortal;
bool? isHmgPatient;
bool? isLoginSuccessfully;
bool? isNeedUpdateIdintificationNo;
bool? kioskSendSMS;
AuthenticatedUser? list;
bool? isPatientAuthorized;
bool? isVidaPlus;
bool? kioskSendSms;
List<AuthenticatedUser>? list;
dynamic listAskHabibMobileLoginInfo;
dynamic listAskHabibPatientFile;
dynamic listFamilyRelationships;
dynamic listMergeFiles;
dynamic listMobileLoginInfo;
dynamic listPatientCount;
dynamic logInTokenID;
dynamic logInTokenId;
dynamic mohemmPrivilegeList;
int? pateintID;
String? patientBloodType;
int? pateintId;
dynamic patientBloodType;
dynamic patientErAdminDriverFileList;
dynamic patientErAdminFile;
dynamic patientErDriverFile;
dynamic patientErDriverFileList;
bool? patientHasFile;
dynamic patientMergedIDs;
bool? patientOutSA;
int? patientShareRequestID;
bool? patientOutSa;
int? patientShareRequestId;
int? patientType;
int? projectIDOut;
int? projectIdOut;
dynamic returnMessage;
bool? sMSLoginRequired;
bool? smsLoginRequired;
dynamic servicePrivilegeList;
dynamic sharePatientName;
bool? userAccountIsActivated;
dynamic verificationCode;
dynamic email;
dynamic errorList;
@ -60,236 +76,572 @@ class CheckActivationCode {
bool? isActiveCode;
bool? isMerged;
bool? isNeedUserAgreement;
bool? isSMSSent;
bool? isSmsSent;
dynamic memberList;
dynamic message;
int? statusCode;
CheckActivationCode(
{this.date,
this.languageID,
this.serviceName,
this.time,
this.androidLink,
this.authenticationTokenID,
this.data,
this.dataw,
this.dietType,
this.errorCode,
this.errorEndUserMessage,
this.errorEndUserMessageN,
this.errorMessage,
this.errorType,
this.foodCategory,
this.iOSLink,
this.isAuthenticated,
this.mealOrderStatus,
this.mealType,
this.messageStatus,
this.numberOfResultRecords,
this.patientBlodType,
this.successMsg,
this.successMsgN,
this.doctorInformationList,
this.getAllPendingRecordsList,
this.getAllSharedRecordsByStatusList,
this.getResponseFileList,
this.isHMGPatient,
this.isLoginSuccessfully,
this.isNeedUpdateIdintificationNo,
this.kioskSendSMS,
this.list,
this.listAskHabibMobileLoginInfo,
this.listAskHabibPatientFile,
this.listMergeFiles,
this.listMobileLoginInfo,
this.listPatientCount,
this.logInTokenID,
this.mohemmPrivilegeList,
this.pateintID,
this.patientBloodType,
this.patientHasFile,
this.patientMergedIDs,
this.patientOutSA,
this.patientShareRequestID,
this.patientType,
this.projectIDOut,
this.returnMessage,
this.sMSLoginRequired,
this.servicePrivilegeList,
this.sharePatientName,
this.verificationCode,
this.email,
this.errorList,
this.hasFile,
this.isActiveCode,
this.isMerged,
this.isNeedUserAgreement,
this.isSMSSent,
this.memberList,
this.message,
this.statusCode});
CheckActivationCode({
this.date,
this.languageId,
this.serviceName,
this.time,
this.androidLink,
this.authenticationTokenId,
this.data,
this.dataw,
this.dietType,
this.dietTypeId,
this.errorCode,
this.errorEndUserMessage,
this.errorEndUserMessageN,
this.errorMessage,
this.errorStatusCode,
this.errorType,
this.foodCategory,
this.iosLink,
this.isAuthenticated,
this.mealOrderStatus,
this.mealType,
this.messageStatus,
this.numberOfResultRecords,
this.patientBlodType,
this.successMsg,
this.successMsgN,
this.vidaUpdatedResponse,
this.doctorInformationList,
this.getAllPendingRecordsList,
this.getAllSharedRecordsByStatusList,
this.getMaritalstatusLst,
this.getOccupationLst,
this.getResponseFileList,
this.hisPatientModelVpPortal,
this.isHmgPatient,
this.isLoginSuccessfully,
this.isNeedUpdateIdintificationNo,
this.isPatientAuthorized,
this.isVidaPlus,
this.kioskSendSms,
this.list,
this.listAskHabibMobileLoginInfo,
this.listAskHabibPatientFile,
this.listFamilyRelationships,
this.listMergeFiles,
this.listMobileLoginInfo,
this.listPatientCount,
this.logInTokenId,
this.mohemmPrivilegeList,
this.pateintId,
this.patientBloodType,
this.patientErAdminDriverFileList,
this.patientErAdminFile,
this.patientErDriverFile,
this.patientErDriverFileList,
this.patientHasFile,
this.patientMergedIDs,
this.patientOutSa,
this.patientShareRequestId,
this.patientType,
this.projectIdOut,
this.returnMessage,
this.smsLoginRequired,
this.servicePrivilegeList,
this.sharePatientName,
this.userAccountIsActivated,
this.verificationCode,
this.email,
this.errorList,
this.hasFile,
this.isActiveCode,
this.isMerged,
this.isNeedUserAgreement,
this.isSmsSent,
this.memberList,
this.message,
this.statusCode,
});
factory CheckActivationCode.fromRawJson(String str) => CheckActivationCode.fromJson(json.decode(str));
CheckActivationCode.fromJson(Map<String, dynamic> json) {
date = json['Date'];
languageID = json['LanguageID'];
serviceName = json['ServiceName'];
time = json['Time'];
androidLink = json['AndroidLink'];
authenticationTokenID = json['AuthenticationTokenID'];
data = json['Data'];
dataw = json['Dataw'];
dietType = json['DietType'];
errorCode = json['ErrorCode'];
errorEndUserMessage = json['ErrorEndUserMessage'];
errorEndUserMessageN = json['ErrorEndUserMessageN'];
errorMessage = json['ErrorMessage'];
errorType = json['ErrorType'];
foodCategory = json['FoodCategory'];
iOSLink = json['IOSLink'];
isAuthenticated = json['IsAuthenticated'];
mealOrderStatus = json['MealOrderStatus'];
mealType = json['MealType'];
messageStatus = json['MessageStatus'];
numberOfResultRecords = json['NumberOfResultRecords'];
patientBlodType = json['PatientBlodType'];
successMsg = json['SuccessMsg'];
successMsgN = json['SuccessMsgN'];
doctorInformationList = json['DoctorInformation_List'];
getAllPendingRecordsList = json['GetAllPendingRecordsList'];
getAllSharedRecordsByStatusList = json['GetAllSharedRecordsByStatusList'];
getResponseFileList = json['GetResponseFileList'];
isHMGPatient = json['IsHMGPatient'];
isLoginSuccessfully = json['IsLoginSuccessfully'];
isNeedUpdateIdintificationNo = json['IsNeedUpdateIdintificationNo'];
kioskSendSMS = json['KioskSendSMS'];
if (json['List'] != null) {
list = AuthenticatedUser.fromJson(json['List'][0]);
}
listAskHabibMobileLoginInfo = json['List_AskHabibMobileLoginInfo'];
listAskHabibPatientFile = json['List_AskHabibPatientFile'];
listMergeFiles = json['List_MergeFiles'];
listMobileLoginInfo = json['List_MobileLoginInfo'];
listPatientCount = json['List_PatientCount'];
logInTokenID = json['LogInTokenID'];
mohemmPrivilegeList = json['MohemmPrivilege_List'];
pateintID = json['PateintID'];
patientBloodType = json['PatientBloodType'];
patientHasFile = json['PatientHasFile'];
patientMergedIDs = json['PatientMergedIDs'];
patientOutSA = json['PatientOutSA'];
patientShareRequestID = json['PatientShareRequestID'];
patientType = json['PatientType'];
projectIDOut = json['ProjectIDOut'];
returnMessage = json['ReturnMessage'];
sMSLoginRequired = json['SMSLoginRequired'];
servicePrivilegeList = json['ServicePrivilege_List'];
sharePatientName = json['SharePatientName'];
verificationCode = json['VerificationCode'];
email = json['email'];
errorList = json['errorList'];
hasFile = json['hasFile'];
isActiveCode = json['isActiveCode'];
isMerged = json['isMerged'];
isNeedUserAgreement = json['isNeedUserAgreement'];
isSMSSent = json['isSMSSent'];
memberList = json['memberList'];
message = json['message'];
statusCode = json['statusCode'];
}
String toRawJson() => json.encode(toJson());
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['Date'] = date;
data['LanguageID'] = languageID;
data['ServiceName'] = serviceName;
data['Time'] = time;
data['AndroidLink'] = androidLink;
data['AuthenticationTokenID'] = authenticationTokenID;
data['Data'] = this.data;
data['Dataw'] = dataw;
data['DietType'] = dietType;
data['ErrorCode'] = errorCode;
data['ErrorEndUserMessage'] = errorEndUserMessage;
data['ErrorEndUserMessageN'] = errorEndUserMessageN;
data['ErrorMessage'] = errorMessage;
data['ErrorType'] = errorType;
data['FoodCategory'] = foodCategory;
data['IOSLink'] = iOSLink;
data['IsAuthenticated'] = isAuthenticated;
data['MealOrderStatus'] = mealOrderStatus;
data['MealType'] = mealType;
data['MessageStatus'] = messageStatus;
data['NumberOfResultRecords'] = numberOfResultRecords;
data['PatientBlodType'] = patientBlodType;
data['SuccessMsg'] = successMsg;
data['SuccessMsgN'] = successMsgN;
data['DoctorInformation_List'] = doctorInformationList;
data['GetAllPendingRecordsList'] = getAllPendingRecordsList;
data['GetAllSharedRecordsByStatusList'] = getAllSharedRecordsByStatusList;
data['GetResponseFileList'] = getResponseFileList;
data['IsHMGPatient'] = isHMGPatient;
data['IsLoginSuccessfully'] = isLoginSuccessfully;
data['IsNeedUpdateIdintificationNo'] = isNeedUpdateIdintificationNo;
data['KioskSendSMS'] = kioskSendSMS;
if (list != null) {
data['List'] = list;
}
data['List_AskHabibMobileLoginInfo'] = listAskHabibMobileLoginInfo;
data['List_AskHabibPatientFile'] = listAskHabibPatientFile;
data['List_MergeFiles'] = listMergeFiles;
data['List_MobileLoginInfo'] = listMobileLoginInfo;
data['List_PatientCount'] = listPatientCount;
data['LogInTokenID'] = logInTokenID;
data['MohemmPrivilege_List'] = mohemmPrivilegeList;
data['PateintID'] = pateintID;
data['PatientBloodType'] = patientBloodType;
data['PatientHasFile'] = patientHasFile;
data['PatientMergedIDs'] = patientMergedIDs;
data['PatientOutSA'] = patientOutSA;
data['PatientShareRequestID'] = patientShareRequestID;
data['PatientType'] = patientType;
data['ProjectIDOut'] = projectIDOut;
data['ReturnMessage'] = returnMessage;
data['SMSLoginRequired'] = sMSLoginRequired;
data['ServicePrivilege_List'] = servicePrivilegeList;
data['SharePatientName'] = sharePatientName;
data['VerificationCode'] = verificationCode;
data['email'] = email;
data['errorList'] = errorList;
data['hasFile'] = hasFile;
data['isActiveCode'] = isActiveCode;
data['isMerged'] = isMerged;
data['isNeedUserAgreement'] = isNeedUserAgreement;
data['isSMSSent'] = isSMSSent;
data['memberList'] = memberList;
data['message'] = message;
data['statusCode'] = statusCode;
return data;
}
factory CheckActivationCode.fromJson(Map<String, dynamic> json) => CheckActivationCode(
date: json["Date"],
languageId: json["LanguageID"],
serviceName: json["ServiceName"],
time: json["Time"],
androidLink: json["AndroidLink"],
authenticationTokenId: json["AuthenticationTokenID"],
data: json["Data"],
dataw: json["Dataw"],
dietType: json["DietType"],
dietTypeId: json["DietTypeID"],
errorCode: json["ErrorCode"],
errorEndUserMessage: json["ErrorEndUserMessage"],
errorEndUserMessageN: json["ErrorEndUserMessageN"],
errorMessage: json["ErrorMessage"],
errorStatusCode: json["ErrorStatusCode"],
errorType: json["ErrorType"],
foodCategory: json["FoodCategory"],
iosLink: json["IOSLink"],
isAuthenticated: json["IsAuthenticated"],
mealOrderStatus: json["MealOrderStatus"],
mealType: json["MealType"],
messageStatus: json["MessageStatus"],
numberOfResultRecords: json["NumberOfResultRecords"],
patientBlodType: json["PatientBlodType"],
successMsg: json["SuccessMsg"],
successMsgN: json["SuccessMsgN"],
vidaUpdatedResponse: json["VidaUpdatedResponse"],
doctorInformationList: json["DoctorInformation_List"],
getAllPendingRecordsList: json["GetAllPendingRecordsList"],
getAllSharedRecordsByStatusList: json["GetAllSharedRecordsByStatusList"],
getMaritalstatusLst: json["GetMaritalstatusLst"],
getOccupationLst: json["GetOccupationLst"],
getResponseFileList: json["GetResponseFileList"],
hisPatientModelVpPortal: json["HIS_PatientModel_VPPortal"],
isHmgPatient: json["IsHMGPatient"],
isLoginSuccessfully: json["IsLoginSuccessfully"],
isNeedUpdateIdintificationNo: json["IsNeedUpdateIdintificationNo"],
isPatientAuthorized: json["IsPatientAuthorized"],
isVidaPlus: json["IsVidaPlus"],
kioskSendSms: json["KioskSendSMS"],
list: json["List"] == null ? [] : List<AuthenticatedUser>.from(json["List"]!.map((x) => AuthenticatedUser.fromJson(x))),
listAskHabibMobileLoginInfo: json["List_AskHabibMobileLoginInfo"],
listAskHabibPatientFile: json["List_AskHabibPatientFile"],
listFamilyRelationships: json["List_FamilyRelationships"],
listMergeFiles: json["List_MergeFiles"],
listMobileLoginInfo: json["List_MobileLoginInfo"],
listPatientCount: json["List_PatientCount"],
logInTokenId: json["LogInTokenID"],
mohemmPrivilegeList: json["MohemmPrivilege_List"],
pateintId: json["PateintID"],
patientBloodType: json["PatientBloodType"],
patientErAdminDriverFileList: json["PatientER_AdminDriverFileList"],
patientErAdminFile: json["PatientER_AdminFile"],
patientErDriverFile: json["PatientER_DriverFile"],
patientErDriverFileList: json["PatientER_DriverFileList"],
patientHasFile: json["PatientHasFile"],
patientMergedIDs: json["PatientMergedIDs"],
patientOutSa: json["PatientOutSA"],
patientShareRequestId: json["PatientShareRequestID"],
patientType: json["PatientType"],
projectIdOut: json["ProjectIDOut"],
returnMessage: json["ReturnMessage"],
smsLoginRequired: json["SMSLoginRequired"],
servicePrivilegeList: json["ServicePrivilege_List"],
sharePatientName: json["SharePatientName"],
userAccountIsActivated: json["UserAccountIsActivated"],
verificationCode: json["VerificationCode"],
email: json["email"],
errorList: json["errorList"],
hasFile: json["hasFile"],
isActiveCode: json["isActiveCode"],
isMerged: json["isMerged"],
isNeedUserAgreement: json["isNeedUserAgreement"],
isSmsSent: json["isSMSSent"],
memberList: json["memberList"],
message: json["message"],
statusCode: json["statusCode"],
);
Map<String, dynamic> toJson() => {
"Date": date,
"LanguageID": languageId,
"ServiceName": serviceName,
"Time": time,
"AndroidLink": androidLink,
"AuthenticationTokenID": authenticationTokenId,
"Data": data,
"Dataw": dataw,
"DietType": dietType,
"DietTypeID": dietTypeId,
"ErrorCode": errorCode,
"ErrorEndUserMessage": errorEndUserMessage,
"ErrorEndUserMessageN": errorEndUserMessageN,
"ErrorMessage": errorMessage,
"ErrorStatusCode": errorStatusCode,
"ErrorType": errorType,
"FoodCategory": foodCategory,
"IOSLink": iosLink,
"IsAuthenticated": isAuthenticated,
"MealOrderStatus": mealOrderStatus,
"MealType": mealType,
"MessageStatus": messageStatus,
"NumberOfResultRecords": numberOfResultRecords,
"PatientBlodType": patientBlodType,
"SuccessMsg": successMsg,
"SuccessMsgN": successMsgN,
"VidaUpdatedResponse": vidaUpdatedResponse,
"DoctorInformation_List": doctorInformationList,
"GetAllPendingRecordsList": getAllPendingRecordsList,
"GetAllSharedRecordsByStatusList": getAllSharedRecordsByStatusList,
"GetMaritalstatusLst": getMaritalstatusLst,
"GetOccupationLst": getOccupationLst,
"GetResponseFileList": getResponseFileList,
"HIS_PatientModel_VPPortal": hisPatientModelVpPortal,
"IsHMGPatient": isHmgPatient,
"IsLoginSuccessfully": isLoginSuccessfully,
"IsNeedUpdateIdintificationNo": isNeedUpdateIdintificationNo,
"IsPatientAuthorized": isPatientAuthorized,
"IsVidaPlus": isVidaPlus,
"KioskSendSMS": kioskSendSms,
"List": list == null ? [] : List<AuthenticatedUser>.from(list!.map((x) => x.toJson())),
"List_AskHabibMobileLoginInfo": listAskHabibMobileLoginInfo,
"List_AskHabibPatientFile": listAskHabibPatientFile,
"List_FamilyRelationships": listFamilyRelationships,
"List_MergeFiles": listMergeFiles,
"List_MobileLoginInfo": listMobileLoginInfo,
"List_PatientCount": listPatientCount,
"LogInTokenID": logInTokenId,
"MohemmPrivilege_List": mohemmPrivilegeList,
"PateintID": pateintId,
"PatientBloodType": patientBloodType,
"PatientER_AdminDriverFileList": patientErAdminDriverFileList,
"PatientER_AdminFile": patientErAdminFile,
"PatientER_DriverFile": patientErDriverFile,
"PatientER_DriverFileList": patientErDriverFileList,
"PatientHasFile": patientHasFile,
"PatientMergedIDs": patientMergedIDs,
"PatientOutSA": patientOutSa,
"PatientShareRequestID": patientShareRequestId,
"PatientType": patientType,
"ProjectIDOut": projectIdOut,
"ReturnMessage": returnMessage,
"SMSLoginRequired": smsLoginRequired,
"ServicePrivilege_List": servicePrivilegeList,
"SharePatientName": sharePatientName,
"UserAccountIsActivated": userAccountIsActivated,
"VerificationCode": verificationCode,
"email": email,
"errorList": errorList,
"hasFile": hasFile,
"isActiveCode": isActiveCode,
"isMerged": isMerged,
"isNeedUserAgreement": isNeedUserAgreement,
"isSMSSent": isSmsSent,
"memberList": memberList,
"message": message,
"statusCode": statusCode,
};
}
class ListElement {
String? setupId;
int? patientType;
int? patientId;
String? firstName;
String? middleName;
String? lastName;
String? firstNameN;
String? middleNameN;
String? lastNameN;
int? relationshipId;
int? gender;
String? dateofBirth;
dynamic dateofBirthN;
String? nationalityId;
String? phoneResi;
String? phoneOffice;
String? mobileNumber;
String? faxNumber;
String? emailAddress;
dynamic bloodGroup;
dynamic rhFactor;
bool? isEmailAlertRequired;
bool? isSmsAlertRequired;
String? preferredLanguage;
bool? isPrivilegedMember;
dynamic memberId;
dynamic expiryDate;
dynamic isHmgEmployee;
dynamic employeeId;
String? emergencyContactName;
String? emergencyContactNo;
int? patientPayType;
dynamic dhccPatientRefId;
bool? isPatientDummy;
int? status;
dynamic isStatusCleared;
int? patientIdentificationType;
String? patientIdentificationNo;
int? projectId;
int? infoSourceId;
dynamic address;
int? age;
String? ageDesc;
int? areaId;
int? crsVerificationStatus;
String? crsVerificationStatusDesc;
String? crsVerificationStatusDescN;
int? createdBy;
String? genderDescription;
String? healthIdFromNhicViaVida;
dynamic ir;
dynamic isoCityId;
dynamic isoCountryId;
bool? isVerfiedFromNhic;
List<ListPrivilege>? listPrivilege;
dynamic marital;
dynamic occupationId;
int? outSa;
dynamic poBox;
bool? receiveHealthSummaryReport;
int? sourceType;
dynamic strDateofBirth;
dynamic tempAddress;
dynamic zipCode;
dynamic eHealthIdField;
dynamic listPatientPayType;
dynamic listPatientType;
dynamic listStatus;
ListElement({
this.setupId,
this.patientType,
this.patientId,
this.firstName,
this.middleName,
this.lastName,
this.firstNameN,
this.middleNameN,
this.lastNameN,
this.relationshipId,
this.gender,
this.dateofBirth,
this.dateofBirthN,
this.nationalityId,
this.phoneResi,
this.phoneOffice,
this.mobileNumber,
this.faxNumber,
this.emailAddress,
this.bloodGroup,
this.rhFactor,
this.isEmailAlertRequired,
this.isSmsAlertRequired,
this.preferredLanguage,
this.isPrivilegedMember,
this.memberId,
this.expiryDate,
this.isHmgEmployee,
this.employeeId,
this.emergencyContactName,
this.emergencyContactNo,
this.patientPayType,
this.dhccPatientRefId,
this.isPatientDummy,
this.status,
this.isStatusCleared,
this.patientIdentificationType,
this.patientIdentificationNo,
this.projectId,
this.infoSourceId,
this.address,
this.age,
this.ageDesc,
this.areaId,
this.crsVerificationStatus,
this.crsVerificationStatusDesc,
this.crsVerificationStatusDescN,
this.createdBy,
this.genderDescription,
this.healthIdFromNhicViaVida,
this.ir,
this.isoCityId,
this.isoCountryId,
this.isVerfiedFromNhic,
this.listPrivilege,
this.marital,
this.occupationId,
this.outSa,
this.poBox,
this.receiveHealthSummaryReport,
this.sourceType,
this.strDateofBirth,
this.tempAddress,
this.zipCode,
this.eHealthIdField,
this.listPatientPayType,
this.listPatientType,
this.listStatus,
});
factory ListElement.fromRawJson(String str) => ListElement.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory ListElement.fromJson(Map<String, dynamic> json) => ListElement(
setupId: json["SetupID"],
patientType: json["PatientType"],
patientId: json["PatientID"],
firstName: json["FirstName"],
middleName: json["MiddleName"],
lastName: json["LastName"],
firstNameN: json["FirstNameN"],
middleNameN: json["MiddleNameN"],
lastNameN: json["LastNameN"],
relationshipId: json["RelationshipID"],
gender: json["Gender"],
dateofBirth: json["DateofBirth"],
dateofBirthN: json["DateofBirthN"],
nationalityId: json["NationalityID"],
phoneResi: json["PhoneResi"],
phoneOffice: json["PhoneOffice"],
mobileNumber: json["MobileNumber"],
faxNumber: json["FaxNumber"],
emailAddress: json["EmailAddress"],
bloodGroup: json["BloodGroup"],
rhFactor: json["RHFactor"],
isEmailAlertRequired: json["IsEmailAlertRequired"],
isSmsAlertRequired: json["IsSMSAlertRequired"],
preferredLanguage: json["PreferredLanguage"],
isPrivilegedMember: json["IsPrivilegedMember"],
memberId: json["MemberID"],
expiryDate: json["ExpiryDate"],
isHmgEmployee: json["IsHmgEmployee"],
employeeId: json["EmployeeID"],
emergencyContactName: json["EmergencyContactName"],
emergencyContactNo: json["EmergencyContactNo"],
patientPayType: json["PatientPayType"],
dhccPatientRefId: json["DHCCPatientRefID"],
isPatientDummy: json["IsPatientDummy"],
status: json["Status"],
isStatusCleared: json["IsStatusCleared"],
patientIdentificationType: json["PatientIdentificationType"],
patientIdentificationNo: json["PatientIdentificationNo"],
projectId: json["ProjectID"],
infoSourceId: json["InfoSourceID"],
address: json["Address"],
age: json["Age"],
ageDesc: json["AgeDesc"],
areaId: json["AreaID"],
crsVerificationStatus: json["CRSVerificationStatus"],
crsVerificationStatusDesc: json["CRSVerificationStatusDesc"],
crsVerificationStatusDescN: json["CRSVerificationStatusDescN"],
createdBy: json["CreatedBy"],
genderDescription: json["GenderDescription"],
healthIdFromNhicViaVida: json["HealthIDFromNHICViaVida"],
ir: json["IR"],
isoCityId: json["ISOCityID"],
isoCountryId: json["ISOCountryID"],
isVerfiedFromNhic: json["IsVerfiedFromNHIC"],
listPrivilege: json["ListPrivilege"] == null ? [] : List<ListPrivilege>.from(json["ListPrivilege"]!.map((x) => ListPrivilege.fromJson(x))),
marital: json["Marital"],
occupationId: json["OccupationID"],
outSa: json["OutSA"],
poBox: json["POBox"],
receiveHealthSummaryReport: json["ReceiveHealthSummaryReport"],
sourceType: json["SourceType"],
strDateofBirth: json["StrDateofBirth"],
tempAddress: json["TempAddress"],
zipCode: json["ZipCode"],
eHealthIdField: json["eHealthIDField"],
listPatientPayType: json["patientPayType"],
listPatientType: json["patientType"],
listStatus: json["status"],
);
Map<String, dynamic> toJson() => {
"SetupID": setupId,
"PatientType": patientType,
"PatientID": patientId,
"FirstName": firstName,
"MiddleName": middleName,
"LastName": lastName,
"FirstNameN": firstNameN,
"MiddleNameN": middleNameN,
"LastNameN": lastNameN,
"RelationshipID": relationshipId,
"Gender": gender,
"DateofBirth": dateofBirth,
"DateofBirthN": dateofBirthN,
"NationalityID": nationalityId,
"PhoneResi": phoneResi,
"PhoneOffice": phoneOffice,
"MobileNumber": mobileNumber,
"FaxNumber": faxNumber,
"EmailAddress": emailAddress,
"BloodGroup": bloodGroup,
"RHFactor": rhFactor,
"IsEmailAlertRequired": isEmailAlertRequired,
"IsSMSAlertRequired": isSmsAlertRequired,
"PreferredLanguage": preferredLanguage,
"IsPrivilegedMember": isPrivilegedMember,
"MemberID": memberId,
"ExpiryDate": expiryDate,
"IsHmgEmployee": isHmgEmployee,
"EmployeeID": employeeId,
"EmergencyContactName": emergencyContactName,
"EmergencyContactNo": emergencyContactNo,
"PatientPayType": patientPayType,
"DHCCPatientRefID": dhccPatientRefId,
"IsPatientDummy": isPatientDummy,
"Status": status,
"IsStatusCleared": isStatusCleared,
"PatientIdentificationType": patientIdentificationType,
"PatientIdentificationNo": patientIdentificationNo,
"ProjectID": projectId,
"InfoSourceID": infoSourceId,
"Address": address,
"Age": age,
"AgeDesc": ageDesc,
"AreaID": areaId,
"CRSVerificationStatus": crsVerificationStatus,
"CRSVerificationStatusDesc": crsVerificationStatusDesc,
"CRSVerificationStatusDescN": crsVerificationStatusDescN,
"CreatedBy": createdBy,
"GenderDescription": genderDescription,
"HealthIDFromNHICViaVida": healthIdFromNhicViaVida,
"IR": ir,
"ISOCityID": isoCityId,
"ISOCountryID": isoCountryId,
"IsVerfiedFromNHIC": isVerfiedFromNhic,
"ListPrivilege": listPrivilege == null ? [] : List<dynamic>.from(listPrivilege!.map((x) => x.toJson())),
"Marital": marital,
"OccupationID": occupationId,
"OutSA": outSa,
"POBox": poBox,
"ReceiveHealthSummaryReport": receiveHealthSummaryReport,
"SourceType": sourceType,
"StrDateofBirth": strDateofBirth,
"TempAddress": tempAddress,
"ZipCode": zipCode,
"eHealthIDField": eHealthIdField,
"patientPayType": listPatientPayType,
"patientType": listPatientType,
"status": listStatus,
};
}
class ListPrivilege {
int? iD;
int? id;
String? serviceName;
bool? previlege;
dynamic region;
ListPrivilege({this.iD, this.serviceName, this.previlege, this.region});
ListPrivilege({
this.id,
this.serviceName,
this.previlege,
this.region,
});
factory ListPrivilege.fromRawJson(String str) => ListPrivilege.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
ListPrivilege.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
serviceName = json['ServiceName'];
previlege = json['Previlege'];
region = json['Region'];
}
factory ListPrivilege.fromJson(Map<String, dynamic> json) => ListPrivilege(
id: json["ID"],
serviceName: json["ServiceName"],
previlege: json["Previlege"],
region: json["Region"],
);
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['ID'] = iD;
data['ServiceName'] = serviceName;
data['Previlege'] = previlege;
data['Region'] = region;
return data;
}
Map<String, dynamic> toJson() => {
"ID": id,
"ServiceName": serviceName,
"Previlege": previlege,
"Region": region,
};
}

@ -0,0 +1,381 @@
import 'dart:convert';
class CheckUserStatusResponseNHIC {
dynamic date;
int? languageId;
int? serviceName;
dynamic time;
dynamic androidLink;
dynamic authenticationTokenId;
dynamic data;
bool? dataw;
int? dietType;
int? dietTypeId;
dynamic errorCode;
dynamic errorEndUserMessage;
dynamic errorEndUserMessageN;
dynamic errorMessage;
int? errorStatusCode;
int? errorType;
int? foodCategory;
dynamic iosLink;
bool? isAuthenticated;
int? mealOrderStatus;
int? mealType;
int? messageStatus;
int? numberOfResultRecords;
dynamic patientBlodType;
dynamic successMsg;
dynamic successMsgN;
dynamic vidaUpdatedResponse;
dynamic accessTokenObject;
int? age;
dynamic clientIdentifierId;
int? createdBy;
String? dateOfBirth;
String? firstNameAr;
String? firstNameEn;
String? gender;
dynamic genderAr;
dynamic genderEn;
String? healthId;
String? idNumber;
String? idType;
bool? isHijri;
int? isInstertedOrUpdated;
int? isNull;
int? isPatientExistNhic;
bool? isRecordLockedByCurrentUser;
String? lastNameAr;
String? lastNameEn;
dynamic listActiveAccessToken;
String? maritalStatus;
String? maritalStatusCode;
String? nationalDateOfBirth;
String? nationality;
String? nationalityCode;
String? occupation;
dynamic pcdTransactionDataResultList;
dynamic pcdGetVidaPatientForManualVerificationList;
dynamic pcdNhicHmgPatientDetailsMatchCalulationList;
int? pcdReturnValue;
dynamic patientStatus;
String? placeofBirth;
dynamic practitionerStatusCode;
dynamic practitionerStatusDescAr;
dynamic practitionerStatusDescEn;
int? rowCount;
String? secondNameAr;
String? secondNameEn;
String? thirdNameAr;
String? thirdNameEn;
dynamic yakeenDoctorDataGetSourceList;
dynamic yakeenVidaPatientDataStatisticsByPatientIdList;
dynamic yakeenVidaPatientDataStatisticsList;
dynamic yakeenVidaPatientDataStatisticsPrefferedList;
dynamic accessToken;
int? categoryCode;
dynamic categoryNameAr;
dynamic categoryNameEn;
int? constraintCode;
dynamic constraintNameAr;
dynamic constraintNameEn;
dynamic content;
dynamic errorList;
dynamic licenseExpiryDate;
dynamic licenseIssuedDate;
dynamic licenseStatusCode;
dynamic licenseStatusDescAr;
dynamic licenseStatusDescEn;
dynamic organizations;
dynamic registrationNumber;
int? specialtyCode;
dynamic specialtyNameAr;
dynamic specialtyNameEn;
CheckUserStatusResponseNHIC({
this.date,
this.languageId,
this.serviceName,
this.time,
this.androidLink,
this.authenticationTokenId,
this.data,
this.dataw,
this.dietType,
this.dietTypeId,
this.errorCode,
this.errorEndUserMessage,
this.errorEndUserMessageN,
this.errorMessage,
this.errorStatusCode,
this.errorType,
this.foodCategory,
this.iosLink,
this.isAuthenticated,
this.mealOrderStatus,
this.mealType,
this.messageStatus,
this.numberOfResultRecords,
this.patientBlodType,
this.successMsg,
this.successMsgN,
this.vidaUpdatedResponse,
this.accessTokenObject,
this.age,
this.clientIdentifierId,
this.createdBy,
this.dateOfBirth,
this.firstNameAr,
this.firstNameEn,
this.gender,
this.genderAr,
this.genderEn,
this.healthId,
this.idNumber,
this.idType,
this.isHijri,
this.isInstertedOrUpdated,
this.isNull,
this.isPatientExistNhic,
this.isRecordLockedByCurrentUser,
this.lastNameAr,
this.lastNameEn,
this.listActiveAccessToken,
this.maritalStatus,
this.maritalStatusCode,
this.nationalDateOfBirth,
this.nationality,
this.nationalityCode,
this.occupation,
this.pcdTransactionDataResultList,
this.pcdGetVidaPatientForManualVerificationList,
this.pcdNhicHmgPatientDetailsMatchCalulationList,
this.pcdReturnValue,
this.patientStatus,
this.placeofBirth,
this.practitionerStatusCode,
this.practitionerStatusDescAr,
this.practitionerStatusDescEn,
this.rowCount,
this.secondNameAr,
this.secondNameEn,
this.thirdNameAr,
this.thirdNameEn,
this.yakeenDoctorDataGetSourceList,
this.yakeenVidaPatientDataStatisticsByPatientIdList,
this.yakeenVidaPatientDataStatisticsList,
this.yakeenVidaPatientDataStatisticsPrefferedList,
this.accessToken,
this.categoryCode,
this.categoryNameAr,
this.categoryNameEn,
this.constraintCode,
this.constraintNameAr,
this.constraintNameEn,
this.content,
this.errorList,
this.licenseExpiryDate,
this.licenseIssuedDate,
this.licenseStatusCode,
this.licenseStatusDescAr,
this.licenseStatusDescEn,
this.organizations,
this.registrationNumber,
this.specialtyCode,
this.specialtyNameAr,
this.specialtyNameEn,
});
factory CheckUserStatusResponseNHIC.fromRawJson(String str) => CheckUserStatusResponseNHIC.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory CheckUserStatusResponseNHIC.fromJson(Map<String, dynamic> json) => CheckUserStatusResponseNHIC(
date: json["Date"],
languageId: json["LanguageID"],
serviceName: json["ServiceName"],
time: json["Time"],
androidLink: json["AndroidLink"],
authenticationTokenId: json["AuthenticationTokenID"],
data: json["Data"],
dataw: json["Dataw"],
dietType: json["DietType"],
dietTypeId: json["DietTypeID"],
errorCode: json["ErrorCode"],
errorEndUserMessage: json["ErrorEndUserMessage"],
errorEndUserMessageN: json["ErrorEndUserMessageN"],
errorMessage: json["ErrorMessage"],
errorStatusCode: json["ErrorStatusCode"],
errorType: json["ErrorType"],
foodCategory: json["FoodCategory"],
iosLink: json["IOSLink"],
isAuthenticated: json["IsAuthenticated"],
mealOrderStatus: json["MealOrderStatus"],
mealType: json["MealType"],
messageStatus: json["MessageStatus"],
numberOfResultRecords: json["NumberOfResultRecords"],
patientBlodType: json["PatientBlodType"],
successMsg: json["SuccessMsg"],
successMsgN: json["SuccessMsgN"],
vidaUpdatedResponse: json["VidaUpdatedResponse"],
accessTokenObject: json["AccessTokenObject"],
age: json["Age"],
clientIdentifierId: json["ClientIdentifierId"],
createdBy: json["CreatedBy"],
dateOfBirth: json["DateOfBirth"],
firstNameAr: json["FirstNameAr"],
firstNameEn: json["FirstNameEn"],
gender: json["Gender"],
genderAr: json["GenderAr"],
genderEn: json["GenderEn"],
healthId: json["HealthId"],
idNumber: json["IdNumber"],
idType: json["IdType"],
isHijri: json["IsHijri"],
isInstertedOrUpdated: json["IsInstertedOrUpdated"],
isNull: json["IsNull"],
isPatientExistNhic: json["IsPatientExistNHIC"],
isRecordLockedByCurrentUser: json["IsRecordLockedByCurrentUser"],
lastNameAr: json["LastNameAr"],
lastNameEn: json["LastNameEn"],
listActiveAccessToken: json["List_ActiveAccessToken"],
maritalStatus: json["MaritalStatus"],
maritalStatusCode: json["MaritalStatusCode"],
nationalDateOfBirth: json["NationalDateOfBirth"],
nationality: json["Nationality"],
nationalityCode: json["NationalityCode"],
occupation: json["Occupation"],
pcdTransactionDataResultList: json["PCDTransactionDataResultList"],
pcdGetVidaPatientForManualVerificationList: json["PCD_GetVidaPatientForManualVerificationList"],
pcdNhicHmgPatientDetailsMatchCalulationList: json["PCD_NHIC_HMG_PatientDetailsMatchCalulationList"],
pcdReturnValue: json["PCD_ReturnValue"],
patientStatus: json["PatientStatus"],
placeofBirth: json["PlaceofBirth"],
practitionerStatusCode: json["PractitionerStatusCode"],
practitionerStatusDescAr: json["PractitionerStatusDescAr"],
practitionerStatusDescEn: json["PractitionerStatusDescEn"],
rowCount: json["RowCount"],
secondNameAr: json["SecondNameAr"],
secondNameEn: json["SecondNameEn"],
thirdNameAr: json["ThirdNameAr"],
thirdNameEn: json["ThirdNameEn"],
yakeenDoctorDataGetSourceList: json["YakeenDoctorData_GetSourceList"],
yakeenVidaPatientDataStatisticsByPatientIdList: json["YakeenVidaPatientDataStatisticsByPatientIdList"],
yakeenVidaPatientDataStatisticsList: json["YakeenVidaPatientDataStatisticsList"],
yakeenVidaPatientDataStatisticsPrefferedList: json["YakeenVidaPatientDataStatisticsPrefferedList"],
accessToken: json["accessToken"],
categoryCode: json["categoryCode"],
categoryNameAr: json["categoryNameAr"],
categoryNameEn: json["categoryNameEn"],
constraintCode: json["constraintCode"],
constraintNameAr: json["constraintNameAr"],
constraintNameEn: json["constraintNameEn"],
content: json["content"],
errorList: json["errorList"],
licenseExpiryDate: json["licenseExpiryDate"],
licenseIssuedDate: json["licenseIssuedDate"],
licenseStatusCode: json["licenseStatusCode"],
licenseStatusDescAr: json["licenseStatusDescAr"],
licenseStatusDescEn: json["licenseStatusDescEn"],
organizations: json["organizations"],
registrationNumber: json["registrationNumber"],
specialtyCode: json["specialtyCode"],
specialtyNameAr: json["specialtyNameAr"],
specialtyNameEn: json["specialtyNameEn"],
);
Map<String, dynamic> toJson() => {
"Date": date,
"LanguageID": languageId,
"ServiceName": serviceName,
"Time": time,
"AndroidLink": androidLink,
"AuthenticationTokenID": authenticationTokenId,
"Data": data,
"Dataw": dataw,
"DietType": dietType,
"DietTypeID": dietTypeId,
"ErrorCode": errorCode,
"ErrorEndUserMessage": errorEndUserMessage,
"ErrorEndUserMessageN": errorEndUserMessageN,
"ErrorMessage": errorMessage,
"ErrorStatusCode": errorStatusCode,
"ErrorType": errorType,
"FoodCategory": foodCategory,
"IOSLink": iosLink,
"IsAuthenticated": isAuthenticated,
"MealOrderStatus": mealOrderStatus,
"MealType": mealType,
"MessageStatus": messageStatus,
"NumberOfResultRecords": numberOfResultRecords,
"PatientBlodType": patientBlodType,
"SuccessMsg": successMsg,
"SuccessMsgN": successMsgN,
"VidaUpdatedResponse": vidaUpdatedResponse,
"AccessTokenObject": accessTokenObject,
"Age": age,
"ClientIdentifierId": clientIdentifierId,
"CreatedBy": createdBy,
"DateOfBirth": dateOfBirth,
"FirstNameAr": firstNameAr,
"FirstNameEn": firstNameEn,
"Gender": gender,
"GenderAr": genderAr,
"GenderEn": genderEn,
"HealthId": healthId,
"IdNumber": idNumber,
"IdType": idType,
"IsHijri": isHijri,
"IsInstertedOrUpdated": isInstertedOrUpdated,
"IsNull": isNull,
"IsPatientExistNHIC": isPatientExistNhic,
"IsRecordLockedByCurrentUser": isRecordLockedByCurrentUser,
"LastNameAr": lastNameAr,
"LastNameEn": lastNameEn,
"List_ActiveAccessToken": listActiveAccessToken,
"MaritalStatus": maritalStatus,
"MaritalStatusCode": maritalStatusCode,
"NationalDateOfBirth": nationalDateOfBirth,
"Nationality": nationality,
"NationalityCode": nationalityCode,
"Occupation": occupation,
"PCDTransactionDataResultList": pcdTransactionDataResultList,
"PCD_GetVidaPatientForManualVerificationList": pcdGetVidaPatientForManualVerificationList,
"PCD_NHIC_HMG_PatientDetailsMatchCalulationList": pcdNhicHmgPatientDetailsMatchCalulationList,
"PCD_ReturnValue": pcdReturnValue,
"PatientStatus": patientStatus,
"PlaceofBirth": placeofBirth,
"PractitionerStatusCode": practitionerStatusCode,
"PractitionerStatusDescAr": practitionerStatusDescAr,
"PractitionerStatusDescEn": practitionerStatusDescEn,
"RowCount": rowCount,
"SecondNameAr": secondNameAr,
"SecondNameEn": secondNameEn,
"ThirdNameAr": thirdNameAr,
"ThirdNameEn": thirdNameEn,
"YakeenDoctorData_GetSourceList": yakeenDoctorDataGetSourceList,
"YakeenVidaPatientDataStatisticsByPatientIdList": yakeenVidaPatientDataStatisticsByPatientIdList,
"YakeenVidaPatientDataStatisticsList": yakeenVidaPatientDataStatisticsList,
"YakeenVidaPatientDataStatisticsPrefferedList": yakeenVidaPatientDataStatisticsPrefferedList,
"accessToken": accessToken,
"categoryCode": categoryCode,
"categoryNameAr": categoryNameAr,
"categoryNameEn": categoryNameEn,
"constraintCode": constraintCode,
"constraintNameAr": constraintNameAr,
"constraintNameEn": constraintNameEn,
"content": content,
"errorList": errorList,
"licenseExpiryDate": licenseExpiryDate,
"licenseIssuedDate": licenseIssuedDate,
"licenseStatusCode": licenseStatusCode,
"licenseStatusDescAr": licenseStatusDescAr,
"licenseStatusDescEn": licenseStatusDescEn,
"organizations": organizations,
"registrationNumber": registrationNumber,
"specialtyCode": specialtyCode,
"specialtyNameAr": specialtyNameAr,
"specialtyNameEn": specialtyNameEn,
};
}

@ -218,11 +218,12 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
final otp = _controllers.map((c) => c.text).join();
debugPrint('Verifying OTP: $otp');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Verifying OTP: $otp')),
);
widget.checkActivationCode(int.parse(otp));
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(content: Text('Verifying OTP: $otp')),
// );
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => RegisterNewStep2(null, {"nationalID": "12345678654321"})));
// Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => RegisterNewStep2(null, {"nationalID": "12345678654321"})));
}
/// Auto fill OTP into text fields

@ -0,0 +1,73 @@
import 'dart:convert';
class CommonAuthanticatedRequest {
String? sessionId;
double? versionId;
int? channel;
int? languageId;
String? ipAdress;
String? generalid;
double? latitude;
double? longitude;
int? deviceTypeId;
int? patientType;
int? patientTypeId;
String? tokenId;
int? patientId;
int? patientOutSa;
CommonAuthanticatedRequest({
this.sessionId,
this.versionId,
this.channel,
this.languageId,
this.ipAdress,
this.generalid,
this.latitude,
this.longitude,
this.deviceTypeId,
this.patientType,
this.patientTypeId,
this.tokenId,
this.patientId,
this.patientOutSa,
});
factory CommonAuthanticatedRequest.fromRawJson(String str) => CommonAuthanticatedRequest.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory CommonAuthanticatedRequest.fromJson(Map<String, dynamic> json) => CommonAuthanticatedRequest(
sessionId: json["SessionID"],
versionId: json["VersionID"]?.toDouble(),
channel: json["Channel"],
languageId: json["LanguageID"],
ipAdress: json["IPAdress"],
generalid: json["generalid"],
latitude: json["Latitude"],
longitude: json["Longitude"],
deviceTypeId: json["DeviceTypeID"],
patientType: json["PatientType"],
patientTypeId: json["PatientTypeID"],
tokenId: json["TokenID"],
patientId: json["PatientID"],
patientOutSa: json["PatientOutSA"],
);
Map<String, dynamic> toJson() => {
"SessionID": sessionId,
"VersionID": versionId,
"Channel": channel,
"LanguageID": languageId,
"IPAdress": ipAdress,
"generalid": generalid,
"Latitude": latitude,
"Longitude": longitude,
"DeviceTypeID": deviceTypeId,
"PatientType": patientType,
"PatientTypeID": patientTypeId,
"TokenID": tokenId,
"PatientID": patientId,
"PatientOutSA": patientOutSa,
};
}

@ -11,7 +11,8 @@ class LabViewModel extends ChangeNotifier {
ErrorHandlerService errorHandlerService;
List<PatientLabOrdersResponseModel> patientLabOrders = [];
List<PatientLabOrdersResponseModel> filteredLabOrders = [];
List<PatientLabOrdersResponseModel> tempLabOrdersList = [];
late List<String> _labSuggestionsList = [];
List<String> get labSuggestions => _labSuggestionsList;
@ -20,6 +21,7 @@ class LabViewModel extends ChangeNotifier {
initLabProvider() {
patientLabOrders.clear();
filteredLabOrders.clear();
isLabOrdersLoading = true;
isLabResultsLoading = true;
getPatientLabOrders();
@ -36,6 +38,8 @@ class LabViewModel extends ChangeNotifier {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
patientLabOrders = apiResponse.data!;
filteredLabOrders = List.from(patientLabOrders);
tempLabOrdersList = apiResponse.data!;
isLabOrdersLoading = false;
isLabResultsLoading = false;
filterSuggestions();
@ -48,14 +52,27 @@ class LabViewModel extends ChangeNotifier {
);
}
filterSuggestions(){
filterSuggestions() {
final List<String> labels = patientLabOrders
.expand((order) => order.testDetails!) // flatten testDetails
.map((detail) => detail.description) // pick description
.whereType<String>() // remove nulls if any
.expand((order) => order.testDetails!)
.map((detail) => detail.description)
.whereType<String>()
.toList();
_labSuggestionsList = labels.toSet().toList(); // remove duplicates by converting to a set and back to a list
_labSuggestionsList = labels.toSet().toList();
notifyListeners();
}
filterLabReports(String query) {
if (query.isEmpty) {
filteredLabOrders = List.from(patientLabOrders); // reset
} else {
filteredLabOrders = patientLabOrders.where((order) {
final descriptions = order.testDetails?.map((d) => d.description?.toLowerCase()).toList() ?? [];
return descriptions.any((desc) => desc != null && desc.contains(query.toLowerCase()));
}).toList();
patientLabOrders = filteredLabOrders;
}
notifyListeners();
}
}

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
class MedicalFileViewModel extends ChangeNotifier {
int selectedTabIndex = 0;
void onTabChanged(int index) {
selectedTabIndex = index;
notifyListeners();
}
}

@ -0,0 +1,311 @@
class PatientAppointmentHistoryResponseModel {
String? setupID;
dynamic projectID;
dynamic appointmentNo;
String? appointmentDate;
dynamic appointmentDateN;
dynamic appointmentType;
String? bookDate;
dynamic patientType;
dynamic patientID;
dynamic clinicID;
dynamic doctorID;
String? endDate;
String? startTime;
String? endTime;
dynamic status;
dynamic visitType;
dynamic visitFor;
dynamic patientStatusType;
dynamic companyID;
dynamic bookedBy;
String? bookedOn;
dynamic confirmedBy;
dynamic confirmedOn;
dynamic arrivalChangedBy;
dynamic arrivedOn;
dynamic editedBy;
dynamic editedOn;
dynamic doctorName;
dynamic doctorNameN;
String? statusDesc;
dynamic statusDescN;
bool? vitalStatus;
dynamic vitalSignAppointmentNo;
dynamic episodeID;
dynamic actualDoctorRate;
String? clinicName;
bool? complainExists;
String? doctorImageURL;
String? doctorNameObj;
dynamic doctorRate;
dynamic decimalDoctorRate;
List<String>? doctorSpeciality;
String? doctorTitle;
dynamic gender;
String? genderDescription;
bool? iSAllowOnlineCheckedIN;
bool? isActiveDoctor;
bool? isActiveDoctorProfile;
bool? isDoctorAllowVedioCall;
bool? isExecludeDoctor;
dynamic isFollowup;
bool? isLiveCareAppointment;
bool? isInOutPatient;
bool? isMedicalReportRequested;
bool? isOnlineCheckedIN;
String? latitude;
dynamic listHISGetContactLensPerscription;
dynamic listHISGetGlassPerscription;
String? longitude;
dynamic nextAction;
dynamic noOfPatientsRate;
dynamic originalClinicID;
dynamic originalProjectID;
String? projectName;
String? qR;
int? remaniningHoursTocanPay;
bool? sMSButtonVisable;
dynamic serviceID;
String? isInOutPatientDescription;
String? isInOutPatientDescriptionN;
bool? hasReminder;
num? patientShare;
num? patientShareWithTax;
num? patientTaxAmount;
PatientAppointmentHistoryResponseModel({
this.setupID,
this.projectID,
this.appointmentNo,
this.appointmentDate,
this.appointmentDateN,
this.appointmentType,
this.bookDate,
this.patientType,
this.patientID,
this.clinicID,
this.doctorID,
this.endDate,
this.startTime,
this.endTime,
this.status,
this.visitType,
this.visitFor,
this.patientStatusType,
this.companyID,
this.bookedBy,
this.bookedOn,
this.confirmedBy,
this.confirmedOn,
this.arrivalChangedBy,
this.arrivedOn,
this.editedBy,
this.editedOn,
this.doctorName,
this.doctorNameN,
this.statusDesc,
this.statusDescN,
this.vitalStatus,
this.vitalSignAppointmentNo,
this.episodeID,
this.actualDoctorRate,
this.clinicName,
this.complainExists,
this.doctorImageURL,
this.doctorNameObj,
this.doctorRate,
this.decimalDoctorRate,
this.doctorSpeciality,
this.doctorTitle,
this.gender,
this.genderDescription,
this.iSAllowOnlineCheckedIN,
this.isActiveDoctor,
this.isActiveDoctorProfile,
this.isDoctorAllowVedioCall,
this.isExecludeDoctor,
this.isFollowup,
this.isLiveCareAppointment,
this.isMedicalReportRequested,
this.isOnlineCheckedIN,
this.latitude,
this.listHISGetContactLensPerscription,
this.listHISGetGlassPerscription,
this.longitude,
this.nextAction,
this.noOfPatientsRate,
this.originalClinicID,
this.originalProjectID,
this.projectName,
this.qR,
this.remaniningHoursTocanPay,
this.sMSButtonVisable,
this.serviceID,
this.isInOutPatientDescription,
this.isInOutPatientDescriptionN,
this.hasReminder = false,
this.patientShare,
this.patientShareWithTax,
this.patientTaxAmount,
});
PatientAppointmentHistoryResponseModel.fromJson(Map<String, dynamic> json) {
setupID = json['SetupID'];
projectID = json['ProjectID'];
appointmentNo = json['AppointmentNo'];
appointmentDate = json['AppointmentDate'];
appointmentDateN = json['AppointmentDateN'];
appointmentType = json['AppointmentType'];
bookDate = json['BookDate'];
patientType = json['PatientType'];
patientID = json['PatientID'];
clinicID = json['ClinicID'];
doctorID = json['DoctorID'];
endDate = json['EndDate'];
startTime = json['StartTime'];
endTime = json['EndTime'];
status = json['Status'];
visitType = json['VisitType'];
visitFor = json['VisitFor'];
patientStatusType = json['PatientStatusType'];
companyID = json['CompanyID'];
bookedBy = json['BookedBy'];
bookedOn = json['BookedOn'];
confirmedBy = json['ConfirmedBy'];
confirmedOn = json['ConfirmedOn'];
arrivalChangedBy = json['ArrivalChangedBy'];
arrivedOn = json['ArrivedOn'];
editedBy = json['EditedBy'];
editedOn = json['EditedOn'];
doctorName = json['DoctorName'];
doctorNameN = json['DoctorNameN'];
statusDesc = json['StatusDesc'];
statusDescN = json['StatusDescN'];
vitalStatus = json['VitalStatus'];
vitalSignAppointmentNo = json['VitalSignAppointmentNo'];
episodeID = json['EpisodeID'];
actualDoctorRate = json['ActualDoctorRate'];
clinicName = json['ClinicName'];
complainExists = json['ComplainExists'];
doctorImageURL = json['DoctorImageURL'];
doctorNameObj = json['DoctorNameObj'];
doctorRate = json['DoctorRate'];
decimalDoctorRate = json['DecimalDoctorRate'];
doctorSpeciality = json['DoctorSpeciality'] != null ? json['DoctorSpeciality'].cast<String>() : ["null"];
doctorTitle = json['DoctorTitle'];
gender = json['Gender'];
genderDescription = json['GenderDescription'];
iSAllowOnlineCheckedIN = json['ISAllowOnlineCheckedIN'];
isActiveDoctor = json['IsActiveDoctor'];
isActiveDoctorProfile = json['IsActiveDoctorProfile'];
isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall'];
isExecludeDoctor = json['IsExecludeDoctor'];
isFollowup = json['IsFollowup'];
isLiveCareAppointment = json['IsLiveCareAppointment'];
isInOutPatient = json['IsInOutPatient'];
isMedicalReportRequested = json['IsMedicalReportRequested'];
isOnlineCheckedIN = json['IsOnlineCheckedIN'];
latitude = json['Latitude'];
listHISGetContactLensPerscription = json['List_HIS_GetContactLensPerscription'];
listHISGetGlassPerscription = json['List_HIS_GetGlassPerscription'];
longitude = json['Longitude'];
nextAction = json['NextAction'];
noOfPatientsRate = json['NoOfPatientsRate'];
originalClinicID = json['OriginalClinicID'];
originalProjectID = json['OriginalProjectID'];
projectName = json['ProjectName'];
qR = json['QR'];
remaniningHoursTocanPay = json['RemaniningHoursTocanPay'];
sMSButtonVisable = json['SMSButtonVisable'];
serviceID = json['ServiceID'];
isInOutPatientDescription = json['IsInOutPatientDescription'];
isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN'];
hasReminder = false;
patientShare = json['PatientShare'];
patientShareWithTax = json['PatientShareWithTax'];
patientTaxAmount = json['PatientTaxAmount'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['SetupID'] = this.setupID;
data['ProjectID'] = this.projectID;
data['AppointmentNo'] = this.appointmentNo;
data['AppointmentDate'] = this.appointmentDate;
data['AppointmentDateN'] = this.appointmentDateN;
data['AppointmentType'] = this.appointmentType;
data['BookDate'] = this.bookDate;
data['PatientType'] = this.patientType;
data['PatientID'] = this.patientID;
data['ClinicID'] = this.clinicID;
data['DoctorID'] = this.doctorID;
data['EndDate'] = this.endDate;
data['StartTime'] = this.startTime;
data['EndTime'] = this.endTime;
data['Status'] = this.status;
data['VisitType'] = this.visitType;
data['VisitFor'] = this.visitFor;
data['PatientStatusType'] = this.patientStatusType;
data['CompanyID'] = this.companyID;
data['BookedBy'] = this.bookedBy;
data['BookedOn'] = this.bookedOn;
data['ConfirmedBy'] = this.confirmedBy;
data['ConfirmedOn'] = this.confirmedOn;
data['ArrivalChangedBy'] = this.arrivalChangedBy;
data['ArrivedOn'] = this.arrivedOn;
data['EditedBy'] = this.editedBy;
data['EditedOn'] = this.editedOn;
data['DoctorName'] = this.doctorName;
data['DoctorNameN'] = this.doctorNameN;
data['StatusDesc'] = this.statusDesc;
data['StatusDescN'] = this.statusDescN;
data['VitalStatus'] = this.vitalStatus;
data['VitalSignAppointmentNo'] = this.vitalSignAppointmentNo;
data['EpisodeID'] = this.episodeID;
data['ActualDoctorRate'] = this.actualDoctorRate;
data['ClinicName'] = this.clinicName;
data['ComplainExists'] = this.complainExists;
data['DoctorImageURL'] = this.doctorImageURL;
data['DoctorNameObj'] = this.doctorNameObj;
data['DoctorRate'] = this.doctorRate;
data['DecimalDoctorRate'] = this.decimalDoctorRate;
data['DoctorSpeciality'] = this.doctorSpeciality;
data['DoctorTitle'] = this.doctorTitle;
data['Gender'] = this.gender;
data['GenderDescription'] = this.genderDescription;
data['ISAllowOnlineCheckedIN'] = this.iSAllowOnlineCheckedIN;
data['IsActiveDoctor'] = this.isActiveDoctor;
data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile;
data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall;
data['IsExecludeDoctor'] = this.isExecludeDoctor;
data['IsFollowup'] = this.isFollowup;
data['IsLiveCareAppointment'] = this.isLiveCareAppointment;
data['IsInOutPatient'] = this.isInOutPatient;
data['IsMedicalReportRequested'] = this.isMedicalReportRequested;
data['IsOnlineCheckedIN'] = this.isOnlineCheckedIN;
data['Latitude'] = this.latitude;
data['List_HIS_GetContactLensPerscription'] = this.listHISGetContactLensPerscription;
data['List_HIS_GetGlassPerscription'] = this.listHISGetGlassPerscription;
data['Longitude'] = this.longitude;
data['NextAction'] = this.nextAction;
data['NoOfPatientsRate'] = this.noOfPatientsRate;
data['OriginalClinicID'] = this.originalClinicID;
data['OriginalProjectID'] = this.originalProjectID;
data['ProjectName'] = this.projectName;
data['QR'] = this.qR;
data['RemaniningHoursTocanPay'] = this.remaniningHoursTocanPay;
data['SMSButtonVisable'] = this.sMSButtonVisable;
data['ServiceID'] = this.serviceID;
return data;
}
}
class PatientAppointmentList {
String? filterName = "";
List<PatientAppointmentHistoryResponseModel>? patientDoctorAppointmentList = [];
PatientAppointmentList({this.filterName, PatientAppointmentHistoryResponseModel? patientDoctorAppointment}) {
patientDoctorAppointmentList!.add(patientDoctorAppointment!);
}
}

@ -0,0 +1,253 @@
class PatientAppointmentShareResponseModel {
dynamic advanceNumber;
dynamic advanceNumberVP;
String? appointmentDate;
int? appointmentNo;
dynamic cardNumber;
dynamic cardType;
int? cashPrice;
int? cashPriceTax;
int? cashPriceWithTax;
int? clinicID;
String? clinicName;
int? companyId;
String? companyName;
int? companyShareWithTax;
int? doctorID;
String? doctorImageURL;
String? doctorNameObj;
List<String>? doctorSpeciality;
dynamic errCode;
int? groupID;
bool? iSAllowOnlineCheckedIN;
String? insurancePolicyNo;
bool? isAppointmentPackaged;
bool? isCash;
bool? isEligible;
bool? isExcludedForOnlineCheckin;
int? isFollowup;
bool? isInsured;
bool? isLiveCareAppointment;
bool? isOnlineCheckedIN;
String? message;
int? nextAction;
dynamic orderId;
String? patientCardID;
int? patientID;
num? patientShare;
num? patientShareWithTax;
int? patientStatusType;
num? patientTaxAmount;
String? patientType;
int? paymentAmount;
String? paymentDate;
dynamic paymentMethodName;
dynamic paymentReferenceNumber;
int? policyId;
String? policyName;
String? procedureName;
int? projectID;
String? projectName;
dynamic rRN;
int? serviceID;
dynamic setupID;
int? sourceType;
String? startTime;
int? status;
int? statusCode;
dynamic statusDesc;
String? subPolicyNo;
int? tax;
int? userID;
PatientAppointmentShareResponseModel({
this.advanceNumber,
this.advanceNumberVP,
this.appointmentDate,
this.appointmentNo,
this.cardNumber,
this.cardType,
this.cashPrice,
this.cashPriceTax,
this.cashPriceWithTax,
this.clinicID,
this.clinicName,
this.companyId,
this.companyName,
this.companyShareWithTax,
this.doctorID,
this.doctorImageURL,
this.doctorNameObj,
this.doctorSpeciality,
this.errCode,
this.groupID,
this.iSAllowOnlineCheckedIN,
this.insurancePolicyNo,
this.isAppointmentPackaged,
this.isCash,
this.isEligible,
this.isExcludedForOnlineCheckin,
this.isFollowup,
this.isInsured,
this.isLiveCareAppointment,
this.isOnlineCheckedIN,
this.message,
this.nextAction,
this.orderId,
this.patientCardID,
this.patientID,
this.patientShare,
this.patientShareWithTax,
this.patientStatusType,
this.patientTaxAmount,
this.patientType,
this.paymentAmount,
this.paymentDate,
this.paymentMethodName,
this.paymentReferenceNumber,
this.policyId,
this.policyName,
this.procedureName,
this.projectID,
this.projectName,
this.rRN,
this.serviceID,
this.setupID,
this.sourceType,
this.startTime,
this.status,
this.statusCode,
this.statusDesc,
this.subPolicyNo,
this.tax,
this.userID,
});
PatientAppointmentShareResponseModel.fromJson(Map<String, dynamic> json) {
advanceNumber = json['AdvanceNumber'];
advanceNumberVP = json['AdvanceNumber_VP'];
appointmentDate = json['AppointmentDate'];
appointmentNo = json['AppointmentNo'];
cardNumber = json['CardNumber'];
cardType = json['CardType'];
cashPrice = json['CashPrice'];
cashPriceTax = json['CashPriceTax'];
cashPriceWithTax = json['CashPriceWithTax'];
clinicID = json['ClinicID'];
clinicName = json['ClinicName'];
companyId = json['CompanyId'];
companyName = json['CompanyName'];
companyShareWithTax = json['CompanyShareWithTax'];
doctorID = json['DoctorID'];
doctorImageURL = json['DoctorImageURL'];
doctorNameObj = json['DoctorNameObj'];
doctorSpeciality = json['DoctorSpeciality'].cast<String>();
errCode = json['ErrCode'];
groupID = json['GroupID'];
iSAllowOnlineCheckedIN = json['ISAllowOnlineCheckedIN'];
insurancePolicyNo = json['InsurancePolicyNo'];
isAppointmentPackaged = json['IsAppointmentPackaged'];
isCash = json['IsCash'];
isEligible = json['IsEligible'];
isExcludedForOnlineCheckin = json['IsExcludedForOnlineCheckin'];
isFollowup = json['IsFollowup'];
isInsured = json['IsInsured'];
isLiveCareAppointment = json['IsLiveCareAppointment'];
isOnlineCheckedIN = json['IsOnlineCheckedIN'];
message = json['Message'];
nextAction = json['NextAction'];
orderId = json['OrderId'];
patientCardID = json['PatientCardID'];
patientID = json['PatientID'];
patientShare = json['PatientShare'];
patientShareWithTax = json['PatientShareWithTax'];
patientStatusType = json['PatientStatusType'];
patientTaxAmount = json['PatientTaxAmount'];
patientType = json['PatientType'];
paymentAmount = json['PaymentAmount'];
paymentDate = json['PaymentDate'];
paymentMethodName = json['PaymentMethodName'];
paymentReferenceNumber = json['PaymentReferenceNumber'];
policyId = json['PolicyId'];
policyName = json['PolicyName'];
procedureName = json['ProcedureName'];
projectID = json['ProjectID'];
projectName = json['ProjectName'];
rRN = json['RRN'];
serviceID = json['ServiceID'];
setupID = json['SetupID'];
sourceType = json['SourceType'];
startTime = json['StartTime'];
status = json['Status'];
statusCode = json['StatusCode'];
statusDesc = json['StatusDesc'];
subPolicyNo = json['SubPolicyNo'];
tax = json['Tax'];
userID = json['UserID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['AdvanceNumber'] = this.advanceNumber;
data['AdvanceNumber_VP'] = this.advanceNumberVP;
data['AppointmentDate'] = this.appointmentDate;
data['AppointmentNo'] = this.appointmentNo;
data['CardNumber'] = this.cardNumber;
data['CardType'] = this.cardType;
data['CashPrice'] = this.cashPrice;
data['CashPriceTax'] = this.cashPriceTax;
data['CashPriceWithTax'] = this.cashPriceWithTax;
data['ClinicID'] = this.clinicID;
data['ClinicName'] = this.clinicName;
data['CompanyId'] = this.companyId;
data['CompanyName'] = this.companyName;
data['CompanyShareWithTax'] = this.companyShareWithTax;
data['DoctorID'] = this.doctorID;
data['DoctorImageURL'] = this.doctorImageURL;
data['DoctorNameObj'] = this.doctorNameObj;
data['DoctorSpeciality'] = this.doctorSpeciality;
data['ErrCode'] = this.errCode;
data['GroupID'] = this.groupID;
data['ISAllowOnlineCheckedIN'] = this.iSAllowOnlineCheckedIN;
data['InsurancePolicyNo'] = this.insurancePolicyNo;
data['IsAppointmentPackaged'] = this.isAppointmentPackaged;
data['IsCash'] = this.isCash;
data['IsEligible'] = this.isEligible;
data['IsExcludedForOnlineCheckin'] = this.isExcludedForOnlineCheckin;
data['IsFollowup'] = this.isFollowup;
data['IsInsured'] = this.isInsured;
data['IsLiveCareAppointment'] = this.isLiveCareAppointment;
data['IsOnlineCheckedIN'] = this.isOnlineCheckedIN;
data['Message'] = this.message;
data['NextAction'] = this.nextAction;
data['OrderId'] = this.orderId;
data['PatientCardID'] = this.patientCardID;
data['PatientID'] = this.patientID;
data['PatientShare'] = this.patientShare;
data['PatientShareWithTax'] = this.patientShareWithTax;
data['PatientStatusType'] = this.patientStatusType;
data['PatientTaxAmount'] = this.patientTaxAmount;
data['PatientType'] = this.patientType;
data['PaymentAmount'] = this.paymentAmount;
data['PaymentDate'] = this.paymentDate;
data['PaymentMethodName'] = this.paymentMethodName;
data['PaymentReferenceNumber'] = this.paymentReferenceNumber;
data['PolicyId'] = this.policyId;
data['PolicyName'] = this.policyName;
data['ProcedureName'] = this.procedureName;
data['ProjectID'] = this.projectID;
data['ProjectName'] = this.projectName;
data['RRN'] = this.rRN;
data['ServiceID'] = this.serviceID;
data['SetupID'] = this.setupID;
data['SourceType'] = this.sourceType;
data['StartTime'] = this.startTime;
data['Status'] = this.status;
data['StatusCode'] = this.statusCode;
data['StatusDesc'] = this.statusDesc;
data['SubPolicyNo'] = this.subPolicyNo;
data['Tax'] = this.tax;
data['UserID'] = this.userID;
return data;
}
}

@ -1,11 +1,32 @@
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_exception.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class MyAppointmentsRepo {
Future<Either<Failure, dynamic>> getMyAppointments();
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointments(
{required String patientId, required bool isActiveAppointment, required bool isArrivedAppointments});
Future<Either<Failure, GenericApiModel<PatientAppointmentShareResponseModel>>> getPatientShareAppointment(
{required String patientId, required int projectID, required int clinicID, required String appointmentNo});
Future<Either<Failure, GenericApiModel<dynamic>>> createAdvancePayment(
{required String paymentMethodName,
required int projectID,
required int clinicID,
required String appointmentNo,
required num payedAmount,
required String paymentReference,
required String patientID,
required int patientType});
Future<Either<Failure, GenericApiModel<dynamic>>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference, required String appointmentNo});
Future<Either<Failure, GenericApiModel<dynamic>>> generateAppointmentQR({required String clinicID, required String projectID, required String appointmentNo, required int isFollowUp});
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@ -15,57 +36,245 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
MyAppointmentsRepoImp({required this.loggerService, required this.apiClient});
@override
Future<Either<Failure, dynamic>> getMyAppointments() async {
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointments(
{required String patientId, required bool isActiveAppointment, required bool isArrivedAppointments}) async {
final mapDevice = {
"IsActiveAppointment": isActiveAppointment,
"isDentalAllowedBackend": false,
"PatientTypeID": 1,
"IsComingFromCOC": false,
"PatientType": 1,
"isForUpcomming": false,
"IsForArrived": isArrivedAppointments,
"PatientOutSA": 0
};
try {
// Mock API call with delayed response
final result = await Future.delayed(
const Duration(seconds: 2),
() => {
'success': true,
'data': [
{
'id': '1',
'doctorName': 'Dr. Ahmed Hassan',
'specialty': 'Cardiology',
'appointmentDate': '2025-09-05',
'appointmentTime': '10:00 AM',
'status': 'confirmed',
'clinicName': 'HMG Hospital',
'patientName': 'John Doe'
},
{
'id': '2',
'doctorName': 'Dr. Sarah Johnson',
'specialty': 'Dermatology',
'appointmentDate': '2025-09-08',
'appointmentTime': '2:30 PM',
'status': 'pending',
'clinicName': 'HMG Medical Center',
'patientName': 'John Doe'
},
{
'id': '3',
'doctorName': 'Dr. Mohamed Ali',
'specialty': 'Pediatrics',
'appointmentDate': '2025-08-25',
'appointmentTime': '11:15 AM',
'status': 'completed',
'clinicName': 'HMG Children\'s Clinic',
'patientName': 'John Doe'
}
]
GenericApiModel<List<PatientAppointmentHistoryResponseModel>>? apiResponse;
Failure? failure;
await apiClient.post(
GET_PATIENT_APPOINTMENT_HISTORY,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['AppoimentAllHistoryResultList'];
if (list == null || list.isEmpty) {
throw Exception("Appointments list is empty");
}
final appointmentsList = list.map((item) => PatientAppointmentHistoryResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientAppointmentHistoryResponseModel>();
apiResponse = GenericApiModel<List<PatientAppointmentHistoryResponseModel>>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: appointmentsList,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<PatientAppointmentShareResponseModel>>> getPatientShareAppointment(
{required String patientId, required int projectID, required int clinicID, required String appointmentNo}) async {
final mapRequest = {
"ProjectID": projectID,
"ClinicID": clinicID,
"AppointmentNo": appointmentNo,
"IsActiveAppointment": true,
"PatientOutSA": 0,
"isDentalAllowedBackend": false,
"PatientID": patientId,
"PatientTypeID": 1,
"PatientType": 1,
};
if (result != null && result is Map && result['success'] != null && result['success'] != false) {
return Right(result);
} else {
loggerService.errorLogs(result.toString());
return Left(ServerFailure(result.toString()));
try {
GenericApiModel<PatientAppointmentShareResponseModel>? apiResponse;
Failure? failure;
await apiClient.post(
GET_PATIENT_SHARE,
body: mapRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['OnlineCheckInAppointments'];
if (list == null || list.isEmpty) {
throw Exception("patient share list is empty");
}
final patientShareObj = PatientAppointmentShareResponseModel.fromJson(list[0]);
patientShareObj.isCash = response["IsCash"];
patientShareObj.isEligible = response["IsEligible"];
patientShareObj.isInsured = response["IsInsured"];
apiResponse = GenericApiModel<PatientAppointmentShareResponseModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: patientShareObj,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
throw UnimplementedError();
}
@override
Future<Either<Failure, GenericApiModel>> createAdvancePayment({
required String paymentMethodName,
required int projectID,
required int clinicID,
required String appointmentNo,
required num payedAmount,
required String paymentReference,
required String patientID,
required int patientType,
}) async {
final requestBody = {
"ProjectID": projectID,
"OnlineCheckInAppointment": {
"AppointmentNo": appointmentNo,
"PaymentMethodName": paymentMethodName,
"PaymentAmount": payedAmount == 0 ? "0" : payedAmount.toString(),
"PaymentDate": payedAmount == 0 ? "" : "/Date(${DateTime.now().millisecondsSinceEpoch})/",
"PaymentReferenceNumber": payedAmount == 0 ? "" : paymentReference,
"ProjectID": projectID,
"PatientID": patientID,
"ClinicID": clinicID,
"UserID": patientID,
"Status": patientType
}
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
CREATE_ADVANCE_PAYMENT,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference, required String appointmentNo}) async {
final requestBody = {
"AdvanceNumber": advanceNumber,
"AdvanceNumber_VP": advanceNumber,
"PaymentReferenceNumber": paymentReference,
"AppointmentID": appointmentNo,
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ADD_ADVANCE_NUMBER_REQUEST,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> generateAppointmentQR({required String clinicID, required String projectID, required String appointmentNo, required int isFollowUp}) async {
final requestBody = {
"AppointmentNo": appointmentNo,
"ClinicID": clinicID,
"ProjectID": projectID,
"IsFollowup": isFollowUp,
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
GENERATE_QR_APPOINTMENT,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
loggerService.errorLogs(e.toString());
return Left(ServerFailure(e.toString()));
return Left(UnknownFailure(e.toString()));
}
}
}

@ -0,0 +1,164 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
class MyAppointmentsViewModel extends ChangeNotifier {
int selectedTabIndex = 0;
MyAppointmentsRepo myAppointmentsRepo;
ErrorHandlerService errorHandlerService;
bool isMyAppointmentsLoading = false;
bool isAppointmentPatientShareLoading = false;
List<PatientAppointmentHistoryResponseModel> patientAppointmentsHistoryList = [];
PatientAppointmentShareResponseModel? patientAppointmentShareResponseModel;
MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService});
void onTabChange(int index) {
selectedTabIndex = index;
notifyListeners();
}
initAppointmentsViewModel() {
patientAppointmentsHistoryList.clear();
isMyAppointmentsLoading = true;
isAppointmentPatientShareLoading = true;
notifyListeners();
}
setIsAppointmentsHistoryLoading(bool val) {
isMyAppointmentsLoading = val;
notifyListeners();
}
setIsPatientAppointmentShareLoading(bool val) {
isAppointmentPatientShareLoading = val;
notifyListeners();
}
setAppointmentReminder(bool value, PatientAppointmentHistoryResponseModel item) {
int index = patientAppointmentsHistoryList.indexOf(item);
if (index != -1) {
patientAppointmentsHistoryList[index].hasReminder = value;
notifyListeners();
}
}
Future<void> getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.getPatientAppointments(patientId: "3628599", isActiveAppointment: isActiveAppointment, isArrivedAppointments: isArrivedAppointments);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
patientAppointmentsHistoryList = apiResponse.data!;
isMyAppointmentsLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.getPatientShareAppointment(patientId: "3628599", projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
patientAppointmentShareResponseModel = apiResponse.data!;
isAppointmentPatientShareLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> addAdvanceNumberRequest(
{required String advanceNumber, required String paymentReference, required String appointmentNo, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> generateAppointmentQR(
{required String clinicID, required String projectID, required String appointmentNo, required int isFollowUp, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.generateAppointmentQR(clinicID: clinicID, projectID: projectID, appointmentNo: appointmentNo, isFollowUp: isFollowUp);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> createAdvancePayment(
{required String paymentMethodName,
required int projectID,
required int clinicID,
required String appointmentNo,
required num payedAmount,
required String paymentReference,
required String patientID,
required int patientType,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result = await myAppointmentsRepo.createAdvancePayment(
paymentMethodName: paymentMethodName,
projectID: projectID,
clinicID: clinicID,
appointmentNo: appointmentNo,
payedAmount: payedAmount,
paymentReference: paymentReference,
patientID: patientID,
patientType: patientType);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
}

@ -0,0 +1,102 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class AppointmentType {
static var BOOKED = 0;
static const BOOKED_STR = 'booked';
static var CONFIRMED = 42;
static const CONFIRMED_STR = 'confirmed';
static var ARRIVED = 43;
static const ARRIVED_STR = 'arrived';
static bool isConfirmed(PatientAppointmentHistoryResponseModel appo) {
return AppointmentType.isValid(appo) && appo.patientStatusType == AppointmentType.CONFIRMED;
}
static bool isBooked(PatientAppointmentHistoryResponseModel appo) {
return AppointmentType.isValid(appo) && appo.patientStatusType == AppointmentType.BOOKED;
}
static bool isArrived(PatientAppointmentHistoryResponseModel appo) {
return AppointmentType.isValid(appo) && appo.patientStatusType == AppointmentType.ARRIVED;
}
static isValid(appo) {
return appo != null && appo.patientStatusType != null;
}
static String getAppointmentStatusType(int appoStatus) {
switch (appoStatus) {
case 0:
return LocaleKeys.booked.tr();
case 42:
return LocaleKeys.confirmed.tr();
case 43:
return LocaleKeys.arrived.tr();
default:
return LocaleKeys.booked.tr();
}
}
static Color getNextActionButtonColor(nextAction) {
switch (nextAction) {
case 0:
return AppColors.successColor;
case 10:
return AppColors.successColor;
case 15:
return AppColors.greyColor;
case 20:
return AppColors.infoColor;
case 50:
return AppColors.successColor;
case 90:
return AppColors.alertColor;
default:
return AppColors.successColor;
}
}
static String getNextActionText(nextAction) {
switch (nextAction) {
case 0:
return "No Action".needTranslation;
case 10:
return LocaleKeys.confirm.tr();
case 15:
return LocaleKeys.pendingPayment.tr();
case 20:
return LocaleKeys.payNow.tr();
case 50:
return LocaleKeys.confirmLiveCare.tr();
case 90:
return LocaleKeys.checkinOption.tr();
default:
return "No Action".needTranslation;
}
}
static String getNextActionIcon(nextAction) {
switch (nextAction) {
case 0:
return AppAssets.checkmark_icon;
case 10:
return AppAssets.confirm_appointment_icon;
case 15:
return AppAssets.appointment_pay_icon;
case 20:
return AppAssets.appointment_pay_icon;
case 50:
return AppAssets.confirm_appointment_icon;
case 90:
return AppAssets.appointment_checkin_icon;
default:
return AppAssets.checkmark_icon;
}
}
}

@ -0,0 +1,187 @@
class ApplePayInsertRequest {
String? clientRequestID;
int? clinicID;
String? currency;
String? customerEmail;
dynamic customerID;
String? customerName;
String? deviceToken;
String? voipToken;
int? doctorID;
String? projectID;
String? serviceID;
int? channelID;
dynamic patientID;
int? patientTypeID;
int? patientOutSA;
dynamic appointmentDate;
int? appointmentNo;
String? orderDescription;
String? liveServiceID;
String? latitude;
String? longitude;
String? amount;
String? isSchedule;
String? language;
int? userName;
String? responseContinueURL;
String? backClickUrl;
String? paymentOption;
double? versionID;
int? channel;
int? languageID;
String? iPAdress;
String? generalid;
String? sessionID;
bool? isDentalAllowedBackend;
int? deviceTypeID;
bool? isMobSDK;
String? merchantReference;
String? merchantIdentifier;
String? commandType;
String? signature;
String? accessCode;
String? shaRequestPhrase;
String? shaResponsePhrase;
String? returnURL;
ApplePayInsertRequest(
{this.clientRequestID,
this.clinicID,
this.currency,
this.customerEmail,
this.customerID,
this.customerName,
this.deviceToken,
this.voipToken,
this.doctorID,
this.projectID,
this.serviceID,
this.channelID,
this.patientID,
this.patientTypeID,
this.patientOutSA,
this.appointmentDate,
this.appointmentNo,
this.orderDescription,
this.liveServiceID,
this.latitude,
this.longitude,
this.amount,
this.isSchedule,
this.language,
this.userName,
this.responseContinueURL,
this.backClickUrl,
this.paymentOption,
this.versionID,
this.channel,
this.languageID,
this.iPAdress,
this.generalid,
this.sessionID,
this.isDentalAllowedBackend,
this.deviceTypeID,
this.isMobSDK,
this.merchantReference,
this.merchantIdentifier,
this.commandType,
this.signature,
this.accessCode,
this.shaRequestPhrase,
this.shaResponsePhrase,
this.returnURL,
});
ApplePayInsertRequest.fromJson(Map<String, dynamic> json) {
clientRequestID = json['ClientRequestID'];
clinicID = json['ClinicID'];
currency = json['Currency'];
customerEmail = json['CustomerEmail'];
customerID = json['CustomerID'];
customerName = json['CustomerName'];
deviceToken = json['DeviceToken'];
voipToken = json['VoipToken'];
doctorID = json['DoctorID'];
projectID = json['ProjectID'];
serviceID = json['Service_ID'];
channelID = json['Channel_ID'];
patientID = json['PatientID'];
patientTypeID = json['PatientTypeID'];
patientOutSA = json['PatientOutSA'];
appointmentDate = json['AppointmentDate'];
appointmentNo = json['AppointmentNo'];
orderDescription = json['OrderDescription'];
liveServiceID = json['Live_ServiceID'];
latitude = json['Latitude'];
longitude = json['Longitude'];
amount = json['Amount'];
isSchedule = json['IsSchedule'];
language = json['Language'];
userName = json['userName'];
responseContinueURL = json['ResponseContinueURL'];
backClickUrl = json['BackClickUrl'];
paymentOption = json['PaymentOption'];
versionID = json['VersionID'];
channel = json['Channel'];
languageID = json['LanguageID'];
iPAdress = json['IPAdress'];
generalid = json['generalid'];
sessionID = json['SessionID'];
isDentalAllowedBackend = json['isDentalAllowedBackend'];
deviceTypeID = json['DeviceTypeID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ClientRequestID'] = this.clientRequestID;
data['ClinicID'] = this.clinicID;
data['Currency'] = this.currency;
data['CustomerEmail'] = this.customerEmail;
data['CustomerID'] = this.customerID;
data['CustomerName'] = this.customerName;
data['DeviceToken'] = this.deviceToken;
data['VoipToken'] = this.voipToken;
data['DoctorID'] = this.doctorID;
data['ProjectID'] = this.projectID;
data['Service_ID'] = this.serviceID;
data['Channel_ID'] = this.channelID;
data['PatientID'] = this.patientID;
data['PatientId'] = this.patientID;
data['PatientTypeID'] = this.patientTypeID;
data['PatientOutSA'] = this.patientOutSA;
data['AppointmentDate'] = this.appointmentDate;
data['AppointmentNo'] = this.appointmentNo;
data['OrderDescription'] = this.orderDescription;
data['Live_ServiceID'] = this.liveServiceID;
data['Latitude'] = this.latitude;
data['Longitude'] = this.longitude;
data['Amount'] = this.amount;
data['IsSchedule'] = this.isSchedule;
data['Language'] = this.language;
data['userName'] = this.userName;
data['ResponseContinueURL'] = this.responseContinueURL;
data['BackClickUrl'] = this.backClickUrl;
data['PaymentOption'] = this.paymentOption;
data['VersionID'] = this.versionID;
data['Channel'] = this.channel;
data['LanguageID'] = this.languageID;
data['IPAdress'] = this.iPAdress;
data['generalid'] = this.generalid;
data['SessionID'] = this.sessionID;
data['isDentalAllowedBackend'] = this.isDentalAllowedBackend;
data['DeviceTypeID'] = this.deviceTypeID;
data['IsMobSDK'] = this.isMobSDK;
data['Merchant_Reference'] = this.merchantReference;
data['Merchant_Identifier'] = this.merchantIdentifier;
data['CommandType'] = this.commandType;
data['Signature'] = this.signature;
data['Access_code'] = this.accessCode;
data['SHA_RequestPhase'] = this.shaRequestPhrase;
data['SHA_ResponsePhase'] = this.shaResponsePhrase;
data['ReturnURL'] = this.returnURL;
return data;
}
}

@ -0,0 +1,60 @@
class PayfortCheckPaymentStatusResponseModel {
num? amount;
String? cardNumber;
dynamic clientRequsetID;
dynamic errorMessage;
String? fortId;
String? merchantReference;
dynamic orderDescription;
dynamic patientFileNumber;
String? paymentMethod;
dynamic rRN;
String? responseMessage;
dynamic vidaAdvancedNumber;
PayfortCheckPaymentStatusResponseModel(
{this.amount,
this.cardNumber,
this.clientRequsetID,
this.errorMessage,
this.fortId,
this.merchantReference,
this.orderDescription,
this.patientFileNumber,
this.paymentMethod,
this.rRN,
this.responseMessage,
this.vidaAdvancedNumber});
PayfortCheckPaymentStatusResponseModel.fromJson(Map<String, dynamic> json) {
amount = json['Amount'];
cardNumber = json['CardNumber'];
clientRequsetID = json['ClientRequsetID'];
errorMessage = json['ErrorMessage'];
fortId = json['Fort_id'];
merchantReference = json['Merchant_Reference'];
orderDescription = json['OrderDescription'];
patientFileNumber = json['PatientFileNumber'];
paymentMethod = json['PaymentMethod'];
rRN = json['RRN'];
responseMessage = json['Response_Message'];
vidaAdvancedNumber = json['VidaAdvancedNumber'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Amount'] = this.amount;
data['CardNumber'] = this.cardNumber;
data['ClientRequsetID'] = this.clientRequsetID;
data['ErrorMessage'] = this.errorMessage;
data['Fort_id'] = this.fortId;
data['Merchant_Reference'] = this.merchantReference;
data['OrderDescription'] = this.orderDescription;
data['PatientFileNumber'] = this.patientFileNumber;
data['PaymentMethod'] = this.paymentMethod;
data['RRN'] = this.rRN;
data['Response_Message'] = this.responseMessage;
data['VidaAdvancedNumber'] = this.vidaAdvancedNumber;
return data;
}
}

@ -0,0 +1,37 @@
class PayfortProjectDetailsRespModel {
String? accessCode;
int? integrationId;
String? merchantIdentifier;
int? projectID;
String? projectName;
int? servID;
String? shaRequest;
String? shaResponse;
String? signature;
PayfortProjectDetailsRespModel({this.accessCode, this.integrationId, this.merchantIdentifier, this.projectID, this.projectName, this.servID, this.shaRequest, this.shaResponse, this.signature});
PayfortProjectDetailsRespModel.fromJson(Map<String, dynamic> json) {
accessCode = json['AccessCode'];
integrationId = json['Integration_Id'];
merchantIdentifier = json['MerchantIdentifier'];
projectID = json['ProjectID'];
projectName = json['ProjectName'];
servID = json['ServID'];
shaRequest = json['Sha_Request'];
shaResponse = json['Sha_Response'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['AccessCode'] = this.accessCode;
data['Integration_Id'] = this.integrationId;
data['MerchantIdentifier'] = this.merchantIdentifier;
data['ProjectID'] = this.projectID;
data['ProjectName'] = this.projectName;
data['ServID'] = this.servID;
data['Sha_Request'] = this.shaRequest;
data['Sha_Response'] = this.shaResponse;
return data;
}
}

@ -0,0 +1,55 @@
class SdkTokenResponse {
SdkTokenResponse({
this.responseCode,
this.deviceId,
this.responseMessage,
this.serviceCommand,
this.sdkToken,
this.signature,
this.merchantIdentifier,
this.accessCode,
this.language,
this.status,
});
String? responseCode;
String? deviceId;
String? responseMessage;
String? serviceCommand;
String? sdkToken;
String? signature;
String? merchantIdentifier;
String? accessCode;
String? language;
String? status;
factory SdkTokenResponse.fromMap(Map<String, dynamic> data) {
return SdkTokenResponse(
responseCode: data['response_code'],
deviceId: data['device_id'],
responseMessage: data['response_message'],
serviceCommand: data['service_command'],
sdkToken: data['sdk_token'],
signature: data['signature'],
merchantIdentifier: data['merchant_identifier'],
accessCode: data['access_code'],
language: data['language'],
status: data['status'],
);
}
Map<String, dynamic> toMap() {
return {
'response_code': responseCode,
'device_id': deviceId,
'response_message': responseMessage,
'service_command': serviceCommand,
'sdk_token': sdkToken,
'signature': signature,
'merchant_identifier': merchantIdentifier,
'access_code': accessCode,
'language': language,
'status': status,
};
}
}

@ -0,0 +1,150 @@
import 'package:amazon_payfort/amazon_payfort.dart';
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_check_payment_status_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_project_details_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/sdk_token_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class PayfortRepo {
Future<Either<Failure, GenericApiModel<PayfortProjectDetailsRespModel>>> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2});
Future<Either<Failure, GenericApiModel<dynamic>>> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest});
Future<Either<Failure, GenericApiModel<SdkTokenResponse>>> generateSdkSignatureFromAPI({required SdkTokenRequest tokenRequest});
Future<Either<Failure, GenericApiModel<PayfortCheckPaymentStatusResponseModel>>> checkPaymentStatus({required String transactionID});
}
class PayfortRepoImp implements PayfortRepo {
final ApiClient apiClient;
final LoggerService loggerService;
PayfortRepoImp({required this.loggerService, required this.apiClient});
@override
Future<Either<Failure, GenericApiModel<PayfortProjectDetailsRespModel>>> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2}) async {
Map<String, dynamic> body = {"Integration_Id": integrationId, "ServID": serviceId, "ProjectID": projectId};
try {
GenericApiModel<PayfortProjectDetailsRespModel>? apiResponse;
Failure? failure;
await apiClient.post(getPayFortProjectDetails, body: body, onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response;
if (list == null || list.isEmpty) {
throw Exception("payfort list is empty");
}
final applePayConfigurationResponse = PayfortProjectDetailsRespModel.fromJson(list[0]);
apiResponse = GenericApiModel<PayfortProjectDetailsRespModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: applePayConfigurationResponse,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest}) async {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(APPLE_PAY_INSERT_REQUEST, body: applePayInsertRequest.toJson(), onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response["result"],
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<SdkTokenResponse>>> generateSdkSignatureFromAPI({required SdkTokenRequest tokenRequest}) async {
try {
GenericApiModel<SdkTokenResponse>? apiResponse;
Failure? failure;
await apiClient.post(ApiConsts.payFortEnvironment.paymentApi, body: tokenRequest.asRequest(), onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final sdkTokenResponse = SdkTokenResponse.fromMap(response);
apiResponse = GenericApiModel<SdkTokenResponse>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: sdkTokenResponse,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true, isExternal: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<PayfortCheckPaymentStatusResponseModel>>> checkPaymentStatus({required String transactionID}) async {
Map<String, dynamic> body = {"ClientRequestID": transactionID, "IsPharmacy": false};
try {
GenericApiModel<PayfortCheckPaymentStatusResponseModel>? apiResponse;
Failure? failure;
await apiClient.post(CHECK_PAYMENT_STATUS, body: body, onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final paymentStatusResponse = PayfortCheckPaymentStatusResponseModel.fromJson(response);
apiResponse = GenericApiModel<PayfortCheckPaymentStatusResponseModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: paymentStatusResponse,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
}

@ -0,0 +1,198 @@
import 'package:amazon_payfort/amazon_payfort.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_check_payment_status_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_project_details_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/sdk_token_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:network_info_plus/network_info_plus.dart';
class PayfortViewModel extends ChangeNotifier {
PayfortRepo payfortRepo;
ErrorHandlerService errorHandlerService;
bool isApplePayConfigurationLoading = false;
PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel;
PayfortCheckPaymentStatusResponseModel? payfortCheckPaymentStatusResponseModel;
late AmazonPayfort _payfort;
final NetworkInfo _info = NetworkInfo();
PayfortViewModel({required this.payfortRepo, required this.errorHandlerService});
setIsApplePayConfigurationLoading(bool value) {
isApplePayConfigurationLoading = value;
notifyListeners();
}
initPayfortViewModel() async {
_payfort = AmazonPayfort.instance;
await AmazonPayfort.initialize(
PayFortOptions(environment: ApiConsts.payFortEnvironment),
);
notifyListeners();
}
Future<void> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.getPayfortConfigurations(serviceId: serviceId, projectId: projectId, integrationId: integrationId);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
payfortProjectDetailsRespModel = apiResponse.data!;
// isApplePayConfigurationLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
// payfortProjectDetailsRespModel = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> checkPaymentStatus({required String transactionID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.checkPaymentStatus(transactionID: transactionID);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
payfortCheckPaymentStatusResponseModel = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<SdkTokenResponse?> _generateSdkResponse({
String? applePayAccessCode,
String? merchantIdentifier,
String? applePayShaType,
String? applePayShaRequestPhrase,
}) async {
try {
String? deviceId = await _payfort.getDeviceId();
/// Step 2: Generate the Signature
SdkTokenRequest tokenRequest = SdkTokenRequest(
accessCode: applePayAccessCode!,
deviceId: deviceId ?? '',
merchantIdentifier: merchantIdentifier!,
);
String? signature = await _payfort.generateSignature(
shaType: applePayShaType!,
concatenatedString: tokenRequest.toConcatenatedString(applePayShaRequestPhrase!),
);
tokenRequest = tokenRequest.copyWith(signature: signature);
/// Step 3: Generate the SDK Token
final result = await payfortRepo.generateSdkSignatureFromAPI(tokenRequest: tokenRequest);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
// payfortProjectDetailsRespModel = apiResponse.data!;
isApplePayConfigurationLoading = false;
notifyListeners();
}
},
);
} catch (e) {
print("Error here: ${e.toString()}");
}
return null;
}
Future<void> paymentWithApplePay({
SucceededCallback? onSucceeded,
FailedCallback? onFailed,
String? customerName,
String? customerEmail,
String? orderDescription,
num? orderAmount,
String? merchantIdentifier,
String? applePayAccessCode,
String? applePayShaRequestPhrase,
String? merchantReference,
String currency = "SAR",
String applePayShaType = "SHA-256",
String countryIsoCode = "SA",
}) async {
try {
SdkTokenResponse? sdkTokenResponse = await _generateSdkResponse(
applePayAccessCode: applePayAccessCode,
merchantIdentifier: merchantIdentifier,
applePayShaType: applePayShaType,
applePayShaRequestPhrase: applePayShaRequestPhrase,
);
if (sdkTokenResponse != null && sdkTokenResponse.sdkToken == null) {
onFailed!((sdkTokenResponse.responseMessage ?? '') as PayFortFailureResult);
return;
}
/// Step 4: Processing Payment [Don't multiply with 100]
/// Amount value send always round ex. [100] not [100.00, 100.21]
FortRequest request = FortRequest(
command: FortCommand.purchase,
amount: orderAmount!,
customerName: customerName!,
customerEmail: customerEmail!,
// orderDescription: orderDescription!,
orderDescription: "Dr. Sulaiman Al Habib Hospital",
sdkToken: sdkTokenResponse?.sdkToken ?? '',
merchantReference: merchantReference!,
currency: currency,
customerIp: (await _info.getWifiIP() ?? ''),
language: 'en');
isApplePayConfigurationLoading = false;
notifyListeners();
_payfort.callPayFortForApplePay(
request: request,
countryIsoCode: countryIsoCode,
applePayMerchantId: ApiConsts.applePayMerchantId,
callback: ApplePayResultCallback(
onSucceeded: onSucceeded!,
onFailed: onFailed!,
),
);
} catch (e) {
onFailed!(e.toString() as PayFortFailureResult);
}
}
}

@ -805,5 +805,9 @@ abstract class LocaleKeys {
static const checkAvailability = 'checkAvailability';
static const readInstructions = 'readInstructions';
static const searchLabReport = 'searchLabReport';
static const lastloginBy = 'lastloginBy';
static const allSet ='allSet';
static const enableQuickLogin = 'enableQuickLogin';
static const enableMsg = 'enableMsg';
static const notNow = 'notNow';
}

@ -11,6 +11,9 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart';
@ -91,6 +94,21 @@ void main() async {
errorHandlerService: getIt(),
),
),
ChangeNotifierProvider<MedicalFileViewModel>(
create: (_) => MedicalFileViewModel(),
),
ChangeNotifierProvider<MyAppointmentsViewModel>(
create: (_) => MyAppointmentsViewModel(
myAppointmentsRepo: getIt(),
errorHandlerService: getIt(),
),
),
ChangeNotifierProvider<PayfortViewModel>(
create: (_) => PayfortViewModel(
payfortRepo: getIt(),
errorHandlerService: getIt(),
),
),
ChangeNotifierProvider<AuthenticationViewModel>(
create: (_) => AuthenticationViewModel(
authenticationRepo: getIt(),
@ -99,6 +117,7 @@ void main() async {
errorHandlerService: getIt(),
navigationService: getIt(),
cacheService: getIt(),
localAuthService: getIt(),
),
),
], child: MyApp()),

@ -0,0 +1,248 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_payment_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:maps_launcher/maps_launcher.dart';
import 'package:provider/provider.dart';
class AppointmentDetailsPage extends StatefulWidget {
AppointmentDetailsPage({super.key, required this.patientAppointmentHistoryResponseModel});
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
@override
State<AppointmentDetailsPage> createState() => _AppointmentDetailsPageState();
}
class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
late MyAppointmentsViewModel myAppointmentsViewModel;
@override
Widget build(BuildContext context) {
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
appBar: AppBar(
title: "Appointment Details".needTranslation.toText18(),
backgroundColor: AppColors.bgScaffoldColor,
),
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Appointment Details".needTranslation.toText24(isBold: true),
],
),
SizedBox(height: 24.h),
AppointmentDoctorCard(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onAskDoctorTap: () {},
onCancelTap: () {},
onRescheduleTap: () {},
),
SizedBox(height: 16.h),
if (!AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel))
Column(
children: [
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
"Appointment Status".needTranslation.toText16(isBold: true),
],
),
SizedBox(height: 4.h),
(!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
? "Not Confirmed".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: "Confirmed".needTranslation.toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h),
Stack(
children: [
ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(24),
child: Image.network(
"https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
fit: BoxFit.contain,
),
),
Positioned(
bottom: 0,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.785,
child: CustomButton(
text: "Get Directions".needTranslation,
onPressed: () {
MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
},
backgroundColor: AppColors.textColor.withOpacity(0.8),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppColors.whiteColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.directions_icon,
iconColor: AppColors.whiteColor,
iconSize: 13.h,
).paddingAll(12.h),
),
),
],
),
],
),
),
),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h),
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
"Notify me before the appointment".needTranslation.toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
],
),
const Spacer(),
Switch(
activeColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
onChanged: (newValue) {
setState(() {
myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
});
},
),
],
).paddingSymmetrical(16.h, 16.h),
),
SizedBox(height: 16.h),
],
),
],
).paddingSymmetrical(24.h, 24.h),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: true,
),
child: SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.patientAppointmentHistoryResponseModel.nextAction == 15 || widget.patientAppointmentHistoryResponseModel.nextAction == 20)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Total amount to pay".needTranslation.toText18(isBold: true),
Utils.getPaymentAmountWithSymbol(widget.patientAppointmentHistoryResponseModel.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
),
SizedBox(height: 4.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.upcomingPaymentNow.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
"VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
],
),
SizedBox(height: 18.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 150.h,
child: Utils.getPaymentMethods(),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Utils.getPaymentAmountWithSymbol(widget.patientAppointmentHistoryResponseModel.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: true),
],
),
],
)
],
).paddingOnly(left: 16.h, top: 24.h, right: 16.h, bottom: 0.h),
CustomButton(
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
onPressed: () {
myAppointmentsViewModel.setIsPatientAppointmentShareLoading(true);
Navigator.of(context).push(
FadePage(
page: AppointmentPaymentPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
);
},
backgroundColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppColors.whiteColor,
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppColors.whiteColor,
iconSize: 18.h,
).paddingSymmetrical(16.h, 24.h),
],
),
),
),
],
),
);
}
}

@ -0,0 +1,494 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/in_app_browser/InAppBrowser.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
class AppointmentPaymentPage extends StatefulWidget {
AppointmentPaymentPage({super.key, required this.patientAppointmentHistoryResponseModel});
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
@override
State<AppointmentPaymentPage> createState() => _AppointmentPaymentPageState();
}
class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
late MyAppointmentsViewModel myAppointmentsViewModel;
late PayfortViewModel payfortViewModel;
late AppState appState;
MyInAppBrowser? browser;
String selectedPaymentMethod = "";
String transID = "";
@override
void initState() {
scheduleMicrotask(() {
payfortViewModel.initPayfortViewModel();
myAppointmentsViewModel.getPatientShareAppointment(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
);
});
super.initState();
}
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context);
payfortViewModel = Provider.of<PayfortViewModel>(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
appBar: AppBar(
title: "Appointment Payment".needTranslation.toText18(),
backgroundColor: AppColors.bgScaffoldColor,
),
body: Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return myAppointmentsVM.isAppointmentPatientShareLoading
? const MoviesShimmerWidget().paddingAll(24.h)
: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Appointment Payment".needTranslation.toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.mada, width: 72.h, height: 25.h),
SizedBox(height: 16.h),
"Mada".needTranslation.toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "MADA";
openPaymentURL("mada");
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
SizedBox(width: 8.h),
Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
],
),
SizedBox(height: 16.h),
"Visa or Mastercard".needTranslation.toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "VISA";
openPaymentURL("visa");
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h),
SizedBox(height: 16.h),
"Tamara".needTranslation.toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "TAMARA";
openPaymentURL("tamara");
}),
],
),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: false,
),
child: Consumer<PayfortViewModel>(builder: (context, payfortVM, child) {
//TODO: Need to add loading state & animation for Apple Pay Configuration
return payfortVM.isApplePayConfigurationLoading
? const MoviesShimmerWidget().paddingAll(16.h)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true)
? Container(
height: 50.h,
decoration: ShapeDecoration(
color: AppColors.secondaryLightRedBorderColor,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
smoothness: 1,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
CustomButton(
text: LocaleKeys.updateInsurance.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.secondaryLightRedBorderColor,
textColor: AppColors.whiteColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
height: 30.h,
).paddingSymmetrical(24.h, 0.h),
],
),
)
: const SizedBox(),
SizedBox(height: 24.h),
"Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Total amount to pay".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
Utils.getPaymentAmountWithSymbol(
myAppointmentsVM.patientAppointmentShareResponseModel!.patientTaxAmount!.toString().toText14(isBold: true, color: AppColors.greyTextColor),
AppColors.greyTextColor,
13,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(
myAppointmentsVM.patientAppointmentShareResponseModel!.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
//TODO: Add Apple Pay Privileges
Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button,
width: 200.h,
height: 80.h,
fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h).onPress(() {
payfortVM.setIsApplePayConfigurationLoading(true);
startApplePay();
}),
SizedBox(height: 12.h),
],
);
}),
),
],
);
}),
);
}
onBrowserLoadStart(String url) {
print("onBrowserLoadStart");
print(url);
if (selectedPaymentMethod == "tamara") {
if (Platform.isAndroid) {
Uri uri = new Uri.dataFromString(url);
// tamaraPaymentStatus = uri.queryParameters['status']!;
// tamaraOrderID = uri.queryParameters['AuthorizePaymentId']!;
} else {
Uri uri = new Uri.dataFromString(url);
// tamaraPaymentStatus = uri.queryParameters['paymentStatus']!;
// tamaraOrderID = uri.queryParameters['orderId']!;
}
}
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.successURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = true;
return;
}
});
// }
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.errorURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = false;
return;
}
});
// }
}
onBrowserExit(bool isPaymentMade) async {
print("onBrowserExit Called!!!!");
if (selectedPaymentMethod == "TAMARA") {
// checkTamaraPaymentStatus(transID!, appo);
// if (tamaraPaymentStatus != null && tamaraPaymentStatus.toLowerCase() == "approved") {
// updateTamaraRequestStatus("success", "14", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
// } else {
// updateTamaraRequestStatus("Failed", "00", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
// }
} else {
showCommonBottomSheet(context,
child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
await payfortViewModel.checkPaymentStatus(
transactionID: transID,
onSuccess: (apiResponse) async {
print(apiResponse.data);
if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
await myAppointmentsViewModel.createAdvancePayment(
paymentMethodName: selectedPaymentMethod,
projectID: widget.patientAppointmentHistoryResponseModel.projectID,
clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
payedAmount: payfortViewModel.payfortCheckPaymentStatusResponseModel!.amount!,
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
patientID: "4767477",
patientType: 1,
onSuccess: (value) async {
print(value);
await myAppointmentsViewModel.addAdvanceNumberRequest(
advanceNumber: Utils.isVidaPlusProject(appState, widget.patientAppointmentHistoryResponseModel.projectID)
? value['data']['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
: value['data']['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
onSuccess: (value) async {
if (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!) {
//TODO: Implement LiveCare Check-In API Call
} else {
await myAppointmentsViewModel.generateAppointmentQR(
clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
projectID: widget.patientAppointmentHistoryResponseModel.projectID,
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!);
}
});
});
Future.delayed(Duration(milliseconds: 500), () {
Navigator.of(context).pop();
print(payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!);
});
} else {}
});
// checkPaymentStatus(appo);
}
}
openPaymentURL(String paymentMethod) {
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
transID = Utils.getAppointmentTransID(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo,
);
//TODO: Need to pass dynamic params to the payment request instead of static values
browser?.openPaymentBrowser(
myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!,
"Appointment check in",
transID,
widget.patientAppointmentHistoryResponseModel.projectID.toString(),
"CustID_3628599@HMG.com",
selectedPaymentMethod,
"1",
"Haroon Amjad",
"3628599",
AuthenticatedUser(outSa: 0, mobileNumber: "0593233758"),
browser!,
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false,
"2",
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? myAppointmentsViewModel.patientAppointmentShareResponseModel!.clinicID.toString() : "",
context,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.appointmentDate,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.appointmentNo,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.clinicID,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.doctorID,
"3");
}
startApplePay() async {
transID = Utils.getAppointmentTransID(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo,
);
ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
await payfortViewModel.getPayfortConfigurations(
serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum(), projectId: widget.patientAppointmentHistoryResponseModel.projectID, integrationId: 2);
applePayInsertRequest.clientRequestID = transID;
applePayInsertRequest.clinicID = widget.patientAppointmentHistoryResponseModel.clinicID;
//TODO: Need to pass dynamic params to the payment request instead of static values
applePayInsertRequest.currency = "SAR";
applePayInsertRequest.customerEmail = "CustID_3628599@HMG.com";
applePayInsertRequest.customerID = "3628599";
applePayInsertRequest.customerName = "Haroon Amjad";
applePayInsertRequest.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
applePayInsertRequest.voipToken = await Utils.getStringFromPrefs(CacheConst.voipToken);
applePayInsertRequest.doctorID = widget.patientAppointmentHistoryResponseModel.doctorID;
applePayInsertRequest.projectID = widget.patientAppointmentHistoryResponseModel.projectID.toString();
applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
applePayInsertRequest.channelID = 3;
applePayInsertRequest.patientID = "3628599";
applePayInsertRequest.patientTypeID = 1;
applePayInsertRequest.patientOutSA = 0;
applePayInsertRequest.appointmentDate = widget.patientAppointmentHistoryResponseModel.appointmentDate;
applePayInsertRequest.appointmentNo = widget.patientAppointmentHistoryResponseModel.appointmentNo;
applePayInsertRequest.orderDescription = "Appointment Payment";
applePayInsertRequest.liveServiceID = "0";
applePayInsertRequest.latitude = "0.0";
applePayInsertRequest.longitude = "0.0";
applePayInsertRequest.amount = myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!.toString();
applePayInsertRequest.isSchedule = widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? "1" : "0";
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
applePayInsertRequest.userName = 3628599;
applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
applePayInsertRequest.paymentOption = "ApplePay";
applePayInsertRequest.isMobSDK = true;
applePayInsertRequest.merchantReference = transID;
applePayInsertRequest.merchantIdentifier = payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier;
applePayInsertRequest.commandType = "PURCHASE";
applePayInsertRequest.signature = payfortViewModel.payfortProjectDetailsRespModel!.signature;
applePayInsertRequest.accessCode = payfortViewModel.payfortProjectDetailsRespModel!.accessCode;
applePayInsertRequest.shaRequestPhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaRequest;
applePayInsertRequest.shaResponsePhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaResponse;
applePayInsertRequest.returnURL = "";
//TODO: Need to pass dynamic params to the Apple Pay instead of static values
await payfortViewModel.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest).then((value) {
payfortViewModel.paymentWithApplePay(
customerName: "Haroon Amjad",
// customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress,
customerEmail: "CustID_3628599@HMG.com",
orderDescription: "Appointment Payment",
orderAmount: double.parse(myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!.toString()),
merchantReference: transID,
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
currency: "SAR",
onFailed: (failureResult) async {
log("failureResult: ${failureResult.message.toString()}");
},
onSucceeded: (successResult) async {
log("successResult: ${successResult.responseMessage.toString()}");
},
// projectId: appo.projectID,
// serviceTypeEnum: ServiceTypeEnum.appointmentPayment,
);
});
}
}

@ -0,0 +1,111 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart';
class MyAppointmentsPage extends StatefulWidget {
const MyAppointmentsPage({super.key});
@override
State<MyAppointmentsPage> createState() => _MyAppointmentsPageState();
}
class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
late MyAppointmentsViewModel myAppointmentsViewModel;
@override
void initState() {
scheduleMicrotask(() {
myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false);
});
super.initState();
}
@override
Widget build(BuildContext context) {
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
appBar: AppBar(
title: "Appointments List".needTranslation.toText18(),
backgroundColor: AppColors.bgScaffoldColor,
),
body: SingleChildScrollView(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Appointments List".needTranslation.toText24(isBold: true),
],
).paddingSymmetrical(24.h, 24.h),
CustomTabBar(
activeTextColor: Color(0xffED1C2B),
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
tabs: [
CustomTabBarModel(null, "All Appt.".needTranslation),
CustomTabBarModel(null, "Upcoming".needTranslation),
CustomTabBarModel(null, LocaleKeys.request.tr(context: context)),
],
onTabChange: (index) {
print(index);
},
).paddingSymmetrical(24.h, 0.h),
Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
// Expandable list
ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: myAppointmentsVM.isMyAppointmentsLoading ? 5 : myAppointmentsVM.patientAppointmentsHistoryList.length,
itemBuilder: (context, index) {
return myAppointmentsVM.isMyAppointmentsLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.h)
: AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 500),
child: SlideAnimation(
verticalOffset: 100.0,
child: FadeInAnimation(
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
margin: EdgeInsets.symmetric(vertical: 8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel,
),
).paddingSymmetrical(24.h, 0.h),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
),
],
);
}),
],
),
),
);
}
}

@ -0,0 +1,263 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
class AppointmentCard extends StatefulWidget {
AppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel});
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
MyAppointmentsViewModel myAppointmentsViewModel;
@override
State<AppointmentCard> createState() => _AppointmentCardState();
}
class _AppointmentCardState extends State<AppointmentCard> {
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return InkWell(
onTap: () {
Navigator.of(context).push(
FadePage(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
);
},
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Wrap(
alignment: WrapAlignment.start,
direction: Axis.horizontal,
spacing: 6.h,
runSpacing: 6.h,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: appState.isArabic()
? widget.patientAppointmentHistoryResponseModel.isInOutPatientDescriptionN!
: widget.patientAppointmentHistoryResponseModel.isInOutPatientDescription!,
onPressed: () {},
backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
borderColor: AppColors.primaryRedColor.withOpacity(0.0),
textColor: AppColors.primaryRedColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
CustomButton(
text: AppointmentType.getAppointmentStatusType(widget.patientAppointmentHistoryResponseModel.patientStatusType!),
onPressed: () {},
backgroundColor: AppColors.successColor.withOpacity(0.1),
borderColor: AppColors.successColor.withOpacity(0.0),
textColor: AppColors.successColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
),
],
),
),
// TODO: Implement the logic to enable/disable the switch based on reminder status
Switch(
activeColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
thumbIcon: WidgetStateProperty.resolveWith<Icon?>(
(Set<WidgetState> states) {
if (states.contains(WidgetState.selected)) {
return const Icon(Icons.check); // Icon when switch is ON
}
return const Icon(Icons.close); // Icon when switch is OFF
},
),
value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
onChanged: (newValue) {
setState(() {
widget.myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
});
},
),
],
),
SizedBox(height: 16.h),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
widget.patientAppointmentHistoryResponseModel.doctorImageURL!,
width: 63.h,
height: 63.h,
fit: BoxFit.fill,
).circle(100),
SizedBox(width: 16.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(isBold: true),
SizedBox(height: 8.h),
Row(
children: [
CustomButton(
text: widget.patientAppointmentHistoryResponseModel.clinicName!,
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
SizedBox(width: 6.h),
CustomButton(
text: widget.patientAppointmentHistoryResponseModel.projectName!,
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
),
SizedBox(height: 6.h),
Row(
children: [
CustomButton(
icon: AppAssets.appointment_calendar_icon,
iconColor: AppColors.blackColor,
iconSize: 12.h,
text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate), false),
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
SizedBox(width: 6.h),
CustomButton(
icon: AppAssets.appointment_time_icon,
iconColor: AppColors.blackColor,
iconSize: 12.h,
text: DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate), false),
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
)
],
),
],
),
SizedBox(height: 16.h),
Row(
children: [
Expanded(
flex: 6,
child: CustomButton(
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
onPressed: () {
Navigator.of(context).push(
FadePage(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
);
},
backgroundColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.1),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction),
iconSize: 14.h,
),
),
SizedBox(width: 8.h),
Expanded(
flex: 1,
child: Container(
height: 40.h,
width: 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.textColor,
borderRadius: 10.h,
),
child: Padding(
padding: EdgeInsets.all(10.h),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
width: 10.h,
height: 10.h,
fit: BoxFit.contain,
),
),
).onPress(() {
Navigator.of(context).push(
FadePage(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
);
}),
),
],
),
],
),
),
);
}
void performAppointmentNextAction(nextAction) {}
}

@ -0,0 +1,189 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
class AppointmentDoctorCard extends StatelessWidget {
AppointmentDoctorCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.onRescheduleTap, required this.onCancelTap, required this.onAskDoctorTap});
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
late Function onRescheduleTap;
late Function onCancelTap;
late Function onAskDoctorTap;
@override
Widget build(BuildContext context) {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
patientAppointmentHistoryResponseModel.doctorImageURL!,
width: 63.h,
height: 63.h,
fit: BoxFit.fill,
).circle(100),
SizedBox(width: 16.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(isBold: true),
SizedBox(height: 8.h),
Row(
children: [
CustomButton(
text: patientAppointmentHistoryResponseModel.clinicName!,
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
SizedBox(width: 6.h),
CustomButton(
text: patientAppointmentHistoryResponseModel.projectName!,
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
),
SizedBox(height: 6.h),
Row(
children: [
CustomButton(
icon: AppAssets.appointment_calendar_icon,
iconColor: AppColors.blackColor,
iconSize: 12.h,
text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false),
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
SizedBox(width: 6.h),
CustomButton(
icon: AppAssets.appointment_time_icon,
iconColor: AppColors.blackColor,
iconSize: 12.h,
text: DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false),
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
)
],
),
],
),
SizedBox(height: 16.h),
getAppointmentActionButtons(
AppointmentType.isArrived(patientAppointmentHistoryResponseModel),
),
],
),
),
);
}
Widget getAppointmentActionButtons(bool isAppointmentArrived) {
if (isAppointmentArrived) {
return CustomButton(
text: LocaleKeys.askDoctor.tr(),
onPressed: () {},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.ask_doctor_icon,
iconColor: AppColors.primaryRedColor,
);
} else {
return Row(
children: [
Expanded(
child: CustomButton(
text: LocaleKeys.reschedule.tr(),
onPressed: () {
onRescheduleTap();
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
height: 40.h,
icon: AppAssets.appointment_calendar_icon,
iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
),
),
SizedBox(width: 16.h),
Expanded(
child: CustomButton(
text: LocaleKeys.cancel.tr(),
onPressed: () {
onCancelTap();
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
height: 40.h,
icon: AppAssets.cancel,
iconColor: AppColors.whiteColor,
iconSize: 16.h,
),
),
],
);
}
}
}

@ -0,0 +1,136 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
class QuickLogin extends StatefulWidget {
final VoidCallback onPressed;
final bool isDone;
const QuickLogin({super.key, required this.onPressed, this.isDone = false});
@override
_QuickLogin createState() => _QuickLogin();
}
class _QuickLogin extends State<QuickLogin> {
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
),
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
widget.isDone
? Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: () {
Navigator.pop(context, true);
},
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle)),
],
),
Utils.showLottie(context: context, assetPath: AppAnimations.checkmark, width: 120, height: 120, repeat: true),
LocaleKeys.allSet.tr().toText16(textAlign:
TextAlign.center, weight: FontWeight.w500)
// Text(
// ' TranslationBase.of(context).allSet',
// textAlign: TextAlign.center,
// style: context.dynamicTextStyle(
// fontSize: 16,
// fontWeight: FontWeight.w500,
// color: Colors.black,
// ),
// ),
],
)
: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(
AppAssets.lockIcon,
height: 101,
),
const SizedBox(height: 10),
LocaleKeys.enableQuickLogin.tr().toText26(isBold: true),
// Text(
// ' TranslationBase.of(context).enableQuickLogin',
// style: context.dynamicTextStyle(
// fontSize: 26,
// fontWeight: FontWeight.bold,
// color: Colors.black,
// ),
// ),
const SizedBox(height: 5),
LocaleKeys.enableQuickLogin.tr().toText16(color: AppColors.quickLoginColor),
// Description
// Text(
// 'TranslationBase.of(context).enableMsg',
// style: context.dynamicTextStyle(
// fontSize: 16,
// color: Color(0xFF666666),
// height: 1.5,
// ),
//),
const SizedBox(height: 24),
// Buttons
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: CustomButton(
text:LocaleKeys.enableQuickLogin.tr(),
onPressed: () {
widget.onPressed();
},
backgroundColor: Color(0xffED1C2B),
borderColor: Color(0xffED1C2B),
textColor: Colors.white,
icon:AppAssets.apple_finder,
)),
],
),
SizedBox(
height: 16,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: CustomButton(
text: LocaleKeys.notNow.tr(),
onPressed: () {
Navigator.pop(context, true);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Colors.red,
// icon: "assets/images/svg/apple-finder.svg",
)),
],
),
],
)
],
),
);
}
}

@ -98,9 +98,6 @@ class _RegisterNew extends State<RegisterNew> {
autoFocus: true,
padding: EdgeInsets.symmetric(vertical: 8.h),
leadingIcon: AppAssets.student_card,
// onChange: (value) {
// print(value);
// }
).withVerticalPadding(8),
Divider(height: 1),
TextInputWidget(
@ -115,6 +112,8 @@ class _RegisterNew extends State<RegisterNew> {
padding: EdgeInsets.symmetric(vertical: 8.h),
leadingIcon: AppAssets.birthday_cake,
selectionType: SelectionTypeEnum.calendar,
onCalendarTypeChanged: authVm.onCalenderTypeChange,
onChange: authVm.onDobChange,
).withVerticalPadding(8),
],
),
@ -222,38 +221,8 @@ class _RegisterNew extends State<RegisterNew> {
padding: const EdgeInsets.only(bottom: 10),
child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => OTPVerificationScreen(
phoneNumber: '504278212',
checkActivationCode: (int code) {},
onResendOTPPressed: (String phone) {},
),
));
// if (mobileNo.isEmpty) {
// context.showBottomSheet(
// child: ExceptionBottomSheet(
// message: TranslationBase.of(context).pleaseEnterMobile,
// showCancel: false,
// onOkPressed: () {
// Navigator.of(context).pop();
// },
// ),
// );
// } else if (!Utils.validateMobileNumber(mobileNo)) {
// context.showBottomSheet(
// child: ExceptionBottomSheet(
// message: TranslationBase.of(context).pleaseEnterValidMobile,
// showCancel: false,
// onOkPressed: () {
// Navigator.of(context).pop();
// },
// ),
// );
// } else {
// registerUser(1);
// }
onPressed: () async {
await authVM.onRegisterPress(otpTypeEnum: OTPTypeEnum.sms);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor,
@ -275,32 +244,8 @@ class _RegisterNew extends State<RegisterNew> {
padding: EdgeInsets.only(bottom: 10.h, top: 10.h),
child: CustomButton(
text: LocaleKeys.sendOTPWHATSAPP.tr(),
onPressed: () {
// if (mobileNo.isEmpty) {
// context.showBottomSheet(
// child: ExceptionBottomSheet(
// message: TranslationBase.of(context).pleaseEnterMobile,
// showCancel: false,
// onOkPressed: () {
// Navigator.of(context).pop();
// },
// ),
// );
// } else if (!Utils.validateMobileNumber(mobileNo)) {
// context.showBottomSheet(
// child: ExceptionBottomSheet(
// message: TranslationBase.of(context).pleaseEnterValidMobile,
// showCancel: false,
// onOkPressed: () {
// Navigator.of(context).pop();
// },
// ),
// );
// } else {
// registerUser(4);
// }
// int? val = Utils.onOtpBtnPressed(OTPType.whatsapp, mobileNo, context);
// registerUser(val);
onPressed: () async {
await authVM.onRegisterPress(otpTypeEnum: OTPTypeEnum.whatsapp);
},
backgroundColor: AppColors.whiteColor,
borderColor: AppColors.borderOnlyColor,

@ -43,7 +43,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
@override
void dispose() {
super.dispose();
authVM!.clearDefaults();
authVM!.clearDefaultInputValues();
}
@override
@ -53,7 +53,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
appBar: CustomAppBar(
onBackPressed: () {
Navigator.of(context).pop();
authVM!.clearDefaults();
authVM!.clearDefaultInputValues();
},
onLanguageChanged: (lang) {},
hideLogoAndLang: true,
@ -263,7 +263,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
icon: AppAssets.cancel,
onPressed: () {
Navigator.of(context).pop();
authVM!.clearDefaults();
authVM!.clearDefaultInputValues();
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,

@ -2,37 +2,51 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
import 'package:hmg_patient_app_new/widgets/bottomsheet/generic_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:provider/provider.dart';
class SavedLogin extends StatefulWidget {
// final SelectDeviceIMEIRES savedLoginData;
// const SavedLogin(this.savedLoginData, {Key? key}) : super(key: key);
const SavedLogin();
const SavedLogin({Key? key}) : super(key: key);
@override
_SavedLogin createState() => _SavedLogin();
}
class _SavedLogin extends State<SavedLogin> {
LoginTypeEnum loginType = LoginTypeEnum.sms;
LoginTypeEnum loginType = LoginTypeEnum.sms;
late AuthenticationViewModel authVm;
late AppState appState;
@override
void initState() {
authVm = context.read<AuthenticationViewModel>();
appState = getIt.get<AppState>();
authVm.phoneNumberController.text = appState.getSelectDeviceByImeiRespModelElement!.mobile!;
authVm.nationalIdController.text = appState.getSelectDeviceByImeiRespModelElement!.identificationNo!;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
onBackPressed: () {},
@ -48,7 +62,7 @@ class _SavedLogin extends State<SavedLogin> {
// Welcome back text
LocaleKeys.welcomeBack.tr().toText16(color: AppColors.inputLabelTextColor),
SizedBox(height: 16.h),
("widget.savedLoginData.name!.toLowerCase().capitalizeFirstofEach").toText26(isBold: true, height: 26 / 36, color: AppColors.textColor),
appState.getSelectDeviceByImeiRespModelElement!.name!.toCamelCase.toText26(isBold: true, height: 26 / 36, color: AppColors.textColor),
SizedBox(height: 24.h),
Container(
padding: EdgeInsets.all(16.h),
@ -63,22 +77,25 @@ class _SavedLogin extends State<SavedLogin> {
child: Column(
children: [
// Last login info
('LocaleKeys.lastloginBy.tr()' + ' {getType(widget.savedLoginData.logInType!, context)}').toText14(isBold: true, color: AppColors.greyTextColor),
('widget.savedLoginData.createdOn != null ? DateUtil.getFormattedDate(DateUtil.convertStringToDate(widget.savedLoginData.createdOn!), "d MMMM, y at HH:mm") : --')
("${LocaleKeys.lastloginBy.tr() } ${LoginTypeExtension.fromValue(appState.getSelectDeviceByImeiRespModelElement!.logInType!)!.displayName}"
).toText14(isBold: true, color: AppColors.greyTextColor),
(appState.getSelectDeviceByImeiRespModelElement!.createdOn != null ? DateUtil.getFormattedDate(DateUtil.convertStringToDate(appState.getSelectDeviceByImeiRespModelElement!.createdOn!), "d MMMM, y at HH:mm") : '--')
.toText16(isBold: true, color: AppColors.textColor),
Container(margin: EdgeInsets.all(16.h), child: Utils.buildSvgWithAssets(icon: getTypeIcons(loginType.toInt), iconColor: loginType.toInt == 4 ? null : AppColors.primaryRedColor)),
Container(margin: EdgeInsets.all(16.h), child: Utils.buildSvgWithAssets(icon: getTypeIcons(loginType.toInt), height: 54, width: 54, iconColor: loginType.toInt == 4 ? null : AppColors.primaryRedColor)),
// Face ID login button
Container(
SizedBox(
height: 45,
child: CustomButton(
text: "${LocaleKeys.loginBy.tr()} ${loginType.displayName}",
onPressed: () {
if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) {
// loginWithFingerPrintFace(loginType.toInt, widget.savedLoginData.iMEI!);
} else {
int? val = loginType.toInt;
//checkUserAuthentication(val);
authVm.loginWithFingerPrintFace(loginType.toInt);
}
else {
// int? val = loginType.toInt;
authVm.checkUserAuthentication(otpTypeEnum: loginType == LoginTypeEnum.sms ? OTPTypeEnum.sms : OTPTypeEnum.whatsapp);
}
},
backgroundColor: Color(0xffED1C2B),
@ -104,7 +121,7 @@ class _SavedLogin extends State<SavedLogin> {
),
const SizedBox(height: 24),
// OTP login button
loginType != null && loginType.toInt != 1
loginType.toInt != 1
? Column(
children: [
loginType.toInt != 1
@ -140,7 +157,7 @@ class _SavedLogin extends State<SavedLogin> {
Navigator.of(context).pop();
loginType = LoginTypeEnum.sms;
int? val = loginType.toInt;
// checkUserAuthentication(val);
authVm.checkUserAuthentication(otpTypeEnum:OTPTypeEnum.sms );
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor,
@ -163,7 +180,7 @@ class _SavedLogin extends State<SavedLogin> {
Navigator.of(context).pop();
loginType = LoginTypeEnum.whatsapp;
int? val = loginType.toInt;
// checkUserAuthentication(val);
authVm.checkUserAuthentication(otpTypeEnum:OTPTypeEnum.whatsapp );
},
backgroundColor: AppColors.transparent,
borderColor: AppColors.textColor,
@ -195,11 +212,12 @@ class _SavedLogin extends State<SavedLogin> {
text: "${LocaleKeys.loginBy.tr()} ${LoginTypeEnum.whatsapp.displayName}",
onPressed: () {
if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) {
// loginWithFingerPrintFace(loginType.toInt, "iMEI");
authVm.loginWithFingerPrintFace(loginType.toInt);
} else {
loginType = LoginTypeEnum.whatsapp;
int? val = loginType.toInt;
// checkUserAuthentication(val);
authVm.checkUserAuthentication(otpTypeEnum:OTPTypeEnum.whatsapp );
}
},
backgroundColor: AppColors.whiteColor,

@ -11,14 +11,17 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/authentication/quick_login.dart';
import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/habib_wallet_card.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/small_service_card.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/welcome_widget.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart' show CustomTabBar;
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
@ -31,11 +34,25 @@ class LandingPage extends StatefulWidget {
}
class _LandingPageState extends State<LandingPage> {
late final AuthenticationViewModel authVM;
@override
void initState() {
authVM = context.read<AuthenticationViewModel>();
if(mounted) {
authVM.checkLastLoginStatus(() {
showQuickLogin(context, false);
});
}
super.initState();
}
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
NavigationService navigationService = getIt.get<NavigationService>();
final AuthenticationViewModel authenticationViewModel = context.read<AuthenticationViewModel>();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: SingleChildScrollView(
@ -46,32 +63,54 @@ class _LandingPageState extends State<LandingPage> {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomButton(
text: LocaleKeys.loginOrRegister.tr(context: context),
onPressed: () async {
await authenticationViewModel.onLoginPressed();
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50,
),
Utils.buildSvgWithAssets(
icon: AppAssets.contact_icon,
width: 24,
height: 24,
).onPress(() {
Navigator.of(context).push(
FadePage(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}),
appState.isAuthenticated
? WelcomeWidget(
onTap: () {},
name: ('${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}'),
imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg,
)
: CustomButton(
text: LocaleKeys.loginOrRegister.tr(context: context),
onPressed: () async {
await authVM.onLoginPressed();
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50,
),
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 20, width: 20).onPress(() {
Navigator.of(context).push(
FadePage(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}).paddingSymmetrical(8.h, 0),
Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 20, width: 20).onPress(() {
Navigator.of(context).push(
FadePage(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}).paddingSymmetrical(8.h, 0),
Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 20, width: 20).onPress(() {
Navigator.of(context).push(
FadePage(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}).paddingSymmetrical(8.h, 0),
],
)
],
).paddingSymmetrical(24.h, 0.h),
),
@ -128,7 +167,13 @@ class _LandingPageState extends State<LandingPage> {
],
),
],
).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(
FadePage(
page: MedicalFilePage(),
),
);
}),
SizedBox(height: 12.h),
Container(
height: 127.h,
@ -275,4 +320,21 @@ class _LandingPageState extends State<LandingPage> {
),
);
}
void showQuickLogin(BuildContext context, bool isDone) {
showCommonBottomSheet(
context,
title: "",
child: QuickLogin(
isDone: isDone,
onPressed: () {
// sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
// loginWithFingerPrintFace(3, 1, user, deviceToken);
},
),
height: 400,
isFullScreen: false,
callBackFunc: (str) {},
);
}
}

@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class WelcomeWidget extends StatelessWidget {
final String name;
final String imageUrl;
final VoidCallback? onTap;
const WelcomeWidget({
super.key,
required this.name,
required this.imageUrl,
this.onTap,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(30),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Profile image
Image.asset(imageUrl, width: 40, height: 40),
const SizedBox(width: 10),
// Text column
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Welcome".toText14(color: AppColors.greyTextColor),
Row(
children: [
name.toText16(isBold: true),
const SizedBox(width: 4),
const Icon(Icons.keyboard_arrow_down, size: 20, color: Colors.black),
],
),
],
),
],
),
);
}
}

@ -64,7 +64,7 @@ class _InsuranceHomePageState extends State<InsuranceHomePage> {
insuranceVM.setIsInsuranceHistoryLoading(true);
insuranceVM.getPatientInsuranceCardHistory();
showCommonBottomSheet(context,
child: InsuranceHistory(), callBackFunc: () {}, title: "", height: ResponsiveExtension.screenHeight * 0.65, isCloseButtonVisible: false, isFullScreen: false);
child: InsuranceHistory(), callBackFunc: (str){}, title: "", height: ResponsiveExtension.screenHeight * 0.65, isCloseButtonVisible: false, isFullScreen: false);
},
backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
borderColor: AppColors.primaryRedColor.withOpacity(0.0),

@ -120,7 +120,7 @@ class PatientInsuranceCard extends StatelessWidget {
insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
insuranceViewModel.getPatientInsuranceDetailsForUpdate();
showCommonBottomSheet(context,
child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", height: ResponsiveExtension.screenHeight * 0.42, isCloseButtonVisible: false, isFullScreen: false);
child: PatientInsuranceCardUpdateCard(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.42, isCloseButtonVisible: false, isFullScreen: false);
},
backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
borderColor: AppColors.bgGreenColor.withOpacity(0.0),

@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
@ -15,6 +16,7 @@ import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart';
@ -30,7 +32,7 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
late LabViewModel labProvider;
List<List<TestDetails>?> labSuggestions = [];
int? expandedIndex;
String? selectedFilterText='';
@override
void initState() {
scheduleMicrotask(() {
@ -60,23 +62,30 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.labResults.tr(context: context).toText24(isBold: true),
Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(() {
if(model.isLabOrdersLoading){
Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(() {
if (model.isLabOrdersLoading) {
return;
}else {
showCommonBottomSheet(context, child: SearchLabResultsContent(labSuggestionsList: model.labSuggestions),
callBackFunc: () {},
callBackFunc: (value) {
selectedFilterText = value;
model.filterLabReports(value!);
},
title: LocaleKeys.searchLabReport.tr(),
height: ResponsiveExtension.screenHeight,
isFullScreen: true,
isCloseButtonVisible: true);
} }),
}
}),
],
),
SizedBox(height: 16.h),
// Build Tab Bar
SizedBox(height: 16.h),
// Expandable list
selectedFilterText!.isNotEmpty ? CustomChipWidget(chipText: selectedFilterText!, chipType: ChipTypeEnum.alert, isSelected: true, ) : SizedBox(),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
@ -275,13 +284,11 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
return "";
}
}
getLabSuggestions(LabViewModel model) {
if(model.patientLabOrders.isEmpty){
if (model.patientLabOrders.isEmpty) {
return [];
}
return model.patientLabOrders.map((m) => m.testDetails).toList();
return model.patientLabOrders.map((m) => m.testDetails).toList();
}
}

@ -8,7 +8,9 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/medical_file_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
@ -16,6 +18,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
class MedicalFilePage extends StatefulWidget {
@ -28,6 +31,8 @@ class MedicalFilePage extends StatefulWidget {
class _MedicalFilePageState extends State<MedicalFilePage> {
late InsuranceViewModel insuranceViewModel;
int currentIndex = 0;
@override
void initState() {
scheduleMicrotask(() {
@ -182,19 +187,65 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
),
).paddingSymmetrical(24.h, 0.0),
SizedBox(height: 16.h),
CustomTabBar(
activeTextColor: Color(0xffED1C2B),
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
tabs: [
CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation),
CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)),
CustomTabBarModel(AppAssets.requests, LocaleKeys.request.tr(context: context).needTranslation),
CustomTabBarModel(AppAssets.more, "More".needTranslation),
Consumer<MedicalFileViewModel>(builder: (context, medicalFileVM, child) {
return Column(
children: [
CustomTabBar(
activeTextColor: Color(0xffED1C2B),
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
tabs: [
CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation),
CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)),
CustomTabBarModel(AppAssets.requests, LocaleKeys.request.tr(context: context).needTranslation),
CustomTabBarModel(AppAssets.more, "More".needTranslation),
],
onTabChange: (index) {
print(index);
medicalFileVM.onTabChanged(index);
},
).paddingSymmetrical(24.h, 0.0),
SizedBox(height: 24.h),
getSelectedTabData(medicalFileVM.selectedTabIndex),
],
);
}),
],
),
),
);
}
Widget getSelectedTabData(int index) {
switch (index) {
case 0:
//General Tab Data
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Appointments & visits".needTranslation.toText18(isBold: true),
Row(
children: [
LocaleKeys.viewAll.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
),
],
onTabChange: (index) {},
).paddingSymmetrical(24.h, 0.0),
SizedBox(height: 16.h),
//Insurance Tab Data
).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(
FadePage(
page: MyAppointmentsPage(),
),
);
}),
],
);
case 1:
//Insurance Tab Data
return Column(
children: [
Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return insuranceVM.isInsuranceLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.0)
@ -217,8 +268,13 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
).paddingSymmetrical(24.h, 0.0),
SizedBox(height: 16.h),
],
),
),
);
);
case 2:
return Container();
case 3:
return Container();
default:
return Container();
}
}
}

@ -1,14 +1,17 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/presentation/home/landing_page.dart';
import 'package:hmg_patient_app_new/splashPage.dart';
class AppRoutes {
static const String initialRoute = '/initialRoute';
static const String loginScreen = '/loginScreen';
static const String registerNewScreen = '/registerNewScreen';
static const String landingScreen = '/landingScreen';
static Map<String, WidgetBuilder> get routes => {
initialRoute: (context) => SplashPage(),
loginScreen: (context) => LoginScreen(),
landingScreen: (context) => LandingPage(),
};
}

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
abstract class DialogService {
@ -70,7 +71,9 @@ class _ErrorBottomSheet extends StatelessWidget {
borderRadius: BorderRadius.circular(8),
),
),
child: const Text("OK"),
child: const Text("OK", style: TextStyle(color: Colors.white)).onPress((){
Navigator.of(context).pop();
}),
),
],
),

@ -0,0 +1,40 @@
import 'package:local_auth/local_auth.dart';
import 'logger_service.dart';
class LocalAuthService {
final LocalAuthentication localAuth;
final LoggerService loggerService;
LocalAuthService({required this.localAuth, required this.loggerService});
Future<bool> authenticate() async {
try {
bool isAuthenticated = await localAuth.authenticate(
localizedReason: 'Please authenticate to proceed',
options: const AuthenticationOptions(
biometricOnly: true,
stickyAuth: true,
),
);
return isAuthenticated;
} catch (e) {
return false;
}
}
Future<bool> canCheckBiometrics() async {
try {
return await localAuth.canCheckBiometrics;
} catch (e) {
return false;
}
}
Future<List<BiometricType>> getAvailableBiometrics() async {
try {
return await localAuth.getAvailableBiometrics();
} catch (e) {
return [];
}
}
}

@ -18,6 +18,10 @@ class NavigationService {
navigatorKey.currentState?.popUntil(ModalRoute.withName(routeName));
}
void pushAndReplace(String routeName) {
navigatorKey.currentState?.pushReplacementNamed(routeName);
}
Future<T?> pushToOtpScreen<T>({
required String phoneNumber,
required Function(int code) checkActivationCode,

@ -59,4 +59,6 @@ static const Color warningLightColor = Color(0xFFFFCC00);
static const Color greyLightColor = Color(0xFFEFEFF0);
static const Color bottomNAVBorder = Color(0xFFEEEEEE);
static const Color quickLoginColor = Color(0xFF666666);
}

@ -7,7 +7,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
void showCommonBottomSheet(BuildContext context,
{required Widget child, required VoidCallback callBackFunc, String? title, required double? height, bool isCloseButtonVisible = true, bool isFullScreen = true}) {
{required Widget child, Function(String?)? callBackFunc, String? title, required double height, bool isCloseButtonVisible = true, bool isFullScreen = true, bool isDismissible = true}) {
showModalBottomSheet<String>(
sheetAnimationStyle: AnimationStyle(
duration: Duration(milliseconds: 500), // Custom animation duration
@ -16,6 +16,7 @@ void showCommonBottomSheet(BuildContext context,
context: context,
isScrollControlled: true,
showDragHandle: false,
isDismissible: isDismissible,
backgroundColor: AppColors.scaffoldBgColor,
builder: (BuildContext context) {
return Container(
@ -29,7 +30,9 @@ void showCommonBottomSheet(BuildContext context,
),
);
}).then((value) {
callBackFunc();
if(value != null) {
callBackFunc!(value);
}
});
}
@ -63,12 +66,14 @@ class ButtonSheetContent extends StatelessWidget {
// Close button
isCloseButtonVisible && isFullScreen
? Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
? Column(children: [
SizedBox(height: 40.h,),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16,),
child: Utils.buildSvgWithAssets(icon: AppAssets.closeBottomNav, width: 32, height: 32).onPress(() {
Navigator.of(context).pop();
}),
)
)])
: SizedBox(),
isFullScreen

@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/int_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class CustomTabBarModel {
String? image;
@ -78,9 +79,9 @@ class _CustomTabBarState extends State<CustomTabBar> {
return Container(
height: 62.h,
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(11),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 11,
),
child: parentWidget);
}
@ -91,9 +92,9 @@ class _CustomTabBarState extends State<CustomTabBar> {
height: 54.h,
padding: EdgeInsets.only(top: 4, bottom: 4, left: 16, right: 16),
alignment: Alignment.center,
decoration: BoxDecoration(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isSelected ? widget.activeBackgroundColor : widget.inActiveBackgroundColor,
borderRadius: BorderRadius.circular(7),
borderRadius: 12,
),
child: Row(
mainAxisSize: MainAxisSize.min,
@ -101,7 +102,7 @@ class _CustomTabBarState extends State<CustomTabBar> {
children: [
if (tabBar.image != null) Utils.buildSvgWithAssets(icon: tabBar.image!, height: 18, width: 18, iconColor: isSelected ? widget.activeTextColor : widget.inActiveTextColor),
tabBar.title
.toText16(weight: isSelected ? FontWeight.w600 : FontWeight.w500, color: isSelected ? widget.activeTextColor : widget.inActiveTextColor, letterSpacing: isSelected ? -0.3 : -0.1),
.toText15(weight: isSelected ? FontWeight.w600 : FontWeight.w500, color: isSelected ? widget.activeTextColor : widget.inActiveTextColor, letterSpacing: isSelected ? -0.3 : -0.1),
],
)).onPress(() {
setState(() {

@ -0,0 +1,489 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/tamara_request_model.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
enum _PAYMENT_TYPE { PACKAGES, PHARMACY, PATIENT }
var _InAppBrowserOptions = InAppBrowserClassOptions(
inAppWebViewGroupOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false),
ios: IOSInAppWebViewOptions(applePayAPIEnabled: true, isFraudulentWebsiteWarningEnabled: false)),
crossPlatform: InAppBrowserOptions(hideUrlBar: true, toolbarTopBackgroundColor: Colors.black),
android: AndroidInAppBrowserOptions(),
ios: IOSInAppBrowserOptions(
hideToolbarBottom: true,
toolbarBottomBackgroundColor: Colors.white,
closeButtonColor: Colors.white,
closeButtonCaption: "Close",
presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN));
class MyInAppBrowser extends InAppBrowser {
_PAYMENT_TYPE? paymentType;
static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL LIVE
// static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL UAT
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE
// static String SERVICE_URL = 'https://uat.hmgwebservices.com/payfortforvidaplus/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL UAT VIDA PLUS
// static String PRESCRIPTION_PAYMENT_WITH_ORDERID =
// 'https://uat.hmgwebservices.com/epharmacy/checkout/OpcCompleteRedirectionPaymentClientbyOrder?orderID=';
static String PRESCRIPTION_PAYMENT_WITH_ORDERID = 'https://mdlaboratories.com/exacartapi/checkout/OpcCompleteRedirectionPaymentClientbyOrder?orderID='; //Live
static List<String> successURLS = ['success?', 'PayFortResponse', 'PayFortSucess', 'mobilepaymentcomplete', 'orderdetails', 'redirectToApplePay', 'mdlaboratories.com/?'];
static List<String> errorURLS = ['PayfortCancel', 'errorpage', 'Failed', 'orderdetails', 'redirectToApplePay', 'mdlaboratories.com/?', 'cancel', 'canceled'];
final Function onExitCallback;
final Function? onLoadStartCallback;
final BuildContext? context;
// AppSharedPreferences sharedPref = AppSharedPreferences();
// AuthProvider authProvider = new AuthProvider();
InAppBrowser browser = InAppBrowser();
// AuthenticatedUser authUser;
// late AppoitmentAllHistoryResultList? appo;
String deviceToken = "";
double lat = 0.0;
double long = 0.0;
static bool isPaymentDone = false;
late AppState appState;
MyInAppBrowser({required this.onExitCallback, this.onLoadStartCallback, this.context});
Future onBrowserCreated() async {
print("\n\nBrowser Created!\n\n");
}
@override
Future onLoadStart(Uri? url) async {
if (onLoadStartCallback != null) onLoadStartCallback!(url.toString());
}
@override
Future onLoadStop(Uri? url) async {
print("\n\nStopped $url\n\n");
}
@override
void onLoadError(Uri? url, int code, String message) {
print("Can't load $url.. Error: $message");
}
@override
void onProgressChanged(int progress) {}
@override
void onExit() {
print("\n\nBrowser closed before!\n\n");
// if (onExitCallback != null) {
try {
onExitCallback(isPaymentDone);
print("\n\nBrowser closed after!\n\n");
} catch (err) {
print(err.toString());
}
// }
}
@override
Future<NavigationActionPolicy> shouldOverrideUrlLoading(NavigationAction navigationAction) {
var url = navigationAction.request.url.toString();
debugPrint("redirecting/overriding to: $url");
// if (paymentType == _PAYMENT_TYPE.PACKAGES && [PACKAGES_PAYMENT_SUCCESS_URL, PACKAGES_PAYMENT_FAIL_URL].contains(url)) {
// isPaymentDone = (url == PACKAGES_PAYMENT_SUCCESS_URL);
// close();
// }
return Future.value(NavigationActionPolicy.ALLOW);
}
// getLanguageID() async {
// return await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
// }
// getDeviceToken() async {
// String deviceToken = await sharedPref.getString(PUSH_TOKEN);
// this.deviceToken = deviceToken;
// }
// openPackagesPaymentBrowser({required int customer_id, required int order_id}) {
// paymentType = _PAYMENT_TYPE.PACKAGES;
// var full_url = '$PACKAGES_REQUEST_PAYMENT_URL?customer_id=$customer_id&order_id=$order_id';
// this.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(full_url))), options: _InAppBrowserOptions);
// }
openPaymentBrowser(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID,
AuthenticatedUser authenticatedUser, InAppBrowser browser, bool isLiveCareAppo, var servID, var LiveServID, BuildContext context,
[var appoDate, var appoNo, var clinicID, var doctorID, var installments]) async {
appState = getIt.get<AppState>();
this.browser = browser;
// await getPatientData();
if (paymentMethod == "ApplePay") {
MyChromeSafariBrowser safariBrowser = MyChromeSafariBrowser(MyInAppBrowser(onExitCallback: browser.onExit), onExitCallback: browser.onExit, onLoadStartCallback: this.browser.onLoadStart);
// if (context != null) GifLoaderDialogUtils.showMyDialog(context);
// LiveCareService service = new LiveCareService();
// ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest();
// applePayInsertRequest.clientRequestID = transactionID;
// applePayInsertRequest.clinicID = (clinicID != null && clinicID != "") ? clinicID : 0;
// applePayInsertRequest.currency = authenticatedUser.outSA == 1 ? "AED" : "SAR";
// applePayInsertRequest.customerEmail = emailId;
// applePayInsertRequest.customerID = patientID;
// applePayInsertRequest.customerName = patientName;
// applePayInsertRequest.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN);
// applePayInsertRequest.voipToken = await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN);
// applePayInsertRequest.doctorID = (doctorID != null && doctorID != "") ? doctorID : 0;
// applePayInsertRequest.projectID = projId;
// applePayInsertRequest.serviceID = servID;
// applePayInsertRequest.channelID = 3;
// applePayInsertRequest.patientID = patientID;
// applePayInsertRequest.patientTypeID = authenticatedUser.patientType;
// applePayInsertRequest.patientOutSA = authenticatedUser.outSA;
// applePayInsertRequest.appointmentDate = (appoDate != null && appoDate != "") ? appoDate : null;
// applePayInsertRequest.appointmentNo = (appoNo != null && appoNo != "") ? appoNo : 0;
// applePayInsertRequest.orderDescription = orderDesc;
// applePayInsertRequest.liveServiceID = LiveServID.toString() == "" ? "0" : LiveServID.toString();
// applePayInsertRequest.latitude = this.lat.toString();
// applePayInsertRequest.longitude = this.long.toString();
// applePayInsertRequest.amount = amount.toString();
// applePayInsertRequest.isSchedule = ((appoNo != null && appoNo != "") && (appoDate != null && appoDate != "")) ? "1" : "0";
// applePayInsertRequest.language = await getLanguageID() == 'ar' ? 'ar' : 'en';
// applePayInsertRequest.userName = authenticatedUser.patientID;
// applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
// applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
// applePayInsertRequest.paymentOption = "ApplePay";
//
// service.applePayInsertRequest(applePayInsertRequest, context).then((res) {
// if (context != null) GifLoaderDialogUtils.hideDialog(context);
// String url = "https://hmgwebservices.com/HMGApplePayLive/applepay/pay?apq=" + res['result']; // Prod
// // String url = "https://uat.hmgwebservices.com/HMGApplePayLive/applepay/pay?apq=" + res['result']; // UAT
// // safariBrowser.open(url: Uri.parse(url));
// this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(url))), options: _InAppBrowserOptions);
// }).catchError((err) {
// print(err);
// if (context != null) GifLoaderDialogUtils.hideDialog(context);
// AppToast.showErrorToast(message: err);
// });
} else if (paymentMethod == "TAMARA") {
// LiveCareService service = new LiveCareService();
TamaraRequestModel tamaraRequestModel = new TamaraRequestModel();
// if (context != null) GifLoaderDialogUtils.showMyDialog(context);
tamaraRequestModel.merchantReference = transactionID;
tamaraRequestModel.merchantIdentifier = "Tamara";
tamaraRequestModel.clientRequestID = transactionID;
tamaraRequestModel.amount = amount;
tamaraRequestModel.currency = "SR";
tamaraRequestModel.language = appState.isArabic() ? 'AR' : 'EN';
tamaraRequestModel.commandType = "PURCHASE";
tamaraRequestModel.customerEmail = emailId;
tamaraRequestModel.orderDescription = orderDesc;
tamaraRequestModel.isInstallment = true;
tamaraRequestModel.projectID = num.parse(projId);
tamaraRequestModel.accessCode = authenticatedUser.mobileNumber!;
tamaraRequestModel.appointmentNo = (appoNo != null && appoNo != "") ? appoNo.toString() : "0";
tamaraRequestModel.customerName = patientName;
tamaraRequestModel.fileNumber = patientID.toString();
tamaraRequestModel.patientOutSA = authenticatedUser.outSa == 1 ? true : false;
tamaraRequestModel.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
tamaraRequestModel.latitude = appState.userLat.toString();
tamaraRequestModel.longitude = appState.userLong.toString();
tamaraRequestModel.serviceID = servID;
tamaraRequestModel.liveServiceID = LiveServID;
tamaraRequestModel.doctorID = (doctorID.toString() != null && doctorID != "") ? doctorID.toString() : "";
tamaraRequestModel.appointmentDate = (appoDate != null && appoDate != "") ? appoDate : null;
tamaraRequestModel.isSchedule = ((appoNo != null && appoNo != "") && (appoDate != null && appoDate != "")) ? true : false;
// service.tamaraInsertRequest(tamaraRequestModel, context).then((res) {
// // if (context != null) GifLoaderDialogUtils.hideDialog(context);
// generateTamaraURL(amount, orderDesc, transactionID, projId, emailId, paymentMethod, patientType, patientName, patientID, authenticatedUser, isLiveCareAppo, servID, LiveServID, appoDate,
// appoNo, clinicID, doctorID, "", installments)
// .then((value) {
// paymentType = _PAYMENT_TYPE.PATIENT;
// this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions);
// });
// }).catchError((err) {
// print(err);
// // if (context != null) GifLoaderDialogUtils.hideDialog(context);
// // AppToast.showErrorToast(message: err);
// });
} else {
generateURL(amount, orderDesc, transactionID, projId, emailId, paymentMethod, patientType, patientName, patientID, authenticatedUser, isLiveCareAppo, servID, LiveServID, appoDate, appoNo,
clinicID, doctorID)
.then((value) {
paymentType = _PAYMENT_TYPE.PATIENT;
this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions);
});
}
}
// openPharmacyPaymentBrowser(OrderDetailModel order, double amount, String orderDesc, String transactionID, String emailId, String paymentMethod, String patientName, dynamic patientID,
// AuthenticatedUser authenticatedUser, InAppBrowser browser) {
// this.browser = browser;
// MyChromeSafariBrowser safariBrowser =
// new MyChromeSafariBrowser(new MyInAppBrowser(onExitCallback: browser.onExit), onExitCallback: browser.onExit, onLoadStartCallback: this.browser.onLoadStart, appo: this.appo!);
// // getPatientData();
// generatePharmacyURL(order, amount, orderDesc, transactionID, emailId, paymentMethod, patientName, patientID, authenticatedUser).then((value) {
// if (order.customValuesXml!.contains("ApplePay")) {
// safariBrowser.open(url: WebUri.uri(Uri.parse(value)));
// } else {
// this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions);
// }
// });
// }
openBrowser(String url) {
this.browser = browser;
this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(url))), options: _InAppBrowserOptions);
}
Future<String> generateURL(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID,
AuthenticatedUser authUser, bool isLiveCareAppo, var servID, var LiveServID,
[var appoDate, var appoNo, var clinicID, var doctorID, var patientData]) async {
// getDeviceToken();
String currentLanguageID = appState.isArabic() ? 'AR' : 'EN';
String form = isLiveCareAppo ? getLiveCareForm() : getForm();
form = form.replaceFirst("EMAIL_VALUE", emailId);
form = form.replaceFirst('AMOUNT_VALUE', amount.toString());
form = form.replaceFirst('ORDER_DESCRIPTION_VALUE', orderDesc);
form = form.replaceFirst('ORDER_ID_VALUE', transactionID);
form = form.replaceFirst('REQUEST_ID_VALUE', transactionID);
form = form.replaceFirst('PROJECT_ID_VALUE', projId);
form = form.replaceFirst('PAYMENT_OPTION_VALUE', paymentMethod);
form = form.replaceFirst('LANG_VALUE', currentLanguageID);
form = form.replaceFirst('PATIENT_OUT_SA', authUser.outSa == 0 ? false.toString() : true.toString());
form = form.replaceFirst('PATIENT_TYPE_ID', patientData == null ? patientType.toString() : "1");
Platform.isIOS
? form = form.replaceFirst('DEVICE_TOKEN', "${await Utils.getStringFromPrefs(CacheConst.pushToken)},${await Utils.getStringFromPrefs(CacheConst.apnsToken)}")
: form = form.replaceFirst('DEVICE_TOKEN', await Utils.getStringFromPrefs(CacheConst.pushToken) ?? "");
// form = form.replaceFirst('DEVICE_TOKEN', await AppSharedPreferences().getString(PUSH_TOKEN) + "," + await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN));
// form = form.replaceFirst('DEVICE_TOKEN', await sharedPref.getString(PUSH_TOKEN));
form = form.replaceFirst('LATITUDE_VALUE', this.lat.toString());
form = form.replaceFirst('LONGITUDE_VALUE', this.long.toString());
// if (servID == "4")
// form = form.replaceFirst('SERVICE_URL_VALUE', MyInAppBrowser.PREAUTH_SERVICE_URL);
// else
form = form.replaceFirst('SERVICE_URL_VALUE', ApiConsts.SERVICE_URL);
if (servID != null) {
form = form.replaceFirst('SERV_ID', servID);
form = form.replaceFirst('LIVE_SERVICE_ID', LiveServID.toString());
} else {
form = form.replaceFirst('SERV_ID', "2");
form = form.replaceFirst('LIVE_SERVICE_ID', "2");
}
form = form.replaceFirst('CUSTNAME_VALUE', patientName);
form = form.replaceFirst('CUSTID_VALUE', patientID.toString());
if (isLiveCareAppo) {
form = form.replaceFirst('IS_SCHEDULE_VALUE', "true");
form = form.replaceFirst('APPOINTMENT_DATE_VALUE', appoDate);
form = form.replaceFirst('APPOINTMENT_NO_VALUE', appoNo.toString());
form = form.replaceFirst('DOCTOR_ID_VALUE', doctorID.toString());
form = form.replaceFirst('CLINIC_ID_VALUE', clinicID.toString());
}
var bytes = utf8.encode(form);
var base64Str = base64.encode(bytes);
return 'data:text/html;base64,' + base64Str;
}
Future<String> generateTamaraURL(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID,
AuthenticatedUser authUser, bool isLiveCareAppo, var servID, var LiveServID,
[var appoDate, var appoNo, var clinicID, var doctorID, var patientData, var installments]) async {
// getDeviceToken();
String currentLanguageID = appState.isArabic() ? 'AR' : 'EN';
String form = getTamaraForm();
form = form.replaceFirst("EMAIL_VALUE", emailId);
form = form.replaceFirst('AMOUNT_VALUE', amount.toString());
form = form.replaceFirst('ORDER_DESCRIPTION_VALUE', orderDesc);
form = form.replaceFirst('ORDER_ID_VALUE', transactionID);
form = form.replaceFirst('REQUEST_ID_VALUE', transactionID);
form = form.replaceFirst('PROJECT_ID_VALUE', projId);
form = form.replaceFirst('PAYMENT_OPTION_VALUE', paymentMethod);
form = form.replaceFirst('LANG_VALUE', currentLanguageID);
form = form.replaceFirst('SERVICE_URL_VALUE', "https://mdlaboratories.com/tamaralive/Home/Checkout");
form = form.replaceFirst('INSTALLMENTS_VALUE', installments);
form = form.replaceFirst('CUSTNATIONALID_VALUE', authUser.patientIdentificationNo!);
form = form.replaceFirst('CUSTMOBILE_VALUE', authUser.mobileNumber!);
form = form.replaceFirst('CUSTDOB_VALUE', DateUtil.getDayMonthYearDateFormatted(authUser.strDateofBirth!));
form = form.replaceFirst('CURRENCY_VALUE', authUser.outSa == 0 ? "SAR" : "AED");
form = form.replaceFirst('COUNTRY_CODE_VALUE', authUser.outSa == 0 ? "966" : "971");
form = form.replaceFirst('CUSTNAME_VALUE', patientName);
form = form.replaceFirst('CUSTLASTNAME_VALUE', patientName);
form = form.replaceFirst('CUSTID_VALUE', patientID.toString());
var bytes = utf8.encode(form);
var base64Str = base64.encode(bytes);
return 'data:text/html;base64,' + base64Str;
}
String getForm() {
return '<html> ' +
'<head></head>' +
'<body>' +
'<form id="paymentForm" action="SERVICE_URL_VALUE" method="post">' +
'<input type="hidden" name="Amount" value="AMOUNT_VALUE">' +
'<input type="hidden" name="ProjID" value="PROJECT_ID_VALUE">' +
'<input type="hidden" name="Order_Desc" value="ORDER_DESCRIPTION_VALUE">' +
'<input type="hidden" name="OrderID" value="ORDER_ID_VALUE">' +
'<input type="hidden" name="PaymentOption" value="PAYMENT_OPTION_VALUE">' +
'<input type="hidden" name="Email" value="EMAIL_VALUE">' +
'<input type="hidden" name="ServID" value="SERV_ID" >' +
'<input type="hidden" name="ChannelID" value="2" >' +
'<input type="hidden" name="Lang" value="LANG_VALUE" >' +
'<input type="hidden" name="ReturnURL" value="" >' +
'<input type="hidden" name="CustName" value="CUSTNAME_VALUE" >' +
'<input type="hidden" name="PatientOutSA" value="PATIENT_OUT_SA" >' +
'<input type="hidden" name="PatientTypeID" value="PATIENT_TYPE_ID" >' +
'<input type="hidden" name="DeviceToken" value="DEVICE_TOKEN" >' +
'<input type="hidden" name="Longitude" value="LONGITUDE_VALUE" >' +
'<input type="hidden" name="Latitude" value="LATITUDE_VALUE" >' +
'<input type="hidden" name="Live_ServiceID" value="LIVE_SERVICE_ID" >' +
'<input type="hidden" name="CustID" value="CUSTID_VALUE" >' +
'<input type="hidden" name="ResponseContinueURL" value="http://hmg.com/Documents/success.html" >' +
'<input type="hidden" name="BackClickUrl" value="http://hmg.com/Documents/success.html" >' +
'</form>' +
'<script type="text/javascript"> document.getElementById("paymentForm").submit(); </script>' +
'</body>' +
'</html>';
}
String getTamaraForm() {
return '<html> ' +
'<head></head>' +
'<body>' +
'<form id="paymentForm" action="SERVICE_URL_VALUE" method="post">' +
'<input type="hidden" name="totalAmount" value="AMOUNT_VALUE">' +
'<input type="hidden" name="shippingAmount" value="0">' +
'<input type="hidden" name="taxAmount" value="0">' +
'<input type="hidden" name="discountAmount" value="0">' +
'<input type="hidden" name="PaymentType" value="PAY_BY_INSTALMENTS">' +
'<input type="hidden" name="Instalments" value="INSTALLMENTS_VALUE">' +
'<input type="hidden" name="ProjID" value="PROJECT_ID_VALUE">' +
'<input type="hidden" name="description" value="ORDER_DESCRIPTION_VALUE">' +
'<input type="hidden" name="OrderID" value="ORDER_ID_VALUE">' +
'<input type="hidden" name="Currency" value="CURRENCY_VALUE">' +
'<input type="hidden" name="CountryCode" value="COUNTRY_CODE_VALUE">' +
'<input type="hidden" name="Consumer.Email" value="EMAIL_VALUE">' +
'<input type="hidden" name="Lang" value="LANG_VALUE" >' +
'<input type="hidden" name="ReturnURL" value="https://mdlaboratories.com">' +
'<input type="hidden" name="Consumer.NationalId" value="CUSTNATIONALID_VALUE" >' +
'<input type="hidden" name="Consumer.PhoneNumber" value="CUSTMOBILE_VALUE" >' +
'<input type="hidden" name="Consumer.FirstName" value="CUSTNAME_VALUE" >' +
'<input type="hidden" name="Consumer.LastName" value="CUSTLASTNAME_VALUE" >' +
'<input type="hidden" name="Consumer.DateOfBirth" value="CUSTDOB_VALUE" >' +
'<input type="hidden" name="Consumer.IsFirstOrder" value="false" >' +
'<input type="hidden" name="address.Line1" value="">' +
'<input type="hidden" name="address.Line2" value="">' +
'<input type="hidden" name="address.City" value="Riyadh">' +
'<input type="hidden" name="address.CountryCode" value="SA">' +
'<input type="hidden" name="address.PostalCode" value="12626">' +
'<input type="hidden" name="address.Region" value="">'
'</form>' +
'<script type="text/javascript"> document.getElementById("paymentForm").submit(); </script>' +
'</body>' +
'</html>';
}
String getLiveCareForm() {
return '<html> ' +
'<head></head>' +
'<body>' +
'<form id="paymentForm" action="SERVICE_URL_VALUE" method="post">' +
'<input type="hidden" name="Amount" value="AMOUNT_VALUE">' +
'<input type="hidden" name="ProjID" value="PROJECT_ID_VALUE">' +
'<input type="hidden" name="IsSchedule" value="IS_SCHEDULE_VALUE">' +
'<input type="hidden" name="AppointmentDate" value="APPOINTMENT_DATE_VALUE">' +
'<input type="hidden" name="AppointmentNo" value="APPOINTMENT_NO_VALUE">' +
'<input type="hidden" name="DoctorID" value="DOCTOR_ID_VALUE">' +
'<input type="hidden" name="ClinicID" value="CLINIC_ID_VALUE">' +
'<input type="hidden" name="Order_Desc" value="ORDER_DESCRIPTION_VALUE">' +
'<input type="hidden" name="OrderID" value="ORDER_ID_VALUE">' +
'<input type="hidden" name="PaymentOption" value="PAYMENT_OPTION_VALUE">' +
'<input type="hidden" name="Email" value="EMAIL_VALUE">' +
'<input type="hidden" name="ServID" value="SERV_ID" >' +
'<input type="hidden" name="ChannelID" value="2" >' +
'<input type="hidden" name="Lang" value="LANG_VALUE" >' +
'<input type="hidden" name="ReturnURL" value="" >' +
'<input type="hidden" name="CustName" value="CUSTNAME_VALUE" >' +
'<input type="hidden" name="PatientOutSA" value="PATIENT_OUT_SA" >' +
'<input type="hidden" name="PatientTypeID" value="PATIENT_TYPE_ID" >' +
'<input type="hidden" name="DeviceToken" value="DEVICE_TOKEN" >' +
'<input type="hidden" name="Longitude" value="LONGITUDE_VALUE" >' +
'<input type="hidden" name="Latitude" value="LATITUDE_VALUE" >' +
'<input type="hidden" name="Live_ServiceID" value="LIVE_SERVICE_ID" >' +
'<input type="hidden" name="CustID" value="CUSTID_VALUE" >' +
'<input type="hidden" name="ResponseContinueURL" value="http://hmg.com/Documents/success.html" >' +
'<input type="hidden" name="BackClickUrl" value="http://hmg.com/Documents/success.html" >' +
'</form>' +
'<script type="text/javascript"> document.getElementById("paymentForm").submit(); </script>' +
'</body>' +
'</html>';
}
safariCallBack() {
print("Safari CallBack!!!");
}
}
class MyChromeSafariBrowser extends ChromeSafariBrowser {
final Function? onExitCallback;
final Function? onLoadStartCallback;
// AppoitmentAllHistoryResultList? appo;
// MyChromeSafariBrowser(browserFallback, {this.onExitCallback, this.onLoadStartCallback, this.appo});
MyChromeSafariBrowser(browserFallback, {this.onExitCallback, this.onLoadStartCallback});
@override
void onOpened() {
print("ChromeSafari browser opened");
}
@override
void onCompletedInitialLoad(bool? didLoadSuccessfully) {
print("ChromeSafari browser initial load completed");
onLoadStartCallback!("ApplePay");
}
@override
void onClosed() {
print("ChromeSafari browser closed");
MyInAppBrowser.isPaymentDone = true;
onExitCallback!();
}
}

@ -19,6 +19,7 @@ class TextInputWidget extends StatelessWidget {
final String hintText;
final TextEditingController? controller;
final Function(String?)? onChange;
final Function(bool)? onCalendarTypeChanged;
final String? prefix;
final bool isEnable;
final bool isBorderAllowed;
@ -45,6 +46,7 @@ class TextInputWidget extends StatelessWidget {
required this.hintText,
this.controller,
this.onChange,
this.onCalendarTypeChanged,
this.prefix,
this.isEnable = true,
this.isBorderAllowed = true,
@ -157,10 +159,10 @@ class TextInputWidget extends StatelessWidget {
isGregorian = value;
});
if (picked != null && onChange != null) {
// if (onCalendarTypeChanged != null) {
// onCalendarTypeChanged.call(isGregorian);
// }
onChange!(picked.toIso8601String());
if (onCalendarTypeChanged != null) {
onCalendarTypeChanged!.call(isGregorian);
}
onChange!(picked.toString());
}
},
child: Utils.buildSvgWithAssets(icon: AppAssets.calendar),

@ -65,11 +65,14 @@ dependencies:
google_api_availability: ^5.0.1
firebase_analytics: ^11.5.1
jiffy: ^6.4.3
hijri_gregorian_calendar: ^0.0.4
hijri_gregorian_calendar: ^0.1.0
web: any
flutter_staggered_animations: ^1.1.1
smooth_corner: ^1.1.1
maps_launcher: ^3.0.0+1
amazon_payfort: ^1.1.4
network_info_plus: ^6.1.4
dev_dependencies:
flutter_test:
@ -81,6 +84,7 @@ flutter:
uses-material-design: true
assets:
- assets/
- assets/json/
- assets/fonts/
- assets/langs/
- assets/images/

Loading…
Cancel
Save