315 Commits

Author SHA1 Message Date
yasien_gmail cfd6b8c5f4 Fix flatpak build and run issues 2026-06-10 12:16:00 +02:00
yasien_gmail 0ea3482e9a revert Dockerfile 2026-06-10 09:40:01 +02:00
yasien_gmail 0e05ce0b89 WIP:update flatpak configs 2026-06-10 09:37:57 +02:00
yasien_gmail 166328df89 updated .git to ignore flatpak build files 2026-06-10 09:35:38 +02:00
yasien_gmail 87b0ebfa27 lock mih-ai to ollama 0.30.6 2026-06-08 08:30:58 +02:00
yasien_gmail c32972ea6d add screenshots for app stores 2026-06-05 10:50:20 +02:00
yasien_gmail 76456fb530 include network to mih-legal 2026-06-05 10:05:05 +02:00
yasien_gmail 1241540bbe create seperate privacy policy server 2026-06-05 09:56:02 +02:00
yasien_gmail 21ae7d92a8 update version numer to 1.3.0 and add remaining files 2026-06-04 10:56:43 +02:00
yasien_gmail ef1f8b18cd fix deep link to privacy policy and update docker file with lastest container for ollama, portainer and api-hub 2026-06-04 10:47:27 +02:00
yasien_gmail 4b1a70f709 update mzansi ai to qwen3.5:9b 2026-06-03 14:26:47 +02:00
yasien_gmail ea3d796013 enable gpu for mzansi ai 2026-06-02 12:35:20 +02:00
yasien_gmail 5f7daadf85 fix deep link for unsigned in user 2026-06-02 10:48:11 +02:00
yasien_gmail 482dde9a72 service worker v4 2026-06-02 10:36:42 +02:00
yasien_gmail b518b9e536 service worker stuff 2026-06-02 10:06:17 +02:00
yasien_gmail a85def8156 fix service worker logic for new mih updates 2026-06-02 09:40:14 +02:00
yasien_gmail 86556e7543 fix docker file flutter 2026-06-01 15:43:32 +02:00
yasien_gmail 95511fdc99 fix font awesome icons use 2026-06-01 15:37:27 +02:00
yasien_gmail 0dc8ac49be fix font awesome icons 2026-06-01 14:44:46 +02:00
yasien_gmail 93942ff060 switch from query paramater to path paramater for profile views 2026-06-01 14:14:56 +02:00
yasien_gmail efe225b9f8 Add business profile links 2026-06-01 12:58:17 +02:00
yasien_gmail 49c7ecce1f add provider indexing for business & user views 2026-05-29 08:26:27 +02:00
yasien_gmail 39bf88356f fix I dont know logo and profile link build issues 2026-05-27 16:32:28 +02:00
yasien_gmail 052f937027 MIH Profile Links 2026-05-27 15:36:56 +02:00
yasien_gmail 33d07b1617 fix alert colors 2026-05-26 14:59:56 +02:00
yasien_gmail 806c25d7b0 fix profile link api 2026-05-26 14:59:41 +02:00
yasien_gmail aee6497ccb Fix go router to work with web and ios nav 2026-05-26 13:19:34 +02:00
yasien_gmail e85bf2d577 fix clicks cardf colors 2026-05-22 10:40:23 +02:00
yasien_gmail 2a5056e7ff profile links display enhancement 2026-04-29 14:44:00 +02:00
yasien_gmail e0a381d00e fix ios icon & fix ios navigation bug pt2 2026-04-28 15:33:21 +02:00
yasien_gmail 2be2f69f30 fix ios icon & fix ios navigation bug 2026-04-28 15:17:16 +02:00
yasien_gmail 17f7f3287d add localhost port 83 for api call 2026-04-24 13:08:04 +02:00
yasien_gmail c2353fef20 update mih ui with stable flutter and optimised docker file caching 2026-04-24 13:07:20 +02:00
yasien_gmail 3e3170b103 fix supertokens to work with lastest version of flutter 2026-04-24 13:02:12 +02:00
yasien_gmail d71f337d37 Mzansi Wallet new list display pt2 2026-04-22 11:52:54 +02:00
yasien_gmail 62c5634cf6 Mzansi Wallet new list display pt1 2026-04-22 10:45:49 +02:00
yasien_gmail 26d3638d80 remove image url print 2026-04-16 10:00:53 +02:00
yasien_gmail 6c591172df update android skd to 36 2026-04-16 10:00:21 +02:00
yasien_gmail 0a5c4a3d20 Get all user and business data on any ackage load 2026-04-15 12:47:01 +02:00
yasien_gmail c0077e532c Mzansi Wallet 2.0 update 2026-04-15 12:39:48 +02:00
yasien_gmail 379633d7f5 remove usage of user type 2026-04-15 08:40:55 +02:00
yasien_gmail c855503edd Mzansi AI model update to qwen3.5 2026-04-14 10:43:04 +02:00
yasien_gmail 0f6c6e51ab New Business Setup Flow 2026-04-08 15:47:33 +02:00
yasien_gmail e5ce03e396 migrate to mih_package_tooklit 2026-03-20 12:04:18 +02:00
yasien_gmail c67529dbac Migration to mih_package_toolkit 2026-03-18 16:42:12 +02:00
yasien_gmail 84cb6b2e83 linux icon image fix 2026-02-26 15:15:49 +02:00
yasien_gmail 6e07a55885 Flatpak linux build 2026-02-26 13:54:38 +02:00
yasien_gmail 8fb31695a8 linux flatpak config pt11 2026-02-26 12:34:01 +02:00
yasien_gmail 4fafa35888 linux flatpak config pt10 2026-02-26 12:17:14 +02:00
yasien_gmail 0cf9634c5d linux flatpak config pt9 2026-02-26 12:15:59 +02:00
yasien_gmail 787a8057b2 linux flatpak config pt8 2026-02-26 12:15:04 +02:00
yasien_gmail 5f911d51f9 linux flatpak config pt7 2026-02-26 09:31:20 +02:00
yasien_gmail 8da29792b4 linux flatpak config pt6 2026-02-26 09:28:18 +02:00
yasien_gmail 5e003a4d71 linux flatpak config pt5 2026-02-25 15:50:02 +02:00
yasien_gmail fcf1bbbb15 linux flatpak config pt4 2026-02-25 15:44:10 +02:00
yasien_gmail ff7f363983 linux flatpak config pt3 2026-02-25 15:35:45 +02:00
yasien_gmail 843997e58c linux flatpak config pt2 2026-02-25 15:09:23 +02:00
yasien_gmail 3778ebb261 linux flatpak config 2026-02-25 14:51:15 +02:00
yasien_gmail b1487839a7 linux name change 2026-02-25 13:58:42 +02:00
yasien_gmail 221030eff3 fix platform specific code not working on web pt2 2026-02-25 12:16:53 +02:00
yasien_gmail 5135629b33 fix platform specific code not working on web 2026-02-25 12:05:07 +02:00
yasien_gmail 281ea863e8 api cros fix 2026-02-25 11:54:49 +02:00
yasien_gmail 1c0dd6d328 update build number to 130 2026-02-25 10:25:28 +02:00
yasien_gmail 07d4ba4afa Support linux version of MIHpt2 2026-02-24 16:30:06 +02:00
yasien_gmail 6ad6b6ccbd Support linux version of MIH 2026-02-24 15:41:55 +02:00
yasien_gmail ce2575035f make profile picture the full height of the window 2026-02-24 12:43:34 +02:00
yasien_gmail baea2c9fdb fix file display on Dev Web & iOS 2026-02-24 12:37:31 +02:00
yasien_gmail 27639cb964 add scroll bar to dropdown fields 2026-02-24 11:05:24 +02:00
yasien_gmail 1143d11054 fix supertoken versioning error 2026-02-24 11:02:30 +02:00
yasien_gmail 213f3d418d update build number to 129 2026-02-18 15:41:37 +02:00
yasien_gmail e33a62b909 update look & feel of attribution list 2026-02-18 14:03:04 +02:00
yasien_gmail ebab9bae52 update build no to 128 2026-02-18 11:52:30 +02:00
yasien_gmail 82c25c5406 make profile picture expandable 2026-02-18 11:51:44 +02:00
yasien_gmail 3f0fc08a5c update business user edit workflow 2026-02-18 10:56:34 +02:00
yasien_gmail f137ea41ac fix loading indicator alignment for business QR code 2026-02-18 10:41:49 +02:00
yasien_gmail a7effa3576 Update profile link and business card Icons alignment 2026-02-18 10:26:41 +02:00
yasien_gmail 74341a9cc6 Enhance Mzansi Profile Look & Feel and workflow 2026-02-18 10:18:03 +02:00
yasien_gmail c5267c0540 change follow us link alignments 2026-02-16 16:27:39 +02:00
yasien_gmail d4ba3aaa03 fix short cut icon issue 2026-02-16 15:34:27 +02:00
yasien_gmail 103ccdc022 Add scroll bar to mih 2026-02-16 15:23:16 +02:00
yasien_gmail f8a722eb50 change design on profile links and add git option 2026-02-16 14:43:34 +02:00
yasien_gmail fdb28080e3 fix web cros issues with fixed dev port pt2 2026-02-16 14:42:33 +02:00
yasien_gmail 8a384921c5 fix web cros issues with fixed dev port 2026-02-16 14:41:51 +02:00
yasien_gmail 4b47bf5288 enhacne install/ update mih button to cater for huawei 2026-02-16 14:08:00 +02:00
yasien_gmail 141611b84d fix mzansi ai modal 2026-02-16 13:43:15 +02:00
yasien_gmail a29d0afeb8 update version number of mih 2026-02-16 13:25:46 +02:00
yasien_gmail eb93714022 add ds_store file to ingore file 2026-02-16 13:09:33 +02:00
yasien_gmail 071612a521 BUG: API Wildcard CROS issue 2026-02-16 13:09:33 +02:00
yasien_gmail 726a60ad25 BUG: Fix exposed ports on mih server 2026-02-16 13:09:33 +02:00
yasien_gmail b897986c1f BUG: Fix hardcoded supertoken api key 2026-02-16 13:09:33 +02:00
yasien_gmail 7d4d7fc713 BUG: Fix Security Flutter Web server 2026-02-16 13:09:33 +02:00
yasien_gmail 91075255f4 add scrolling to about package 2026-02-10 14:07:05 +02:00
yasien_gmail 5c2f19dcc4 enable linux platform & rename widnow 2026-02-10 11:58:35 +02:00
yaso_meth 58aebbeabe Merge pull request 'ruleset test' (#1) from tester-branch into main
Reviewed-on: #1
2026-02-04 11:18:21 +00:00
yasien_gmail 670480910b ruleset test 2026-02-04 13:16:15 +02:00
yasien_gmail 45c1b247d3 testing 2026-02-04 13:13:21 +02:00
yaso-meth ecd24670e9 Simplify MIH Server start/stop instructions 2026-02-03 16:43:46 +02:00
yaso-meth ab99518ff2 Fix directory name in README for navigation 2026-02-03 16:41:39 +02:00
yaso-meth 6ac6aff59e Update directory name in README for navigation 2026-02-03 16:40:59 +02:00
yasien_gmail 33ca7b613e remove old nginx 2026-02-03 16:31:10 +02:00
yaso-meth e83b0b50ae Merge pull request #265 from yaso-meth/yaso-meth-patch-1
Update README with Gitea and WordPress SQL config
2026-02-03 16:19:38 +02:00
yaso-meth bcd19de256 Update README with Gitea and WordPress SQL config
Add database configuration variables for Gitea and WordPress.
2026-02-03 16:18:48 +02:00
yaso-meth ae36879ec5 Revise title and add introduction in README
Updated project title and added introductory text.
2026-02-03 16:15:41 +02:00
yaso-meth eda609cf7e Update license information for the MIH Project 2026-02-03 15:46:42 +02:00
yaso-meth e1744b09e3 Merge pull request #264 from yaso-meth/V.1.2.5
V.1.2.5
2026-02-03 14:01:14 +02:00
yasien_gmail a3845df8bd Merge branch 'main' into V.1.2.5 2026-02-03 13:57:15 +02:00
yasien_gmail d7eebe152b test file 2026-02-03 13:52:47 +02:00
yasien_gmail d8a807b43e update build to 1.2.5+1.2.6 2026-02-03 13:29:20 +02:00
yasien_gmail 5172017a54 Update MZansi AI prod Model 2026-02-03 13:26:37 +02:00
yasien_gmail 535924691e NEW: Add Mzansi Directory Shortcut 2026-02-03 13:26:17 +02:00
yasien_gmail ca8e0f56ac Remove women4change info and revert colors 2026-02-03 10:17:56 +02:00
yasien_gmail 63071325cb favourite business load fix 2026-02-03 10:15:07 +02:00
yasien_gmail 800cd635c2 Remove profile link from personal profile for now 2026-02-03 10:05:00 +02:00
yasien_gmail f46ce36861 linux app config 2026-02-03 09:57:38 +02:00
yasien_gmail b69fd92b19 Update docker compose file for new architechure 2026-01-29 13:02:24 +02:00
yasien_gmail 9e19dc0fa4 Update API files for new architechure 2026-01-29 13:02:05 +02:00
yasien_gmail 38c40e2dfe Update launch file for new architechure 2026-01-29 13:01:41 +02:00
yasien_gmail 02bbc32d23 Update ignore file for new architechure 2026-01-29 13:01:28 +02:00
yasien_gmail 5b052a1fa9 rename container folders 2026-01-29 11:11:45 +02:00
yasien_gmail d5349d981c update architecture 2026-01-29 11:11:25 +02:00
yasien_gmail d6c28b631a ignore new mih_minio 2026-01-29 11:07:50 +02:00
yasien_gmail 74c5276c94 remove old database ignore 2026-01-29 11:06:01 +02:00
yasien_gmail d5e349d218 ignore new db folder 2026-01-29 11:04:53 +02:00
yasien_gmail 44527c8f10 Add self hosted GIT plaform 2026-01-29 10:08:44 +02:00
yasien_gmail fbb9d8573c pat man loading 2026-01-06 16:49:32 +02:00
yasien_gmail 010fc0bc74 BUG: file viewer opening bug 2025-12-17 20:12:51 +02:00
yasien_gmail 45ac3f03e6 BUG: Supertokens api fix 2025-12-14 23:36:11 +02:00
yasien_gmail eea3248525 NEW: MIH Profile Links pt1 2025-12-11 12:57:12 +02:00
yasien_gmail b945a34ad4 BUG: Profile set up bug 2025-12-10 19:42:55 +02:00
yasien_gmail e3ac1be71c BUG: Business Profile Vew pt2 2025-12-10 12:52:31 +02:00
yasien_gmail 3a955e67ef BUG: Business Profile Vew 2025-12-10 12:52:13 +02:00
yasien_gmail 777043e2ca NEW: Config firebase Cloud Messaging for Notifications 2025-12-10 10:18:57 +02:00
yasien_gmail 6a8b9c6902 QOL: Package Tile Update 2025-12-09 19:14:50 +02:00
yasien_gmail 07360dd308 QOL: only get user data if user is null 2025-12-09 11:46:16 +02:00
yasien_gmail 7c59e2a5c8 NEW: New python package added to requirements 2025-12-09 10:54:33 +02:00
yasien_gmail 0b57e10532 QOL: Button alignment 2025-12-08 19:46:21 +02:00
yasien_gmail 5681c6d73b BUG: Patient Manager Data fix pt2 2025-12-04 09:19:30 +02:00
yasien_gmail f44ff6443c BUG: Patient Manager Data fix 2025-12-03 22:01:49 +02:00
yasien_gmail fe5b61f6bc QOL: Switch from Network Image to CachedNetworkImage 2025-12-03 21:42:42 +02:00
yasien_gmail e7729a8ce8 QOL: About MIH Share button update 2025-12-03 21:35:41 +02:00
yasien_gmail 227a2f7ae7 update buiold to 125 2025-12-03 21:09:22 +02:00
yasien_gmail f26c1eb01a QOL: Mzansi Ai LLM detection 2025-12-03 12:31:21 +02:00
yasien_gmail ca0f13a6df build number update to 124 2025-12-03 11:40:29 +02:00
yasien_gmail 021a25f50c QOL: Data display load minesweeper pt1 2025-12-03 11:26:47 +02:00
yasien_gmail 0a9f0c000e QOL: Data display load Mzansi Direct pt4 2025-12-03 11:16:24 +02:00
yasien_gmail 3ff670886c QOL: Data display load Mzansi Direct pt3 2025-12-03 11:08:22 +02:00
yasien_gmail a6d5e4ad35 QOL: Data display load Mzansi Direct pt2 2025-12-03 10:51:18 +02:00
yasien_gmail 456dff6402 QOL: Data display load Mzansi Direct pt1 2025-12-03 10:32:03 +02:00
yasien_gmail d3fdc83373 BUG: incorrect code display style 2025-12-03 09:21:15 +02:00
yasien_gmail 8704d4dd64 BUG: Patient Infor Scrolling 2025-12-02 19:20:24 +02:00
yasien_gmail 37920466ac Update build to 123 2025-12-01 10:51:01 +02:00
yasien_gmail 56d54a3711 QOL: Calanedar message alingment 2025-12-01 10:49:14 +02:00
yasien_gmail aef501cd25 QOL: Cache leaderboard images 2025-12-01 10:40:29 +02:00
yasien_gmail 4f5761271c QOL: Mzansi AI Suggestion update 2025-12-01 10:37:57 +02:00
yasien_gmail 252e120b99 BUG: Business Team list view 2025-12-01 10:36:25 +02:00
yasien_gmail b5c26c3e43 BUG: Mzansi Directory person search on person press 2025-12-01 10:32:26 +02:00
yasien_gmail 74be2fc559 BUG: File list icons 2025-12-01 10:29:02 +02:00
yasien_gmail b519b99a91 QOL: Mzansi Home Scroll 2025-12-01 10:26:17 +02:00
yasien_gmail 72261af7b9 build number update to 122 2025-11-28 13:49:02 +02:00
yasien_gmail ad96725478 QOL: Mzansi Profile Package performance improvements pt2 2025-11-28 13:48:25 +02:00
yasien_gmail ef4c3102a9 QOL: MIH Authentication Package performance improvements 2025-11-28 13:43:51 +02:00
yasien_gmail 9a75bcc810 QOL: MIH Access Controls Package performance improvements pt2 2025-11-28 13:38:14 +02:00
yasien_gmail 586e67b369 QOL: MIH Mine Sweeper Package performance improvements pt2 2025-11-28 13:30:12 +02:00
yasien_gmail e8cae1a894 QOL: MIH Calendar Package performance improvements pt2 2025-11-28 13:26:32 +02:00
yasien_gmail cd8115c597 QOL: Patient Manager Package performance improvements pt2 2025-11-28 13:22:54 +02:00
yasien_gmail 730c5d2bdf QOL: MIH Package performance improvements pt2 2025-11-28 13:13:27 +02:00
yasien_gmail cea8ccab5a QOL: Mzansi Wallet Package performance improvements pt2 2025-11-28 13:02:34 +02:00
yasien_gmail 4f168c5b0e QOL: MIH About Package performance improvements 2025-11-28 12:57:19 +02:00
yasien_gmail 99f8b1a3f9 QOL: MIH Access Controls Package performance improvements 2025-11-28 12:54:31 +02:00
yasien_gmail 30c06261c8 QOL: MIH Mine Sweeper Package performance improvements 2025-11-28 12:52:33 +02:00
yasien_gmail c843c0a55d QOL: MIH Calculator Package performance improvements 2025-11-28 12:47:44 +02:00
yasien_gmail 94ac83db9e QOL: Mzansi AI Package performance improvements 2025-11-28 12:44:51 +02:00
yasien_gmail a3b8da5357 QOL: MIH Calendar Package performance improvements 2025-11-28 12:43:07 +02:00
yasien_gmail 47bc23c029 QOL: Patient Manager Package performance improvements 2025-11-28 12:41:30 +02:00
yasien_gmail c16d8b6e91 QOL: Mzansi Wallet Package performance improvements 2025-11-28 12:31:39 +02:00
yasien_gmail a6fe4499d0 QOL: Mzansi Profile Package performance improvements 2025-11-28 12:29:09 +02:00
yasien_gmail 004c2397c5 QOL: MIH Home Package performance improvements 2025-11-28 12:15:12 +02:00
yasien_gmail d64193d1f8 QOL: MIH Package performance improvements 2025-11-28 12:14:20 +02:00
yasien_gmail e330875c6f build update to 121 2025-11-28 11:43:38 +02:00
yasien_gmail 3d2addf1d6 BUG: fav bus view fix performace pt 2 2025-11-28 11:33:26 +02:00
yasien_gmail 3b6e1d22ec build update to 120 2025-11-28 10:30:33 +02:00
yasien_gmail ff913c0c54 BUG: fav bus view fix 2025-11-28 10:26:36 +02:00
yasien_gmail c45c933277 Update version and build 2025-11-27 13:16:30 +02:00
yasien_gmail 89d6999abf BUG: patient profile picture in patient manager 2025-11-27 13:14:40 +02:00
yasien_gmail 969ecf8fdc BUG: User search piture load 2025-11-27 12:57:15 +02:00
yasien_gmail ee7d3881e6 BUG: Image loading of businesses 2025-11-27 12:40:34 +02:00
yasien_gmail cc3f18f7e2 QOL: Mzansi AI Enhancement pt1 2025-11-27 09:48:42 +02:00
yasien_gmail 08bfe1d417 Update build to 118 2025-11-25 16:51:03 +02:00
yasien_gmail 3593011d6d minio storage uploud fix pt9 2025-11-25 16:47:42 +02:00
yasien_gmail 5ae11f6625 minio storage uploud fix pt8 2025-11-25 16:40:48 +02:00
yasien_gmail a61bca7d81 minio storage uploud fix pt7 2025-11-25 16:31:13 +02:00
yasien_gmail fb3b033f45 minio storage uploud fix pt6 2025-11-25 16:11:28 +02:00
yasien_gmail 91a2d0dd1e minio storage uploud fix pt5 2025-11-25 16:08:20 +02:00
yasien_gmail 04c643561b minio storage uploud fix pt4 2025-11-25 16:05:53 +02:00
yasien_gmail 526bd40255 minio storage uploud fix pt3 2025-11-25 15:53:09 +02:00
yasien_gmail 1889f6cada minio storage uploud fix pt2 2025-11-25 15:39:23 +02:00
yasien_gmail c1dd9a60f2 minio storage uploud fix pt1 2025-11-25 15:31:53 +02:00
yasien_gmail ec869c54c3 minio storage fix pt14 2025-11-25 15:29:07 +02:00
yasien_gmail b440c0a42b minio storage fix pt13 2025-11-25 15:24:02 +02:00
yasien_gmail baa826c52c minio storage fix pt12 2025-11-25 15:22:27 +02:00
yasien_gmail 6b530529e3 minio storage fix pt11 2025-11-25 15:20:58 +02:00
yasien_gmail a633b52949 minio storage fix pt10 2025-11-25 15:16:41 +02:00
yasien_gmail c103d1979c minio storage fix pt9 2025-11-25 15:12:38 +02:00
yasien_gmail 82c01cb7bf minio storage fix pt8 2025-11-25 15:05:16 +02:00
yasien_gmail 43bc552698 minio storage fix pt7 2025-11-25 15:00:20 +02:00
yasien_gmail bb6a8e3090 minio storage fix pt6 2025-11-25 14:49:56 +02:00
yasien_gmail 565e9199d4 minio storage fix pt5 2025-11-25 14:38:59 +02:00
yasien_gmail c5de46040d minio storage fix pt4 2025-11-25 14:31:37 +02:00
yasien_gmail 934b1b2301 minio storage fix pt3 2025-11-25 13:51:42 +02:00
yasien_gmail 302152449f minio storage fix pt2 2025-11-25 13:42:46 +02:00
yasien_gmail 0f591bd111 minio storage fix 2025-11-25 13:37:20 +02:00
yaso-meth ea04c000cf Merge pull request #263 from yaso-meth/V.1.2.3
V.1.2.3
2025-11-25 12:27:36 +02:00
yasien_gmail a59d2bf336 update build to 117 2025-11-25 11:40:22 +02:00
yasien_gmail d5fcad8fa5 BUG: Image display when error 2025-11-25 11:38:19 +02:00
yasien_gmail 609828a26c update build to 116 2025-11-25 11:18:46 +02:00
yasien_gmail d0a5c6c858 QOL: Mzansi AI trigger from home 2025-11-25 11:16:18 +02:00
yasien_gmail 4a293c0aa4 add toot titles to missing packages 2025-11-25 10:45:39 +02:00
yasien_gmail d51d13a685 update build to 115 2025-11-21 12:15:34 +02:00
yasien_gmail bf6bda04a6 get business data when opening mxzansi profile as standalone 2025-11-21 12:14:03 +02:00
yasien_gmail b749dc62d9 fix alert padding for desktop 2025-11-21 12:11:51 +02:00
yasien_gmail b82a5a72c7 NEW: Hide sensitive data on my business user 2025-11-21 11:59:34 +02:00
yasien_gmail 56ab6bb950 QOL: use advanced varding when adding & removing card to fav 2025-11-21 10:27:22 +02:00
yasien_gmail bb54605ddb QOL: Create advanced warning alert 2025-11-21 10:26:57 +02:00
yasien_gmail c4b3a12213 BUG: add jpeg icons 2025-11-21 10:17:24 +02:00
yasien_gmail 43d715f4f8 QOL: Reorder Minesweeper alert buttons 2025-11-21 10:16:19 +02:00
yasien_gmail a9d6ca1baa QOL: Get loaction in bg 2025-11-21 10:12:51 +02:00
yasien_gmail dfcfced28f BUG: Remove hint when keyboard is open 2025-11-21 09:57:12 +02:00
yasien_gmail d0474fed21 BUG: Social Links colour fix 2025-11-21 09:44:06 +02:00
yasien_gmail f228307859 Update Business QR code share text 2025-11-21 09:34:40 +02:00
yasien_gmail ab9cbce41c BUG: remove token text in reset password 2025-11-21 09:34:16 +02:00
yasien_gmail 70413cc294 QOL: About MIH button placement 2025-11-21 09:33:45 +02:00
yasien_gmail a4d510f023 v.1.2.4 Build Number Updated to 114 2025-11-20 11:22:24 +02:00
yasien_gmail e99388711d v.1.2.3 pt 2 Build Number Updated to 113 2025-11-20 11:05:29 +02:00
yasien_gmail 00cd5488e3 NEW: MIh Alerts 2025-11-20 10:56:15 +02:00
yasien_gmail b69a52a5a8 Mih File Structure enhancement 2025-11-18 12:42:22 +02:00
yasien_gmail f5c05d7431 remove prints 2025-11-17 12:59:19 +02:00
yasien_gmail 0403d8c4b5 fix naming convention 2025-11-17 12:58:24 +02:00
yasien_gmail fb7bf4ad65 QOL: Remove legacy layout widgets 2025-11-17 12:56:18 +02:00
yasien_gmail 3417299989 NEW: create new file viewer with MIH package 2025-11-17 12:55:34 +02:00
yasien_gmail 66887d23f8 QOL: MIH Go Router get data on package open pt2 2025-11-17 11:32:39 +02:00
yasien_gmail f064730dcf QOL: Patient Manager get data on package open pt2 2025-11-17 11:32:23 +02:00
yasien_gmail a49505c153 QOL: MIH Test Package get data on package open 2025-11-17 11:25:51 +02:00
yasien_gmail 9d898d8dff QOL: Mzansi profile Business get data on package open 2025-11-17 11:25:37 +02:00
yasien_gmail c517075197 QOL: MIH Acces Controls get data on package open 2025-11-17 11:17:16 +02:00
yasien_gmail 2dc3396fcc QOL: MIH Minesweeper get data on package open 2025-11-17 11:09:38 +02:00
yasien_gmail d318b17b18 QOL: Mzansi AI get data on package open 2025-11-17 11:05:59 +02:00
yasien_gmail 4221ae73b9 QOL: MIH Calendar get data on package open 2025-11-17 10:59:47 +02:00
yasien_gmail b49e93825e QOL: Mzansi Directory get data on package open 2025-11-17 10:53:52 +02:00
yasien_gmail 790bf0e4f8 QOL: Patient Manager get data on package open 2025-11-17 10:46:24 +02:00
yasien_gmail a0bd74b703 QOL: Mzansi Wallet get data on package open 2025-11-17 10:46:09 +02:00
yasien_gmail 96daf77b45 QOL: Mzansi profile Personal get data on package open 2025-11-17 10:45:57 +02:00
yasien_gmail 77ffd95fb6 QOL: MIH Home get data on package open 2025-11-17 10:45:31 +02:00
yasien_gmail 24cc7f64b5 QOL: Update file service 2025-11-17 09:24:32 +02:00
yasien_gmail d76512c11f BUG: dont initialise shortcuts on web 2025-11-14 14:25:32 +02:00
yasien_gmail e1e7542a6d optimisation web pt 3 2025-11-14 14:22:30 +02:00
yasien_gmail 121cde211f optimisation web pt 2 2025-11-14 14:22:30 +02:00
yasien_gmail b79decf04f cancel timeout on load 2025-11-14 14:22:30 +02:00
yasien_gmail a26b826729 increase timeut time 2025-11-14 14:22:30 +02:00
yasien_gmail cc3d1ae430 web load v2 2025-11-14 14:22:30 +02:00
yasien_gmail 329e450f5b revert 2025-11-14 14:22:30 +02:00
yasien_gmail 0a03b1c60c web loadtime 2025-11-14 14:22:30 +02:00
yasien_gmail 652d4bb2fd increase load 2025-11-14 14:22:30 +02:00
yasien_gmail 5903fcd31a reduce load speed 2025-11-14 14:22:30 +02:00
yasien_gmail b0825fe7cb optimisation web pt 3 2025-11-14 14:02:55 +02:00
yasien_gmail 8a2debcaa8 optimisation web pt 2 2025-11-14 13:53:20 +02:00
yasien_gmail 609c8d46db cancel timeout on load 2025-11-14 13:04:04 +02:00
yasien_gmail 1387fb1af5 increase timeut time 2025-11-14 12:52:11 +02:00
yasien_gmail 1f73aa3b87 web load v2 2025-11-14 12:47:15 +02:00
yasien_gmail 47ca6d7311 revert 2025-11-14 12:33:35 +02:00
yasien_gmail 64443a5076 web loadtime 2025-11-14 12:22:21 +02:00
yasien_gmail 20d5bc4004 increase load 2025-11-14 12:07:36 +02:00
yasien_gmail 9257786191 reduce load speed 2025-11-14 11:28:52 +02:00
yasien_gmail 66db154b02 user service update 2025-11-14 11:27:02 +02:00
yasien_gmail 5770f6c353 QOL: Patient Manager overhaul pt3 2025-11-14 11:27:02 +02:00
yasien_gmail c5713cf6e0 QOL: Patient Manager overhaul pt2 2025-11-14 11:27:02 +02:00
yasien_gmail 4fe544b35f QOL: Patient Manager overhaul pt1 2025-11-14 11:27:02 +02:00
yasien_gmail 6542f1c399 QOL: MIh WIndows ehnacement 2025-11-14 11:27:02 +02:00
yaso-meth 963a708ab8 Merge pull request #262 from yaso-meth/V.1.2.3
V.1.2.3
2025-11-10 17:03:44 +02:00
yaso-meth 2f0b11e5ba Merge branch 'main' into V.1.2.3 2025-11-10 17:03:31 +02:00
yasien_gmail d9b2598bca update web icoon 2025-11-10 16:59:14 +02:00
yasien_gmail 0c15bd3e90 iod svg assets 2025-11-10 16:57:49 +02:00
yasien_gmail 0daffb5041 QOL: Mzansi AI Chat Look and Feel & Startup question pt6 2025-11-10 15:36:38 +02:00
yasien_gmail 9485213d6e NEW: MIH Shortcuts pt3 2025-11-10 15:36:22 +02:00
yasien_gmail 9a8f157451 QOL: Mzansi AI Chat Look and Feel & Startup question pt5 2025-11-10 14:48:15 +02:00
yasien_gmail a6f6cdaace NEW: MIH Stands with Women For Change SA 2025-11-10 14:19:40 +02:00
yasien_gmail effbac2c91 NEW: MIH Colors W4C 2025-11-10 13:59:21 +02:00
yasien_gmail f8de726959 QOL: Mzansi AI Chat Look and Feel & Startup question pt4 2025-11-10 13:35:04 +02:00
yasien_gmail 01220144c3 NEW: MIH Loading revamp 2025-11-10 13:34:41 +02:00
yasien_gmail 3f93cc9a7a NEW: MIH Shortcuts pt2 2025-11-10 13:34:15 +02:00
yasien_gmail 83a16bad79 NEW: MIH Shortcuts pt1 2025-11-08 03:02:47 +02:00
yasien_gmail d2f93db580 include busines home 2025-11-07 15:04:52 +02:00
yasien_gmail a3c1963d30 QOL: Mzansi AI Chat Look and Feel & Startup question pt3 2025-11-07 15:03:36 +02:00
yasien_gmail 8e6ef25954 QOL: Mzansi AI Chat Look and Feel pt2 & Startup question 2025-11-07 14:44:42 +02:00
yasien_gmail 580fa027f2 QOL: Build number update to 103 2025-11-07 14:44:42 +02:00
yasien_gmail 9346cccd20 BUG: Get patient data from tile 2025-11-07 14:44:42 +02:00
yasien_gmail 51f2435c33 QOL: Update Mzansi AI System PRompt 2025-11-07 14:44:42 +02:00
yasien_gmail ba5772f3ac NFC deep linking 2025-11-07 14:44:42 +02:00
yasien_gmail 662d20617d QOL: Update build to 101 2025-11-07 14:44:42 +02:00
yasien_gmail e6d1cf0268 favourite business fix 2025-11-07 14:44:42 +02:00
yasien_gmail ed7c5a2269 IOS encryption compliance 2025-11-07 14:44:42 +02:00
yasien_gmail 98beb20827 deeplinking fix 2025-11-07 14:44:07 +02:00
yasien_gmail 76a54ce969 QOL: Update build to 100 2025-11-07 14:44:07 +02:00
yasien_gmail c53f30035d BUG: Update Appointment & Clear Coltrollers 2025-11-07 14:44:07 +02:00
yasien_gmail ec01e2212b BUG: Bookmarked businesses data load 2025-11-07 14:44:07 +02:00
yasien_gmail f840418caf BUG: back Nav from favourite business selection 2025-11-07 14:44:07 +02:00
yasien_gmail 76d24a8e2b BUG: Business Profile Tool Transitions 2025-11-07 14:44:07 +02:00
yasien_gmail 821cbc0a0d BUG: Set up patient flow 2025-11-07 14:44:07 +02:00
yasien_gmail ea25598144 QOL: update guide 2025-11-07 14:44:07 +02:00
yasien_gmail 70fc306789 QOL: Change reset game to start new game 2025-11-07 14:44:07 +02:00
yasien_gmail ba46f38497 BUG: MIH Ad Display Strategy 2025-11-07 14:44:07 +02:00
yasien_gmail 67692967c3 BUG: Add card refresh list 2025-11-07 14:44:07 +02:00
yasien_gmail cc51afadb3 BUG: Menue showing in claims in personal mode 2025-11-07 14:44:07 +02:00
yasien_gmail d9fb9dd758 QOL: Mzansi AI Chat Look and Feel pt2 & Startup question 2025-11-07 14:29:05 +02:00
yasien_gmail d75da5389a QOL: Mzansi AI Chat Look and Feel pt1 2025-11-07 12:03:44 +02:00
yaso-meth efaf9b3574 Merge pull request #261 from yaso-meth/V.1.2.2
V.1.2.2
2025-11-06 08:35:35 +02:00
897 changed files with 25023 additions and 26252 deletions
Vendored
BIN
View File
Binary file not shown.
+7 -9
View File
@@ -1,16 +1,14 @@
# *database/auto.cnf
# *database/binlog.index
# *database/mysql.sock
File_Storage
database/
mih_minio/
mih_db/
mih_git/
mih_nginx/
mih_monitor/
mih_wp/
certbot/
Firebase-emulator/
Mzansi_Mail/
# database/ibdata1
# database/mysql.ibd
# database/undo*
# database/#innodb_redo/#ib_redo*
.venv
google-chrome-stable_current_amd64.deb
.env
Frontend/android/app/.cxx/
.DS_Store
+14 -3
View File
@@ -6,14 +6,25 @@
"configurations": [
{
"name": "Debug",
"cwd": "Frontend",
"cwd": "mih_ui",
"request": "launch",
"type": "dart",
"program": "lib/main_dev.dart"
},
{
"name": "Debug (web)",
"cwd": "mih_ui",
"request": "launch",
"type": "dart",
"program": "lib/main_dev.dart",
"args": [
"--web-port",
"1995"
]
},
{
"name": "Profile",
"cwd": "Frontend",
"cwd": "mih_ui",
"request": "launch",
"type": "dart",
"flutterMode": "profile",
@@ -21,7 +32,7 @@
},
{
"name": "Release",
"cwd": "Frontend",
"cwd": "mih_ui",
"request": "launch",
"type": "dart",
"flutterMode": "release",
-45
View File
@@ -1,45 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "8defaa71a77c16e8547abdbfad2053ce3a6e2d5b"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: android
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: ios
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: linux
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: macos
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: web
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: windows
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
-48
View File
@@ -1,48 +0,0 @@
# Install Operating system and dependencies
#FROM ubuntu:22.04
FROM debian:latest AS build-env
#ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update --fix-missing
RUN apt-get install -y curl git wget unzip gdb libstdc++6 libglu1-mesa fonts-droid-fallback
# RUN apt-get install -y curl git wget unzip libgconf-2-4 gdb libstdc++6 libglu1-mesa fonts-droid-fallback
RUN apt-get install python3 -y
# download Flutter SDK from Flutter Github repo
RUN git clone -b flutter-3.32-candidate.0 https://github.com/flutter/flutter.git /usr/local/flutter
# RUN git clone -b stable https://github.com/flutter/flutter.git /usr/local/flutter
# Set flutter environment path
ENV PATH="/usr/local/flutter/bin:/usr/local/flutter/bin/cache/dart-sdk/bin:${PATH}"
#ENV PATH "$PATH:/home/developer/flutter/bin"
RUN flutter doctor -v
# Enable flutter web
RUN flutter channel flutter-3.32-candidate.0
# RUN flutter channel stable
RUN flutter config --enable-web
# Copy files to container and build
RUN mkdir /app/
COPY . /app/
WORKDIR /app
# RUN flutter upgrade
RUN flutter build web --release -t ./lib/main_prod.dart
# RUN flutter build web --release --web-renderer canvaskit -t ./lib/main_prod.dart
# RUN cd ..
# WORKDIR /app/build/web/
EXPOSE 83
RUN ["chmod", "+x", "/app/server/server.sh"]
ENTRYPOINT [ "/app/server/server.sh"]
# RUN ["python3", "-u", "/app/server/MIH_web_server.py"]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#3A4454</color>
</resources>
-32
View File
@@ -1,32 +0,0 @@
# flutter pub run flutter_launcher_icons
flutter_launcher_icons:
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_app_icon.png"
android: "launcher_icon"
# image_path_android: "assets/icon/icon.png"
min_sdk_android: 21 # android min sdk min:16, default 21
adaptive_icon_background: "#3A4454"
adaptive_icon_foreground: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_app_icon.png"
# adaptive_icon_monochrome: "assets/icon/monochrome.png"
ios: true
image_path_ios: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_app_icon.png"
remove_alpha_channel_ios: true
# image_path_ios_dark_transparent: "assets/icon/icon_dark.png"
# image_path_ios_tinted_grayscale: "assets/icon/icon_tinted.png"
# desaturate_tinted_to_grayscale_ios: true
web:
generate: true
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/circle_logo.png"
background_color: "#3A4454"
theme_color: "#3A4454"
windows:
generate: true
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/circle_logo.png"
icon_size: 48 # min:48, max:256, default: 48
macos:
generate: true
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/circle_logo.png"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

@@ -1 +0,0 @@
{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

-92
View File
@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v9wttpbfk9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>n38lu8286q.skadnetwork</string>
</dict>
</array>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-4781880856775334~6935644635</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>MIH</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>mzansi_innovation_hub</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sms</string>
<string>tel</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string>
<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to your location at all times to provide [Explain your specific, complete reason here, e.g., real-time tracking, background updates, etc.].</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs to access your photo library to select images.</string>
<key>NSDownloadsFolderUsageDescription</key>
<string>This app needs to access your downloads folder to select files from there.</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIStatusBarHidden</key>
<false/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
-144
View File
@@ -1,144 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:provider/provider.dart';
import 'package:upgrader/upgrader.dart';
import 'mih_config/mih_env.dart';
import 'mih_config/mih_theme.dart';
class MzansiInnovationHub extends StatefulWidget {
final GoRouter router;
const MzansiInnovationHub({
super.key,
required this.router,
});
@override
State<MzansiInnovationHub> createState() => _MzansiInnovationHubState();
// ignore: library_private_types_in_public_api
static _MzansiInnovationHubState? of(BuildContext context) =>
context.findAncestorStateOfType<_MzansiInnovationHubState>();
}
class _MzansiInnovationHubState extends State<MzansiInnovationHub> {
late MihTheme theme;
Color getPrimany() {
return MihColors.getPrimaryColor(theme.mode == "Dark");
}
String getTitle() {
if (AppEnviroment.getEnv() == "Dev") {
return "Dev | MIH App: Mzansi Innovation Hub";
} else {
return "MIH App: Mzansi Innovation Hub";
}
}
void changeTheme(ThemeMode themeMode) {
setState(() {
if (themeMode == ThemeMode.light) {
setState(() {
theme.mode = "Light";
});
} else if (themeMode == ThemeMode.dark) {
setState(() {
theme.mode = "Dark";
});
} else {
setState(() {
theme.mode = "Dark";
});
}
});
}
@override
void initState() {
theme = MihTheme();
super.initState();
theme.mode = "Dark";
theme.platform = Theme.of(context).platform;
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.sizeOf(context).width;
theme.setScreenType(width);
precacheImage(theme.loadingImage(), context);
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => MihAuthenticationProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiProfileProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiWalletProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiAiProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiDirectoryProvider(),
),
ChangeNotifierProvider(
create: (context) => MihBannerAdProvider(),
),
ChangeNotifierProvider(
create: (context) => MihCalculatorProvider(),
),
ChangeNotifierProvider(
create: (context) => MihAccessControllsProvider(),
),
ChangeNotifierProvider(
create: (context) => MihCalendarProvider(),
),
ChangeNotifierProvider(
create: (context) => AboutMihProvider(),
),
ChangeNotifierProvider(
create: (context) => MihMineSweeperProvider(),
),
ChangeNotifierProvider(
create: (context) => PatientManagerProvider(),
),
],
child: MaterialApp.router(
title: getTitle(),
themeMode: ThemeMode.dark,
theme: theme.getThemeData(),
darkTheme: theme.getThemeData(),
debugShowCheckedModeBanner: false,
routerConfig: widget.router,
builder: (context, child) {
if (child == null) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
return UpgradeAlert(
navigatorKey: widget.router.routerDelegate.navigatorKey,
child: child,
);
},
),
);
}
}
@@ -1,38 +0,0 @@
import 'package:flutter/material.dart';
class MIHAction extends StatefulWidget {
final void Function()? onTap;
final double iconSize;
final Widget icon;
const MIHAction({
super.key,
required this.icon,
required this.iconSize,
required this.onTap,
});
@override
State<MIHAction> createState() => _MIHActionState();
}
class _MIHActionState extends State<MIHAction> {
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return IconButton(
iconSize: widget.iconSize,
padding: const EdgeInsets.all(0),
onPressed: widget.onTap,
icon: widget.icon,
);
}
}
@@ -1,106 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../main.dart';
class MIHBody extends StatefulWidget {
final bool borderOn;
final List<Widget> bodyItems;
const MIHBody({
super.key,
required this.borderOn,
required this.bodyItems,
});
@override
State<MIHBody> createState() => _MIHBodyState();
}
class _MIHBodyState extends State<MIHBody> {
//double paddingSize = 10;
double getHorizontalPaddingSize(Size screenSize) {
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
if (widget.borderOn) {
return 10;
} else {
return 0;
}
} else {
// mobile
if (widget.borderOn) {
return 10;
} else {
return 0;
}
}
}
double getVerticalPaddingSize(Size screenSize) {
// mobile
if (widget.borderOn) {
return 10;
} else {
return 0;
}
}
Decoration? getBoader() {
if (widget.borderOn) {
return BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25.0),
border: Border.all(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 3.0),
);
} else {
return null;
}
}
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.sizeOf(context);
return Padding(
padding: EdgeInsets.only(
left: getHorizontalPaddingSize(screenSize),
right: getHorizontalPaddingSize(screenSize),
bottom: getVerticalPaddingSize(screenSize),
top: 0,
),
child: Container(
padding: EdgeInsets.only(
left: 10,
right: 10,
bottom: 10,
top: getVerticalPaddingSize(screenSize),
),
width: screenSize.width,
height: screenSize.height,
decoration: getBoader(),
child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: widget.bodyItems,
),
),
),
),
);
}
}
@@ -1,39 +0,0 @@
import 'package:flutter/material.dart';
class MIHHeader extends StatefulWidget {
final MainAxisAlignment headerAlignment;
final List<Widget> headerItems;
const MIHHeader({
super.key,
required this.headerAlignment,
required this.headerItems,
});
@override
State<MIHHeader> createState() => _MIHHeaderState();
}
class _MIHHeaderState extends State<MIHHeader> {
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: 50,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: widget.headerAlignment,
mainAxisSize: MainAxisSize.max,
children: widget.headerItems,
),
);
}
}
@@ -1,152 +0,0 @@
import 'package:flutter/material.dart';
import '../../mih_packages/mih_home/components/mih_app_drawer.dart';
import 'mih_body.dart';
import 'mih_header.dart';
class MIHLayoutBuilder extends StatefulWidget {
final Widget actionButton;
final Widget? secondaryActionButton;
final MIHHeader header;
final MIHBody body;
final MIHAppDrawer? actionDrawer;
final Widget? secondaryActionDrawer;
final Widget? bottomNavBar;
final bool pullDownToRefresh;
final Future<void> Function() onPullDown;
//final String type;
const MIHLayoutBuilder({
super.key,
required this.actionButton,
required this.header,
required this.secondaryActionButton,
required this.body,
required this.actionDrawer,
required this.secondaryActionDrawer,
required this.bottomNavBar,
required this.pullDownToRefresh,
required this.onPullDown,
});
@override
State<MIHLayoutBuilder> createState() => _MIHLayoutBuilderState();
}
class _MIHLayoutBuilderState extends State<MIHLayoutBuilder> {
List<Widget> getList() {
List<Widget> temp = [];
temp.add(widget.header);
temp.add(widget.body);
return temp;
}
// openTheDrawer() {
// _scaffoldKey.currentState!.openEndDrawer();
// }
Widget getLayoutHeader() {
List<Widget> temp = [];
temp.add(widget.actionButton);
temp.add(Flexible(child: widget.header));
if (widget.secondaryActionButton != null) {
temp.add(widget.secondaryActionButton!);
} else {
//print(widget.header.headerItems.length);
if (widget.header.headerItems.length == 1) {
temp.add(const SizedBox(
width: 50,
));
}
}
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: temp,
);
}
Widget getBody(double width, double height) {
if (widget.pullDownToRefresh == true) {
return SafeArea(
child: LayoutBuilder(builder: (context, BoxConstraints constraints) {
double newheight = constraints.maxHeight;
//print(newheight);
return RefreshIndicator(
onRefresh: widget.onPullDown,
child: ListView.builder(
itemCount: 1,
itemBuilder: (BuildContext context, int index) {
return SafeArea(
child: SizedBox(
width: width,
height: newheight,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 5),
getLayoutHeader(),
const SizedBox(height: 5),
Expanded(child: widget.body),
],
),
),
);
},
// child: SafeArea(
// child: SizedBox(
// width: width,
// height: height,
// child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// getLayoutHeader(),
// Expanded(child: widget.body),
// ],
// ),
// ),
// ),
),
);
}),
);
} else {
return SafeArea(
child: SizedBox(
width: width,
height: height,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 5),
getLayoutHeader(),
const SizedBox(height: 5),
Expanded(child: widget.body),
],
),
),
);
}
}
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.sizeOf(context);
return Scaffold(
//drawerEnableOpenDragGesture: true,
drawer: widget.actionDrawer,
endDrawer: widget.secondaryActionDrawer,
body: getBody(screenSize.width, screenSize.height),
bottomNavigationBar: widget.bottomNavBar,
);
}
}
@@ -1,126 +0,0 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_yt_video_player.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MIHTile extends StatefulWidget {
final String tileName;
final String? videoID;
final Widget tileIcon;
final void Function() onTap;
// final Widget tileIcon;
final Color p;
final Color s;
const MIHTile({
super.key,
required this.onTap,
required this.tileName,
this.videoID,
required this.tileIcon,
required this.p,
required this.s,
});
@override
State<MIHTile> createState() => _MIHTileState();
}
class _MIHTileState extends State<MIHTile> {
late Color mainC;
late Color secondC;
@override
void dispose() {
super.dispose();
}
@override
void initState() {
mainC = widget.p;
secondC = widget.s;
super.initState();
}
void displayHint() {
if (widget.videoID != null) {
showDialog(
context: context,
builder: (context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: widget.tileName,
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Column(
children: [
MIHYTVideoPlayer(videoYTLink: widget.videoID!),
],
),
);
},
);
}
}
@override
Widget build(BuildContext context) {
// print(
// "Tile Name: ${widget.tileName}\nTitle Type: ${widget.tileIcon.runtimeType.toString()}");
return FittedBox(
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AnimatedContainer(
//alignment: Alignment.center,
width: 250,
height: 250,
duration: const Duration(seconds: 2),
child: Material(
color: mainC,
// shadowColor:
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// elevation: 5,
borderRadius: BorderRadius.circular(80),
child: InkWell(
borderRadius: BorderRadius.circular(80),
// ho
onTap: widget.onTap,
onLongPress: () {
displayHint();
},
// hoverDuration: ,
splashColor: MihColors.getHighlightColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
highlightColor: MihColors.getHighlightColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: widget.tileIcon,
),
),
),
const SizedBox(height: 10),
SizedBox(
width: 300,
child: Text(
widget.tileName,
textAlign: TextAlign.center,
softWrap: true,
overflow: TextOverflow.visible,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
)
],
),
);
}
}
@@ -1,164 +0,0 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/Example/package_tools/package_tool_two.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class PackageTest extends StatefulWidget {
// final AppUser user;
// final Business business;
final TestArguments arguments;
const PackageTest({
super.key,
required this.arguments,
// required this.user,
// required this.business,
});
@override
State<PackageTest> createState() => _PackageTestState();
}
class _PackageTestState extends State<PackageTest> {
int _selcetedIndex = 0;
MihPackageAction getAction() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
'mihHome',
extra: true,
);
FocusScope.of(context).unfocus();
// Navigator.of(context).pop();
// Navigator.of(context).popAndPushNamed(
// '/',
// arguments: AuthArguments(true, false),
// );
},
);
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = Map();
temp[const Icon(Icons.inbox)] = () {
setState(() {
_selcetedIndex = 0;
});
};
temp[const Icon(Icons.outbond)] = () {
setState(() {
_selcetedIndex = 1;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
void showAlert() {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.warning_amber_rounded,
size: 100,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Oops! Looks like some fields are missing.",
alertBody: Column(
children: [
Text(
"We noticed that some required fields are still empty. To ensure your request is processed smoothly, please fill out all the highlighted fields before submitting the form again.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
RichText(
text: TextSpan(
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
children: <TextSpan>[
TextSpan(
text: "Here's a quick tip: ",
style: TextStyle(
fontStyle: FontStyle.italic,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"))),
const TextSpan(text: "Look for fields with an asterisk ("),
TextSpan(
text: "*",
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"))),
const TextSpan(
text: ") next to them, as these are mandatory."),
],
),
),
],
),
alertColour: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
PackageToolOne(
user: widget.arguments.user,
business: widget.arguments.business,
),
const PackageToolTwo(),
];
return toolBodies;
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Tool One",
"Tool Two",
];
return toolTitles;
}
@override
Widget build(BuildContext context) {
return MihPackage(
appActionButton: getAction(),
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
print("Index: $_selcetedIndex");
},
);
}
}
@@ -1,58 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class TestPackageTile extends StatefulWidget {
final AppUser signedInUser;
final Business? business;
final double packageSize;
const TestPackageTile({
super.key,
required this.signedInUser,
required this.business,
required this.packageSize,
});
@override
State<TestPackageTile> createState() => _TestPackageTileState();
}
class _TestPackageTileState extends State<TestPackageTile> {
@override
Widget build(BuildContext context) {
return MihPackageTile(
onTap: () {
context.goNamed(
'testPackage',
extra: TestArguments(
widget.signedInUser,
widget.business,
),
);
// Navigator.of(context).pushNamed(
// '/package-dev',
// arguments: TestArguments(
// widget.signedInUser,
// widget.business,
// ),
// );
},
appName: "Test",
appIcon: Icon(
Icons.warning_amber_rounded,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
iconSize: widget.packageSize,
primaryColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

@@ -1,68 +0,0 @@
import 'package:flutter/material.dart';
class MihButton extends StatelessWidget {
final void Function()? onPressed;
final void Function()? onLongPressed;
final Color buttonColor;
final double? width;
final double? height;
final double? borderRadius;
final double? elevation; // 0 = flat, higher = more shadow
final Widget child;
const MihButton({
super.key,
required this.onPressed,
this.onLongPressed,
required this.buttonColor,
this.width,
this.height,
this.borderRadius,
this.elevation,
required this.child,
});
Color _darkerColor(Color color, [double amount = .1]) {
final hsl = HSLColor.fromColor(color);
final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
return hslDark.toColor();
}
@override
Widget build(BuildContext context) {
final Color effectiveButtonColor = onPressed == null
? buttonColor.withValues(alpha: 0.6) // Example disabled color
: buttonColor;
final Color rippleColor = _darkerColor(effectiveButtonColor, 0.1);
final double radius = borderRadius ?? 25.0;
final double effectiveElevation =
onPressed == null ? 0.0 : (elevation ?? 4.0);
return MouseRegion(
cursor: onPressed == null
? SystemMouseCursors.basic
: SystemMouseCursors.click,
child: Material(
color: effectiveButtonColor,
borderRadius: BorderRadius.circular(radius),
elevation: effectiveElevation,
shadowColor: Colors.black,
child: InkWell(
borderRadius: BorderRadius.circular(radius),
splashColor: rippleColor,
highlightColor: rippleColor.withValues(alpha: 0.2),
hoverColor: rippleColor.withValues(alpha: 0.3),
onTap: onPressed,
onLongPress: onLongPressed,
child: Container(
width: width,
height: height,
padding: (width == null || height == null)
? const EdgeInsets.symmetric(horizontal: 24, vertical: 12)
: null,
alignment: Alignment.center,
child: child,
),
),
),
);
}
}
@@ -1,173 +0,0 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihCircleAvatar extends StatefulWidget {
final ImageProvider<Object>? imageFile;
final double width;
final bool editable;
final TextEditingController? fileNameController;
final onChange;
final PlatformFile? userSelectedfile;
final Color frameColor;
final Color? backgroundColor;
const MihCircleAvatar({
super.key,
required this.imageFile,
required this.width,
required this.editable,
required this.fileNameController,
required this.userSelectedfile,
required this.frameColor,
required this.backgroundColor,
required this.onChange,
});
@override
State<MihCircleAvatar> createState() => _MihCircleAvatarState();
}
class _MihCircleAvatarState extends State<MihCircleAvatar> {
late ImageProvider<Object>? imagePreview;
ImageProvider<Object>? getAvatar() {
// Color dark = const Color(0XFF3A4454);
if (widget.imageFile == null) {
return null;
// if (widget.backgroundColor == dark) {
// print("here in light icon");
// return const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/i-dont-know-light.png');
// } else {
// print("here in dark icon");
// return const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/i-dont-know-dark.png');
// }
} else {
return widget.imageFile;
}
}
@override
void initState() {
super.initState();
setState(() {
imagePreview = getAvatar();
});
}
@override
Widget build(BuildContext context) {
return Container(
// color: Colors.white,
alignment: Alignment.center,
width: widget.width,
height: widget.width,
child: Stack(
alignment: Alignment.center,
children: [
Visibility(
visible: imagePreview != null,
child: Positioned(
right: widget.width * 0.03,
child: CircleAvatar(
radius: widget.width / 2.2,
backgroundColor: widget.backgroundColor,
backgroundImage: imagePreview,
),
),
),
Visibility(
visible: imagePreview != null,
child: Icon(
size: widget.width,
MihIcons.mihRing,
color: widget.frameColor,
),
),
Visibility(
visible: imagePreview == null,
child: Icon(
MihIcons.iDontKnow,
size: widget.width,
color: widget.frameColor,
),
),
Visibility(
visible: widget.editable,
child: Positioned(
bottom: 0,
right: 0,
child: IconButton.filled(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all<Color>(
MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
onPressed: () async {
try {
FilePickerResult? result =
await FilePicker.platform.pickFiles(
type: FileType.image,
);
// print("Here 1");
if (MzansiInnovationHub.of(context)!.theme.getPlatform() ==
"Web") {
// print("Here 2");
if (result == null) return;
// print("Here 3");
PlatformFile? selectedFile = result.files.first;
setState(() {
// print("Here 4");
widget.onChange(selectedFile);
// print("Here 5");
imagePreview = MemoryImage(selectedFile.bytes!);
});
setState(() {
widget.fileNameController!.text = selectedFile.name;
});
} else {
if (result != null) {
File file = File(result.files.single.path!);
PlatformFile? androidFile = PlatformFile(
path: file.path,
name: file.path.split('/').last,
size: file.lengthSync(),
bytes: await file.readAsBytes(), // Read file bytes
//extension: fileExtension,
);
setState(() {
widget.onChange(androidFile);
imagePreview = FileImage(file);
});
setState(() {
widget.fileNameController!.text =
file.path.split('/').last;
});
} else {
print("here in else");
// User canceled the picker
}
}
} catch (e) {
print("Here Error: $e");
}
},
icon: Icon(
Icons.edit,
),
),
),
),
],
),
);
}
}
@@ -1,207 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihDateField extends StatefulWidget {
final TextEditingController controller;
final String labelText;
final bool required;
final double? width;
final double? height;
final double? borderRadius;
final double? elevation;
final FormFieldValidator<String>? validator;
const MihDateField({
super.key,
required this.controller,
required this.labelText,
required this.required,
this.width,
this.height,
this.borderRadius,
this.elevation,
this.validator,
});
@override
State<MihDateField> createState() => _MihDateFieldState();
}
class _MihDateFieldState extends State<MihDateField> {
FormFieldState<String>? _formFieldState;
Future<void> _selectDate(BuildContext context) async {
DateTime? picked = await showDatePicker(
context: context,
initialDate: widget.controller.text.isNotEmpty
? DateTime.tryParse(widget.controller.text) ?? DateTime.now()
: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime(2100),
);
if (picked != null) {
widget.controller.text = picked.toString().split(" ")[0];
_formFieldState?.didChange(widget.controller.text);
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
width: widget.width,
height: widget.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.labelText,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
if (!widget.required)
Text(
"(Optional)",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 4),
FormField<String>(
initialValue: widget.controller.text,
validator: widget.validator,
autovalidateMode: AutovalidateMode.onUserInteraction,
builder: (field) {
_formFieldState = field;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Material(
elevation: widget.elevation ?? 4.0,
borderRadius:
BorderRadius.circular(widget.borderRadius ?? 8.0),
child: TextFormField(
controller: widget.controller,
readOnly: true,
onTap: () => _selectDate(context),
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.w500,
),
decoration: InputDecoration(
suffixIcon: Icon(
Icons.calendar_today,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
errorStyle: const TextStyle(height: 0, fontSize: 0),
contentPadding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 8.0),
filled: true,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(
widget.borderRadius ?? 8.0),
borderSide: field.hasError
? BorderSide(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
width: 2.0,
)
: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
widget.borderRadius ?? 8.0),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
widget.borderRadius ?? 8.0),
borderSide: BorderSide(
color: field.hasError
? MihColors.getRedColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark")
: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
width: 3.0,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
widget.borderRadius ?? 8.0),
borderSide: BorderSide(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
widget.borderRadius ?? 8.0),
borderSide: BorderSide(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
),
onChanged: (value) {
field.didChange(value);
},
),
),
if (field.hasError)
Padding(
padding: const EdgeInsets.only(left: 8.0, top: 4.0),
child: Text(
field.errorText ?? '',
style: TextStyle(
fontSize: 12,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.bold,
),
),
),
],
);
},
),
],
),
),
);
}
}
@@ -1,248 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihDropdownField extends StatefulWidget {
final TextEditingController controller;
final String hintText;
final bool requiredText;
final List<String> dropdownOptions;
final bool editable;
final bool enableSearch;
final FormFieldValidator<String>? validator;
final Function(String?)? onSelected;
const MihDropdownField({
super.key,
required this.controller,
required this.hintText,
required this.dropdownOptions,
required this.requiredText,
required this.editable,
required this.enableSearch,
this.validator,
this.onSelected,
});
@override
State<MihDropdownField> createState() => _MihDropdownFieldState();
}
class _MihDropdownFieldState extends State<MihDropdownField> {
late List<DropdownMenuEntry<String>> menu;
List<DropdownMenuEntry<String>> buildMenuOptions(List<String> options) {
List<DropdownMenuEntry<String>> menuList = [];
for (final i in options) {
menuList.add(DropdownMenuEntry(
value: i,
label: i,
style: ButtonStyle(
foregroundColor: WidgetStatePropertyAll(MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
),
));
}
return menuList;
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
menu = buildMenuOptions(widget.dropdownOptions);
}
@override
void initState() {
super.initState();
menu = widget.dropdownOptions
.map((e) => DropdownMenuEntry(value: e, label: e))
.toList();
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.hintText,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
if (!widget.requiredText)
Text(
"(Optional)",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 4),
FormField<String>(
validator: widget.validator,
autovalidateMode: AutovalidateMode.onUserInteraction,
initialValue: widget.controller.text,
builder: (field) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Theme(
data: Theme.of(context).copyWith(
textSelectionTheme: TextSelectionThemeData(
cursorColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
selectionColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")
.withValues(alpha: 0.3),
selectionHandleColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
child: DropdownMenu(
controller: widget.controller,
dropdownMenuEntries: menu,
enableSearch: widget.enableSearch,
enableFilter: widget.enableSearch,
enabled: widget.editable,
textInputAction: widget.enableSearch
? TextInputAction.search
: TextInputAction.none,
requestFocusOnTap: widget.enableSearch,
menuHeight: 400,
expandedInsets: EdgeInsets.zero,
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.w500,
),
trailingIcon: Icon(
Icons.arrow_drop_down,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
selectedTrailingIcon: Icon(
Icons.arrow_drop_up,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
leadingIcon: IconButton(
onPressed: () {
widget.controller.clear();
field.didChange('');
},
icon: Icon(
Icons.delete_outline_rounded,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
onSelected: (String? selectedValue) {
field.didChange(selectedValue);
widget.onSelected?.call(selectedValue);
},
menuStyle: MenuStyle(
backgroundColor: WidgetStatePropertyAll(
MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
side: WidgetStatePropertyAll(
BorderSide(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 1.0),
),
shape: WidgetStatePropertyAll(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
10), // Increase for more roundness
),
),
),
inputDecorationTheme: InputDecorationTheme(
errorStyle: const TextStyle(height: 0, fontSize: 0),
contentPadding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 8.0),
filled: true,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: field.hasError
? MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")
: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
),
),
),
if (field.hasError)
Padding(
padding: const EdgeInsets.only(left: 8.0, top: 4.0),
child: Text(
field.errorText ?? '',
style: TextStyle(
fontSize: 12,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.bold,
),
),
),
],
);
},
),
],
);
}
}
@@ -1,47 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihFloatingMenu extends StatefulWidget {
final IconData? icon;
final double? iconSize;
final AnimatedIconData? animatedIcon;
final SpeedDialDirection? direction;
final List<SpeedDialChild> children;
const MihFloatingMenu({
super.key,
this.icon,
this.iconSize,
this.animatedIcon,
this.direction,
required this.children,
});
@override
State<MihFloatingMenu> createState() => _MihFloatingMenuState();
}
class _MihFloatingMenuState extends State<MihFloatingMenu> {
@override
Widget build(BuildContext context) {
return SpeedDial(
icon: widget.icon,
buttonSize: Size(widget.iconSize ?? 56.0, widget.iconSize ?? 56.0),
animatedIcon: widget.animatedIcon,
direction: widget.direction ?? SpeedDialDirection.up,
activeIcon: Icons.close,
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
activeBackgroundColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
foregroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
overlayColor: Colors.black,
overlayOpacity: 0.5,
children: widget.children,
onOpen: () => debugPrint('OPENING DIAL'),
onClose: () => debugPrint('DIAL CLOSED'),
);
}
}
@@ -1,27 +0,0 @@
import 'package:flutter/material.dart';
class MihForm extends StatefulWidget {
final GlobalKey<FormState> formKey;
final List<Widget> formFields;
const MihForm({
super.key,
required this.formKey,
required this.formFields,
});
@override
State<MihForm> createState() => _MihFormState();
}
class _MihFormState extends State<MihForm> {
@override
Widget build(BuildContext context) {
return Form(
key: widget.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widget.formFields,
),
);
}
}
@@ -1,67 +0,0 @@
import 'package:flutter/widgets.dart'; // You need this import for IconData
class MihIcons {
MihIcons._(); // This makes the class non-instantiable (good practice for utility classes)
// This MUST match the 'family' name you specify in pubspec.yaml
static const _mihFontFam = 'MihIcons';
// Set to your package name ONLY if this font is part of a separate package you created
static const String? _mihFontPkg = null;
// IconData constants based on your style.css file
// Note: We convert the hex code from CSS (\eXXX) to an integer (0xeXXX)
static const IconData mineSweeper =
IconData(0xe900, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mzansiDirectory =
IconData(0xe901, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData personalProfile =
IconData(0xe902, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData aboutMih =
IconData(0xe903, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData accessControl =
IconData(0xe904, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData businessProfile =
IconData(0xe905, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData businessSetup =
IconData(0xe906, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData calculator =
IconData(0xe907, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData calendar =
IconData(0xe908, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData iDontKnow =
IconData(0xe909, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mihLogo =
IconData(0xe90a, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mihRing =
IconData(0xe90b, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mzansiAi =
IconData(0xe90c, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mzansiWallet =
IconData(0xe90d, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData notifications =
IconData(0xe90e, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData patientManager =
IconData(0xe90f, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData patientProfile =
IconData(0xe910, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData profileSetup =
IconData(0xe911, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
}
@@ -1,238 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
class MihNumericStepper extends StatefulWidget {
final TextEditingController controller;
final Color fillColor;
final Color inputColor;
final String hintText;
final bool requiredText;
final double? width;
final int? minValue;
final int? maxValue;
final bool validationOn;
const MihNumericStepper({
super.key,
required this.controller,
required this.fillColor,
required this.inputColor,
required this.hintText,
required this.requiredText,
this.width,
this.minValue,
this.maxValue,
required this.validationOn,
});
@override
State<MihNumericStepper> createState() => _MihNumericStepperState();
}
class _MihNumericStepperState extends State<MihNumericStepper> {
late int _currentValue;
late bool error;
@override
void dispose() {
widget.controller.removeListener(_syncCurrentValue);
super.dispose();
}
@override
void initState() {
super.initState();
_currentValue =
int.tryParse(widget.controller.text) ?? widget.minValue ?? 0;
widget.controller.text = _currentValue.toString();
int.tryParse(widget.controller.text) ?? widget.minValue ?? 0;
widget.controller.addListener(_syncCurrentValue);
// print("Current Value: $_currentValue");
}
void _syncCurrentValue() {
final newValue =
int.tryParse(widget.controller.text) ?? widget.minValue ?? 0;
if (newValue != _currentValue) {
setState(() {
_currentValue = newValue;
});
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: [
Text(
widget.hintText,
style: TextStyle(
fontWeight: FontWeight.bold,
color: widget.fillColor,
fontSize: 18,
),
),
],
),
const SizedBox(height: 4),
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Column(
children: [
Container(
// color: Colors.white,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
25), // Optional: rounds the corners
boxShadow: const [
BoxShadow(
color: Color.fromARGB(60, 0, 0,
0), // 0.2 opacity = 51 in alpha (255 * 0.2)
spreadRadius: -2,
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Padding(
padding: const EdgeInsets.only(
top: 2.0,
left: 5.0,
),
child: SizedBox(
width: 40,
child: IconButton.filled(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all<Color>(
MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
),
color: widget.inputColor,
iconSize: 20,
onPressed: () {
print("Current Value: $_currentValue");
if (_currentValue >= (widget.minValue ?? 0)) {
setState(() {
widget.controller.text =
(_currentValue - 1).toString();
_currentValue =
int.tryParse(widget.controller.text)!;
});
}
print("New Current Value: $_currentValue");
},
icon: const Icon(
Icons.remove,
),
),
),
),
),
Visibility(
visible: _currentValue < (widget.minValue ?? 0) ||
(widget.maxValue != null &&
_currentValue > widget.maxValue!),
child: const SizedBox(
height: 21,
),
),
],
),
const SizedBox(width: 15),
Expanded(
child: MihTextFormField(
width: widget.width,
fillColor: widget.fillColor,
inputColor: widget.inputColor,
controller: widget.controller,
hintText: null,
requiredText: widget.requiredText,
readOnly: true,
numberMode: true,
textIputAlignment: TextAlign.center,
validator: (value) {
if (widget.validationOn) {
return MihValidationServices().validateNumber(
value, widget.minValue, widget.maxValue);
}
return null;
},
),
),
const SizedBox(width: 10),
Column(
children: [
Container(
// color: Colors.white,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
25), // Optional: rounds the corners
boxShadow: const [
BoxShadow(
color: Color.fromARGB(60, 0, 0,
0), // 0.2 opacity = 51 in alpha (255 * 0.2)
spreadRadius: -2,
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Padding(
padding: const EdgeInsets.only(
top: 2.0,
left: 5.0,
),
child: SizedBox(
width: 40,
child: IconButton.filled(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all<Color>(
MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
),
color: widget.inputColor,
iconSize: 20,
onPressed: () {
print("Current Value: $_currentValue");
if (widget.maxValue == null ||
_currentValue <= widget.maxValue!) {
setState(() {
widget.controller.text =
(_currentValue + 1).toString();
_currentValue =
int.tryParse(widget.controller.text)!;
});
}
print("New Current Value: $_currentValue");
},
icon: const Icon(
Icons.add,
),
),
),
),
),
Visibility(
visible: _currentValue < (widget.minValue ?? 0) ||
(widget.maxValue != null &&
_currentValue > widget.maxValue!),
child: const SizedBox(
height: 21,
),
),
],
),
],
),
],
);
}
}
@@ -1,217 +0,0 @@
import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_scack_bar.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/components/mih_app_drawer.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class MihPackage extends StatefulWidget {
final Widget appActionButton;
final MihPackageTools appTools;
final List<Widget> appBody;
final List<String>? appToolTitles;
final MIHAppDrawer? actionDrawer;
int selectedbodyIndex;
final Function(int) onIndexChange;
MihPackage({
super.key,
required this.appActionButton,
required this.appTools,
required this.appBody,
this.appToolTitles,
this.actionDrawer,
required this.selectedbodyIndex,
required this.onIndexChange,
});
@override
State<MihPackage> createState() => _MihPackageState();
}
class _MihPackageState extends State<MihPackage>
with SingleTickerProviderStateMixin {
late PageController _pageController;
late AnimationController _animationController;
DateTime? lastPressedAt;
void unfocusAll() {
FocusScope.of(context).unfocus();
}
Future<void> _peakAnimation() async {
int currentPage = widget.selectedbodyIndex;
double peakOffset = _pageController.position.viewportDimension * 0.075;
double currentOffset =
_pageController.page! * _pageController.position.viewportDimension;
int nextPage =
currentPage + 1 < widget.appBody.length ? currentPage + 1 : currentPage;
if (nextPage != currentPage) {
await Future.delayed(const Duration(milliseconds: 100));
await _pageController.animateTo(
currentOffset + peakOffset,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
);
// await Future.delayed(const Duration(milliseconds: 100));
await _pageController.animateTo(
currentPage * _pageController.position.viewportDimension,
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
);
}
}
@override
void dispose() {
super.dispose();
_pageController.dispose();
_animationController.dispose();
}
@override
void didUpdateWidget(covariant MihPackage oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.selectedbodyIndex != widget.selectedbodyIndex) {
_pageController.animateToPage(
widget.selectedbodyIndex,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
}
@override
void initState() {
super.initState();
_pageController = PageController(initialPage: widget.selectedbodyIndex);
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400),
);
// if (!MzansiInnovationHub.of(context)!.theme.kIsWeb) {
// // Trigger the peak animation on start (or call this elsewhere)
// WidgetsBinding.instance.addPostFrameCallback((_) {
// _peakAnimation();
// });
// }
if (!MzansiInnovationHub.of(context)!.theme.kIsWeb) {
// Trigger the peak animation only AFTER the route transition is complete
WidgetsBinding.instance.addPostFrameCallback((_) {
final ModalRoute? currentRoute = ModalRoute.of(context);
if (currentRoute != null) {
currentRoute.animation?.addStatusListener((status) {
if (status == AnimationStatus.completed && mounted) {
// Ensure the widget is still mounted and the animation is completed
_peakAnimation();
}
});
}
});
}
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return GestureDetector(
onTap: unfocusAll,
child: PopScope(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (GoRouterState.of(context).name == 'mihHome' ||
GoRouterState.of(context).name == 'mihAuthentication') {
if (lastPressedAt == null ||
DateTime.now().difference(lastPressedAt!) >
const Duration(seconds: 2)) {
// First press: show a message and update the timestamp.
lastPressedAt = DateTime.now();
ScaffoldMessenger.of(context).showSnackBar(
MihSnackBar(
child: Text("Press back again to exit"),
),
);
} else {
// Second press within 2 seconds: exit the app.
KenLogger.warning('Exiting app...'); // Your custom logger
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
}
} else {
context.goNamed(
'mihHome',
extra: true,
);
}
},
child: Scaffold(
drawer: widget.actionDrawer,
body: SafeArea(
bottom: false,
minimum: EdgeInsets.only(bottom: 0),
child: Container(
width: screenSize.width,
height: screenSize.height,
//color: Colors.black,
padding: const EdgeInsets.only(top: 5),
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
widget.appActionButton,
const SizedBox(
width: 10,
),
Expanded(
child: Container(
// alignment: Alignment.center,
// alignment: Alignment.centerRight,
alignment: Alignment.centerLeft,
// color: Colors.black,
child: FittedBox(
child: Text(
widget.appToolTitles != null
? widget
.appToolTitles![widget.selectedbodyIndex]
: "",
style: const TextStyle(
fontSize: 23,
fontWeight: FontWeight.w600,
),
),
),
),
),
const SizedBox(width: 5),
widget.appTools,
const SizedBox(width: 5),
],
),
const SizedBox(height: 5),
Expanded(
child: PageView.builder(
controller: _pageController,
itemCount: widget.appBody.length,
itemBuilder: (context, index) {
return widget.appBody[index];
},
onPageChanged: (index) {
setState(() {
widget.selectedbodyIndex = index;
widget.onIndexChange(widget.selectedbodyIndex);
});
},
),
),
],
),
),
),
),
),
);
}
}
@@ -1,38 +0,0 @@
import 'package:flutter/material.dart';
class MihPackageAction extends StatefulWidget {
final void Function()? onTap;
final double iconSize;
final Widget icon;
const MihPackageAction({
super.key,
required this.icon,
required this.iconSize,
required this.onTap,
});
@override
State<MihPackageAction> createState() => _MihPackageActionState();
}
class _MihPackageActionState extends State<MihPackageAction> {
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return IconButton(
iconSize: widget.iconSize,
padding: const EdgeInsets.all(0),
onPressed: widget.onTap,
icon: widget.icon,
);
}
}
@@ -1,117 +0,0 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihPackageAlert extends StatefulWidget {
final Widget alertIcon;
final String alertTitle;
final Widget alertBody;
final Color alertColour;
const MihPackageAlert({
super.key,
required this.alertIcon,
required this.alertTitle,
required this.alertBody,
required this.alertColour,
});
@override
State<MihPackageAlert> createState() => _MihPackageAlertState();
}
class _MihPackageAlertState extends State<MihPackageAlert> {
late double popUpWidth;
late double? popUpheight;
late double popUpTitleSize;
late double popUpSubtitleSize;
late double popUpBodySize;
late double popUpIconSize;
late double popUpPaddingSize;
Size? size;
void checkScreenSize() {
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
setState(() {
popUpWidth = (size!.width / 4) * 2;
popUpheight = null;
popUpTitleSize = 30.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
popUpIconSize = 100;
});
} else {
setState(() {
popUpWidth = size!.width - (size!.width * 0.1);
popUpheight = null;
popUpTitleSize = 25.0;
popUpSubtitleSize = 18.0;
popUpBodySize = 15;
popUpPaddingSize = 15.0;
popUpIconSize = 100;
});
}
}
@override
Widget build(BuildContext context) {
size = MediaQuery.of(context).size;
checkScreenSize();
return Dialog(
child: Stack(
children: [
Container(
padding: EdgeInsets.all(popUpPaddingSize),
width: popUpWidth,
height: popUpheight,
decoration: BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25.0),
border: Border.all(color: widget.alertColour, width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
widget.alertIcon,
//const SizedBox(height: 5),
Text(
widget.alertTitle,
textAlign: TextAlign.center,
style: TextStyle(
color: widget.alertColour,
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
widget.alertBody,
const SizedBox(height: 10),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
context.pop();
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
),
);
}
}
@@ -1,234 +0,0 @@
import 'package:app_settings/app_settings.dart';
import 'package:flutter/foundation.dart';
import 'package:local_auth/local_auth.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_yt_video_player.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihPackageTile extends StatefulWidget {
final String appName;
final String? ytVideoID;
final Widget appIcon;
final void Function() onTap;
final double iconSize;
final Color primaryColor;
final Color secondaryColor;
final bool? authenticateUser;
const MihPackageTile({
super.key,
required this.onTap,
required this.appName,
this.ytVideoID,
required this.appIcon,
required this.iconSize,
required this.primaryColor,
required this.secondaryColor,
this.authenticateUser,
});
@override
State<MihPackageTile> createState() => _MihPackageTileState();
}
class _MihPackageTileState extends State<MihPackageTile> {
final LocalAuthentication _auth = LocalAuthentication();
void displayHint() {
if (widget.ytVideoID != null) {
showDialog(
context: context,
builder: (context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: widget.appName,
// windowTools: const [],
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: MIHYTVideoPlayer(
videoYTLink: widget.ytVideoID!,
),
);
},
);
}
}
Future<bool> isUserAuthenticated() async {
final bool canAuthWithBio = await _auth.canCheckBiometrics;
final bool canAuthenticate =
canAuthWithBio || await _auth.isDeviceSupported();
print("Auth Available: $canAuthenticate");
if (canAuthenticate) {
try {
final bool didBioAuth = await _auth.authenticate(
localizedReason: "Authenticate to access ${widget.appName}",
options: const AuthenticationOptions(
biometricOnly: false,
),
);
if (didBioAuth) {
return true;
} else {
authErrorPopUp();
}
// print("Authenticated: $didBioAuth");
} catch (error) {
print("Auth Error: $error");
authErrorPopUp();
}
} else {
print("Auth Error: No Biometrics Available");
authErrorPopUp();
}
return false;
}
void authErrorPopUp() {
Widget alertpopUp = MihPackageAlert(
alertIcon: Icon(
Icons.fingerprint,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 100,
),
alertTitle: "Biometric Authentication Required",
alertBody: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Hi there! To jump into the ${widget.appName} Package, you'll need to authenticate yourself with your devices biometrics, please set up biometric authentication (like fingerprint, face ID, pattern or pin) on your device first.\n\nIf you have already set up biometric authentication, press \"Authenticate now\" to try again or press \"Set Up Authentication\" to go to your device settings.",
style: TextStyle(
fontSize: 15,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 20),
Wrap(
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
AppSettings.openAppSettings(
type: AppSettingsType.security,
);
Navigator.of(context).pop();
},
buttonColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Set Up Authentication",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
MihButton(
onPressed: () {
Navigator.of(context).pop();
authenticateUser();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Authenticate Now",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
alertColour: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
showDialog(
context: context,
builder: (context) {
return alertpopUp;
},
);
}
Future<void> authenticateUser() async {
if (widget.authenticateUser != null &&
widget.authenticateUser! &&
!kIsWeb) {
if (await isUserAuthenticated()) {
widget.onTap();
}
} else {
widget.onTap();
}
}
@override
Widget build(BuildContext context) {
return Container(
// alignment: Alignment.topCenter,
// color: Colors.black,
// width: widget.iconSize,
// height: widget.iconSize + widget.iconSize / 3,
child: GestureDetector(
onTap: () async {
authenticateUser();
},
onLongPress: null, // Do this later
child: Column(
children: [
Flexible(
flex: 3,
child: LayoutBuilder(
builder: (context, constraints) {
double iconHeight = constraints.maxWidth;
return Container(
width: iconHeight,
height: iconHeight,
child:
FittedBox(fit: BoxFit.fitHeight, child: widget.appIcon),
);
},
),
),
const SizedBox(height: 10),
Flexible(
flex: 1,
child: FittedBox(
child: Text(
widget.appName,
textAlign: TextAlign.center,
// softWrap: true,
// overflow: TextOverflow.visible,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
),
);
}
}
@@ -1,95 +0,0 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihPackageToolBody extends StatefulWidget {
final bool borderOn;
final Widget bodyItem;
final double? innerHorizontalPadding;
const MihPackageToolBody({
super.key,
required this.borderOn,
required this.bodyItem,
this.innerHorizontalPadding,
});
@override
State<MihPackageToolBody> createState() => _MihPackageToolBodyState();
}
class _MihPackageToolBodyState extends State<MihPackageToolBody> {
late double _innerBodyPadding;
double getHorizontalPaddingSize(Size screenSize) {
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
if (widget.borderOn) {
return widget.innerHorizontalPadding ?? 10;
} else {
return widget.innerHorizontalPadding ?? 0;
}
} else {
// mobile
if (widget.borderOn) {
return widget.innerHorizontalPadding ?? 10;
} else {
return widget.innerHorizontalPadding ?? 0;
}
}
}
double getVerticalPaddingSize(Size screenSize) {
// mobile
if (widget.borderOn) {
return 10;
} else {
return 0;
}
}
Decoration? getBoader() {
if (widget.borderOn) {
_innerBodyPadding = 10.0;
return BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25.0),
border: Border.all(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 3.0),
);
} else {
_innerBodyPadding = 0.0;
return BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25.0),
border: Border.all(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 3.0),
);
}
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.sizeOf(context);
return Padding(
padding: EdgeInsets.only(
left: getHorizontalPaddingSize(screenSize),
right: getHorizontalPaddingSize(screenSize),
bottom: getVerticalPaddingSize(screenSize),
top: 0,
),
child: Container(
height: screenSize.height,
decoration: getBoader(),
child: Padding(
padding: EdgeInsets.all(_innerBodyPadding),
child: widget.bodyItem,
),
),
);
}
}

Some files were not shown because too many files have changed in this diff Show More