Merge branch 'master' into dev_aamir
# Conflicts: # lib/core/app_state.dartpull/15/head
| After Width: | Height: | Size: 10 KiB | 
| 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 | 
| @ -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 | 
| @ -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 | 
| @ -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; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,73 @@ | ||||
| class PatientInsuranceCardHistoryResponseModel { | ||||
|   int? createdBy; | ||||
|   String? createdOn; | ||||
|   int? editedBy; | ||||
|   String? editedOn; | ||||
|   String? insuranceCardImage; | ||||
|   String? mobileNumber; | ||||
|   int? patientID; | ||||
|   String? patientIdentificationNo; | ||||
|   String? patientInsuranceCardUpdateInfoID; | ||||
|   int? patientType; | ||||
|   int? projectID; | ||||
|   String? rejectionRemarks; | ||||
|   int? setupID; | ||||
|   int? status; | ||||
|   String? statusDescription; | ||||
| 
 | ||||
|   PatientInsuranceCardHistoryResponseModel( | ||||
|       {this.createdBy, | ||||
|         this.createdOn, | ||||
|         this.editedBy, | ||||
|         this.editedOn, | ||||
|         this.insuranceCardImage, | ||||
|         this.mobileNumber, | ||||
|         this.patientID, | ||||
|         this.patientIdentificationNo, | ||||
|         this.patientInsuranceCardUpdateInfoID, | ||||
|         this.patientType, | ||||
|         this.projectID, | ||||
|         this.rejectionRemarks, | ||||
|         this.setupID, | ||||
|         this.status, | ||||
|         this.statusDescription}); | ||||
| 
 | ||||
|   PatientInsuranceCardHistoryResponseModel.fromJson(Map<String, dynamic> json) { | ||||
|     createdBy = json['CreatedBy']; | ||||
|     createdOn = json['CreatedOn']; | ||||
|     editedBy = json['EditedBy']; | ||||
|     editedOn = json['EditedOn']; | ||||
|     insuranceCardImage = json['InsuranceCardImage']; | ||||
|     mobileNumber = json['MobileNumber']; | ||||
|     patientID = json['PatientID']; | ||||
|     patientIdentificationNo = json['PatientIdentificationNo']; | ||||
|     patientInsuranceCardUpdateInfoID = json['PatientInsuranceCardUpdateInfoID']; | ||||
|     patientType = json['PatientType']; | ||||
|     projectID = json['ProjectID']; | ||||
|     rejectionRemarks = json['RejectionRemarks']; | ||||
|     setupID = json['SetupID']; | ||||
|     status = json['Status']; | ||||
|     statusDescription = json['StatusDescription']; | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() { | ||||
|     final Map<String, dynamic> data = new Map<String, dynamic>(); | ||||
|     data['CreatedBy'] = this.createdBy; | ||||
|     data['CreatedOn'] = this.createdOn; | ||||
|     data['EditedBy'] = this.editedBy; | ||||
|     data['EditedOn'] = this.editedOn; | ||||
|     data['InsuranceCardImage'] = this.insuranceCardImage; | ||||
|     data['MobileNumber'] = this.mobileNumber; | ||||
|     data['PatientID'] = this.patientID; | ||||
|     data['PatientIdentificationNo'] = this.patientIdentificationNo; | ||||
|     data['PatientInsuranceCardUpdateInfoID'] = | ||||
|         this.patientInsuranceCardUpdateInfoID; | ||||
|     data['PatientType'] = this.patientType; | ||||
|     data['ProjectID'] = this.projectID; | ||||
|     data['RejectionRemarks'] = this.rejectionRemarks; | ||||
|     data['SetupID'] = this.setupID; | ||||
|     data['Status'] = this.status; | ||||
|     data['StatusDescription'] = this.statusDescription; | ||||
|     return data; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,88 @@ | ||||
| class PatientInsuranceUpdateResponseModel { | ||||
|   dynamic approvalLimit; | ||||
|   int? companyGroupID; | ||||
|   String? companyName; | ||||
|   String? companyRemarks; | ||||
|   String? dOB; | ||||
|   dynamic deductible; | ||||
|   String? effectiveFrom; | ||||
|   String? effectiveTo; | ||||
|   String? eligabilityFailureReason; | ||||
|   bool? isMemberEligible; | ||||
|   String? memberID; | ||||
|   String? memberName; | ||||
|   String? memberStatus; | ||||
|   dynamic message; | ||||
|   String? nationalId; | ||||
|   String? policyNumber; | ||||
|   String? responseMessage; | ||||
|   dynamic room; | ||||
|   String? subCategory; | ||||
| 
 | ||||
|   PatientInsuranceUpdateResponseModel( | ||||
|       {this.approvalLimit, | ||||
|         this.companyGroupID, | ||||
|         this.companyName, | ||||
|         this.companyRemarks, | ||||
|         this.dOB, | ||||
|         this.deductible, | ||||
|         this.effectiveFrom, | ||||
|         this.effectiveTo, | ||||
|         this.eligabilityFailureReason, | ||||
|         this.isMemberEligible, | ||||
|         this.memberID, | ||||
|         this.memberName, | ||||
|         this.memberStatus, | ||||
|         this.message, | ||||
|         this.nationalId, | ||||
|         this.policyNumber, | ||||
|         this.responseMessage, | ||||
|         this.room, | ||||
|         this.subCategory}); | ||||
| 
 | ||||
|   PatientInsuranceUpdateResponseModel.fromJson(Map<String, dynamic> json) { | ||||
|     approvalLimit = json['ApprovalLimit']; | ||||
|     companyGroupID = json['CompanyGroupID']; | ||||
|     companyName = json['CompanyName']; | ||||
|     companyRemarks = json['CompanyRemarks']; | ||||
|     dOB = json['DOB']; | ||||
|     deductible = json['Deductible']; | ||||
|     effectiveFrom = json['EffectiveFrom']; | ||||
|     effectiveTo = json['EffectiveTo']; | ||||
|     eligabilityFailureReason = json['EligabilityFailureReason']; | ||||
|     isMemberEligible = json['IsMemberEligible']; | ||||
|     memberID = json['MemberID']; | ||||
|     memberName = json['MemberName']; | ||||
|     memberStatus = json['MemberStatus']; | ||||
|     message = json['Message']; | ||||
|     nationalId = json['NationalId']; | ||||
|     policyNumber = json['PolicyNumber']; | ||||
|     responseMessage = json['ResponseMessage']; | ||||
|     room = json['Room']; | ||||
|     subCategory = json['SubCategory']; | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() { | ||||
|     final Map<String, dynamic> data = new Map<String, dynamic>(); | ||||
|     data['ApprovalLimit'] = this.approvalLimit; | ||||
|     data['CompanyGroupID'] = this.companyGroupID; | ||||
|     data['CompanyName'] = this.companyName; | ||||
|     data['CompanyRemarks'] = this.companyRemarks; | ||||
|     data['DOB'] = this.dOB; | ||||
|     data['Deductible'] = this.deductible; | ||||
|     data['EffectiveFrom'] = this.effectiveFrom; | ||||
|     data['EffectiveTo'] = this.effectiveTo; | ||||
|     data['EligabilityFailureReason'] = this.eligabilityFailureReason; | ||||
|     data['IsMemberEligible'] = this.isMemberEligible; | ||||
|     data['MemberID'] = this.memberID; | ||||
|     data['MemberName'] = this.memberName; | ||||
|     data['MemberStatus'] = this.memberStatus; | ||||
|     data['Message'] = this.message; | ||||
|     data['NationalId'] = this.nationalId; | ||||
|     data['PolicyNumber'] = this.policyNumber; | ||||
|     data['ResponseMessage'] = this.responseMessage; | ||||
|     data['Room'] = this.room; | ||||
|     data['SubCategory'] = this.subCategory; | ||||
|     return data; | ||||
|   } | ||||
| } | ||||
| @ -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; | ||||
|   } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -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", | ||||
|                       )), | ||||
|                 ], | ||||
|               ), | ||||
|             ], | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -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), | ||||
|                 ], | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,139 @@ | ||||
| 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/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/insurance/insurance_view_model.dart'; | ||||
| import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; | ||||
| import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||
| import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; | ||||
| import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| 
 | ||||
| class PatientInsuranceCardUpdateCard extends StatelessWidget { | ||||
|   PatientInsuranceCardUpdateCard({super.key}); | ||||
| 
 | ||||
|   late InsuranceViewModel insuranceViewModel; | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     insuranceViewModel = Provider.of<InsuranceViewModel>(context); | ||||
|     return Column( | ||||
|       children: [ | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|           children: [ | ||||
|             LocaleKeys.insuranceCards.tr(context: context).toText24(isBold: true), | ||||
|             Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon).onPress(() { | ||||
|               Navigator.of(context).pop(); | ||||
|             }), | ||||
|           ], | ||||
|         ).paddingSymmetrical(24.h, 24.h), | ||||
|         insuranceViewModel.isInsuranceUpdateDetailsLoading | ||||
|             ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 24.h) | ||||
|             : Container( | ||||
|                 // height: 120.h, | ||||
|                 decoration: RoundedRectangleBorder().toSmoothCornerDecoration( | ||||
|                   color: AppColors.whiteColor, | ||||
|                   borderRadius: 24, | ||||
|                 ), | ||||
|                 child: Column( | ||||
|                   crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                   children: [ | ||||
|                     "Haroon Amjad".toText16(weight: FontWeight.w600), | ||||
|                     "Policy: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.policyNumber}".toText12(isBold: true, color: AppColors.lightGrayColor), | ||||
|                     SizedBox(height: 8.h), | ||||
|                     Row( | ||||
|                       children: [ | ||||
|                         insuranceViewModel.patientInsuranceUpdateResponseModel!.companyName!.toText12(isBold: true), | ||||
|                         SizedBox( | ||||
|                           width: 6.h, | ||||
|                         ), | ||||
|                         Container( | ||||
|                           padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 3.h), | ||||
|                           decoration: RoundedRectangleBorder().toSmoothCornerDecoration( | ||||
|                             color: AppColors.infoColor, | ||||
|                             borderRadius: 50, | ||||
|                           ), | ||||
|                           child: insuranceViewModel.patientInsuranceUpdateResponseModel!.subCategory!.toText8(isBold: true, color: AppColors.whiteColor), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                     SizedBox(height: 8.h), | ||||
|                     Row( | ||||
|                       children: [ | ||||
|                         Wrap( | ||||
|                           direction: Axis.horizontal, | ||||
|                           spacing: 4.h, | ||||
|                           runSpacing: 4.h, | ||||
|                           children: [ | ||||
|                             Row( | ||||
|                               children: [ | ||||
|                                 CustomButton( | ||||
|                                   icon: AppAssets.doctor_calendar_icon, | ||||
|                                   iconColor: AppColors.blackColor, | ||||
|                                   iconSize: 13.h, | ||||
|                                   text: "${LocaleKeys.expiryOn.tr(context: context)} ${insuranceViewModel.patientInsuranceUpdateResponseModel!.effectiveTo}", | ||||
|                                   onPressed: () {}, | ||||
|                                   backgroundColor: AppColors.greyColor, | ||||
|                                   borderColor: AppColors.greyColor, | ||||
|                                   textColor: AppColors.blackColor, | ||||
|                                   fontSize: 10, | ||||
|                                   fontWeight: FontWeight.w500, | ||||
|                                   borderRadius: 12, | ||||
|                                   padding: EdgeInsets.fromLTRB(10, 0, 10, 0), | ||||
|                                   height: 30.h, | ||||
|                                 ), | ||||
|                               ], | ||||
|                             ), | ||||
|                             Row( | ||||
|                               children: [ | ||||
|                                 CustomButton( | ||||
|                                   text: "Member ID: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.memberID!}", | ||||
|                                   onPressed: () {}, | ||||
|                                   backgroundColor: AppColors.greyColor, | ||||
|                                   borderColor: AppColors.greyColor, | ||||
|                                   textColor: AppColors.blackColor, | ||||
|                                   fontSize: 10, | ||||
|                                   fontWeight: FontWeight.w500, | ||||
|                                   borderRadius: 12, | ||||
|                                   padding: EdgeInsets.fromLTRB(10, 0, 10, 0), | ||||
|                                   height: 30.h, | ||||
|                                 ), | ||||
|                               ], | ||||
|                             ), | ||||
|                           ], | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ], | ||||
|                 ).paddingSymmetrical(16.h, 16.h), | ||||
|               ).paddingSymmetrical(24.h, 0.h), | ||||
|         SizedBox( | ||||
|           height: 24.h, | ||||
|         ), | ||||
|         CustomButton( | ||||
|           icon: AppAssets.insurance_active_icon, | ||||
|           iconColor: AppColors.whiteColor, | ||||
|           iconSize: 20.h, | ||||
|           text: "Update Insurance", | ||||
|           onPressed: () {}, | ||||
|           backgroundColor: AppColors.successColor, | ||||
|           borderColor: AppColors.successColor.withOpacity(0.01), | ||||
|           textColor: AppColors.whiteColor, | ||||
|           fontSize: 16, | ||||
|           fontWeight: FontWeight.w500, | ||||
|           borderRadius: 12, | ||||
|           padding: EdgeInsets.fromLTRB(10, 0, 10, 0), | ||||
|           height: 56.h, | ||||
|         ).paddingSymmetrical(24.h, 0.h), | ||||
|         SizedBox( | ||||
|           height: 24.h, | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -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 []; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -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!(); | ||||
|   } | ||||
| } | ||||