379 Commits
V1.2.0 ... main

Author SHA1 Message Date
971623af77 Merge pull request 'Linux Flatpak config set up' (#26) from V.1.2.6 into main
Reviewed-on: #26
2026-02-26 13:21:15 +00:00
84cb6b2e83 linux icon image fix 2026-02-26 15:15:49 +02:00
6e07a55885 Flatpak linux build 2026-02-26 13:54:38 +02:00
8fb31695a8 linux flatpak config pt11 2026-02-26 12:34:01 +02:00
4fafa35888 linux flatpak config pt10 2026-02-26 12:17:14 +02:00
0cf9634c5d linux flatpak config pt9 2026-02-26 12:15:59 +02:00
787a8057b2 linux flatpak config pt8 2026-02-26 12:15:04 +02:00
5f911d51f9 linux flatpak config pt7 2026-02-26 09:31:20 +02:00
8da29792b4 linux flatpak config pt6 2026-02-26 09:28:18 +02:00
fd4c34c59d Merge pull request 'linux flatpak config pt5' (#25) from V.1.2.6 into main
Reviewed-on: #25
2026-02-25 13:50:19 +00:00
5e003a4d71 linux flatpak config pt5 2026-02-25 15:50:02 +02:00
dca595bf60 Merge pull request 'linux flatpak config pt4' (#24) from V.1.2.6 into main
Reviewed-on: #24
2026-02-25 13:44:37 +00:00
fcf1bbbb15 linux flatpak config pt4 2026-02-25 15:44:10 +02:00
8a0c0d7dba Merge pull request 'linux flatpak config pt3' (#23) from V.1.2.6 into main
Reviewed-on: #23
2026-02-25 13:36:22 +00:00
ff7f363983 linux flatpak config pt3 2026-02-25 15:35:45 +02:00
a54f1c61ae Merge pull request 'linux flatpak config pt2' (#22) from V.1.2.6 into main
Reviewed-on: #22
2026-02-25 13:10:05 +00:00
843997e58c linux flatpak config pt2 2026-02-25 15:09:23 +02:00
cbe70e2e44 Merge pull request 'linux flatpak config' (#21) from V.1.2.6 into main
Reviewed-on: #21
2026-02-25 12:52:15 +00:00
3778ebb261 linux flatpak config 2026-02-25 14:51:15 +02:00
c911e88453 Merge pull request 'linux name change' (#20) from V.1.2.6 into main
Reviewed-on: #20
2026-02-25 11:59:39 +00:00
b1487839a7 linux name change 2026-02-25 13:58:42 +02:00
518dd1300e Merge pull request 'fix platform specific code not working on web pt2' (#19) from V.1.2.6 into main
Reviewed-on: #19
2026-02-25 10:19:05 +00:00
221030eff3 fix platform specific code not working on web pt2 2026-02-25 12:16:53 +02:00
707b49c088 Merge pull request 'fix platform specific code not working on web' (#18) from V.1.2.6 into main
Reviewed-on: #18
2026-02-25 10:05:42 +00:00
5135629b33 fix platform specific code not working on web 2026-02-25 12:05:07 +02:00
bb64be077f Merge pull request 'api cros fix' (#17) from V.1.2.6 into main
Reviewed-on: #17
2026-02-25 09:55:54 +00:00
281ea863e8 api cros fix 2026-02-25 11:54:49 +02:00
64af64f28b Merge pull request 'V.1.2.6' (#16) from V.1.2.6 into main
Reviewed-on: #16
2026-02-25 09:30:49 +00:00
1c0dd6d328 update build number to 130 2026-02-25 10:25:28 +02:00
07d4ba4afa Support linux version of MIHpt2 2026-02-24 16:30:06 +02:00
6ad6b6ccbd Support linux version of MIH 2026-02-24 15:41:55 +02:00
ce2575035f make profile picture the full height of the window 2026-02-24 12:43:34 +02:00
baea2c9fdb fix file display on Dev Web & iOS 2026-02-24 12:37:31 +02:00
27639cb964 add scroll bar to dropdown fields 2026-02-24 11:05:24 +02:00
1143d11054 fix supertoken versioning error 2026-02-24 11:02:30 +02:00
213f3d418d update build number to 129 2026-02-18 15:41:37 +02:00
e33a62b909 update look & feel of attribution list 2026-02-18 14:03:04 +02:00
ebab9bae52 update build no to 128 2026-02-18 11:52:30 +02:00
82c25c5406 make profile picture expandable 2026-02-18 11:51:44 +02:00
3f0fc08a5c update business user edit workflow 2026-02-18 10:56:34 +02:00
f137ea41ac fix loading indicator alignment for business QR code 2026-02-18 10:41:49 +02:00
a7effa3576 Update profile link and business card Icons alignment 2026-02-18 10:26:41 +02:00
74341a9cc6 Enhance Mzansi Profile Look & Feel and workflow 2026-02-18 10:18:03 +02:00
c5267c0540 change follow us link alignments 2026-02-16 16:27:39 +02:00
d4ba3aaa03 fix short cut icon issue 2026-02-16 15:34:27 +02:00
103ccdc022 Add scroll bar to mih 2026-02-16 15:23:16 +02:00
f8a722eb50 change design on profile links and add git option 2026-02-16 14:43:34 +02:00
fdb28080e3 fix web cros issues with fixed dev port pt2 2026-02-16 14:42:33 +02:00
8a384921c5 fix web cros issues with fixed dev port 2026-02-16 14:41:51 +02:00
4b47bf5288 enhacne install/ update mih button to cater for huawei 2026-02-16 14:08:00 +02:00
141611b84d fix mzansi ai modal 2026-02-16 13:43:15 +02:00
a29d0afeb8 update version number of mih 2026-02-16 13:25:46 +02:00
eb93714022 add ds_store file to ingore file 2026-02-16 13:09:33 +02:00
071612a521 BUG: API Wildcard CROS issue 2026-02-16 13:09:33 +02:00
726a60ad25 BUG: Fix exposed ports on mih server 2026-02-16 13:09:33 +02:00
b897986c1f BUG: Fix hardcoded supertoken api key 2026-02-16 13:09:33 +02:00
7d4d7fc713 BUG: Fix Security Flutter Web server 2026-02-16 13:09:33 +02:00
91075255f4 add scrolling to about package 2026-02-10 14:07:05 +02:00
5c2f19dcc4 enable linux platform & rename widnow 2026-02-10 11:58:35 +02:00
58aebbeabe Merge pull request 'ruleset test' (#1) from tester-branch into main
Reviewed-on: #1
2026-02-04 11:18:21 +00:00
670480910b ruleset test 2026-02-04 13:16:15 +02:00
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
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
a3845df8bd Merge branch 'main' into V.1.2.5 2026-02-03 13:57:15 +02:00
d7eebe152b test file 2026-02-03 13:52:47 +02:00
d8a807b43e update build to 1.2.5+1.2.6 2026-02-03 13:29:20 +02:00
5172017a54 Update MZansi AI prod Model 2026-02-03 13:26:37 +02:00
535924691e NEW: Add Mzansi Directory Shortcut 2026-02-03 13:26:17 +02:00
ca8e0f56ac Remove women4change info and revert colors 2026-02-03 10:17:56 +02:00
63071325cb favourite business load fix 2026-02-03 10:15:07 +02:00
800cd635c2 Remove profile link from personal profile for now 2026-02-03 10:05:00 +02:00
f46ce36861 linux app config 2026-02-03 09:57:38 +02:00
b69fd92b19 Update docker compose file for new architechure 2026-01-29 13:02:24 +02:00
9e19dc0fa4 Update API files for new architechure 2026-01-29 13:02:05 +02:00
38c40e2dfe Update launch file for new architechure 2026-01-29 13:01:41 +02:00
02bbc32d23 Update ignore file for new architechure 2026-01-29 13:01:28 +02:00
5b052a1fa9 rename container folders 2026-01-29 11:11:45 +02:00
d5349d981c update architecture 2026-01-29 11:11:25 +02:00
d6c28b631a ignore new mih_minio 2026-01-29 11:07:50 +02:00
74c5276c94 remove old database ignore 2026-01-29 11:06:01 +02:00
d5e349d218 ignore new db folder 2026-01-29 11:04:53 +02:00
44527c8f10 Add self hosted GIT plaform 2026-01-29 10:08:44 +02:00
fbb9d8573c pat man loading 2026-01-06 16:49:32 +02:00
010fc0bc74 BUG: file viewer opening bug 2025-12-17 20:12:51 +02:00
45ac3f03e6 BUG: Supertokens api fix 2025-12-14 23:36:11 +02:00
eea3248525 NEW: MIH Profile Links pt1 2025-12-11 12:57:12 +02:00
b945a34ad4 BUG: Profile set up bug 2025-12-10 19:42:55 +02:00
e3ac1be71c BUG: Business Profile Vew pt2 2025-12-10 12:52:31 +02:00
3a955e67ef BUG: Business Profile Vew 2025-12-10 12:52:13 +02:00
777043e2ca NEW: Config firebase Cloud Messaging for Notifications 2025-12-10 10:18:57 +02:00
6a8b9c6902 QOL: Package Tile Update 2025-12-09 19:14:50 +02:00
07360dd308 QOL: only get user data if user is null 2025-12-09 11:46:16 +02:00
7c59e2a5c8 NEW: New python package added to requirements 2025-12-09 10:54:33 +02:00
0b57e10532 QOL: Button alignment 2025-12-08 19:46:21 +02:00
5681c6d73b BUG: Patient Manager Data fix pt2 2025-12-04 09:19:30 +02:00
f44ff6443c BUG: Patient Manager Data fix 2025-12-03 22:01:49 +02:00
fe5b61f6bc QOL: Switch from Network Image to CachedNetworkImage 2025-12-03 21:42:42 +02:00
e7729a8ce8 QOL: About MIH Share button update 2025-12-03 21:35:41 +02:00
227a2f7ae7 update buiold to 125 2025-12-03 21:09:22 +02:00
f26c1eb01a QOL: Mzansi Ai LLM detection 2025-12-03 12:31:21 +02:00
ca0f13a6df build number update to 124 2025-12-03 11:40:29 +02:00
021a25f50c QOL: Data display load minesweeper pt1 2025-12-03 11:26:47 +02:00
0a9f0c000e QOL: Data display load Mzansi Direct pt4 2025-12-03 11:16:24 +02:00
3ff670886c QOL: Data display load Mzansi Direct pt3 2025-12-03 11:08:22 +02:00
a6d5e4ad35 QOL: Data display load Mzansi Direct pt2 2025-12-03 10:51:18 +02:00
456dff6402 QOL: Data display load Mzansi Direct pt1 2025-12-03 10:32:03 +02:00
d3fdc83373 BUG: incorrect code display style 2025-12-03 09:21:15 +02:00
8704d4dd64 BUG: Patient Infor Scrolling 2025-12-02 19:20:24 +02:00
37920466ac Update build to 123 2025-12-01 10:51:01 +02:00
56d54a3711 QOL: Calanedar message alingment 2025-12-01 10:49:14 +02:00
aef501cd25 QOL: Cache leaderboard images 2025-12-01 10:40:29 +02:00
4f5761271c QOL: Mzansi AI Suggestion update 2025-12-01 10:37:57 +02:00
252e120b99 BUG: Business Team list view 2025-12-01 10:36:25 +02:00
b5c26c3e43 BUG: Mzansi Directory person search on person press 2025-12-01 10:32:26 +02:00
74be2fc559 BUG: File list icons 2025-12-01 10:29:02 +02:00
b519b99a91 QOL: Mzansi Home Scroll 2025-12-01 10:26:17 +02:00
72261af7b9 build number update to 122 2025-11-28 13:49:02 +02:00
ad96725478 QOL: Mzansi Profile Package performance improvements pt2 2025-11-28 13:48:25 +02:00
ef4c3102a9 QOL: MIH Authentication Package performance improvements 2025-11-28 13:43:51 +02:00
9a75bcc810 QOL: MIH Access Controls Package performance improvements pt2 2025-11-28 13:38:14 +02:00
586e67b369 QOL: MIH Mine Sweeper Package performance improvements pt2 2025-11-28 13:30:12 +02:00
e8cae1a894 QOL: MIH Calendar Package performance improvements pt2 2025-11-28 13:26:32 +02:00
cd8115c597 QOL: Patient Manager Package performance improvements pt2 2025-11-28 13:22:54 +02:00
730c5d2bdf QOL: MIH Package performance improvements pt2 2025-11-28 13:13:27 +02:00
cea8ccab5a QOL: Mzansi Wallet Package performance improvements pt2 2025-11-28 13:02:34 +02:00
4f168c5b0e QOL: MIH About Package performance improvements 2025-11-28 12:57:19 +02:00
99f8b1a3f9 QOL: MIH Access Controls Package performance improvements 2025-11-28 12:54:31 +02:00
30c06261c8 QOL: MIH Mine Sweeper Package performance improvements 2025-11-28 12:52:33 +02:00
c843c0a55d QOL: MIH Calculator Package performance improvements 2025-11-28 12:47:44 +02:00
94ac83db9e QOL: Mzansi AI Package performance improvements 2025-11-28 12:44:51 +02:00
a3b8da5357 QOL: MIH Calendar Package performance improvements 2025-11-28 12:43:07 +02:00
47bc23c029 QOL: Patient Manager Package performance improvements 2025-11-28 12:41:30 +02:00
c16d8b6e91 QOL: Mzansi Wallet Package performance improvements 2025-11-28 12:31:39 +02:00
a6fe4499d0 QOL: Mzansi Profile Package performance improvements 2025-11-28 12:29:09 +02:00
004c2397c5 QOL: MIH Home Package performance improvements 2025-11-28 12:15:12 +02:00
d64193d1f8 QOL: MIH Package performance improvements 2025-11-28 12:14:20 +02:00
e330875c6f build update to 121 2025-11-28 11:43:38 +02:00
3d2addf1d6 BUG: fav bus view fix performace pt 2 2025-11-28 11:33:26 +02:00
3b6e1d22ec build update to 120 2025-11-28 10:30:33 +02:00
ff913c0c54 BUG: fav bus view fix 2025-11-28 10:26:36 +02:00
c45c933277 Update version and build 2025-11-27 13:16:30 +02:00
89d6999abf BUG: patient profile picture in patient manager 2025-11-27 13:14:40 +02:00
969ecf8fdc BUG: User search piture load 2025-11-27 12:57:15 +02:00
ee7d3881e6 BUG: Image loading of businesses 2025-11-27 12:40:34 +02:00
cc3f18f7e2 QOL: Mzansi AI Enhancement pt1 2025-11-27 09:48:42 +02:00
08bfe1d417 Update build to 118 2025-11-25 16:51:03 +02:00
3593011d6d minio storage uploud fix pt9 2025-11-25 16:47:42 +02:00
5ae11f6625 minio storage uploud fix pt8 2025-11-25 16:40:48 +02:00
a61bca7d81 minio storage uploud fix pt7 2025-11-25 16:31:13 +02:00
fb3b033f45 minio storage uploud fix pt6 2025-11-25 16:11:28 +02:00
91a2d0dd1e minio storage uploud fix pt5 2025-11-25 16:08:20 +02:00
04c643561b minio storage uploud fix pt4 2025-11-25 16:05:53 +02:00
526bd40255 minio storage uploud fix pt3 2025-11-25 15:53:09 +02:00
1889f6cada minio storage uploud fix pt2 2025-11-25 15:39:23 +02:00
c1dd9a60f2 minio storage uploud fix pt1 2025-11-25 15:31:53 +02:00
ec869c54c3 minio storage fix pt14 2025-11-25 15:29:07 +02:00
b440c0a42b minio storage fix pt13 2025-11-25 15:24:02 +02:00
baa826c52c minio storage fix pt12 2025-11-25 15:22:27 +02:00
6b530529e3 minio storage fix pt11 2025-11-25 15:20:58 +02:00
a633b52949 minio storage fix pt10 2025-11-25 15:16:41 +02:00
c103d1979c minio storage fix pt9 2025-11-25 15:12:38 +02:00
82c01cb7bf minio storage fix pt8 2025-11-25 15:05:16 +02:00
43bc552698 minio storage fix pt7 2025-11-25 15:00:20 +02:00
bb6a8e3090 minio storage fix pt6 2025-11-25 14:49:56 +02:00
565e9199d4 minio storage fix pt5 2025-11-25 14:38:59 +02:00
c5de46040d minio storage fix pt4 2025-11-25 14:31:37 +02:00
934b1b2301 minio storage fix pt3 2025-11-25 13:51:42 +02:00
302152449f minio storage fix pt2 2025-11-25 13:42:46 +02:00
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
a59d2bf336 update build to 117 2025-11-25 11:40:22 +02:00
d5fcad8fa5 BUG: Image display when error 2025-11-25 11:38:19 +02:00
609828a26c update build to 116 2025-11-25 11:18:46 +02:00
d0a5c6c858 QOL: Mzansi AI trigger from home 2025-11-25 11:16:18 +02:00
4a293c0aa4 add toot titles to missing packages 2025-11-25 10:45:39 +02:00
d51d13a685 update build to 115 2025-11-21 12:15:34 +02:00
bf6bda04a6 get business data when opening mxzansi profile as standalone 2025-11-21 12:14:03 +02:00
b749dc62d9 fix alert padding for desktop 2025-11-21 12:11:51 +02:00
b82a5a72c7 NEW: Hide sensitive data on my business user 2025-11-21 11:59:34 +02:00
56ab6bb950 QOL: use advanced varding when adding & removing card to fav 2025-11-21 10:27:22 +02:00
bb54605ddb QOL: Create advanced warning alert 2025-11-21 10:26:57 +02:00
c4b3a12213 BUG: add jpeg icons 2025-11-21 10:17:24 +02:00
43d715f4f8 QOL: Reorder Minesweeper alert buttons 2025-11-21 10:16:19 +02:00
a9d6ca1baa QOL: Get loaction in bg 2025-11-21 10:12:51 +02:00
dfcfced28f BUG: Remove hint when keyboard is open 2025-11-21 09:57:12 +02:00
d0474fed21 BUG: Social Links colour fix 2025-11-21 09:44:06 +02:00
f228307859 Update Business QR code share text 2025-11-21 09:34:40 +02:00
ab9cbce41c BUG: remove token text in reset password 2025-11-21 09:34:16 +02:00
70413cc294 QOL: About MIH button placement 2025-11-21 09:33:45 +02:00
a4d510f023 v.1.2.4 Build Number Updated to 114 2025-11-20 11:22:24 +02:00
e99388711d v.1.2.3 pt 2 Build Number Updated to 113 2025-11-20 11:05:29 +02:00
00cd5488e3 NEW: MIh Alerts 2025-11-20 10:56:15 +02:00
b69a52a5a8 Mih File Structure enhancement 2025-11-18 12:42:22 +02:00
f5c05d7431 remove prints 2025-11-17 12:59:19 +02:00
0403d8c4b5 fix naming convention 2025-11-17 12:58:24 +02:00
fb7bf4ad65 QOL: Remove legacy layout widgets 2025-11-17 12:56:18 +02:00
3417299989 NEW: create new file viewer with MIH package 2025-11-17 12:55:34 +02:00
66887d23f8 QOL: MIH Go Router get data on package open pt2 2025-11-17 11:32:39 +02:00
f064730dcf QOL: Patient Manager get data on package open pt2 2025-11-17 11:32:23 +02:00
a49505c153 QOL: MIH Test Package get data on package open 2025-11-17 11:25:51 +02:00
9d898d8dff QOL: Mzansi profile Business get data on package open 2025-11-17 11:25:37 +02:00
c517075197 QOL: MIH Acces Controls get data on package open 2025-11-17 11:17:16 +02:00
2dc3396fcc QOL: MIH Minesweeper get data on package open 2025-11-17 11:09:38 +02:00
d318b17b18 QOL: Mzansi AI get data on package open 2025-11-17 11:05:59 +02:00
4221ae73b9 QOL: MIH Calendar get data on package open 2025-11-17 10:59:47 +02:00
b49e93825e QOL: Mzansi Directory get data on package open 2025-11-17 10:53:52 +02:00
790bf0e4f8 QOL: Patient Manager get data on package open 2025-11-17 10:46:24 +02:00
a0bd74b703 QOL: Mzansi Wallet get data on package open 2025-11-17 10:46:09 +02:00
96daf77b45 QOL: Mzansi profile Personal get data on package open 2025-11-17 10:45:57 +02:00
77ffd95fb6 QOL: MIH Home get data on package open 2025-11-17 10:45:31 +02:00
24cc7f64b5 QOL: Update file service 2025-11-17 09:24:32 +02:00
d76512c11f BUG: dont initialise shortcuts on web 2025-11-14 14:25:32 +02:00
e1e7542a6d optimisation web pt 3 2025-11-14 14:22:30 +02:00
121cde211f optimisation web pt 2 2025-11-14 14:22:30 +02:00
b79decf04f cancel timeout on load 2025-11-14 14:22:30 +02:00
a26b826729 increase timeut time 2025-11-14 14:22:30 +02:00
cc3d1ae430 web load v2 2025-11-14 14:22:30 +02:00
329e450f5b revert 2025-11-14 14:22:30 +02:00
0a03b1c60c web loadtime 2025-11-14 14:22:30 +02:00
652d4bb2fd increase load 2025-11-14 14:22:30 +02:00
5903fcd31a reduce load speed 2025-11-14 14:22:30 +02:00
b0825fe7cb optimisation web pt 3 2025-11-14 14:02:55 +02:00
8a2debcaa8 optimisation web pt 2 2025-11-14 13:53:20 +02:00
609c8d46db cancel timeout on load 2025-11-14 13:04:04 +02:00
1387fb1af5 increase timeut time 2025-11-14 12:52:11 +02:00
1f73aa3b87 web load v2 2025-11-14 12:47:15 +02:00
47ca6d7311 revert 2025-11-14 12:33:35 +02:00
64443a5076 web loadtime 2025-11-14 12:22:21 +02:00
20d5bc4004 increase load 2025-11-14 12:07:36 +02:00
9257786191 reduce load speed 2025-11-14 11:28:52 +02:00
66db154b02 user service update 2025-11-14 11:27:02 +02:00
5770f6c353 QOL: Patient Manager overhaul pt3 2025-11-14 11:27:02 +02:00
c5713cf6e0 QOL: Patient Manager overhaul pt2 2025-11-14 11:27:02 +02:00
4fe544b35f QOL: Patient Manager overhaul pt1 2025-11-14 11:27:02 +02:00
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
d9b2598bca update web icoon 2025-11-10 16:59:14 +02:00
0c15bd3e90 iod svg assets 2025-11-10 16:57:49 +02:00
0daffb5041 QOL: Mzansi AI Chat Look and Feel & Startup question pt6 2025-11-10 15:36:38 +02:00
9485213d6e NEW: MIH Shortcuts pt3 2025-11-10 15:36:22 +02:00
9a8f157451 QOL: Mzansi AI Chat Look and Feel & Startup question pt5 2025-11-10 14:48:15 +02:00
a6f6cdaace NEW: MIH Stands with Women For Change SA 2025-11-10 14:19:40 +02:00
effbac2c91 NEW: MIH Colors W4C 2025-11-10 13:59:21 +02:00
f8de726959 QOL: Mzansi AI Chat Look and Feel & Startup question pt4 2025-11-10 13:35:04 +02:00
01220144c3 NEW: MIH Loading revamp 2025-11-10 13:34:41 +02:00
3f93cc9a7a NEW: MIH Shortcuts pt2 2025-11-10 13:34:15 +02:00
83a16bad79 NEW: MIH Shortcuts pt1 2025-11-08 03:02:47 +02:00
d2f93db580 include busines home 2025-11-07 15:04:52 +02:00
a3c1963d30 QOL: Mzansi AI Chat Look and Feel & Startup question pt3 2025-11-07 15:03:36 +02:00
8e6ef25954 QOL: Mzansi AI Chat Look and Feel pt2 & Startup question 2025-11-07 14:44:42 +02:00
580fa027f2 QOL: Build number update to 103 2025-11-07 14:44:42 +02:00
9346cccd20 BUG: Get patient data from tile 2025-11-07 14:44:42 +02:00
51f2435c33 QOL: Update Mzansi AI System PRompt 2025-11-07 14:44:42 +02:00
ba5772f3ac NFC deep linking 2025-11-07 14:44:42 +02:00
662d20617d QOL: Update build to 101 2025-11-07 14:44:42 +02:00
e6d1cf0268 favourite business fix 2025-11-07 14:44:42 +02:00
ed7c5a2269 IOS encryption compliance 2025-11-07 14:44:42 +02:00
98beb20827 deeplinking fix 2025-11-07 14:44:07 +02:00
76a54ce969 QOL: Update build to 100 2025-11-07 14:44:07 +02:00
c53f30035d BUG: Update Appointment & Clear Coltrollers 2025-11-07 14:44:07 +02:00
ec01e2212b BUG: Bookmarked businesses data load 2025-11-07 14:44:07 +02:00
f840418caf BUG: back Nav from favourite business selection 2025-11-07 14:44:07 +02:00
76d24a8e2b BUG: Business Profile Tool Transitions 2025-11-07 14:44:07 +02:00
821cbc0a0d BUG: Set up patient flow 2025-11-07 14:44:07 +02:00
ea25598144 QOL: update guide 2025-11-07 14:44:07 +02:00
70fc306789 QOL: Change reset game to start new game 2025-11-07 14:44:07 +02:00
ba46f38497 BUG: MIH Ad Display Strategy 2025-11-07 14:44:07 +02:00
67692967c3 BUG: Add card refresh list 2025-11-07 14:44:07 +02:00
cc51afadb3 BUG: Menue showing in claims in personal mode 2025-11-07 14:44:07 +02:00
d9fb9dd758 QOL: Mzansi AI Chat Look and Feel pt2 & Startup question 2025-11-07 14:29:05 +02:00
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
763c4cdb54 QOL: Build number update to 103 2025-11-05 10:04:30 +02:00
b37f0f71db BUG: Get patient data from tile 2025-11-05 09:59:58 +02:00
8ceb443964 QOL: Update Mzansi AI System PRompt 2025-11-05 09:44:54 +02:00
a87e52d22c NFC deep linking 2025-11-04 12:29:55 +02:00
46c281d288 QOL: Update build to 101 2025-11-04 12:07:47 +02:00
5289cf8511 favourite business fix 2025-11-04 12:07:00 +02:00
22ae804c2d IOS encryption compliance 2025-11-04 12:06:49 +02:00
1a7293fc12 deeplinking fix 2025-11-04 11:43:47 +02:00
e318e03805 QOL: Update build to 100 2025-11-04 11:36:04 +02:00
11b6ec9edb BUG: Update Appointment & Clear Coltrollers 2025-11-04 11:34:28 +02:00
2a7e3e17ce BUG: Bookmarked businesses data load 2025-11-04 11:00:29 +02:00
9cbdc849b1 BUG: back Nav from favourite business selection 2025-11-04 10:17:38 +02:00
0cabe11ab7 BUG: Business Profile Tool Transitions 2025-11-04 10:15:34 +02:00
a561f4fa5f BUG: Set up patient flow 2025-11-03 19:28:52 +02:00
429e91b638 QOL: update guide 2025-11-03 13:12:16 +02:00
c0d152002c QOL: Change reset game to start new game 2025-11-03 11:30:46 +02:00
1329c8aba4 BUG: MIH Ad Display Strategy 2025-11-03 11:27:44 +02:00
52f9eb7ba6 BUG: Add card refresh list 2025-11-03 10:18:29 +02:00
bcff545dd7 BUG: Menue showing in claims in personal mode 2025-11-03 09:25:16 +02:00
6a5b4f7f4b QOL: Location compliance update for app store 2025-11-03 09:20:14 +02:00
yaso-meth
b2b9d8f046 Merge pull request #260 from yaso-meth/V.1.2.2
V.1.2.2
2025-10-31 13:16:34 +02:00
yaso-meth
4c39e9163b Merge branch 'main' into V.1.2.2 2025-10-31 13:15:41 +02:00
yaso-meth
6541ac883f Merge pull request #259 from yaso-meth/V.1.2.1
Add Meta Add Mediation & Build Update
2025-10-31 13:14:47 +02:00
ffe9f6e9fb NEW: Version Update 2025-10-31 12:53:37 +02:00
8e6f3d7d45 Android Config Changes 2025-10-31 12:52:58 +02:00
abd56d5a14 Clean up 2025-10-31 12:18:13 +02:00
cb25b932ba NEW: Patient Manager Provider Setup pt4 2025-10-31 11:55:49 +02:00
771d809ce2 NEW: MIH MineSweeper Package pt4 2025-10-31 11:55:31 +02:00
d6f1629485 NEW: MIH MineSweeper Package Pt 3 2025-10-30 11:58:46 +02:00
39a42048c2 NEW: Patient Manager Provider Setup pt3 2025-10-29 15:43:05 +02:00
99d0fa4aa8 NEW: Patient Manager Provider Setup pt2 2025-10-29 13:59:09 +02:00
79ed959b42 BUG: Dropdown search text disabled 2025-10-29 13:17:05 +02:00
23c3cf4173 NEW: MIH MineSweeper Package pt2 2025-10-29 13:06:55 +02:00
f548db7d82 NEW: Patient Manager Provider Setup pt1 2025-10-27 18:46:20 +02:00
fd2f3a2138 BUG: Fix MIH Logo press on app drawer 2025-10-24 13:11:42 +02:00
1fe817919f QOL: Fix New User Setup flow 2025-10-24 13:00:19 +02:00
656e1cd3d7 QOL: reset providers on signout and signin 2025-10-24 12:59:11 +02:00
a9ea3594b9 QOL: Add reset function to providers 2025-10-24 12:58:29 +02:00
7de2cb7b36 QOL: Update Alert title size 2025-10-24 12:57:49 +02:00
ac22e50eca Change patient profile folder to patient manager 2025-10-23 11:01:39 +02:00
9bd039ca25 NEW: Mzansi Directory Provider Setup 2025-10-22 14:43:01 +02:00
b0d38b4b11 NEW: MIH Access Controlls Provider Setup 2025-10-21 15:42:38 +02:00
926b749fa8 NEW: MIH Calendar Provider Setup 2025-10-21 13:00:52 +02:00
b2ed1e0b51 NEW: About MIH Provider Setup pt2 2025-10-21 10:46:50 +02:00
3dc9ce30e6 NEW: MIH Calc Provider Setup pt2 2025-10-21 10:45:15 +02:00
91241aa399 NEW: Mzansi AI Provider Setup 2025-10-21 10:40:40 +02:00
c79904d132 NEW: complete provider mzansi wallet 2025-10-21 10:22:20 +02:00
15106d0a00 NEW: fix home nav 2025-10-21 09:53:37 +02:00
2e69e1dd92 NEW: MIH Home & Mzansi Profile Provider Setup pt 2 done 2025-10-20 16:41:24 +02:00
c89932755f BUG: Tab movement on password fields 2025-10-20 11:18:06 +02:00
540e13dfe0 mine sweeper pt2 2025-10-17 08:24:23 +02:00
d51603ff5d NEW: MIH Home & Mzansi Profile Provider Setup pt 1 2025-10-16 10:16:18 +02:00
553d22dd6b BUG: Package Auth Loop 2025-10-16 09:59:52 +02:00
5f5107ee99 QOL: Add Long Press to mih button 2025-10-16 09:46:02 +02:00
6ecce1e9ff NEW: MIH MineSweeper Package pt1 2025-10-16 09:45:17 +02:00
22d8c64994 QOL: Change Users to People in About MIH 2025-10-16 09:03:02 +02:00
ebd78eb72b NEW: MIH Authentication Provider Setup 2025-10-13 11:14:11 +02:00
f828ba1786 NEW: About MIH Provider Setup 2025-10-13 10:45:30 +02:00
bbadc58ab8 NEW: MIH Calculator Provider Setup 2025-10-08 15:06:04 +02:00
a1b7a3ef28 NEW: MIH Banner Ads Provider Set Up 2025-10-08 14:43:03 +02:00
7373a1b8cb NEW: Mzansi Wallet Provider Setup 2025-10-08 13:35:47 +02:00
0edbfadc90 NEW: Import & Set Up Provider 2025-10-08 12:53:09 +02:00
ef479b633d NEW: Add Test Device to main dev 2025-10-08 12:51:52 +02:00
081e7d5533 BUG: Special Chars in Business Type 2025-10-08 09:40:34 +02:00
18e8217ce1 NEW: Engen Card Added to Mzansi Wallet 2025-10-07 11:45:37 +02:00
cadd51535e Add Meta Ads SDK 2025-10-07 10:38:26 +02:00
ba394e7fea BUG: Business QR Code Picture Display 2025-10-07 10:38:04 +02:00
04c92804b8 BUG: Fix blank screen on load 2025-10-07 09:49:18 +02:00
a5d72d745d Add Meta Add Mediation & Build Update 2025-10-03 11:04:04 +02:00
yaso-meth
a2d1bebca1 Merge pull request #258 from yaso-meth/V.1.2.1
app sign pt2
2025-10-03 09:49:37 +02:00
69d225f22f app sign pt2 2025-10-02 15:49:12 +02:00
yaso-meth
1a448572ea Merge pull request #257 from yaso-meth/V.1.2.1
app signing
2025-10-02 15:35:25 +02:00
eb4bf4b77b app signing 2025-10-02 15:32:08 +02:00
yaso-meth
04b247aa99 Merge pull request #256 from yaso-meth/V.1.2.1
BUG: Mzansi Wallet Card Scanner
2025-10-02 13:55:34 +02:00
4a1e35d700 BUG: Mzansi Wallet Card Scanner 2025-10-01 20:59:45 +02:00
yaso-meth
aa0d756979 Merge pull request #255 from yaso-meth/V.1.2.1
fix docker compose alignment
2025-10-01 09:27:13 +02:00
f6c631c221 fix docker compose alignment 2025-10-01 09:26:34 +02:00
yaso-meth
16f50f826b Merge pull request #254 from yaso-meth/V.1.2.1
V.1.2.1 First Push
2025-10-01 09:22:45 +02:00
eb2f70e721 miscalanius changes 2 2025-10-01 08:57:35 +02:00
07009f832a miscalanious changes 2025-09-30 19:51:15 +02:00
bcdaf55761 QOL: Selectable Text in Mzansi AI Thoughts 2025-09-30 19:50:40 +02:00
81c932a0e6 NEW: Update version to 1.2.1+98 2025-09-30 11:44:01 +02:00
aabaf21248 QOL: Align fonsize of text pt2 2025-09-30 11:43:36 +02:00
7a2ba21156 QOL: Comment out phpMyAdmin from docker compose 2025-09-30 11:26:55 +02:00
d7af659b23 NEW: Privacy Policy and TOS Popup 2025-09-30 11:12:58 +02:00
9d807f7d28 BUG: Fix PP & TOS in Drawer 2025-09-30 11:11:13 +02:00
6a12fa9e6e BUG: Fix screen brightness changing 2025-09-29 10:57:09 +02:00
de4b6e8fcc QOL: Align fonsize of text 2025-09-29 10:56:44 +02:00
0f0e19b6f3 . 2025-09-25 11:26:22 +02:00
a4be7fb74d QOL: Download Full Business QR Code Image 2025-09-25 11:26:22 +02:00
291882abc5 BUG: Fix Profile Picture Alignment 2025-09-25 11:26:22 +02:00
ffcee3b7a7 NEW: Add user and business count to about MIH 2025-09-25 11:26:22 +02:00
5548a23f69 NEW: Simplified Chinese Privacy Policy and TOS 2025-09-25 11:26:22 +02:00
93e10aad46 QOL: toggle elavation 2025-09-25 11:26:22 +02:00
d7023b8505 Update MIH Pop Up alert 2025-09-25 11:26:22 +02:00
52b71cef61 update android build 2025-09-25 11:26:22 +02:00
058e852e68 Update minio server version 2025-09-25 11:26:22 +02:00
e4dc84647d Add Simplified Chinese Verson of Privacy Policy 2025-09-25 11:26:22 +02:00
822 changed files with 34420 additions and 27863 deletions

BIN
.DS_Store vendored

Binary file not shown.

16
.gitignore vendored
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

17
.vscode/launch.json vendored
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",

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"]

View File

@@ -1,57 +0,0 @@
{
"agcgw_all":{
"CN":"connect-drcn.dbankcloud.cn",
"CN_back":"connect-drcn.hispace.hicloud.com",
"DE":"connect-dre.dbankcloud.cn",
"DE_back":"connect-dre.hispace.hicloud.com",
"RU":"connect-drru.hispace.dbankcloud.ru",
"RU_back":"connect-drru.hispace.dbankcloud.cn",
"SG":"connect-dra.dbankcloud.cn",
"SG_back":"connect-dra.hispace.hicloud.com"
},
"websocketgw_all":{
"CN":"connect-ws-drcn.hispace.dbankcloud.cn",
"CN_back":"connect-ws-drcn.hispace.dbankcloud.com",
"DE":"connect-ws-dre.hispace.dbankcloud.cn",
"DE_back":"connect-ws-dre.hispace.dbankcloud.com",
"RU":"connect-ws-drru.hispace.dbankcloud.ru",
"RU_back":"connect-ws-drru.hispace.dbankcloud.cn",
"SG":"connect-ws-dra.hispace.dbankcloud.cn",
"SG_back":"connect-ws-dra.hispace.dbankcloud.com"
},
"client":{
"cp_id":"30027000028342692",
"product_id":"461323198429473763",
"client_id":"1605107650066918016",
"client_secret":"F0A7DCFC40BBE823749E9CDAFA95BC7EF6CF37AE4CCC47F20E3434521625E1E1",
"project_id":"461323198429473763",
"app_id":"113315335",
"api_key":"DQEDAFJrB8PGLd+BmY2xafYqt6NgGE+W3ShbW2/b8xNkMTX1Elf1u7NLU73LkMl676mVHeQvLkwluYHi0FEJXEzfXtLR6P6jmW5q5A==",
"package_name":"za.co.mzansiinnovationhub.mih"
},
"oauth_client":{
"client_id":"113315335",
"client_type":1
},
"app_info":{
"app_id":"113315335",
"package_name":"za.co.mzansiinnovationhub.mih"
},
"configuration_version":"3.0",
"appInfos":[
{
"package_name":"za.co.mzansiinnovationhub.mih",
"client":{
"app_id":"113315335"
},
"app_info":{
"package_name":"za.co.mzansiinnovationhub.mih",
"app_id":"113315335"
},
"oauth_client":{
"client_type":1,
"client_id":"113315335"
}
}
]
}

View File

@@ -1,103 +0,0 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
namespace "za.co.mzansiinnovationhub.mih"
compileSdkVersion flutter.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "za.co.mzansiinnovationhub.mih"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 24 //flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
signingConfigs {
release {
keyAlias = keystoreProperties['keyAlias']
keyPassword = keystoreProperties['keyPassword']
storeFile = keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword = keystoreProperties['storePassword']
}
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
// signingConfig signingConfigs.debug
signingConfig = signingConfigs.release
}
}
}
flutter {
source '../..'
}
dependencies {
// implementation("com.google.android.material:material:<version>")
implementation "com.google.android.material:material:1.12.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation(platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version"))
// implementation 'com.google.android.gms:play-services-ads:23.1.0'
// implementation 'com.huawei.agconnect:agconnect-core:1.5.2.300'
}
// apply plugin: 'com.huawei.agconnect'
configurations.all {
resolutionStrategy {
eachDependency { details ->
if (details.requested.group == 'org.jetbrains.kotlin') {
if (!details.requested.version.startsWith(rootProject.ext.kotlin_version)) {
details.useVersion rootProject.ext.kotlin_version
}
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#3A4454</color>
</resources>

View File

@@ -1,34 +0,0 @@
buildscript {
ext.kotlin_version = '2.1.21'
repositories {
google()
mavenCentral()
// maven { url 'https://developer.huawei.com/repo/' }
}
dependencies {
classpath "com.android.tools.build:gradle:8.8.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// classpath 'com.huawei.agconnect:agcp:1.5.2.300'
}
}
allprojects {
repositories {
google()
mavenCentral()
// maven {url 'https://developer.huawei.com/repo/'}
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
//subprojects {
// project.evaluationDependsOn(':app')
//}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -1,6 +0,0 @@
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View File

@@ -1,30 +0,0 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
plugins {
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
id "org.jetbrains.kotlin.android" version "2.1.21" apply false
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version '8.8.1' apply false
}
include ":app"

View File

@@ -1,32 +0,0 @@
# flutter pub run flutter_launcher_icons
flutter_launcher_icons:
image_path: "images/app_icon/App_Icon_3.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: "images/app_icon/App_Icon_3.png"
# adaptive_icon_monochrome: "assets/icon/monochrome.png"
ios: true
image_path_ios: "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: "images/app_icon/circle_logo.png"
background_color: "#3A4454"
theme_color: "#3A4454"
windows:
generate: true
image_path: "images/app_icon/circle_logo.png"
icon_size: 48 # min:48, max:256, default: 48
macos:
generate: true
image_path: "images/app_icon/circle_logo.png"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 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.5 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

View File

@@ -1,77 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.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 MaterialApp.router(
title: getTitle(),
themeMode: ThemeMode.dark,
theme: theme.getThemeData(),
darkTheme: theme.getThemeData(),
debugShowCheckedModeBanner: false,
routerConfig: widget.router,
);
}
}

View File

@@ -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,
);
}
}

View File

@@ -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,
),
),
),
),
);
}
}

View File

@@ -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,
),
);
}
}

View File

@@ -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,
);
}
}

View File

@@ -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,
),
),
)
],
),
);
}
}

View File

@@ -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");
},
);
}
}

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

View File

@@ -1,75 +0,0 @@
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
class MihBannerAd extends StatefulWidget {
const MihBannerAd({super.key});
@override
State<MihBannerAd> createState() => _MihBannerAdState();
}
class _MihBannerAdState extends State<MihBannerAd> {
BannerAd? _bannerAd;
bool _isBannerAdLoaded = false;
final adUnitId = AppEnviroment.bannerAdUnitId;
String errorMessage = '';
void _loadBannerAd() {
_bannerAd = BannerAd(
adUnitId: adUnitId,
request: const AdRequest(),
size: AdSize.banner,
listener: BannerAdListener(
onAdLoaded: (ad) {
debugPrint('$ad loaded.');
setState(() {
_isBannerAdLoaded = true;
});
},
onAdFailedToLoad: (ad, err) {
debugPrint('BannerAd failed to load: $err');
setState(() {
errorMessage =
'Failed to load ad- Message: ${err.message} Code :${err.code}';
});
ad.dispose(); // Dispose the ad to free resources
},
onAdOpened: (Ad ad) => debugPrint('$ad opened.'),
onAdClosed: (Ad ad) => debugPrint('$ad closed.'),
onAdImpression: (Ad ad) => debugPrint('$ad impression.'),
),
);
_bannerAd!.load();
}
@override
void dispose() {
_bannerAd?.dispose(); // Dispose the ad when the widget is removed
super.dispose();
}
@override
void initState() {
super.initState();
_loadBannerAd();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
_bannerAd != null && _isBannerAdLoaded
? SizedBox(
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!))
: SizedBox(
child:
Text(AppEnviroment.getEnv() == "Dev" ? errorMessage : ""),
),
],
);
}
}

View File

@@ -1,120 +0,0 @@
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_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
class MihBusinessProfilePreview extends StatefulWidget {
final Business business;
final String? myLocation;
const MihBusinessProfilePreview({
super.key,
required this.business,
required this.myLocation,
});
@override
State<MihBusinessProfilePreview> createState() =>
_MihBusinessProfilePreviewState();
}
class _MihBusinessProfilePreviewState extends State<MihBusinessProfilePreview> {
late Future<String> futureImageUrl;
PlatformFile? file;
String calculateDistance() {
try {
double distanceInKm = MIHLocationAPI().getDistanceInMeaters(
widget.myLocation!, widget.business.gps_location) /
1000;
return "${distanceInKm.toStringAsFixed(2)} km";
} catch (error) {
print(error);
return "*.** km";
}
}
@override
void initState() {
super.initState();
futureImageUrl =
MihFileApi.getMinioFileUrl(widget.business.logo_path, context);
}
@override
Widget build(BuildContext context) {
double profilePictureWidth = 60;
return Row(
children: [
FutureBuilder(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: NetworkImage(asyncSnapshot.requireData),
width: profilePictureWidth,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: () {},
);
} else {
return Icon(
MihIcons.iDontKnow,
size: profilePictureWidth,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
}
}),
const SizedBox(width: 15),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.business.Name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Text(
widget.business.type,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
Text(
widget.myLocation != null || widget.myLocation!.isEmpty
? calculateDistance()
: "0.00 km",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10,
),
),
],
)
],
);
}
}

View File

@@ -1,172 +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(
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("Error: $e");
}
},
icon: Icon(
Icons.edit,
),
),
),
),
],
),
);
}
}

View File

@@ -1,243 +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;
const MihDropdownField({
super.key,
required this.controller,
required this.hintText,
required this.dropdownOptions,
required this.requiredText,
required this.editable,
required this.enableSearch,
this.validator,
});
@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: TextInputAction.search,
requestFocusOnTap: true,
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);
},
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,
),
),
),
],
);
},
),
],
);
}
}

View File

@@ -1,116 +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 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 = 25.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
popUpIconSize = 100;
});
} else {
setState(() {
popUpWidth = size!.width - (size!.width * 0.1);
popUpheight = null;
popUpTitleSize = 20.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: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
),
);
}
}

View File

@@ -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,
),
),
),
)
],
),
),
);
}
}

View File

@@ -1,217 +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_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihPackageWindow extends StatefulWidget {
final String windowTitle;
final Widget windowBody;
final List<SpeedDialChild>? menuOptions;
final void Function() onWindowTapClose;
final bool fullscreen;
const MihPackageWindow({
super.key,
required this.fullscreen,
required this.windowTitle,
this.menuOptions,
required this.onWindowTapClose,
required this.windowBody,
});
@override
State<MihPackageWindow> createState() => _MihPackageWindowState();
}
class _MihPackageWindowState extends State<MihPackageWindow> {
late double windowTitleSize;
late double horizontralWindowPadding;
late double vertticalWindowPadding;
late double windowWidth;
late double windowHeight;
late double width;
late double height;
void checkScreenSize() {
// print("screen width: $width");
// print("screen height: $height");
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
setState(() {
windowTitleSize = 25;
horizontralWindowPadding = width / 7;
vertticalWindowPadding = 10;
windowWidth = width;
windowHeight = height;
});
} else {
setState(() {
windowTitleSize = 20;
horizontralWindowPadding = 10;
vertticalWindowPadding = 10;
windowWidth = width;
windowHeight = height;
});
}
}
Widget getHeader() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
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: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconSize: 20,
onPressed: () {
widget.onWindowTapClose();
},
icon: const Icon(
Icons.close,
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Text(
widget.windowTitle,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: windowTitleSize,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
),
Visibility(
visible: (widget.menuOptions?.isNotEmpty ?? false),
child: Padding(
padding: const EdgeInsets.only(
top: 2.0,
right: 5.0,
),
child: SizedBox(
width: 40,
child: MihFloatingMenu(
iconSize: 40,
animatedIcon: AnimatedIcons.menu_close,
direction: SpeedDialDirection.down,
children: widget.menuOptions != null ? widget.menuOptions! : [],
),
),
),
),
// If no menu, add a SizedBox to keep alignment
if (!(widget.menuOptions?.isNotEmpty ?? false))
const SizedBox(width: 40),
],
);
}
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
setState(() {
width = size.width;
height = size.height;
});
checkScreenSize();
return Dialog(
insetPadding: EdgeInsets.symmetric(
horizontal: horizontralWindowPadding,
vertical: vertticalWindowPadding,
),
insetAnimationCurve: Easing.emphasizedDecelerate,
insetAnimationDuration: Durations.short1,
child: Container(
decoration: 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: 5.0),
),
child: widget.fullscreen
? Column(
mainAxisSize: MainAxisSize.max,
children: [
getHeader(),
const SizedBox(height: 5),
Expanded(
child: SingleChildScrollView(child: widget.windowBody)),
],
)
: Column(
mainAxisSize: MainAxisSize.min,
children: [
getHeader(),
const SizedBox(height: 5),
Flexible(
child: Padding(
padding: EdgeInsets.only(
left: 25,
right: 25,
bottom: vertticalWindowPadding,
),
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: windowHeight * 0.85,
maxWidth: windowWidth * 0.85,
),
child: MihSingleChildScroll(child: widget.windowBody),
),
),
),
],
),
),
);
}
}

View File

@@ -1,109 +0,0 @@
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_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
class MihPersonalProfilePreview extends StatefulWidget {
final AppUser user;
const MihPersonalProfilePreview({
super.key,
required this.user,
});
@override
State<MihPersonalProfilePreview> createState() =>
_MihPersonalProfilePreviewState();
}
class _MihPersonalProfilePreviewState extends State<MihPersonalProfilePreview> {
late Future<String> futureImageUrl;
// String imageUrl = "";
PlatformFile? file;
@override
void initState() {
super.initState();
futureImageUrl =
MihFileApi.getMinioFileUrl(widget.user.pro_pic_path, context);
}
@override
Widget build(BuildContext context) {
double profilePictureWidth = 60;
return Row(
children: [
FutureBuilder(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: NetworkImage(asyncSnapshot.requireData),
width: profilePictureWidth,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: () {},
);
} else {
return Icon(
MihIcons.iDontKnow,
size: profilePictureWidth,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
}
},
),
const SizedBox(width: 15),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.user.username.isNotEmpty
? widget.user.username
: "Username",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Text(
widget.user.fname.isNotEmpty
? "${widget.user.fname} ${widget.user.lname}"
: "Name Surname",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
Text(
widget.user.type.toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10,
),
),
],
)
],
);
}
}

View File

@@ -1,108 +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 MihToggle extends StatefulWidget {
final String hintText;
final bool initialPostion;
final Color fillColor;
final Color secondaryFillColor;
final bool? readOnly;
final void Function(bool) onChange;
const MihToggle({
super.key,
required this.hintText,
required this.initialPostion,
required this.fillColor,
required this.secondaryFillColor,
this.readOnly,
required this.onChange,
});
@override
State<MihToggle> createState() => _MihToggleState();
}
class _MihToggleState extends State<MihToggle> {
late bool togglePosition;
@override
void didUpdateWidget(covariant MihToggle oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.initialPostion != oldWidget.initialPostion) {
setState(() {
togglePosition = widget.initialPostion;
});
}
}
@override
void initState() {
super.initState();
togglePosition = widget.initialPostion;
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Text(
widget.hintText,
style: TextStyle(
fontWeight: FontWeight.bold,
color: widget.fillColor,
fontSize: 18,
),
),
),
const SizedBox(width: 10),
Switch(
value: togglePosition,
trackOutlineColor: WidgetStateProperty.resolveWith<Color?>(
(states) {
if (widget.readOnly == true) {
return Colors.grey;
}
if (states.contains(WidgetState.selected)) {
return MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"); // Outline color when active
}
return MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"); // Outline color when active
},
),
activeColor:
widget.readOnly == true ? Colors.grey : widget.secondaryFillColor,
activeTrackColor: widget.readOnly == true
? Colors.grey.shade400
: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inactiveThumbColor:
widget.readOnly == true ? Colors.grey : widget.secondaryFillColor,
inactiveTrackColor: widget.readOnly == true
? Colors.grey.shade400
: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// activeColor: widget.secondaryFillColor,
// activeTrackColor: widget.fillColor,
// inactiveThumbColor: widget.fillColor,
// inactiveTrackColor: widget.secondaryFillColor,
// onChanged: widget.readOnly != true ? widget.onChange : null,
onChanged: widget.readOnly != true
? (newValue) {
setState(() {
togglePosition = newValue; // Update internal state
});
widget.onChange(newValue); // Call the parent's onChange
}
: null,
),
],
);
}
}

View File

@@ -1,530 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../main.dart';
class MIHDeleteMessage extends StatefulWidget {
final String deleteType;
final void Function() onTap;
const MIHDeleteMessage({
super.key,
required this.deleteType,
required this.onTap,
});
@override
State<MIHDeleteMessage> createState() => _MIHDeleteMessageState();
}
class _MIHDeleteMessageState extends State<MIHDeleteMessage> {
var messageTypes = <String, Widget>{};
late double popUpWidth;
late double? popUpheight;
late double popUpTitleSize;
late double popUpSubtitleSize;
late double popUpBodySize;
late double popUpIconSize;
late double popUpPaddingSize;
late double width;
late double height;
void checkScreenSize() {
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
setState(() {
popUpWidth = (width / 4) * 2;
popUpheight = null;
popUpTitleSize = 25.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
popUpIconSize = 100;
});
} else {
setState(() {
popUpWidth = width - (width * 0.1);
popUpheight = null;
popUpTitleSize = 20.0;
popUpSubtitleSize = 18.0;
popUpBodySize = 15;
popUpPaddingSize = 15.0;
popUpIconSize = 100;
});
}
}
void setDeleteNote() {
messageTypes["Note"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Are you sure you want to delete this?",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"This note will be deleted permanently. Are you certain you want to delete it?",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
MihButton(
onPressed: widget.onTap,
buttonColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Delete",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setFileNote() {
messageTypes["File"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Are you sure you want to delete this?",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"This file will be deleted permanently. Are you certain you want to delete it?",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
MihButton(
onPressed: widget.onTap,
buttonColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Delete",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setDeleteEmployee() {
messageTypes["Employee"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Are you sure you want to delete this?",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"This team member will be deleted permanently from the business profile. Are you certain you want to delete it?",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
MihButton(
onPressed: widget.onTap,
buttonColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Delete",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setDeleteAppointment() {
messageTypes["Appointment"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Are you sure you want to delete this?",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"This appointment will be deleted permanently from your calendar. Are you certain you want to delete it?",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
MihButton(
onPressed: widget.onTap,
buttonColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Delete",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setDeleteLoyaltyCard() {
messageTypes["Loyalty Card"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Are you sure you want to delete this?",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"This Card will be deleted permanently from your Mzansi Wallet. Are you certain you want to delete it?",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
MihButton(
onPressed: widget.onTap,
buttonColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Delete",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
Widget? getDeleteMessage(String type) {
return messageTypes[type];
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
setState(() {
width = size.width;
height = size.height;
});
checkScreenSize();
setDeleteNote();
setFileNote();
setDeleteEmployee();
setDeleteAppointment();
setDeleteLoyaltyCard();
//print(size);
// setState(() {
// width = size.width;
// height = size.height;
// });
return Dialog(child: getDeleteMessage(widget.deleteType));
}
}

View File

@@ -1,909 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../main.dart';
class MIHErrorMessage extends StatefulWidget {
final String errorType;
const MIHErrorMessage({
super.key,
required this.errorType,
});
@override
State<MIHErrorMessage> createState() => _MIHErrorMessageState();
}
class _MIHErrorMessageState extends State<MIHErrorMessage> {
var messageTypes = <String, Widget>{};
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 = 25.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
popUpIconSize = 100;
});
} else {
setState(() {
popUpWidth = size!.width - (size!.width * 0.1);
popUpheight = null;
popUpTitleSize = 20.0;
popUpSubtitleSize = 18.0;
popUpBodySize = 15;
popUpPaddingSize = 15.0;
popUpIconSize = 100;
});
}
}
void setInputError() {
messageTypes["Input Error"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 5),
Text(
"Oops! Looks like some fields are missing.",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
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: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
RichText(
text: TextSpan(
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: popUpBodySize,
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."),
],
),
),
const SizedBox(height: 10),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setPasswordRequirementsError() {
messageTypes["Password Requirements"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Password Doesn't Meet Requirements",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"Oops! Your password doesn't quite meet our standards. To keep your account secure, please make sure your password meets the following requirements",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
RichText(
text: TextSpan(
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
children: <TextSpan>[
TextSpan(
text: "Requirements:\n",
style: TextStyle(
fontStyle: FontStyle.italic,
fontSize: popUpBodySize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"))),
const TextSpan(
text: "1) Contailes at least 8 characters\n",
),
const TextSpan(
text: "2) Contains at least 1 uppercase letter (A-Z)\n",
),
const TextSpan(
text: "3) Contains at least 1 lowercase letter (a-z)\n",
),
const TextSpan(
text: "4) Contains at least 1 number (0-9)\n",
),
const TextSpan(
text:
"5) Contains at least 1 special character (!@#\$%^&*)\n",
),
],
),
),
const SizedBox(height: 10),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setInvalidUsernameError() {
messageTypes["Invalid Username"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Let's Fix That Username",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"Let's create a great username for you! Just a few quick tips:\n• Your username should start with a letter.\n• You can use letters, numbers, and/ or underscores.\n• Keep it between 6 and 20 characters.\n• Avoid special characters like @, #, or \$.\"",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setInvalidEmailError() {
messageTypes["Invalid Email"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Oops! Invalid Email",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"Looks like there's a little hiccup with that email address. Please double-check that you've entered it correctly, including the \"@\" symbol and a domain (like example@email.com).",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setUserExistsError() {
messageTypes["User Exists"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//SizedBox(height: 15),
Text(
"Email Already Exists",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"An account is already registered with this email address. Please try logging in or use a different email.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"Here are some things to keep in mind:",
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpSubtitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"1) Are you sure you're using the correct email address associated with your account?\n2) Is your caps lock key on? Passwords are case-sensitive.\n3) If you've forgotten your password, no worries! Click on \"Forgot Password?\" to reset it.",
textAlign: TextAlign.left,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setPwdMatchError() {
messageTypes["Password Match"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//SizedBox(height: 15),
Text(
"Passwords Don't Match",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"The password and confirm password fields do not match. Please make sure they are identical.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"Here are some things to keep in mind:",
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpSubtitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"1) Are you sure you're using the correct email address associated with your account?\n2) Is your caps lock key on? Passwords are case-sensitive.\n3) If you've forgotten your password, no worries! Click on \"Forgot Password?\" to reset it.",
textAlign: TextAlign.left,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setinvalidCredError() {
messageTypes["Invalid Credentials"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//SizedBox(height: 15),
Text(
"Uh oh! Login attempt unsuccessful.",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"The email address or password you entered doesn't seem to match our records. Please double-check your information and try again.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"Here are some things to keep in mind:",
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpSubtitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"1) Are you sure you're using the correct email address associated with your account?\n2) Is your caps lock key on? Passwords are case-sensitive.\n3) If you've forgotten your password, no worries! Click on \"Forgot Password?\" to reset it.",
textAlign: TextAlign.left,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setInternetError() {
messageTypes["Internet Connection"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Internet Connection Lost!",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"We seem to be having some trouble connecting you to the internet. This could be due to a temporary outage or an issue with your device's connection.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"Here are a few things you can try:",
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpSubtitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"1) Check your Wi-Fi signal strength or try connecting to a different network.\n2) Restart your device (computer, phone, etc.) and your router/modem.\n3) If you're using cellular data, ensure you have a strong signal and haven't reached your data limit.",
textAlign: TextAlign.left,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setLocationError() {
messageTypes["Location Denied"] = 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: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Location Services Not Enabled",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"To get the most out of MIH, we need your location. Please go to the site settings of the app and enable location services. Once you do that, we can start showing you relevant information based on your location.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
// const SizedBox(height: 15),
// Text(
// "Here are a few things you can try:",
// style: TextStyle(
// color: MihColors.getRedColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// fontSize: popUpSubtitleSize,
// fontWeight: FontWeight.bold,
// ),
// ),
// const SizedBox(height: 10),
// Text(
// "1) Check your Wi-Fi signal strength or try connecting to a different network.\n2) Restart your device (computer, phone, etc.) and your router/modem.\n3) If you're using cellular data, ensure you have a strong signal and haven't reached your data limit.",
// textAlign: TextAlign.left,
// style: TextStyle(
// color:
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// fontSize: popUpBodySize,
// fontWeight: FontWeight.bold,
// ),
// ),
const SizedBox(height: 10),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
Widget? getErrorMessage(String type) {
return messageTypes[type];
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
size = MediaQuery.of(context).size;
checkScreenSize();
setInputError();
setinvalidCredError();
setInternetError();
setUserExistsError();
setPwdMatchError();
setPasswordRequirementsError();
setInvalidEmailError();
setInvalidUsernameError();
setLocationError();
//print(size);
// setState(() {
// width = size.width;
// height = size.height;
// });
return Dialog(child: getErrorMessage(widget.errorType));
}
}

View File

@@ -1,97 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../main.dart';
import 'package:gif_view/gif_view.dart';
class Mihloadingcircle extends StatefulWidget {
final String? message;
const Mihloadingcircle({super.key, this.message});
@override
State<Mihloadingcircle> createState() => _MihloadingcircleState();
}
class _MihloadingcircleState extends State<Mihloadingcircle> {
// final GifController _controller = GifController();
late double popUpPaddingSize;
late double popUpWidth;
late double? popUpheight;
late double width;
late double height;
void checkScreenSize() {
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
setState(() {
popUpWidth = 250;
popUpheight = 250;
popUpPaddingSize = 25.0;
});
} else {
setState(() {
popUpWidth = 250;
popUpheight = 250;
popUpPaddingSize = 15.0;
});
}
}
@override
void initState() {
//_controller.animateTo(26);
super.initState();
checkScreenSize();
}
@override
void dispose() {
// _controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Dialog(
child: IntrinsicWidth(
child: IntrinsicHeight(
child: Container(
padding: EdgeInsets.all(popUpPaddingSize),
// width: 250,
// height: 275,
decoration: 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: 5.0),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
GifView.asset(
MzansiInnovationHub.of(context)!
.theme
.loadingImageLocation(),
height: 200,
width: 200,
frameRate: 30,
),
widget.message != null
? Text(
widget.message!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
)
: SizedBox(),
],
)),
),
),
);
}
}

View File

@@ -1,150 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../main.dart';
class MIHSuccessMessage extends StatefulWidget {
final String successType;
final String successMessage;
const MIHSuccessMessage({
super.key,
required this.successType,
required this.successMessage,
});
@override
State<MIHSuccessMessage> createState() => _MIHSuccessMessageState();
}
class _MIHSuccessMessageState extends State<MIHSuccessMessage> {
var messageTypes = <String, Widget>{};
late String message;
late double popUpWidth;
late double? popUpheight;
late double popUpTitleSize;
late double popUpSubtitleSize;
late double popUpBodySize;
late double popUpIconSize;
late double popUpPaddingSize;
late Size? size;
void checkScreenSize() {
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
setState(() {
popUpWidth = (size!.width / 4) * 2;
popUpheight = null;
popUpTitleSize = 25.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
popUpIconSize = 100;
});
} else {
setState(() {
popUpWidth = size!.width - (size!.width * 0.1);
popUpheight = null;
popUpTitleSize = 20.0;
popUpSubtitleSize = 18.0;
popUpBodySize = 15;
popUpPaddingSize = 15.0;
popUpIconSize = 100;
});
}
}
void setSuccessmessage() {
messageTypes["Success"] = 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: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.check_circle_outline_rounded,
size: popUpIconSize,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Success!",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Center(
child: Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 15),
MihButton(
onPressed: () {
Navigator.pop(context);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
],
);
}
Widget? getSuccessMessage(String type) {
return messageTypes[type];
}
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
size = MediaQuery.of(context).size;
checkScreenSize();
message = widget.successMessage;
setSuccessmessage();
return Dialog(child: getSuccessMessage(widget.successType));
}
}

View File

@@ -1,519 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../main.dart';
class MIHWarningMessage extends StatefulWidget {
final String warningType;
const MIHWarningMessage({
super.key,
required this.warningType,
});
@override
State<MIHWarningMessage> createState() => _MIHDeleteMessageState();
}
class _MIHDeleteMessageState extends State<MIHWarningMessage> {
var messageTypes = <String, Widget>{};
late double popUpWidth;
late double? popUpheight;
late double popUpTitleSize;
late double popUpSubtitleSize;
late double popUpBodySize;
late double popUpIconSize;
late double popUpPaddingSize;
late double width;
late double height;
void checkScreenSize() {
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
setState(() {
popUpWidth = (width / 4) * 2;
popUpheight = null;
popUpTitleSize = 25.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
popUpIconSize = 100;
});
} else {
setState(() {
popUpWidth = width - (width * 0.1);
popUpheight = null;
popUpTitleSize = 20.0;
popUpSubtitleSize = 18.0;
popUpBodySize = 15;
popUpPaddingSize = 15.0;
popUpIconSize = 100;
});
}
}
void setNoAccess() {
messageTypes["No Access"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Access Pending",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"Your access request is currently being reviewed.\nOnce approved, you'll be able to view patient data.\nPlease follow up with the patient to approve your access request.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setNoPatientAccess() {
messageTypes["No Patient Access"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Patient Profile Access Needed",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"To proceed with booking an appointment, you must have access to the patient's profile. This will allow you to view their medical history and other relevant information. Please contact the appropriate administrator to request access.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setAppointmentCanelled() {
messageTypes["Appointment Canelled"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Appointment Cancelled",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"This appointment has been canceled. As a result, you no longer have access to the patient's profile. If you would like to view the patient's profile again, please book a new appointment.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setAccessCanelled() {
messageTypes["Access Cancelled"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Access Cancelled",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"This appointment has been canceled. As a result, access has been cancelled and the doctor no longer have access to the patient's profile. If you would like them to view the patient's profile again, please book a new appointment through them.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setAccessDeclined() {
messageTypes["Access Declined"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Access Declined",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"Your request to access the patient's profile has been denied. Please contact the patient directly to inquire about the reason for this restriction.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
void setExpiredAccess() {
messageTypes["Expired Access"] = 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: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber_rounded,
size: popUpIconSize,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//const SizedBox(height: 15),
Text(
"Access Expired",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpTitleSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
Text(
"You no longer have access to this patient profile. The authorized access period has ended. Access to a patients profile is limited to 7 days from appointment date.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: popUpBodySize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
);
}
Widget? getDeleteMessage(String type) {
return messageTypes[type];
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
setState(() {
width = size.width;
height = size.height;
});
checkScreenSize();
setNoAccess();
setExpiredAccess();
setAccessDeclined();
setAppointmentCanelled();
setAccessCanelled();
//print(size);
// setState(() {
// width = size.width;
// height = size.height;
// });
return Dialog(child: getDeleteMessage(widget.warningType));
}
}

View File

@@ -1,253 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import "package:universal_html/html.dart" as html;
class MihTheme {
// late int _mainColor;
// late int _secondColor;
//late int _errColor;
//late int _succColor;
// late int _mesColor;
late String mode;
late String screenType;
late AssetImage loading;
late String loadingAssetText;
late TargetPlatform platform;
bool kIsWeb = const bool.fromEnvironment('dart.library.js_util');
String latestVersion = "1.2.0";
// Options:-
// f3f9d2 = Cream
// f0f0c9 = cream2
// caffd0 = light green
// B0F2B4 = light grean 2 *
// 85bda6 = light green 3
// 70f8ba = green
// F7F3EA = white
// a63446 = red
//747474
MihTheme() {
mode = "Dark";
//_errColor = 0xffD87E8B;
//_succColor = 0xffB0F2B4;
//_mesColor = 0xffc8c8c8d9;
}
ThemeData getData(bool bool) {
return ThemeData(
fontFamily: 'Segoe UI',
scaffoldBackgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
// pageTransitionsTheme: PageTransitionsTheme(
// builders: Map<TargetPlatform, PageTransitionsBuilder>.fromIterable(
// TargetPlatform.values,
// value: (dynamic _) => const FadeUpwardsPageTransitionsBuilder(),
// ),
// ),
colorScheme: ColorScheme(
brightness: getBritness(),
primary: MihColors.getSecondaryColor(mode == "Dark"),
onPrimary: MihColors.getPrimaryColor(mode == "Dark"),
secondary: MihColors.getPrimaryColor(mode == "Dark"),
onSecondary: MihColors.getSecondaryColor(mode == "Dark"),
error: MihColors.getRedColor(mode == "Dark"),
onError: MihColors.getPrimaryColor(mode == "Dark"),
surface: MihColors.getPrimaryColor(mode == "Dark"),
onSurface: MihColors.getSecondaryColor(mode == "Dark"),
),
datePickerTheme: DatePickerThemeData(
backgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
headerBackgroundColor: MihColors.getSecondaryColor(mode == "Dark"),
headerForegroundColor: MihColors.getPrimaryColor(mode == "Dark"),
),
appBarTheme: AppBarTheme(
color: MihColors.getSecondaryColor(mode == "Dark"),
foregroundColor: MihColors.getPrimaryColor(mode == "Dark"),
titleTextStyle: TextStyle(
color: MihColors.getPrimaryColor(mode == "Dark"),
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: MihColors.getSecondaryColor(mode == "Dark"),
foregroundColor: MihColors.getPrimaryColor(mode == "Dark"),
extendedTextStyle:
TextStyle(color: MihColors.getPrimaryColor(mode == "Dark")),
),
drawerTheme: DrawerThemeData(
backgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
));
}
String getPlatform() {
// if (isPwa()) {
// if (platform == TargetPlatform.android) {
// return "Android";
// } else if (platform == TargetPlatform.iOS) {
// return "iOS";
// }
// } else
if (kIsWeb) {
return "Web";
} else if (!kIsWeb) {
if (platform == TargetPlatform.android) {
return "Android";
} else if (platform == TargetPlatform.iOS) {
return "iOS";
}
}
return "Other";
}
bool isPwa() {
return html.window.matchMedia('(display-mode: standalone)').matches;
}
void setMode(String m) {
mode;
}
String getLatestVersion() {
return latestVersion;
}
ThemeData getThemeData() {
return getData(mode == "Dark");
}
ThemeData darkMode() {
return getData(mode == "Dark");
}
ThemeData lightMode() {
return getData(mode == "Dark");
}
Brightness getBritness() {
if (mode == "Dark") {
return Brightness.dark;
} else {
return Brightness.light;
}
}
// Color messageTextColor() {
// if (mode == "Dark") {
// _mesColor = 0XFFc8c8c8;
// } else {
// _mesColor = 0XFF747474;
// }
// return Color(_mesColor);
// }
// Color errorColor() {
// if (mode == "Dark") {
// return const Color(0xffD87E8B);
// } else {
// return const Color(0xffbb3d4f);
// }
// //return Color(_errColor);
// }
// Color highlightColor() {
// if (mode == "Dark") {
// return const Color(0XFF9bc7fa);
// } else {
// return const Color(0XFF354866);
// }
// }
// Color successColor() {
// if (mode == "Dark") {
// return const Color(0xffB0F2B4);
// } else {
// return const Color(0xff56a95b);
// }
// }
AssetImage loadingImage() {
if (mode == "Dark") {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_light.gif',
);
} else {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif',
);
}
return loading;
}
AssetImage altLoadingImage() {
if (mode == "Dark") {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif',
);
} else {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_light.gif',
);
}
return loading;
}
String loadingImageLocation() {
if (mode == "Dark") {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_light.gif';
} else {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif';
}
return loadingAssetText;
}
String altLoadingImageLocation() {
if (mode == "Dark") {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif';
} else {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_light.gif';
}
return loadingAssetText;
}
AssetImage aiLogoImage() {
if (mode == "Dark") {
return const AssetImage(
'lib/mih_components/mih_package_components/assets/images/mzansi_ai-dark.png',
);
} else {
return const AssetImage(
'lib/mih_components/mih_package_components/assets/images/mzansi_ai-light.png',
);
}
}
void setScreenType(double width) {
if (width <= 800) {
screenType = "mobile";
} else {
screenType = "desktop";
}
}
// Color MihColors.getPrimaryColor(mode == "Dark") {
// if (mode == "Dark") {
// _mainColor = 0XFF3A4454;
// } else {
// _mainColor = 0XFFbedcfe;
// }
// return Color(_mainColor);
// }
// Color MihColors.getSecondaryColor(mode == "Dark") {
// if (mode == "Dark") {
// _secondColor = 0XFFbedcfe;
// } else {
// _secondColor = 0XFF3A4454;
// }
// return Color(_secondColor);
// }
}

View File

@@ -1,60 +0,0 @@
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_layout_builder.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_packages/about_mih/mih_policy_tos_ext/policy_and_terms_text.dart';
import 'package:flutter/material.dart';
class MIHPrivacyPolocyExternal extends StatefulWidget {
const MIHPrivacyPolocyExternal({super.key});
@override
State<MIHPrivacyPolocyExternal> createState() =>
_MIHPrivacyPolocyExternalState();
}
class _MIHPrivacyPolocyExternalState extends State<MIHPrivacyPolocyExternal> {
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
Navigator.of(context).pushNamedAndRemoveUntil(
'/',
arguments: AuthArguments(true, false),
(route) => false,
);
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [],
);
}
MIHBody getBody() {
return MIHBody(
borderOn: false,
bodyItems: PolicyAndTermsText().getPrivacyPolicyText(context),
);
}
@override
Widget build(BuildContext context) {
return MIHLayoutBuilder(
actionButton: getActionButton(),
header: getHeader(),
secondaryActionButton: null,
body: getBody(),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
}
}

View File

@@ -1,60 +0,0 @@
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_layout_builder.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_packages/about_mih/mih_policy_tos_ext/policy_and_terms_text.dart';
import 'package:flutter/material.dart';
class MIHTermsOfServiceExternal extends StatefulWidget {
const MIHTermsOfServiceExternal({super.key});
@override
State<MIHTermsOfServiceExternal> createState() =>
_MIHTermsOfServiceExternalState();
}
class _MIHTermsOfServiceExternalState extends State<MIHTermsOfServiceExternal> {
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
Navigator.of(context).pushNamedAndRemoveUntil(
'/',
arguments: AuthArguments(true, false),
(route) => false,
);
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [],
);
}
MIHBody getBody() {
return MIHBody(
borderOn: false,
bodyItems: PolicyAndTermsText().getTermsOfServiceText(context),
);
}
@override
Widget build(BuildContext context) {
return MIHLayoutBuilder(
actionButton: getActionButton(),
header: getHeader(),
secondaryActionButton: null,
body: getBody(),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
}
}

View File

@@ -1,287 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.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_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:url_launcher/url_launcher.dart';
class MihAttributes extends StatefulWidget {
const MihAttributes({super.key});
@override
State<MihAttributes> createState() => _MihAttributesState();
}
class _MihAttributesState extends State<MihAttributes> {
Future<void> launchUrlLink(Uri linkUrl) async {
if (!await launchUrl(linkUrl)) {
throw Exception('Could not launch $linkUrl');
}
}
TableRow displayIcon(IconData icon, String creator, String link) {
return TableRow(
children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: SizedBox(
height: 150,
child: Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: FittedBox(
child: Center(
child: Icon(
icon,
// size: 125,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
),
),
),
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(
child: Text(
creator,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: MihButton(
onPressed: () {
launchUrlLink(
Uri.parse(
link,
),
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 100,
child: Text(
"Visit",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
);
}
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(),
);
}
Widget getBody() {
String message =
"Some APIs, Icons and Assets used in MIH were sourced from third party providers.\n";
message +=
"We are grateful to the talented creators for providing these resources.\n";
message +=
"As per the terms for free use for these third party providers, the following assets require attribution";
return MihSingleChildScroll(
child: Column(
children: [
Icon(
MihIcons.mihLogo,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 165,
),
const SizedBox(
height: 10,
),
SelectableText(
message,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 10,
),
SizedBox(
width: 700,
child: Table(
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
columnWidths: const {
0: FlexColumnWidth(1),
1: FlexColumnWidth(1),
2: FlexColumnWidth(1),
},
children: [
const TableRow(
children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: Center(
child: Text(
"Resources",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
),
),
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: Center(
child: Text(
"Creator",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
),
),
TableCell(
child: Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: Center(
child: Text(
"Link",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
displayIcon(MihIcons.mihRing, "Tarah Meth",
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
displayIcon(MihIcons.mihLogo, "Tarah Meth",
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
displayIcon(MihIcons.mzansiAi, "Ollama", "https://ollama.com/"),
displayIcon(MihIcons.mzansiWallet, "Freepik",
"https://www.flaticon.com/free-icon/wallet-passes-app_3884407?term=wallet&page=1&position=21&origin=search&related_id=3884407"),
displayIcon(MihIcons.patientProfile, "RaftelDesign",
"https://www.flaticon.com/free-icon/patient_2376100?term=medication&page=1&position=6&origin=search&related_id=2376100"),
displayIcon(MihIcons.patientProfile, "Srip",
"https://www.flaticon.com/free-icon/hospital_1233930?term=medical+snake&page=1&position=7&origin=search&related_id=1233930"),
displayIcon(MihIcons.calendar, "Freepik",
"https://www.flaticon.com/free-icon/calendar_2278049?term=calendar&page=1&position=5&origin=search&related_id=2278049"),
displayIcon(MihIcons.calculator, "Freepik",
"https://www.flaticon.com/free-icon/calculator_2374409?term=calculator&page=1&position=20&origin=search&related_id=2374409"),
displayIcon(MihIcons.aboutMih, "Chanut",
"https://www.flaticon.com/free-icon/info_151776?term=about&page=1&position=8&origin=search&related_id=151776"),
displayIcon(MihIcons.personalProfile, "Freepik",
"https://www.flaticon.com/free-icon/user_1077063?term=profile&page=1&position=6&origin=search&related_id=1077063"),
displayIcon(MihIcons.businessProfile, "Gravisio",
"https://www.flaticon.com/free-icon/contractor_11813336?term=company+profile&page=1&position=2&origin=search&related_id=11813336"),
displayIcon(MihIcons.patientManager, "Vector Tank",
"https://www.flaticon.com/free-icon/doctor_10215061?term=doctor&page=1&position=73&origin=search&related_id=10215061"),
displayIcon(MihIcons.profileSetup, "Freepik",
"https://www.flaticon.com/free-icon/add-user_748137?term=profile+add&page=1&position=1&origin=search&related_id=748137"),
displayIcon(MihIcons.businessSetup, "kerismaker",
"https://www.flaticon.com/free-icon/business_13569850?term=company+add&page=1&position=25&origin=search&related_id=13569850"),
displayIcon(MihIcons.calculator, "fawazahmed0",
"https://github.com/fawazahmed0/exchange-api"),
displayIcon(MihIcons.iDontKnow, "Freepik",
"https://www.flaticon.com/free-icon/i-dont-know_5359909?term=i+dont+know&page=1&position=7&origin=search&related_id=5359909"),
],
),
),
// SizedBox(
// width: 500,
// child: Column(
// children: [
// const SizedBox(
// width: double.infinity,
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// mainAxisSize: MainAxisSize.max,
// children: [
// Flexible(
// child: Text(
// "Icon",
// style: TextStyle(
// fontSize: 25,
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
// Flexible(
// child: Text(
// "Creator",
// style: TextStyle(
// fontSize: 25,
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
// Flexible(
// child: Text(
// "Link",
// style: TextStyle(
// fontSize: 25,
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
// ],
// ),
// ),
// const Padding(
// padding: EdgeInsets.symmetric(vertical: 10.0),
// child: Divider(),
// ),
// displayIcon(MihIcons.mihLogo, "Tarah Meth",
// "https://app.mzansi-innovation-hub.co.za/"),
// const SizedBox(height: 10),
// displayIcon(MihIcons.mihLogo, "Test",
// "https://www.flaticon.com/free-icons/mih"),
// const SizedBox(height: 10),
// displayIcon(MihIcons.mihLogo, "Test",
// "https://www.flaticon.com/free-icons/mih"),
// const SizedBox(height: 10),
// displayIcon(MihIcons.mihLogo, "Test",
// "https://www.flaticon.com/free-icons/mih"),
// const SizedBox(height: 10),
// ],
// ),
// )
],
),
);
}
}

View File

@@ -1,768 +0,0 @@
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';
import 'package:mzansi_innovation_hub/mih_services/mih_install_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_tile.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_tool_body.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:share_plus/share_plus.dart';
class MihInfo extends StatefulWidget {
const MihInfo({super.key});
@override
State<MihInfo> createState() => _MihInfoState();
}
class _MihInfoState extends State<MihInfo> {
final Uri _tiktokUrl =
Uri.parse('https://www.tiktok.com/@mzansi.innovation.hub');
final Uri _whatsappUrl =
Uri.parse('https://whatsapp.com/channel/0029Vax3INCIyPtMn8KgeM2F');
final Uri _twitch = Uri.parse('https://www.twitch.tv/mzansi_innovation_hub');
final Uri _kick = Uri.parse('https://kick.com/mzansi-innovation-hub');
final Uri _threadsUrl =
Uri.parse('https://www.threads.net/@mzansi.innovation.hub');
final Uri _instagramUrl =
Uri.parse('https://www.instagram.com/mzansi.innovation.hub');
final Uri _youtubeUrl =
Uri.parse('https://www.youtube.com/@mzansiinnovationhub');
final Uri _xUrl = Uri.parse('https://x.com/mzansi_inno_hub');
final Uri _linkedinUrl =
Uri.parse('https://www.linkedin.com/company/mzansi-innovation-hub/');
final Uri _facebookUrl =
Uri.parse('https://www.facebook.com/profile.php?id=61565345762136');
final Uri _redditUrl =
Uri.parse('https://www.reddit.com/r/Mzani_Innovation_Hub/');
Widget founderBio() {
String bio = "";
bio += "BSc Computer Science & Information Systems\n";
bio += "(University of the Western Cape)\n";
bio +=
"6 Year of banking experience with one of the big 5 banks of South Africa.";
return Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
SizedBox(
width: 300,
child: Stack(
alignment: Alignment.center,
fit: StackFit.loose,
children: [
Padding(
padding: const EdgeInsets.only(left: 4.0),
child: CircleAvatar(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundImage: const AssetImage(
"lib/mih_components/mih_package_components/assets/images/founder.jpg"),
//'https://media.licdn.com/dms/image/D4D03AQGd1-QhjtWWpA/profile-displayphoto-shrink_400_400/0/1671698053061?e=2147483647&v=beta&t=a3dJI5yxs5-KeXjj10LcNCFuC9IOfa8nNn3k_Qyr0CA'),
radius: 75,
),
),
Icon(
MihIcons.mihRing,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
],
),
),
SizedBox(
width: 400,
child: Text(
bio,
textAlign: TextAlign.center,
style: const TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
const SizedBox(
height: 10,
),
],
);
}
Widget founderTitle() {
String heading = "Yasien Meth (Founder & CEO)";
return Column(
children: [
Text(
heading,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
const SizedBox(
height: 10,
),
],
);
}
Widget ourVision() {
String heading = "Our Vision";
String vision =
"Digitizing Mzansi one process at a time. Discover essential Mzansi apps to streamline your personal and professional life. Simplify your daily tasks with our user-friendly solutions.";
return SizedBox(
width: 500,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Text(
heading,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
const SizedBox(
height: 10,
),
Text(
vision,
textAlign: TextAlign.center,
style: const TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 15,
),
),
],
),
);
}
Widget ourMission() {
String heading = "Our Mission";
String mission =
"Bridge the digital divide in Mzansi, ensuring that everyone can benefit from the power of technology. We empower lives by providing simple, elegant solutions that elevate daily experiences. With our user-friendly approach, we're making the digital world accessible to all, ensuring no one is left behind in the digital revolution.";
return SizedBox(
width: 500,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
heading,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
const SizedBox(
height: 10,
),
Text(
mission,
textAlign: TextAlign.center,
style: const TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 15,
),
),
],
),
);
}
Widget mihSocials() {
String heading = "Follow Our Journey";
return Column(
children: [
Text(
heading,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
const SizedBox(
height: 10,
),
SizedBox(
width: 500,
height: 600,
child: GridView.builder(
padding: const EdgeInsets.only(
// left: width / 10,
// right: width / 10,
// //bottom: height / 5,
// top: 20,
),
physics: const NeverScrollableScrollPhysics(),
// shrinkWrap: true,
itemCount: getSocialsList().length,
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
mainAxisSpacing: 15, maxCrossAxisExtent: 150),
itemBuilder: (context, index) {
return getSocialsList()[index];
},
),
),
],
);
}
List<Widget> getSocialsList() {
List<Widget> socials = [];
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_youtubeUrl);
},
tileName: "YouTube",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.youtube,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 175,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_tiktokUrl);
},
tileName: "TikTok",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.tiktok,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_twitch);
},
tileName: "Twitch",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.twitch,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_threadsUrl);
},
tileName: "Threads",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.threads,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_whatsappUrl);
},
tileName: "Whatsapp",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.whatsapp,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_instagramUrl);
},
tileName: "Instagram",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.instagram,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_xUrl);
},
tileName: "X",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.xTwitter,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_linkedinUrl);
},
tileName: "LinkedIn",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.linkedin,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_facebookUrl);
},
tileName: "FaceBook",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.facebook,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_redditUrl);
},
tileName: "Reddit",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.reddit,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 200,
),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
socials.add(MIHTile(
onTap: () {
launchSocialUrl(_kick);
},
tileName: "Kick",
tileIcon: Center(
child: Text(
"KICK",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
fontSize: 100,
),
),
// FaIcon(
// FontAwesomeIcons.tv,
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// size: 200,
// ),
),
p: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
s: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
));
//==================================================================
return socials;
}
Future<void> launchSocialUrl(Uri linkUrl) async {
if (!await launchUrl(linkUrl)) {
throw Exception('Could not launch $linkUrl');
}
}
Widget getInstallButtonText() {
final isWebAndroid =
kIsWeb && (defaultTargetPlatform == TargetPlatform.android);
final isWebIos = kIsWeb && (defaultTargetPlatform == TargetPlatform.iOS);
String btnText = "";
IconData platformIcon;
if (isWebAndroid) {
btnText = "Install MIH";
platformIcon = FontAwesomeIcons.googlePlay;
} else if (isWebIos) {
btnText = "Install MIH";
platformIcon = FontAwesomeIcons.appStoreIos;
} else if (MzansiInnovationHub.of(context)!.theme.getPlatform() ==
"Android") {
btnText = "Update MIH";
platformIcon = FontAwesomeIcons.googlePlay;
} else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "iOS") {
btnText = "Update MIH";
platformIcon = FontAwesomeIcons.appStoreIos;
} else {
btnText = "Install MIH";
platformIcon = FontAwesomeIcons.globe;
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
platformIcon,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(width: 10),
Text(
btnText,
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
);
}
void shareMIHLink(BuildContext context, String message, String link) {
String shareText = "$message: $link";
Share.share(
shareText,
);
}
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(),
);
}
Widget getBody() {
return Stack(
children: [
MihSingleChildScroll(
child: Column(
children: [
SizedBox(
width: 165,
child: FittedBox(
child: Icon(
MihIcons.mihLogo,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
const SizedBox(
height: 10,
),
const Text(
"Mzansi Innovation Hub",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30,
),
),
Text(
"MIH App Version: ${MzansiInnovationHub.of(context)!.theme.getLatestVersion()}",
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 15,
),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Divider(),
),
// const SizedBox(
// height: 10,
// ),
Wrap(
alignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
spacing: 10,
runSpacing: 10,
children: [
ourVision(),
ourMission(),
],
),
const SizedBox(
height: 10,
),
Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
MihInstallServices().installMihTrigger(context);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: getInstallButtonText(),
),
MihButton(
onPressed: () {
launchSocialUrl(
Uri.parse(
"https://www.youtube.com/playlist?list=PLuT35kJIui0H5kXjxNOZlHoOPZbQLr4qh",
),
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
FontAwesomeIcons.youtube,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(width: 10),
Text(
"MIH Beginners Guide",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
MihButton(
onPressed: () {
launchSocialUrl(
Uri.parse(
"https://patreon.com/MzansiInnovationHub?utm_medium=unknown&utm_source=join_link&utm_campaign=creatorshare_creator&utm_content=copyLink",
),
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
FontAwesomeIcons.patreon,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(width: 10),
Text(
"Support Our Journey",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
]),
const SizedBox(
height: 10,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Divider(),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
// spacing: 10,
// runSpacing: 10,
children: [
founderTitle(),
founderBio(),
],
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Divider(),
),
mihSocials(),
],
),
),
Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
icon: Icons.share,
children: [
SpeedDialChild(
child: Icon(
Icons.vpn_lock,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "MIH - Web",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
shareMIHLink(
context,
"Check out the MIH app on the Web",
"https://app.mzansi-innovation-hub.co.za/",
);
},
),
SpeedDialChild(
child: Icon(
Icons.apple,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "MIH - iOS",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
shareMIHLink(
context,
"Check out the MIH app on the App Store",
"https://apps.apple.com/za/app/mzansi-innovation-hub/id6743310890",
);
},
),
SpeedDialChild(
child: Icon(
Icons.android,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "MIH - Android",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
shareMIHLink(
context,
"Check out the MIH app on the Play Store",
"https://play.google.com/store/apps/details?id=za.co.mzansiinnovationhub.mih",
);
},
),
],
),
)
],
);
}
}

View File

@@ -1,25 +0,0 @@
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_packages/about_mih/mih_policy_tos_ext/policy_and_terms_text.dart';
import 'package:flutter/material.dart';
class MihPrivacyPolicy extends StatelessWidget {
const MihPrivacyPolicy({super.key});
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(context),
);
}
Widget getBody(BuildContext context) {
return MihSingleChildScroll(
child: Column(
children: PolicyAndTermsText().getPrivacyPolicyText(context),
),
);
}
}

View File

@@ -1,25 +0,0 @@
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_packages/about_mih/mih_policy_tos_ext/policy_and_terms_text.dart';
import 'package:flutter/material.dart';
class MIHTermsOfService extends StatelessWidget {
const MIHTermsOfService({super.key});
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(context),
);
}
Widget getBody(BuildContext context) {
return MihSingleChildScroll(
child: Column(
children: PolicyAndTermsText().getTermsOfServiceText(context),
),
);
}
}

View File

@@ -1,81 +0,0 @@
import 'package:go_router/go_router.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_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tools/mih_access_requests.dart';
import 'package:flutter/material.dart';
class MihAccess extends StatefulWidget {
final AppUser signedInUser;
const MihAccess({
super.key,
required this.signedInUser,
});
@override
State<MihAccess> createState() => _MihAccessState();
}
class _MihAccessState extends State<MihAccess> {
int _selcetedIndex = 0;
@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");
},
);
}
MihPackageAction getAction() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
'mihHome',
extra: true,
);
FocusScope.of(context).unfocus();
},
);
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.people)] = () {
setState(() {
_selcetedIndex = 0;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
MihAccessRequest(
signedInUser: widget.signedInUser,
),
];
return toolBodies;
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Access",
];
return toolTitles;
}
}

View File

@@ -1,320 +0,0 @@
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_icons.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_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:flutter/material.dart';
import '../../../mih_services/mih_service_calls.dart';
import '../../../mih_components/mih_layout/mih_action.dart';
import '../../../mih_components/mih_layout/mih_header.dart';
import '../../../mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import '../../../mih_config/mih_env.dart';
import '../../../mih_components/mih_objects/app_user.dart';
import '../../../mih_components/mih_objects/patient_access.dart';
import '../builder/build_business_access_list.dart';
class MihAccessRequest extends StatefulWidget {
final AppUser signedInUser;
const MihAccessRequest({
super.key,
required this.signedInUser,
});
@override
State<MihAccessRequest> createState() => _MihAccessRequestState();
}
class _MihAccessRequestState extends State<MihAccessRequest> {
TextEditingController filterController = TextEditingController();
String baseUrl = AppEnviroment.baseApiUrl;
String errorCode = "";
String errorBody = "";
String datefilter = "";
String accessFilter = "";
bool forceRefresh = false;
late String selectedDropdown;
late Future<List<PatientAccess>> accessList;
// Future<List<AccessRequest>> fetchAccessRequests() async {
// //print("Patien manager page: $endpoint");
// final response = await http.get(
// Uri.parse("$baseUrl/access-requests/${widget.signedInUser.app_id}"));
// // print("Here");
// // print("Body: ${response.body}");
// // print("Code: ${response.statusCode}");
// errorCode = response.statusCode.toString();
// errorBody = response.body;
// if (response.statusCode == 200) {
// //print("Here1");
// Iterable l = jsonDecode(response.body);
// //print("Here2");
// List<AccessRequest> patientQueue = List<AccessRequest>.from(
// l.map((model) => AccessRequest.fromJson(model)));
// //print("Here3");
// //print(patientQueue);
// return patientQueue;
// } else {
// throw Exception('failed to load patients');
// }
// }
List<PatientAccess> filterSearchResults(List<PatientAccess> accessList) {
List<PatientAccess> templist = [];
for (var item in accessList) {
if (filterController.text == "All") {
templist.add(item);
} else {
if (item.status.contains(filterController.text.toLowerCase())) {
templist.add(item);
}
}
}
return templist;
}
void refreshList() {
if (forceRefresh == true) {
setState(() {
accessList = MIHApiCalls.getBusinessAccessListOfPatient(
widget.signedInUser.app_id);
forceRefresh = false;
});
} else if (selectedDropdown != filterController.text) {
setState(() {
accessList = MIHApiCalls.getBusinessAccessListOfPatient(
widget.signedInUser.app_id);
selectedDropdown = filterController.text;
});
}
// setState(() {
// accessRequestResults = fetchAccessRequests();
// });
}
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
'mihHome',
extra: false,
);
FocusScope.of(context).unfocus();
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [
Text(
"Forever Access List",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
],
);
}
Widget getBody() {
return MihSingleChildScroll(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: MihDropdownField(
controller: filterController,
hintText: "Access Type",
dropdownOptions: const [
"All",
"Approved",
"Pending",
"Declined",
"Cancelled",
],
requiredText: true,
editable: true,
enableSearch: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
),
IconButton(
iconSize: 35,
onPressed: () {
setState(() {
forceRefresh = true;
});
KenLogger.warning("Refreshing Access List");
refreshList();
},
icon: const Icon(
Icons.refresh,
),
),
],
),
const SizedBox(height: 10),
FutureBuilder(
future: accessList,
builder: (context, snapshot) {
//print("patient Queue List ${snapshot.hasData}");
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done) {
List<PatientAccess> accessRequestList;
accessRequestList = filterSearchResults(snapshot.requireData);
if (accessRequestList.isNotEmpty) {
return BuildBusinessAccessList(
signedInUser: widget.signedInUser,
patientAccessList: accessRequestList,
onSuccessUpate: () {
setState(() {
forceRefresh = true;
});
refreshList();
},
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.accessControl,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"No access has been granted to your MIH Profile",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
// const SizedBox(height: 10),
// Center(
// child: RichText(
// textAlign: TextAlign.center,
// text: TextSpan(
// style: TextStyle(
// fontSize: 20,
// fontWeight: FontWeight.normal,
// color: MzansiInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// ),
// children: [
// TextSpan(text: "Press "),
// WidgetSpan(
// alignment: PlaceholderAlignment.middle,
// child: Icon(
// Icons.menu,
// size: 20,
// color: MzansiInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// ),
// ),
// TextSpan(
// text: " to add your first loyalty card."),
// ],
// ),
// ),
// ),
],
),
);
// return Center(
// child: Text(
// "No Request have been made.",
// style: TextStyle(
// fontSize: 25,
// color: MzansiInnovationHub.of(context)!
// .theme
// .messageTextColor()),
// textAlign: TextAlign.center,
// ),
// );
}
// return Expanded(
// child: displayAccessRequestList(accessRequestList),
// );
} else {
return Center(
child: Text(
"$errorCode: Error pulling Patients Data\n$baseUrl/queue/patients/\n$errorBody",
style: TextStyle(
fontSize: 25,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
textAlign: TextAlign.center,
),
);
}
},
),
],
),
);
}
@override
void dispose() {
filterController.dispose();
super.dispose();
}
@override
void initState() {
selectedDropdown = "All";
filterController.text = "All";
filterController.addListener(refreshList);
setState(() {
accessList = MIHApiCalls.getBusinessAccessListOfPatient(
widget.signedInUser.app_id);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(),
);
}
}

View File

@@ -1,88 +0,0 @@
import 'package:go_router/go_router.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_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tools/appointments.dart';
import 'package:flutter/material.dart';
class MzansiCalendar extends StatefulWidget {
final CalendarArguments arguments;
const MzansiCalendar({
super.key,
required this.arguments,
});
@override
State<MzansiCalendar> createState() => _MzansiCalendarState();
}
class _MzansiCalendarState extends State<MzansiCalendar> {
int _selcetedIndex = 0;
@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");
},
);
}
MihPackageAction getAction() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
// Navigator.of(context).pop();
context.goNamed(
'mihHome',
extra: widget.arguments.personalSelected,
);
FocusScope.of(context).unfocus();
},
);
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.calendar_month)] = () {
setState(() {
_selcetedIndex = 0;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
//appointment here
Appointments(
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
personalSelected: widget.arguments.personalSelected,
),
];
return toolBodies;
}
List<String> getToolTitle() {
List<String> toolTitles = [
widget.arguments.personalSelected == true ? "Personal" : "Business",
];
return toolTitles;
}
}

View File

@@ -1,550 +0,0 @@
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.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_date_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.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_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_packages/calendar/builder/build_appointment_list.dart';
import 'package:flutter/material.dart';
import '../../../main.dart';
import '../../../mih_components/mih_package_components/mih_calendar.dart';
import '../../../mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import '../../../mih_config/mih_env.dart';
import '../../../mih_components/mih_objects/app_user.dart';
class Appointments extends StatefulWidget {
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final bool personalSelected;
const Appointments({
super.key,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.personalSelected,
});
@override
State<Appointments> createState() => _PatientAccessRequestState();
}
class _PatientAccessRequestState extends State<Appointments> {
TextEditingController selectedAppointmentDateController =
TextEditingController();
final TextEditingController _appointmentTitleController =
TextEditingController();
final TextEditingController _appointmentDescriptionIDController =
TextEditingController();
final TextEditingController _appointmentDateController =
TextEditingController();
final TextEditingController _appointmentTimeController =
TextEditingController();
String baseUrl = AppEnviroment.baseApiUrl;
String selectedDay = DateTime.now().toString().split(" ")[0];
late Future<List<Appointment>> personalAppointmentResults;
late Future<List<Appointment>> businessAppointmentResults;
late Future<List<Appointment>> appointmentResults;
final _formKey = GlobalKey<FormState>();
Widget displayAppointmentList(List<Appointment> appointmentList) {
if (appointmentList.isNotEmpty) {
return Expanded(
child: BuildAppointmentList(
appointmentList: appointmentList,
signedInUser: widget.signedInUser,
business: widget.business,
businessUser: widget.businessUser,
personalSelected: widget.personalSelected,
inWaitingRoom: false,
titleController: _appointmentTitleController,
descriptionIDController: _appointmentDescriptionIDController,
patientIdController: null,
dateController: _appointmentDateController,
timeController: _appointmentTimeController,
),
);
}
return Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.calendar,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"No appointments for $selectedDay",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 25),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.menu,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(
text:
" to add an appointment or select a different date"),
],
),
),
),
],
),
),
);
}
void addAppointmentWindow(double width) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: "Add Appointment",
onWindowTapClose: () {
Navigator.of(context).pop();
_appointmentDateController.clear();
_appointmentTimeController.clear();
_appointmentTitleController.clear();
_appointmentDescriptionIDController.clear();
},
windowBody: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.05)
: const EdgeInsets.symmetric(horizontal: 0),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: _appointmentTitleController,
multiLineInput: false,
requiredText: true,
hintText: "Appointment Title",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihDateField(
controller: _appointmentDateController,
labelText: "Date",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihTimeField(
controller: _appointmentTimeController,
labelText: "Time",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: _appointmentDescriptionIDController,
multiLineInput: true,
height: 250,
requiredText: true,
hintText: "Appointment Description",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 20),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
addAppointmentCall();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Add",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
);
},
);
}
bool isAppointmentInputValid() {
if (_appointmentTitleController.text.isEmpty ||
_appointmentDescriptionIDController.text.isEmpty ||
_appointmentDateController.text.isEmpty ||
_appointmentTimeController.text.isEmpty) {
return false;
} else {
return true;
}
}
Future<void> addAppointmentCall() async {
if (isAppointmentInputValid()) {
int statusCode;
if (widget.personalSelected == false) {
statusCode = await MihMzansiCalendarApis.addBusinessAppointment(
widget.signedInUser,
widget.business!,
widget.businessUser!,
false,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
context,
);
} else {
statusCode = await MihMzansiCalendarApis.addPersonalAppointment(
widget.signedInUser,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
context,
);
}
if (statusCode == 201) {
context.pop();
successPopUp("Successfully Added Appointment",
"You appointment has been successfully added to your calendar.");
setState(() {
if (widget.personalSelected) {
appointmentResults = MihMzansiCalendarApis.getPersonalAppointments(
widget.signedInUser.app_id,
selectedDay,
);
} else {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
}
});
} else {
internetConnectionPopUp();
}
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
checkforchange();
}
void successPopUp(String title, String message) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: title,
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.pop();
setState(() {
_appointmentDateController.clear();
_appointmentTimeController.clear();
_appointmentTitleController.clear();
_appointmentDescriptionIDController.clear();
});
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Internet Connection",
);
},
);
}
String getTitle() {
if (widget.personalSelected == false) {
return "Business Appointments";
} else {
return "Personal Appointments";
}
}
void checkforchange() {
setState(() {
if (widget.personalSelected == false) {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
} else {
appointmentResults = MihMzansiCalendarApis.getPersonalAppointments(
widget.signedInUser.app_id,
selectedDay,
);
}
});
}
Widget getBody(double width) {
return Stack(
children: [
MihSingleChildScroll(
child: Column(
children: [
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
setState(() {
selectedDay = value;
selectedAppointmentDateController.text = selectedDay;
});
}),
// Divider(
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
Row(
mainAxisSize: MainAxisSize.max,
children: [
FutureBuilder(
future: appointmentResults,
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Expanded(
child: Center(child: Mihloadingcircle()));
} else if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
return displayAppointmentList(snapshot.requireData);
} else {
return Center(
child: Text(
"Error pulling appointments",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark")),
textAlign: TextAlign.center,
),
);
}
}),
],
)
],
),
),
Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
icon: Icons.add,
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.add,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Add Appointment",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
addAppointmentWindow(width);
},
)
],
),
),
],
);
}
@override
void dispose() {
selectedAppointmentDateController.dispose();
_appointmentDateController.dispose();
_appointmentTimeController.dispose();
_appointmentTitleController.dispose();
_appointmentDescriptionIDController.dispose();
super.dispose();
}
@override
void initState() {
selectedAppointmentDateController.addListener(checkforchange);
setState(() {
if (widget.personalSelected == false) {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
} else {
appointmentResults = MihMzansiCalendarApis.getPersonalAppointments(
widget.signedInUser.app_id,
selectedDay,
);
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(screenWidth),
);
}
}

View File

@@ -1,83 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.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_tools.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_register.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_sign_in.dart';
class MihAuthentication extends StatefulWidget {
const MihAuthentication({super.key});
@override
State<MihAuthentication> createState() => _MihAuthenticationState();
}
class _MihAuthenticationState extends State<MihAuthentication> {
int _selcetedIndex = 0;
@override
Widget build(BuildContext context) {
return MihPackage(
appActionButton: getAction(),
appTools: getTools(),
appBody: getToolBody(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
},
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
MihSignIn(
onNewUserButtonTap: () {
setState(() {
_selcetedIndex = 1;
});
},
),
MihRegister(onExistingUserButtonTap: () {
setState(() {
_selcetedIndex = 0;
});
})
];
return toolBodies;
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.perm_identity)] = () {
setState(() {
_selcetedIndex = 0;
});
};
temp[const Icon(Icons.create)] = () {
setState(() {
_selcetedIndex = 1;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
Widget getAction() {
return Padding(
padding: const EdgeInsets.only(left: 5.0),
child: MihPackageAction(
icon: const Icon(MihIcons.mihLogo),
iconSize: 45,
onTap: () {
context.goNamed("aboutMih", extra: 0);
},
),
);
}
}

View File

@@ -1,295 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
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_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.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_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
class MihForgotPassword extends StatefulWidget {
const MihForgotPassword({super.key});
@override
State<MihForgotPassword> createState() => _MihForgotPasswordState();
}
class _MihForgotPasswordState extends State<MihForgotPassword> {
final emailController = TextEditingController();
bool successfulForgotPassword = false;
final _formKey = GlobalKey<FormState>();
final FocusNode _focusNode = FocusNode();
bool acceptWarning = false;
Future<void> submitPasswodReset() async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
try {
var resetPassEmailSent = await MihAuthenticationServices()
.forgotPassword(emailController.text);
context.pop();
if (resetPassEmailSent) {
setState(() {
successfulForgotPassword = true;
});
}
} on Exception {
//loginError();
}
}
void prePassResteWarning() {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.warning_amber_rounded,
size: 100,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Password Reset Confirmation",
alertBody: Column(
//mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Text(
"Before you reset your password, please be aware that you'll receive an email with a link to confirm your identity and set a new password. Make sure to check your inbox, including spam or junk folders. If you don't receive the email within a few minutes, please try resending the reset request.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 25),
MihButton(
onPressed: () {
setState(() {
acceptWarning = true;
});
Navigator.of(context).pop();
validateInput();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Continue",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
alertColour: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
);
}
void resetLinkSentSuccessfully() {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Sent Reset Link",
alertBody: Column(
children: [
Text(
"We've sent a password reset link to your email address. Please check your inbox, including spam or junk folders.\n\nOnce you find the email, click on the link to reset your password.\n\nIf you don't receive the email within a few minutes, please try resending the reset request.\n\nThe reset link will expire after 2 hours",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.goNamed(
'mihHome',
extra: true,
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return const MIHSuccessMessage(
// successType: "Success",
// successMessage:
// "We've sent a password reset link to your email address. Please check your inbox, including spam or junk folders.\n\nOnce you find the email, click on the link to reset your password.\n\nIf you don't receive the email within a few minutes, please try resending the reset request.\n\nThe reset link will expire after 2 hours");
},
);
}
void validateInput() async {
if (emailController.text.isEmpty) {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
} else {
await submitPasswodReset();
if (successfulForgotPassword) {
// Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
resetLinkSentSuccessfully();
}
}
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
validateInput();
}
},
child: SafeArea(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Padding(
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
"desktop"
? EdgeInsets.symmetric(vertical: 25, horizontal: width * 0.2)
: EdgeInsets.symmetric(vertical: 25, horizontal: width * 0.075),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
//logo
Icon(
Icons.lock,
size: 100,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//spacer
const SizedBox(height: 10),
//Heading
Text(
'Forgot Password',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 25),
MihForm(
formKey: _formKey,
formFields: [
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: emailController,
multiLineInput: false,
requiredText: true,
hintText: "Email",
validator: (value) {
return MihValidationServices().validateEmail(value);
},
),
//spacer
const SizedBox(height: 20),
Align(
alignment: Alignment.center,
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
prePassResteWarning();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Reset Password",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
),
),
);
}
}

View File

@@ -1,266 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
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_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.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_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
class MihResetPassword extends StatefulWidget {
final String token;
const MihResetPassword({
super.key,
required this.token,
});
@override
State<MihResetPassword> createState() => _MihResetPasswordState();
}
class _MihResetPasswordState extends State<MihResetPassword> {
final passwordController = TextEditingController();
final confirmPasswordController = TextEditingController();
final FocusNode _focusNode = FocusNode();
final _formKey = GlobalKey<FormState>();
void submitFormInput() async {
if (passwordController.text != confirmPasswordController.text) {
passwordError();
} else {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
bool successfulResetPassword = await MihAuthenticationServices()
.resetPassword(widget.token, passwordController.text);
context.pop();
if (successfulResetPassword) {
resetSuccessfully();
} else {
loginError();
}
}
}
void resetSuccessfully() {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Reset Password",
alertBody: Column(
children: [
Text(
"Great news! Your password reset is complete. You can now log in to Mzansi Innovation Hub using your new password.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.goNamed(
'mihHome',
extra: true,
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return const MIHSuccessMessage(
// successType: "Success",
// successMessage:
// "We've sent a password reset link to your email address. Please check your inbox, including spam or junk folders.\n\nOnce you find the email, click on the link to reset your password.\n\nIf you don't receive the email within a few minutes, please try resending the reset request.\n\nThe reset link will expire after 2 hours");
},
);
}
void loginError() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Invalid Credentials");
},
);
}
void passwordError() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Password Match");
},
);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
if (_formKey.currentState!.validate()) {
submitFormInput();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
}
},
child: SafeArea(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.2)
: EdgeInsets.symmetric(horizontal: width * 0.075),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Token: ${widget.token}"), // For testing purposes only
//logo
Icon(
Icons.lock,
size: 100,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
//spacer
const SizedBox(height: 10),
//Heading
Text(
'Reset Password',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
//spacer
const SizedBox(height: 25),
MihForm(
formKey: _formKey,
formFields: [
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: passwordController,
multiLineInput: false,
requiredText: true,
hintText: "Password",
passwordMode: true,
autofillHints: const [AutofillHints.password],
validator: (value) {
return MihValidationServices().validatePassword(value);
},
),
//spacer
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: confirmPasswordController,
multiLineInput: false,
requiredText: true,
hintText: "Confirm Password",
passwordMode: true,
autofillHints: const [AutofillHints.password],
validator: (value) {
return MihValidationServices().validatePassword(value);
},
),
//spacer
const SizedBox(height: 25),
// sign in button
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitFormInput();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Reset Password",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
),
),
);
}
}

View File

@@ -1,350 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.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_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../../main.dart';
import 'package:supertokens_flutter/supertokens.dart';
class MIHAppDrawer extends StatefulWidget {
final AppUser signedInUser;
final ImageProvider<Object>? propicFile;
const MIHAppDrawer({
super.key,
required this.signedInUser,
required this.propicFile,
});
@override
State<MIHAppDrawer> createState() => _MIHAppDrawerState();
}
class _MIHAppDrawerState extends State<MIHAppDrawer> {
final proPicController = TextEditingController();
late Widget profilePictureLoaded;
Future<bool> signOut() async {
await SuperTokens.signOut(completionHandler: (error) {
// handle error if any
});
return true;
}
Widget displayProPic() {
return GestureDetector(
onTap: () {
context.goNamed(
'mzansiProfileManage',
extra: AppProfileUpdateArguments(
widget.signedInUser,
widget.propicFile,
),
);
},
child: MihCircleAvatar(
imageFile: widget.propicFile,
width: 60,
editable: false,
fileNameController: proPicController,
onChange: (_) {},
userSelectedfile: null,
frameColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
}
@override
void dispose() {
proPicController.dispose();
super.dispose();
}
@override
void initState() {
setState(() {
profilePictureLoaded = displayProPic();
});
super.initState();
}
@override
Widget build(BuildContext context) {
// precacheImage(
// MzansiInnovationHub.of(context)!.theme.logoImage().image, context);
return SafeArea(
child: Drawer(
//backgroundColor: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Stack(
//fit: StackFit.passthrough,
children: [
Column(
// reverse: false,
// padding: EdgeInsets.zero,
mainAxisSize: MainAxisSize.max,
children: [
DrawerHeader(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
child: SizedBox(
height: 400,
width: constraints.maxWidth,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
profilePictureLoaded,
Text(
"${widget.signedInUser.fname} ${widget.signedInUser.lname}",
style: TextStyle(
fontWeight: FontWeight.bold,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
Text(
"@${widget.signedInUser.username}",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
Text(
widget.signedInUser.type.toUpperCase(),
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
],
),
),
),
// ListTile(
// title: Row(
// mainAxisSize: MainAxisSize.max,
// children: [
// Icon(
// Icons.home_outlined,
// color:
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// const SizedBox(width: 25.0),
// Text(
// "Home",
// style: TextStyle(
// //fontWeight: FontWeight.bold,
// color: MzansiInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// ),
// ),
// ],
// ),
// onTap: () {
// Navigator.of(context)
// .pushNamedAndRemoveUntil('/', (route) => false);
// },
// ),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
ListTile(
title: Row(
mainAxisSize: MainAxisSize.max,
children: [
Icon(
Icons.policy,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
const SizedBox(width: 25.0),
Text(
"Privacy Policy",
style: TextStyle(
//fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
],
),
onTap: () {
context.goNamed("aboutMih", extra: 1);
},
),
ListTile(
title: Row(
mainAxisSize: MainAxisSize.max,
children: [
Icon(
Icons.design_services_rounded,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
const SizedBox(width: 25.0),
Text(
"Terms of Service",
style: TextStyle(
//fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
],
),
onTap: () {
context.goNamed("aboutMih", extra: 2);
},
),
ListTile(
title: Row(
mainAxisSize: MainAxisSize.max,
children: [
Icon(
Icons.logout,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
const SizedBox(width: 25.0),
Text(
"Sign Out",
style: TextStyle(
//fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
],
),
onTap: () async {
await SuperTokens.signOut(
completionHandler: (error) {
print(error);
});
if (await SuperTokens.doesSessionExist() ==
false) {
context.goNamed(
'mihHome',
extra: true,
);
// Navigator.of(context).pop();
// Navigator.of(context).popAndPushNamed(
// '/',
// arguments: AuthArguments(true, false),
// );
}
},
),
],
),
),
],
),
Positioned(
top: 5,
right: 5,
width: 30,
height: 30,
child: InkWell(
onTap: () {
setState(() {
if (MzansiInnovationHub.of(context)?.theme.mode ==
"Dark") {
//darkm = !darkm;
MzansiInnovationHub.of(context)!
.changeTheme(ThemeMode.light);
//print("Dark Mode: $darkm");
} else {
//darkm = !darkm;
MzansiInnovationHub.of(context)!
.changeTheme(ThemeMode.dark);
//print("Dark Mode: $darkm");
}
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed(
'/',
arguments: AuthArguments(true, false),
);
// Navigator.of(context).popAndPushNamed('/',);
});
},
child: Icon(
MihIcons.mihLogo,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
// IconButton(
// onPressed: () {
// setState(() {
// if (MzansiInnovationHub.of(context)?.theme.mode == "Dark") {
// //darkm = !darkm;
// MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.light);
// //print("Dark Mode: $darkm");
// } else {
// //darkm = !darkm;
// MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.dark);
// //print("Dark Mode: $darkm");
// }
// Navigator.of(context).popAndPushNamed('/');
// });
// },
// icon: Icon(
// Icons.light_mode,
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// size: 35,
// ),
// ),
),
],
);
},
),
),
);
}
}

View File

@@ -1,233 +0,0 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.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_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/components/mih_app_drawer.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/mih_home_error.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_business_home.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_personal_home.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_service_calls.dart';
// ignore: must_be_immutable
class MihHome extends StatefulWidget {
// final AppUser signedInUser;
// final BusinessUser? businessUser;
// final Business? business;
// final Patient? patient;
// final List<MIHNotification> notifications;
// final ImageProvider<Object>? propicFile;
// final bool isUserNew;
// final bool isBusinessUser;
// final bool isBusinessUserNew;
// final bool isDevActive;
final bool personalSelected;
const MihHome({
super.key,
// required this.signedInUser,
// required this.businessUser,
// required this.business,
// required this.patient,
// required this.notifications,
// required this.propicFile,
// required this.isUserNew,
// required this.isBusinessUser,
// required this.isBusinessUserNew,
// required this.isDevActive,
required this.personalSelected,
});
@override
State<MihHome> createState() => _MihHomeState();
}
class _MihHomeState extends State<MihHome> {
final proPicController = TextEditingController();
late int _selcetedIndex;
late bool _personalSelected;
late Future<HomeArguments> profileData;
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
profileData = MIHApiCalls().getProfile(10, context);
if (widget.personalSelected == true) {
setState(() {
_selcetedIndex = 0;
_personalSelected = true;
});
} else {
setState(() {
_selcetedIndex = 1;
_personalSelected = false;
});
}
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Personal",
"Business",
];
return toolTitles;
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: profileData,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
return Scaffold(
body: const Mihloadingcircle(
// message: "Fetching your Data...",
),
);
} else if (asyncSnapshot.connectionState == ConnectionState.done &&
asyncSnapshot.hasData) {
return MihPackage(
appActionButton: getAction(asyncSnapshot.data!.profilePicUrl),
appTools:
getTools(asyncSnapshot.data!.signedInUser.type != "personal"),
appBody: getToolBody(asyncSnapshot.data!),
appToolTitles: getToolTitle(),
actionDrawer: getActionDrawer(
asyncSnapshot.data!.signedInUser,
asyncSnapshot.data!.profilePicUrl,
),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
if (_selcetedIndex == 0) {
setState(() {
_selcetedIndex = newValue;
_personalSelected = true;
});
} else {
setState(() {
_selcetedIndex = newValue;
_personalSelected = false;
});
}
},
);
} else {
return MihHomeError(
errorMessage: asyncSnapshot.hasError
? asyncSnapshot.error.toString()
: "An unknown error occurred",
);
}
},
);
}
Widget getAction(String proPicUrl) {
return Builder(builder: (context) {
return MihPackageAction(
icon: Padding(
padding: const EdgeInsets.only(left: 5.0),
child: MihCircleAvatar(
imageFile: proPicUrl != "" ? NetworkImage(proPicUrl) : null,
width: 50,
editable: false,
fileNameController: proPicController,
userSelectedfile: null,
// frameColor: frameColor,
frameColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: (_) {},
),
// MIHProfilePicture(
// profilePictureFile: widget.propicFile,
// proPicController: proPicController,
// proPic: null,
// width: 45,
// radius: 21,
// drawerMode: false,
// editable: false,
// frameColor: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// onChange: (newProPic) {},
// ),
),
iconSize: 45,
onTap: () {
Scaffold.of(context).openDrawer();
FocusScope.of(context)
.requestFocus(FocusNode()); // Fully unfocus all fields
// FocusScope.of(context).unfocus(); // Unfocus any text fields
},
);
});
}
MIHAppDrawer getActionDrawer(AppUser signedInUser, String proPicUrl) {
return MIHAppDrawer(
signedInUser: signedInUser,
propicFile: proPicUrl != "" ? NetworkImage(proPicUrl) : null,
);
}
MihPackageTools getTools(bool isBusinessUser) {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.person)] = () {
setState(() {
_selcetedIndex = 0;
_personalSelected = true;
});
};
if (isBusinessUser) {
temp[const Icon(Icons.business_center)] = () {
setState(() {
_selcetedIndex = 1;
_personalSelected = false;
});
};
}
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
List<Widget> getToolBody(HomeArguments profData) {
List<Widget> toolBodies = [];
toolBodies.add(
MihPersonalHome(
signedInUser: profData.signedInUser,
personalSelected: _personalSelected,
business: profData.business,
businessUser: profData.businessUser,
propicFile: profData.profilePicUrl != ""
? NetworkImage(profData.profilePicUrl)
: null,
isDevActive: AppEnviroment.getEnv() == "Dev",
isUserNew: profData.signedInUser.username == "",
),
);
if (profData.signedInUser.type != "personal") {
toolBodies.add(
MihBusinessHome(
signedInUser: profData.signedInUser,
personalSelected: _personalSelected,
businessUser: profData.businessUser,
business: profData.business,
isBusinessUserNew: profData.businessUser == null,
),
);
}
return toolBodies;
}
}

View File

@@ -1,343 +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_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.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_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart';
import 'package:flutter/material.dart';
class MihBusinessHome extends StatefulWidget {
final AppUser signedInUser;
final bool personalSelected;
final Business? business;
final BusinessUser? businessUser;
final bool isBusinessUserNew;
const MihBusinessHome({
super.key,
required this.signedInUser,
required this.personalSelected,
required this.business,
required this.businessUser,
required this.isBusinessUserNew,
});
@override
State<MihBusinessHome> createState() => _MihBusinessHomeState();
}
class _MihBusinessHomeState extends State<MihBusinessHome>
with SingleTickerProviderStateMixin {
final TextEditingController searchController = TextEditingController();
late List<Map<String, Widget>> businessPackagesMap;
final ValueNotifier<List<Map<String, Widget>>> searchPackageName =
ValueNotifier([]);
double packageSize = 200;
// late final AnimationController _marqueeController;
// late final ScrollController _scrollController;
final FocusNode _searchFocusNode = FocusNode();
final String maintenanceMsg =
"\tHeads up! We're doing maintenance on Thur, 15 May 2025 at 10 PM (CAT). MIH may be unavailable briefly.";
// void _startMarquee() async {
// while (mounted) {
// final double maxScroll = _scrollController.position.maxScrollExtent;
// await Future.delayed(const Duration(milliseconds: 500));
// await _scrollController.animateTo(
// maxScroll,
// duration: _marqueeController.duration!,
// curve: Curves.linear,
// );
// await Future.delayed(const Duration(milliseconds: 500));
// _scrollController.jumpTo(0);
// await Future.delayed(const Duration(milliseconds: 500));
// }
// }
List<Map<String, Widget>> setNewBusinessUserPackages() {
List<Map<String, Widget>> temp = [];
temp.add({
"Setup Business": MzansiSetupBusinessProfileTile(
signedInUser: widget.signedInUser,
packageSize: packageSize,
)
});
return temp;
}
List<Map<String, Widget>> setBusinessPackages() {
List<Map<String, Widget>> temp = [];
//=============== Biz Profile ===============
temp.add({
"Business Profile": MzansiBusinessProfileTile(
arguments: BusinessArguments(
widget.signedInUser,
widget.businessUser,
widget.business,
),
packageSize: packageSize,
)
});
//=============== Pat Manager ===============
temp.add({
"Patient Manager": PatManagerTile(
arguments: PatManagerArguments(
widget.signedInUser,
false,
widget.business,
widget.businessUser,
),
packageSize: packageSize,
)
});
//=============== Calendar ===============
temp.add({
"Calendar": MzansiCalendarTile(
arguments: CalendarArguments(
widget.signedInUser,
false,
widget.business,
widget.businessUser,
),
packageSize: packageSize,
)
});
//=============== Mzansi Directory ===============
temp.add({
"Mzansi Directory": MzansiDirectoryTile(
packageSize: packageSize,
personalSelected: false,
)
});
//=============== Calculator ===============
temp.add({
"Calculator": MihCalculatorTile(
personalSelected: widget.personalSelected,
packageSize: packageSize,
)
});
//=============== Mzansi AI ===============
temp.add({
"Mzansi AI": MzansiAiTile(
arguments: MzansiAiArguments(
widget.signedInUser,
"",
false,
),
packageSize: packageSize,
)
});
//=============== About MIH ===============
temp.add({
"About MIH": AboutMihTile(
packageSize: packageSize,
personalSelected: false,
)
});
return temp;
}
EdgeInsets getPadding(double width, double height) {
if (MzansiInnovationHub.of(context)!.theme.screenType == "mobile") {
double mobilePadding = 10;
return EdgeInsets.only(
left: mobilePadding,
right: mobilePadding,
bottom: mobilePadding,
);
} else {
return EdgeInsets.only(
left: width / 13,
right: width / 13,
bottom: height / 15,
);
}
}
void searchPackage() {
if (searchController.text.isEmpty) {
searchPackageName.value = businessPackagesMap;
} else {
List<Map<String, Widget>> temp = [];
for (var item in businessPackagesMap) {
if (item.keys.first.toLowerCase().contains(searchController.text)) {
temp.add(item);
}
}
searchPackageName.value = temp;
}
}
@override
void dispose() {
super.dispose();
searchController.removeListener(searchPackage);
searchController.dispose();
// _marqueeController.dispose();
// _scrollController.dispose();
_searchFocusNode.dispose();
}
@override
void initState() {
super.initState();
searchController.addListener(searchPackage);
if (widget.isBusinessUserNew) {
businessPackagesMap = setNewBusinessUserPackages();
} else {
businessPackagesMap = setBusinessPackages();
}
searchPackage();
//Scrolling Banner message
// _marqueeController = AnimationController(
// vsync: this,
// duration: const Duration(seconds: 12),
// );
// _scrollController = ScrollController();
// WidgetsBinding.instance.addPostFrameCallback((_) => _startMarquee());
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final double width = size.width;
final double height = size.height;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(width, height),
);
}
Widget getBody(double width, double height) {
return MihSingleChildScroll(
child: Column(
children: [
// Icon(
// MihIcons.mihLogo,
// size: width / 2,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// const SizedBox(height: 10),
// Text(
// // "Welcome, ${widget.signedInUser.fname}!",
// "Mzansi Innovation Hub",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 30,
// fontWeight: FontWeight.bold,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// const SizedBox(height: 20),
Visibility(
visible: !widget.isBusinessUserNew,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: MihSearchBar(
controller: searchController,
hintText: "Ask Mzansi",
prefixIcon: Icons.search,
prefixAltIcon: MihIcons.mzansiAi,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
context.goNamed(
"mzansiAi",
extra: MzansiAiArguments(
widget.signedInUser,
searchController.text.isEmpty
? null
: searchController.text,
false,
),
);
// Navigator.of(context).pushNamed(
// '/mzansi-ai',
// arguments: MzansiAiArguments(
// widget.signedInUser,
// searchController.text.isEmpty
// ? null
// : searchController.text,
// ),
// );
searchController.clear();
},
searchFocusNode: _searchFocusNode,
),
),
),
const SizedBox(height: 20),
ValueListenableBuilder(
valueListenable: searchPackageName,
builder: (context, value, child) {
List<Widget> filteredPackages = value
.where((package) => package.keys.first
.toLowerCase()
.contains(searchController.text.toLowerCase()))
.map((package) => package.values.first)
.toList();
if (filteredPackages.isNotEmpty) {
return GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: getPadding(width, height),
// shrinkWrap: true,
itemCount: filteredPackages.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: packageSize,
crossAxisSpacing: 5,
),
itemBuilder: (context, index) {
return filteredPackages[index];
},
);
} else {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mzansiAi,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"Mzansi AI is here to help you!",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
);
}
},
),
],
),
);
}
}

View File

@@ -1,382 +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/Example/package_tiles/test_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.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_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tile/mih_access_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/package_tiles/patient_profile_tile.dart';
import 'package:flutter/material.dart';
class MihPersonalHome extends StatefulWidget {
final AppUser signedInUser;
final bool personalSelected;
final Business? business;
final BusinessUser? businessUser;
final ImageProvider<Object>? propicFile;
final bool isUserNew;
final bool isDevActive;
const MihPersonalHome({
super.key,
required this.signedInUser,
required this.personalSelected,
required this.business,
required this.businessUser,
required this.propicFile,
required this.isUserNew,
required this.isDevActive,
});
@override
State<MihPersonalHome> createState() => _MihPersonalHomeState();
}
class _MihPersonalHomeState extends State<MihPersonalHome>
with SingleTickerProviderStateMixin {
final TextEditingController searchController = TextEditingController();
late List<Map<String, Widget>> personalPackagesMap;
final ValueNotifier<List<Map<String, Widget>>> searchPackageName =
ValueNotifier([]);
double packageSize = 200;
// late final AnimationController _marqueeController;
// late final ScrollController _scrollController;
final FocusNode _searchFocusNode = FocusNode();
final String maintenanceMsg =
"\tHeads up! We're doing maintenance on Thur, 15 May 2025 at 10 PM (CAT). MIH may be unavailable briefly.";
// void _startMarquee() async {
// while (mounted) {
// final double maxScroll = _scrollController.position.maxScrollExtent;
// await Future.delayed(const Duration(milliseconds: 500));
// await _scrollController.animateTo(
// maxScroll,
// duration: _marqueeController.duration!,
// curve: Curves.linear,
// );
// await Future.delayed(const Duration(milliseconds: 500));
// _scrollController.jumpTo(0);
// await Future.delayed(const Duration(milliseconds: 500));
// }
// }
List<Map<String, Widget>> setNerUserPersonalPackage() {
List<Map<String, Widget>> temp = [];
temp.add({
"Setup Profile": MzansiSetupProfileTile(
signedInUser: widget.signedInUser,
propicFile: widget.propicFile,
packageSize: packageSize,
)
});
return temp;
}
List<Map<String, Widget>> setPersonalPackagesMap() {
List<Map<String, Widget>> temp = [];
//=============== Mzansi Profile ===============
temp.add({
"Mzansi Profile": MzansiProfileTile(
signedInUser: widget.signedInUser,
propicFile: widget.propicFile,
packageSize: packageSize,
)
});
//=============== Mzansi Wallet ===============
temp.add({
"Mzansi Wallet": MihWalletTile(
signedInUser: widget.signedInUser,
packageSize: packageSize,
)
});
//=============== Patient Profile ===============
temp.add({
"Patient Profile": PatientProfileTile(
arguments: PatientViewArguments(
widget.signedInUser,
null,
null,
null,
"personal",
),
packageSize: packageSize,
)
});
//=============== Mzansi Directory ===============
temp.add({
"Mzansi Directory": MzansiDirectoryTile(
packageSize: packageSize,
personalSelected: true,
)
});
//=============== Calendar ===============
temp.add({
"Calendar": MzansiCalendarTile(
arguments: CalendarArguments(
widget.signedInUser,
true,
widget.business,
widget.businessUser,
),
packageSize: packageSize,
)
});
//=============== Mzansi AI ===============
temp.add({
"Mzansi AI": MzansiAiTile(
arguments: MzansiAiArguments(
widget.signedInUser,
"",
true,
),
packageSize: packageSize,
)
});
//=============== Calculator ===============
temp.add({
"Calculator": MihCalculatorTile(
personalSelected: widget.personalSelected,
packageSize: packageSize,
)
});
//=============== MIH Access ===============
temp.add({
"MIH Access": MihAccessTile(
signedInUser: widget.signedInUser,
packageSize: packageSize,
)
});
//=============== About MIH ===============
temp.add({
"About MIH": AboutMihTile(
packageSize: packageSize,
personalSelected: true,
)
});
//=============== Dev ===============
if (widget.isDevActive) {
temp.add({
"test": TestPackageTile(
signedInUser: widget.signedInUser,
business: widget.business,
packageSize: packageSize,
)
});
}
return temp;
}
EdgeInsets getPadding(double width, double height) {
if (MzansiInnovationHub.of(context)!.theme.screenType == "mobile") {
double mobilePadding = 10;
return EdgeInsets.only(
left: mobilePadding,
right: mobilePadding,
bottom: mobilePadding,
);
} else {
return EdgeInsets.only(
left: width / 13,
right: width / 13,
bottom: height / 15,
);
}
}
void searchPackage() {
if (searchController.text.isEmpty) {
searchPackageName.value = personalPackagesMap;
} else {
List<Map<String, Widget>> temp = [];
for (var item in personalPackagesMap) {
if (item.keys.first.toLowerCase().contains(searchController.text)) {
temp.add(item);
}
}
searchPackageName.value = temp;
}
}
void autoNavToProfile() {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.goNamed(
'mzansiProfileManage',
extra: AppProfileUpdateArguments(
widget.signedInUser,
widget.propicFile,
),
);
});
}
@override
void dispose() {
super.dispose();
searchController.removeListener(searchPackage);
searchController.dispose();
_searchFocusNode.dispose();
// _marqueeController.dispose();
// _scrollController.dispose();
}
@override
void initState() {
super.initState();
searchController.addListener(searchPackage);
if (widget.isUserNew) {
personalPackagesMap = setNerUserPersonalPackage();
autoNavToProfile();
} else {
personalPackagesMap = setPersonalPackagesMap();
}
searchPackage();
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final double width = size.width;
final double height = size.height;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(width, height),
);
}
Widget getBody(double width, double height) {
return MihSingleChildScroll(
child: Column(
children: [
// Icon(
// MihIcons.mihLogo,
// size: 200,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// const SizedBox(height: 10),
// Text(
// // "Welcome, ${widget.signedInUser.fname}!",
// "Mzansi Innovation Hub",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 30,
// fontWeight: FontWeight.bold,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// const SizedBox(height: 20),
Visibility(
visible: !widget.isUserNew,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: MihSearchBar(
controller: searchController,
hintText: "Ask Mzansi",
prefixIcon: Icons.search,
prefixAltIcon: MihIcons.mzansiAi,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
context.goNamed(
"mzansiAi",
extra: MzansiAiArguments(
widget.signedInUser,
searchController.text.isEmpty
? null
: searchController.text,
true,
),
);
// Navigator.of(context).pushNamed(
// '/mzansi-ai',
// arguments: MzansiAiArguments(
// widget.signedInUser,
// searchController.text.isEmpty
// ? null
// : searchController.text,
// ),
// );
searchController.clear();
},
searchFocusNode: _searchFocusNode,
),
),
),
const SizedBox(height: 20),
ValueListenableBuilder(
valueListenable: searchPackageName,
builder: (context, value, child) {
List<Widget> filteredPackages = value
.where((package) => package.keys.first
.toLowerCase()
.contains(searchController.text.toLowerCase()))
.map((package) => package.values.first)
.toList();
if (filteredPackages.isNotEmpty) {
return GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: getPadding(width, height),
// shrinkWrap: true,
itemCount: filteredPackages.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: packageSize,
crossAxisSpacing: 5,
),
itemBuilder: (context, index) {
return filteredPackages[index];
// return personalPackages[index];
},
);
} else {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mzansiAi,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"Mzansi AI is here to help you!",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
);
}
},
),
],
),
);
}
}

View File

@@ -1,93 +0,0 @@
import 'package:go_router/go_router.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_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tools/ai_chat.dart';
import 'package:flutter/material.dart';
class MzansiAi extends StatefulWidget {
// final AppUser signedInUser;
// final String? startUpQuestion;
final MzansiAiArguments arguments;
const MzansiAi({
super.key,
required this.arguments,
// required this.signedInUser,
// this.startUpQuestion,
});
@override
State<MzansiAi> createState() => _MzansiAiState();
}
class _MzansiAiState extends State<MzansiAi> {
int _selcetedIndex = 0;
MihPackageAction getAction() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
'mihHome',
extra: widget.arguments.personalSelected,
);
FocusScope.of(context).unfocus();
},
);
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.chat)] = () {
setState(() {
_selcetedIndex = 0;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
AiChat(
signedInUser: widget.arguments.signedInUser,
startUpQuestion: widget.arguments.startUpQuestion,
),
];
return toolBodies;
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Ask Mzansi",
];
return toolTitles;
}
@override
void initState() {
super.initState();
}
@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");
},
);
}
}

View File

@@ -1,879 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:gpt_markdown/gpt_markdown.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';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_numeric_stepper.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.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_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_radio_options.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:flutter/material.dart';
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter_tts/flutter_tts.dart';
import 'package:ollama_dart/ollama_dart.dart' as ollama;
import 'package:uuid/uuid.dart';
class AiChat extends StatefulWidget {
final AppUser signedInUser;
final String? startUpQuestion;
const AiChat({
super.key,
required this.signedInUser,
this.startUpQuestion,
});
@override
State<AiChat> createState() => _AiChatState();
}
class _AiChatState extends State<AiChat> {
final TextEditingController _modelController = TextEditingController();
final TextEditingController _fontSizeController = TextEditingController();
final TextEditingController _ttsVoiceController = TextEditingController();
final ValueNotifier<bool> _showModelOptions = ValueNotifier(false);
FlutterTts _flutterTts = FlutterTts();
final ValueNotifier<String> _ttsVoiceName = ValueNotifier("");
// bool _ttsOn = false;
String? textStream;
List<Map> _voices = [];
List<String> _voicesString = [];
List<types.Message> _messages = [];
late types.User _user;
late types.User _mihAI;
String systemPromt = "0";
bool _aiThinking = false;
final client = ollama.OllamaClient(
baseUrl: "${AppEnviroment.baseAiUrl}/api",
);
List<ollama.Message> _chatHistory = [];
double _chatFrontSize = 15;
String getModel() {
return AppEnviroment.getEnv() == "Prod" ? 'gemma3n:e4b' : "gemma3:1b";
}
String setSystemPromt() {
String temp = "";
temp +=
"You are Mzansi AI, a helpful and friendly AI assistant running on the 'MIH App'.\n";
temp +=
"The MIH App was created by 'Mzansi Innovation Hub', a South African-based startup company.";
temp +=
"Your primary purpose is to assist users by answering general questions and helping with creative writing tasks or any other task a user might have for you.\n";
temp +=
"Maintain a casual and friendly tone, but always remain professional.\n";
temp +=
"Strive for a balance between being empathetic and delivering factual information accurately.\n";
temp +=
"You may use lighthearted or playful language if the context is appropriate and enhances the user experience.\n";
temp += "You operate within the knowledge domain of the 'MIH App'.\n";
temp += "Here is a description of the MIH App and its features:\n";
temp +=
"MIH App Description: MIH is the first super app of Mzansi, designed to streamline both personal and business life. It's an all-in-one platform for managing professional profiles, teams, appointments, and quick calculations. \n";
temp += "Key Features:\n";
temp +=
"- Mzansi Profile: Central hub for managing personal and business information, including business team details.";
temp += "- Mzansi Wallet: Digitally store loyalty cards.\n";
temp +=
"- Patient Manager (For Medical Practices): Seamless patient appointment scheduling and data management.\n";
temp +=
"- Mzansi AI: Your friendly AI assistant for quick answers and support (that's you!).\n";
temp +=
"- Mzansi Directory: A place to search and find out more about the people and businesses across Mzansi.\n";
temp +=
"- Calendar: Integrated calendar for managing personal and business appointments.\n";
temp +=
"- Calculator: Simple calculator with tip and forex calculation functionality.\n";
temp += "- MIH Access: Manage and view profile access security.\n";
temp += "**Core Rules and Guidelines:**\n";
temp +=
"- **Accuracy First:** Always prioritize providing correct information.\n";
temp +=
"- **Uncertainty Handling:** If you are unsure about an answer, politely respond with: 'Please bear with us as we are still learning and do not have all the answers.'\n";
temp +=
"- **Response Length:** Aim to keep responses under 250 words. If a more comprehensive answer is required, exceed this limit but offer to elaborate further (e.g., 'Would you like me to elaborate on this topic?').\n";
temp +=
"- **Language & Safety:** Never use offensive language or generate harmful content. If a user presses for information that is inappropriate or out of bounds, clearly state why you cannot provide it (e.g., 'I cannot assist with that request as it goes against my safety guidelines.').\n";
temp +=
"- **Out-of-Scope Questions:** - If a question is unclear, ask the user to rephrase or clarify it. - If a question is entirely out of your scope and you cannot provide a useful answer, admit you don't know. - If a user is unhappy with your response or needs further assistance beyond your capabilities, suggest they visit the 'Mzansi Innovation Hub Social Media Pages' for more direct support. Do not provide specific links, just refer to the pages generally.\n";
temp +=
"- **Target Audience:** Adapt your explanations to beginners and intermediate users, but be prepared for more complex questions from expert users. Ensure your language is clear and easy to understand.\n";
return temp;
}
void _addMessage(types.Message message) {
setState(() {
_messages.insert(0, message);
});
}
void _loadMessages() async {
final response = await rootBundle.loadString('assets/messages.json');
final messages = (jsonDecode(response) as List)
.map((e) => types.Message.fromJson(e as Map<String, dynamic>))
.toList();
setState(() {
_messages = messages;
});
}
void _handleSendPressed(types.PartialText message) {
FocusScope.of(context).unfocus();
final textMessage = types.TextMessage(
author: _user,
createdAt: DateTime.now().millisecondsSinceEpoch,
id: const Uuid().v4(),
text: message.text,
);
//Add user prompt to history
setState(() {
_chatHistory.add(
ollama.Message(
role: ollama.MessageRole.user,
content: message.text,
),
);
});
_addMessage(textMessage);
_handleMessageBack(message.text);
}
void _handleMessageBack(String userMessage) async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
Stream<String> aiChatStream =
_generateChatCompletionWithHistoryStream(userMessage, client);
Navigator.of(context).pop();
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return responseWindow(aiChatStream);
},
);
}
Widget responseWindow(
Stream<String> aiChatStream,
) {
return StreamBuilder(
stream: aiChatStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
textStream = snapshot.requireData;
// print("Text: $textStream");
// _speakText(textStream!);
return MihPackageWindow(
fullscreen: false,
windowTitle: 'Mzansi AI Thoughts',
menuOptions: _aiThinking == true
? null
: [
SpeedDialChild(
child: Icon(
Icons.volume_up,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
label: "Read Aloud",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
onTap: () {
_speakText(snapshot.requireData);
},
)
],
onWindowTapClose: () {
_captureAIResponse(snapshot.requireData);
_flutterTts.stop();
Navigator.of(context).pop();
},
windowBody: SizedBox(
width: double.infinity,
// color: Colors.black,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
GptMarkdown(
snapshot.requireData,
textAlign: TextAlign.left,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: _chatFrontSize,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
} else {
return MihPackageWindow(
fullscreen: false,
windowTitle: 'Mzansi AI Thoughts',
// windowTools: [],
onWindowTapClose: () {
Navigator.of(context).pop();
},
windowBody: Mihloadingcircle(),
);
}
},
);
}
void _captureAIResponse(String responseMessage) {
types.TextMessage textMessage;
setState(() {
_chatHistory.add(
ollama.Message(
role: ollama.MessageRole.assistant,
content: responseMessage,
),
);
});
textMessage = types.TextMessage(
author: _mihAI,
createdAt: DateTime.now().millisecondsSinceEpoch,
id: const Uuid().v4(),
text: responseMessage
.replaceAll("<think>\n\n", "**Thinking:**\n")
.replaceAll("<think>\n", "**Thinking:**\n")
.replaceAll("</think>\n\n", "\n**Answer:**\n"), //message.text,
);
_addMessage(textMessage);
}
Stream<String> _generateChatCompletionWithHistoryStream(
String userMessage,
final ollama.OllamaClient client,
) async* {
final aiStream = client.generateChatCompletionStream(
request: ollama.GenerateChatCompletionRequest(
model: _modelController.text,
messages: _chatHistory,
),
);
String text = '';
setState(() {
_aiThinking = true;
});
await for (final res in aiStream) {
text += (res.message.content);
yield text;
}
setState(() {
_aiThinking = false;
});
}
void _resetChat() {
setState(() {
_messages = [];
_chatHistory = [];
_loadMessages();
});
}
ChatTheme getChatTheme() {
return DarkChatTheme(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputBackgroundColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputTextColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputTextCursorColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
primaryColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
errorColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
sentMessageBodyTextStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: _chatFrontSize,
fontWeight: FontWeight.w500,
fontFamily: 'Segoe UI',
),
receivedMessageBodyTextStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: _chatFrontSize,
fontWeight: FontWeight.w500,
fontFamily: 'Segoe UI',
),
emptyChatPlaceholderTextStyle: TextStyle(
color: MihColors.getGreyColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: _chatFrontSize,
fontWeight: FontWeight.w500,
fontFamily: 'Segoe UI',
),
);
}
Widget _getSettings() {
return ValueListenableBuilder(
valueListenable: _showModelOptions,
builder: (BuildContext context, bool value, Widget? child) {
return Visibility(
visible: value,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Align(
alignment: Alignment.centerLeft,
child: FittedBox(
child: Container(
padding: const EdgeInsets.all(10.0),
decoration: 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),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Settings",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
),
const SizedBox(height: 15),
Row(
children: [
SizedBox(
width: 300,
child: MihRadioOptions(
controller: _modelController,
hintText: "AI Model",
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
requiredText: true,
radioOptions: [getModel()],
),
),
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(
width: 230,
child: MihDropdownField(
controller: _ttsVoiceController,
hintText: "AI Voice",
dropdownOptions: _voicesString,
editable: true,
enableSearch: true,
requiredText: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
),
const SizedBox(width: 10),
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: 50,
height: 50,
child: IconButton.filled(
style: ButtonStyle(
backgroundColor:
WidgetStateProperty.all<Color>(
MihColors.getGreenColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark")),
),
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
iconSize: 25,
onPressed: () {
print("Start TTS now");
_speakText(
"This is the sample of the Mzansi A.I Voice.");
},
icon: const Icon(
Icons.volume_up,
),
),
),
),
),
],
),
const SizedBox(height: 10),
Row(
children: [
SizedBox(
width: 300,
child: MihNumericStepper(
controller: _fontSizeController,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
hintText: "Font Size",
requiredText: true,
minValue: 1,
// maxValue: 5,
validationOn: true,
),
),
],
),
const SizedBox(height: 15),
],
),
),
),
),
),
);
},
);
}
static void loadingPopUp(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
}
void _speakText(String text) async {
try {
loadingPopUp(context);
await _flutterTts.stop(); // Stop any ongoing speech
await _flutterTts.speak(text).then((value) {
Navigator.of(context).pop();
}); // Speak the new text
} catch (e) {
Navigator.of(context).pop();
print("TTS Error: $e");
}
}
void setTtsVoice(String voiceName) {
_flutterTts.setVoice(
{
"name": voiceName,
"locale": _voices
.where((_voice) => _voice["name"].contains(voiceName))
.first["locale"]
},
);
_ttsVoiceController.text = voiceName;
}
void voiceSelected() {
if (_ttsVoiceController.text.isNotEmpty) {
_ttsVoiceName.value = _ttsVoiceController.text;
// print(
// "======================================== Voice Set ========================================");
setTtsVoice(_ttsVoiceController.text);
} else {
_ttsVoiceName.value = "";
}
}
void fontSizeChanged() {
setState(() {
_chatFrontSize = double.parse(_fontSizeController.text);
});
}
@override
void dispose() {
super.dispose();
_modelController.dispose();
_fontSizeController.dispose();
_ttsVoiceController.dispose();
_ttsVoiceController.removeListener(voiceSelected);
_fontSizeController.removeListener(fontSizeChanged);
client.endSession();
_flutterTts.stop();
}
void initTTS() {
_flutterTts.setVolume(1);
_fontSizeController.addListener(fontSizeChanged);
// _flutterTts.setSpeechRate(0.6);
// _flutterTts.setPitch(1.0);
_flutterTts.getVoices.then(
(data) {
try {
_voices = List<Map>.from(data);
setState(() {
_voices = _voices
.where(
(_voice) => _voice["name"].toLowerCase().contains("en-us"))
.toList();
_voicesString =
_voices.map((_voice) => _voice["name"] as String).toList();
_voicesString.sort();
// print(
// "=================== Voices ===================\n$_voicesString");
setTtsVoice(_voicesString.first);
});
} catch (e) {
print(e);
}
},
);
}
@override
void initState() {
super.initState();
_user = types.User(
firstName: widget.signedInUser.fname,
id: widget.signedInUser.app_id, //'82091008-a484-4a89-ae75-a22bf8d6f3ac',
);
_mihAI = types.User(
firstName: "Mzansi AI",
id: const Uuid().v4(),
);
_modelController.text = getModel();
_fontSizeController.text = _chatFrontSize.ceil().toString();
systemPromt = setSystemPromt();
_chatHistory.add(
ollama.Message(
role: ollama.MessageRole.system,
content: systemPromt,
),
);
initTTS();
_ttsVoiceController.addListener(voiceSelected);
if (widget.startUpQuestion != null && widget.startUpQuestion!.isNotEmpty) {
final partialText = types.PartialText(text: widget.startUpQuestion!);
WidgetsBinding.instance.addPostFrameCallback((_) {
_handleSendPressed(partialText);
});
}
}
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(),
);
}
Widget getBody() {
return Stack(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
_getSettings(),
Expanded(
child: GestureDetector(
onTap: () {
if (_showModelOptions.value == true) {
setState(() {
_showModelOptions.value = false;
});
}
},
child: Chat(
messages: _messages,
emptyState: noMessagescDisplay(),
// onAttachmentPressed: _handleAttachmentPressed,
// onMessageTap: _handleMessageTap,
// onPreviewDataFetched: _handlePreviewDataFetched,
onSendPressed: _handleSendPressed,
showUserAvatars: false,
showUserNames: false,
user: _user,
theme: getChatTheme(),
),
),
)
],
),
Positioned(
left: 15,
top: 15,
child: Visibility(
visible: _showModelOptions.value == true,
child: 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: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconSize: 20,
onPressed: () {
if (_showModelOptions.value == true) {
setState(() {
_showModelOptions.value = false;
});
} else {
setState(() {
_showModelOptions.value = true;
});
}
},
icon: const Icon(
Icons.close,
),
),
),
),
),
// IconButton.filled(
// iconSize: 20,
// onPressed: () {
// if (_showModelOptions.value == true) {
// setState(() {
// _showModelOptions.value = false;
// });
// } else {
// setState(() {
// _showModelOptions.value = true;
// });
// }
// },
// icon: const Icon(
// Icons.settings,
// ),
// ),
),
),
Positioned(
right: 10,
bottom: 80,
child: MihFloatingMenu(
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.refresh,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "New Chat",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
_resetChat();
},
),
SpeedDialChild(
child: Icon(
Icons.settings,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Settings",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
if (_showModelOptions.value == true) {
setState(() {
_showModelOptions.value = false;
});
} else {
setState(() {
_showModelOptions.value = true;
});
}
},
),
],
),
),
],
);
}
Widget? noMessagescDisplay() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// const SizedBox(height: 50),
Icon(
MihIcons.mzansiAi,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Mzansi AI is here to help",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 25),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
children: [
TextSpan(
text:
"Send us a message and we'll try our best to assist you"),
// WidgetSpan(
// alignment: PlaceholderAlignment.middle,
// child: Icon(
// Icons.menu,
// size: 20,
// color: MzansiInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// ),
// ),
// TextSpan(text: " to add your first loyalty card."),
],
),
),
),
],
),
);
}
}

View File

@@ -1,79 +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/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class BuildBusinessSearchResultsList extends StatefulWidget {
final List<Business> businessList;
final String myLocation;
final String? startUpSearch;
const BuildBusinessSearchResultsList({
super.key,
required this.businessList,
required this.myLocation,
required this.startUpSearch,
});
@override
State<BuildBusinessSearchResultsList> createState() =>
_BuildBusinessSearchResultsListState();
}
class _BuildBusinessSearchResultsListState
extends State<BuildBusinessSearchResultsList> {
@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: widget.businessList.length,
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemBuilder: (context, index) {
return Material(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: InkWell(
onTap: () {
context.goNamed(
'businessProfileView',
extra: BusinessViewArguments(
widget.businessList[index],
widget.businessList[index].Name,
),
);
// // Navigator.of(context).pushNamed(
// // '/business-profile/view',
// // arguments: BusinessViewArguments(
// // widget.businessList[index],
// // widget.businessList[index].Name,
// // ),
// );
},
splashColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
.withOpacity(0.2),
borderRadius: BorderRadius.circular(15),
child: Padding(
padding: EdgeInsetsGeometry.symmetric(
// vertical: 5,
horizontal: 25,
),
child: MihBusinessProfilePreview(
business: widget.businessList[index],
myLocation: widget.myLocation,
),
),
),
);
},
);
}
}

View File

@@ -1,79 +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/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class BuildFavouriteBusinessesList extends StatefulWidget {
final List<Business?> favouriteBusinesses;
final String? myLocation;
const BuildFavouriteBusinessesList({
super.key,
required this.favouriteBusinesses,
required this.myLocation,
});
@override
State<BuildFavouriteBusinessesList> createState() =>
_BuildFavouriteBusinessesListState();
}
class _BuildFavouriteBusinessesListState
extends State<BuildFavouriteBusinessesList> {
@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: widget.favouriteBusinesses.length,
separatorBuilder: (BuildContext context, index) {
return Divider(
color: Theme.of(context).colorScheme.secondary,
);
},
itemBuilder: (context, index) {
final Business? business = widget.favouriteBusinesses[index];
if (business == null) {
return const SizedBox(); // Or a placeholder if a business couldn't be loaded
}
return Material(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: InkWell(
onTap: () {
context.goNamed(
'businessProfileView',
extra: BusinessViewArguments(
widget.favouriteBusinesses[index]!,
widget.favouriteBusinesses[index]!.Name,
),
);
// Navigator.of(context).pushNamed(
// '/business-profile/view',
// arguments: BusinessViewArguments(
// business,
// business.Name,
// ),
// );
},
splashColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
.withOpacity(0.2),
borderRadius: BorderRadius.circular(15),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 25,
),
child: MihBusinessProfilePreview(
business: business, myLocation: widget.myLocation),
),
),
);
},
);
}
}

View File

@@ -1,67 +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_package_components/mih_personal_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class BuildUserSearchResultsList extends StatefulWidget {
final List<AppUser> userList;
const BuildUserSearchResultsList({
super.key,
required this.userList,
});
@override
State<BuildUserSearchResultsList> createState() =>
_BuildUserSearchResultsListState();
}
class _BuildUserSearchResultsListState
extends State<BuildUserSearchResultsList> {
@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: widget.userList.length,
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemBuilder: (context, index) {
return Material(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: InkWell(
onTap: () {
context.goNamed(
'mzansiProfileView',
extra: widget.userList[index],
);
// Navigator.of(context).pushNamed(
// '/mzansi-profile/view',
// arguments: widget.userList[index],
// );
},
splashColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
.withOpacity(0.2),
borderRadius: BorderRadius.circular(15),
child: Padding(
padding: EdgeInsetsGeometry.symmetric(
// vertical: 5,
horizontal: 25,
),
child: MihPersonalProfilePreview(
user: widget.userList[index],
),
),
),
);
},
);
}
}

View File

@@ -1,141 +0,0 @@
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.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_tools.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
class MzansiDirectory extends StatefulWidget {
final MzansiDirectoryArguments arguments;
const MzansiDirectory({
super.key,
required this.arguments,
});
@override
State<MzansiDirectory> createState() => _MzansiDirectoryState();
}
class _MzansiDirectoryState extends State<MzansiDirectory> {
int _selcetedIndex = 0;
late Future<Position?> futurePosition =
MIHLocationAPI().getGPSPosition(context);
@override
void initState() {
super.initState();
if (widget.arguments.packageIndex == null) {
_selcetedIndex = 0;
} else {
_selcetedIndex = widget.arguments.packageIndex!;
}
}
@override
Widget build(BuildContext context) {
print('MzansiDirectory build method called!');
return MihPackage(
appActionButton: getAction(),
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
},
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
FutureBuilder(
future: futurePosition,
builder: (context, asyncSnapshot) {
String myLocation = "";
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
myLocation = "Getting Your GPS Location Ready";
} else {
myLocation = asyncSnapshot.data
.toString()
.replaceAll("Latitude: ", "")
.replaceAll("Longitude: ", "");
}
return MihSearchMzansi(
personalSearch: widget.arguments.personalSearch,
myLocation: myLocation,
startSearchText: widget.arguments.startSearchText,
);
}),
// MihContacts(),
FutureBuilder(
future: futurePosition,
builder: (context, asyncSnapshot) {
String myLocation = "";
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
myLocation = "Getting Your GPS Location Ready";
} else {
myLocation = asyncSnapshot.data
.toString()
.replaceAll("Latitude: ", "")
.replaceAll("Longitude: ", "");
}
return MihFavouriteBusinesses(
myLocation: myLocation,
);
}),
];
return toolBodies;
}
MihPackageAction getAction() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
'mihHome',
extra: widget.arguments.personalSearch,
);
FocusScope.of(context).unfocus();
},
);
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.search)] = () {
setState(() {
_selcetedIndex = 0;
});
};
// temp[const Icon(Icons.person)] = () {
// setState(() {
// _selcetedIndex = 1;
// });
// };
temp[const Icon(Icons.business_center)] = () {
setState(() {
_selcetedIndex = 1;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Mzansi Search",
"Favourite Businesses",
"Contacts",
];
return toolTitles;
}
}

View File

@@ -1,266 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
import 'package:supertokens_flutter/supertokens.dart';
class MihFavouriteBusinesses extends StatefulWidget {
final String? myLocation;
const MihFavouriteBusinesses({
super.key,
required this.myLocation,
});
@override
State<MihFavouriteBusinesses> createState() => _MihFavouriteBusinessesState();
}
class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
final TextEditingController businessSearchController =
TextEditingController();
final FocusNode searchFocusNode = FocusNode();
late Future<List<BookmarkedBusiness>> boookmarkedBusinessListFuture;
List<BookmarkedBusiness> listBookmarkedBusinesses = [];
final ValueNotifier<List<Business?>> searchBookmarkedBusinesses =
ValueNotifier([]);
late Future<Map<String, Business?>> businessDetailsMapFuture;
Map<String, Business?> _businessDetailsMap = {};
Timer? _debounce;
Future<Map<String, Business?>>
getAndMapAllBusinessDetailsForBookmarkedBusinesses() async {
String user_id = await SuperTokens.getUserId();
List<BookmarkedBusiness> bookmarked = await MihMzansiDirectoryServices()
.getAllUserBookmarkedBusiness(user_id);
listBookmarkedBusinesses = bookmarked;
Map<String, Business?> businessMap = {};
List<Future<Business?>> detailFutures = [];
for (var item in bookmarked) {
detailFutures.add(MihBusinessDetailsServices()
.getBusinessDetailsByBusinessId(item.business_id));
}
List<Business?> details = await Future.wait(detailFutures);
for (int i = 0; i < bookmarked.length; i++) {
businessMap[bookmarked[i].business_id] = details[i];
}
_businessDetailsMap = businessMap;
_filterAndSetBusinesses();
return businessMap;
}
void _filterAndSetBusinesses() {
List<Business?> businessesToDisplay = [];
String query = businessSearchController.text.toLowerCase();
for (var bookmarked in listBookmarkedBusinesses) {
if (bookmarked.business_name.toLowerCase().contains(query)) {
if (_businessDetailsMap.containsKey(bookmarked.business_id)) {
businessesToDisplay.add(_businessDetailsMap[bookmarked.business_id]);
}
}
}
searchBookmarkedBusinesses.value = businessesToDisplay;
}
@override
void dispose() {
super.dispose();
businessSearchController.dispose();
searchFocusNode.dispose();
searchBookmarkedBusinesses.dispose();
}
@override
void initState() {
super.initState();
businessDetailsMapFuture =
getAndMapAllBusinessDetailsForBookmarkedBusinesses();
businessSearchController.addListener(() {
if (_debounce?.isActive ?? false) {
_debounce!.cancel();
}
_debounce = Timer(const Duration(milliseconds: 200), () {
_filterAndSetBusinesses();
});
});
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final double width = size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(width),
);
}
Widget getBody(double width) {
return MihSingleChildScroll(
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: MihSearchBar(
controller: businessSearchController,
hintText: "Search Businesses",
prefixIcon: Icons.search,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {},
searchFocusNode: searchFocusNode,
),
),
const SizedBox(height: 10),
FutureBuilder<Map<String, Business?>>(
future: businessDetailsMapFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Mihloadingcircle(
message: "Getting your favourites",
);
} else if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
// No need to re-filter here, _filterAndSetBusinesses is called in initState
// and by the text controller listener.
return ValueListenableBuilder<List<Business?>>(
valueListenable:
searchBookmarkedBusinesses, // Listen to changes in this
builder: (context, businesses, child) {
// Display message if no results after search
if (businesses.isEmpty &&
businessSearchController.text.isNotEmpty) {
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"Let's try refining your search",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
],
);
}
return BuildFavouriteBusinessesList(
favouriteBusinesses:
businesses, // Pass the filtered list from ValueNotifier
myLocation: widget.myLocation,
);
},
);
} else {
// This block handles the case where there are no bookmarked businesses initially
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.businessProfile,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"No favourite businesses added to your mzansi directory",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
const SizedBox(height: 25),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
children: [
TextSpan(text: "Use the mzansi search"),
// WidgetSpan(
// alignment:
// PlaceholderAlignment.middle,
// child: Icon(
// Icons.search,
// size: 20,
// color:
// MzansiInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// ),
// ),
TextSpan(
text:
" to find your favourite businesses of mzansi"),
],
),
),
),
],
),
);
}
} else if (snapshot.hasError) {
return Center(
child: Text(
"Error loading bookmarked businesses: ${snapshot.error}"), // Show specific error
);
} else {
// Fallback for unexpected states
return Center(
child: Text("An unknown error occurred."),
);
}
}),
],
),
);
}
}

View File

@@ -1,566 +0,0 @@
import 'package:flutter/material.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/business.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_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
class MihSearchMzansi extends StatefulWidget {
final bool personalSearch;
final String? myLocation;
final String? startSearchText;
const MihSearchMzansi({
super.key,
required this.personalSearch,
required this.myLocation,
required this.startSearchText,
});
@override
State<MihSearchMzansi> createState() => _MihSearchMzansiState();
}
class _MihSearchMzansiState extends State<MihSearchMzansi> {
final TextEditingController mzansiSearchController = TextEditingController();
final TextEditingController businessTypeController = TextEditingController();
final FocusNode searchFocusNode = FocusNode();
late bool userSearch;
Future<List<AppUser>?> futureUserSearchResults = Future.value();
Future<List<Business>?> futureBusinessSearchResults = Future.value();
List<AppUser> userSearchResults = [];
List<Business> businessSearchResults = [];
late Future<List<String>> availableBusinessTypes;
bool filterOn = false;
void swapPressed() {
setState(() {
userSearch = !userSearch;
if (filterOn) {
filterOn = !filterOn;
}
});
if (businessTypeController.text.isNotEmpty) {
setState(() {
futureBusinessSearchResults = Future.value();
businessTypeController.clear();
});
}
searchPressed();
}
void clearAll() {
setState(() {
futureUserSearchResults = Future.value();
futureBusinessSearchResults = Future.value();
mzansiSearchController.clear();
businessTypeController.clear();
});
}
void searchPressed() {
setState(() {
// userSearch = !userSearch;
if (userSearch && mzansiSearchController.text.isNotEmpty) {
futureUserSearchResults =
MihUserServices().searchUsers(mzansiSearchController.text, context);
} else {
if (
// mzansiSearchController.text.isNotEmpty &&
businessTypeController.text.isNotEmpty) {
futureBusinessSearchResults = MihBusinessDetailsServices()
.searchBusinesses(mzansiSearchController.text,
businessTypeController.text, context);
} else if (mzansiSearchController.text.isNotEmpty) {
futureBusinessSearchResults = MihBusinessDetailsServices()
.searchBusinesses(mzansiSearchController.text,
businessTypeController.text, context);
}
}
});
}
@override
void dispose() {
super.dispose();
mzansiSearchController.dispose();
}
@override
void initState() {
super.initState();
setState(() {
userSearch = widget.personalSearch;
availableBusinessTypes =
MihBusinessDetailsServices().fetchAllBusinessTypes();
if (widget.startSearchText != null) {
mzansiSearchController.text = widget.startSearchText!;
searchPressed();
} else {
mzansiSearchController.text = "";
}
});
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final double width = size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(width),
);
}
Widget getBody(double width) {
return MihSingleChildScroll(
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: MihSearchBar(
controller: mzansiSearchController,
hintText: "Search Mzansi",
prefixIcon: Icons.search,
prefixAltIcon: userSearch ? Icons.person : Icons.business,
suffixTools: [
IconButton(
onPressed: () {
swapPressed();
},
icon: Icon(
Icons.swap_horiz_rounded,
size: 35,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
searchPressed();
},
onClearIconTap: () {
clearAll();
},
searchFocusNode: searchFocusNode,
),
),
Visibility(
visible: !userSearch,
child: const SizedBox(width: 10),
),
Visibility(
visible: !userSearch,
child: IconButton(
onPressed: () {
if (filterOn) {
clearAll();
}
setState(() {
filterOn = !filterOn;
});
},
icon: Icon(
!filterOn
? Icons.filter_list_rounded
: Icons.filter_list_off_rounded,
size: 35,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
],
),
),
const SizedBox(height: 10),
FutureBuilder(
future: availableBusinessTypes,
builder: (context, asyncSnapshot) {
List<String> options = [];
if (asyncSnapshot.connectionState == ConnectionState.done) {
options.addAll(asyncSnapshot.data!);
}
return Visibility(
visible: filterOn,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: MihDropdownField(
controller: businessTypeController,
hintText: "Business Type",
dropdownOptions: options,
requiredText: true,
editable: true,
enableSearch: true,
),
),
const SizedBox(width: 10),
MihButton(
onPressed: () {
if (businessTypeController.text.isNotEmpty) {
searchPressed();
} else {
MihAlertServices().errorAlert(
"Business Type Not Selected",
"Please ensure you have selected a Business Type before seareching for Businesses of Mzansi",
context,
);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
elevation: 10,
child: Text(
"Search",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
}),
const SizedBox(height: 10),
displaySearchResults(userSearch, widget.myLocation ?? ""),
],
),
);
}
Widget displaySearchResults(bool userSearch, String myLocation) {
if (userSearch) {
return FutureBuilder(
future: futureUserSearchResults,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isNotEmpty) {
// return Text("Pulled Data successfully");
snapshot.requireData!
.sort((a, b) => a.username.compareTo(b.username));
return Column(
children: [
Text(
"People of Mzansi",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
BuildUserSearchResultsList(userList: snapshot.requireData!),
],
);
} else if (!snapshot.hasData) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.personalProfile,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Search for people of Mzansi!",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
const SizedBox(height: 25),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.swap_horiz_rounded,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(text: " to search for businesses of Mzansi"),
],
),
),
),
],
),
);
// return Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// const SizedBox(height: 50),
// Icon(
// MihIcons.personalProfile,
// size: 165,
// color:
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// const SizedBox(height: 10),
// Text(
// "People Of Mzansi!",
// textAlign: TextAlign.center,
// overflow: TextOverflow.visible,
// style: TextStyle(
// fontSize: 25,
// fontWeight: FontWeight.bold,
// color:
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// ],
// );
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isEmpty) {
// return Text("Pulled Data successfully");
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Let's try refining your search",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
],
);
} else {
return Center(
child: Text(
"Error pulling Patients Data\n/users/search/${mzansiSearchController.text}",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.center,
),
);
}
},
);
} else {
return FutureBuilder(
future: futureBusinessSearchResults,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isNotEmpty) {
// return Text("Pulled Data successfully");
snapshot.requireData!.sort((a, b) => a.Name.compareTo(b.Name));
return Column(
children: [
Text(
"Businesses of Mzansi",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
BuildBusinessSearchResultsList(
businessList: snapshot.requireData!,
myLocation: myLocation,
startUpSearch: mzansiSearchController.text,
),
],
);
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isEmpty) {
// return Text("Pulled Data successfully");
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 25),
Text(
"Let's try refining your search",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
],
);
} else if (!snapshot.hasData) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.businessProfile,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Search for businesses of Mzansi!",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
const SizedBox(height: 25),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.swap_horiz_rounded,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(text: " to search for people of Mzansi"),
],
),
),
),
const SizedBox(height: 10),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.filter_list_rounded,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(text: " to filter business types"),
],
),
),
),
],
),
);
} else {
return Center(
child: Text(
"Error pulling Patients Data\n/users/search/${mzansiSearchController.text}",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.center,
),
);
}
},
);
}
}
}

View File

@@ -1,407 +0,0 @@
import 'dart:convert';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
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_alert.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.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_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.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_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
class BuildEmployeeList extends StatefulWidget {
final List<BusinessEmployee> employees;
final BusinessArguments arguments;
const BuildEmployeeList({
super.key,
required this.employees,
required this.arguments,
});
@override
State<BuildEmployeeList> createState() => _BuildEmployeeListState();
}
class _BuildEmployeeListState extends State<BuildEmployeeList> {
TextEditingController accessController = TextEditingController();
TextEditingController typeController = TextEditingController();
TextEditingController fnameController = TextEditingController();
TextEditingController lnameController = TextEditingController();
final _formKey = GlobalKey<FormState>();
final baseAPI = AppEnviroment.baseApiUrl;
Future<void> updateEmployeeAPICall(int index) async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
var response = await http.put(
Uri.parse("$baseAPI/business-user/employees/update/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"business_id": widget.employees[index].business_id,
"app_id": widget.employees[index].app_id,
"title": typeController.text,
"access": accessController.text,
}),
);
if (response.statusCode == 200) {
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// //setState(() {});
// Navigator.of(context).pushNamed(
// '/business-profile/manage',
// arguments: BusinessArguments(
// widget.arguments.signedInUser,
// widget.arguments.businessUser,
// widget.arguments.business,
// ),
// );
String message = "Your employees details have been updated.";
successPopUp(message, false);
} else {
internetConnectionPopUp();
}
}
Future<void> deleteNoteApiCall(int index) async {
var response = await http.delete(
Uri.parse("$baseAPI/business-user/employees/delete/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"business_id": widget.employees[index].business_id,
"app_id": widget.employees[index].app_id,
}),
);
//print("Here4");
//print(response.statusCode);
if (response.statusCode == 200) {
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pushNamed(
// '/business-profile/manage',
// arguments: BusinessArguments(
// widget.arguments.signedInUser,
// widget.arguments.businessUser,
// widget.arguments.business,
// ),
// );
String message =
"The employee has been deleted successfully. This means they will no longer have access to your business profile";
successPopUp(message, false);
} else {
internetConnectionPopUp();
}
}
void successPopUp(String message, bool stayOnPersonalSide) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Updated Profile",
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.goNamed(
'mihHome',
extra: stayOnPersonalSide,
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return MIHSuccessMessage(
// successType: "Success",
// successMessage: message,
// );
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
bool isRequiredFieldsCaptured() {
if (accessController.text.isEmpty || typeController.text.isEmpty) {
return false;
} else {
return true;
}
}
void updateEmployeePopUp(int index, double width) {
setState(() {
accessController.text = widget.employees[index].access;
typeController.text = widget.employees[index].title;
fnameController.text = widget.employees[index].fname;
lnameController.text = widget.employees[index].lname;
});
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Employee Details",
menuOptions: [
SpeedDialChild(
child: Icon(
Icons.delete,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Delete Employee",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
showDeleteWarning(index);
},
),
],
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.05)
: const EdgeInsets.symmetric(horizontal: 0),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: fnameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "First Name",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: lnameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Surname",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: typeController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Title",
),
// MihDropdownField(
// controller: typeController,
// hintText: "Title",
// dropdownOptions: const ["Doctor", "Assistant", "Other"],
// editable: true,
// enableSearch: true,
// validator: (value) {
// return MihValidationServices().isEmpty(value);
// },
// requiredText: true,
// ),
const SizedBox(height: 10.0),
MihDropdownField(
controller: accessController,
hintText: "Access Type",
dropdownOptions: const ["Full", "Partial"],
editable: true,
enableSearch: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
requiredText: true,
),
const SizedBox(height: 20.0),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
if (isRequiredFieldsCaptured()) {
updateEmployeeAPICall(index);
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Input Error");
},
);
}
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Update",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
),
);
}
void showDeleteWarning(int index) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHDeleteMessage(
deleteType: "Employee",
onTap: () {
deleteNoteApiCall(index);
}));
}
@override
void dispose() {
accessController.dispose();
typeController.dispose();
fnameController.dispose();
lnameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.employees.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
//print(index);
var isMe = "";
if (widget.arguments.signedInUser.app_id ==
widget.employees[index].app_id) {
isMe = "(You)";
}
return ListTile(
title: Text(
"${widget.employees[index].fname} ${widget.employees[index].lname} - ${widget.employees[index].title} $isMe"),
subtitle: Text(
"${widget.employees[index].username}\n${widget.employees[index].email}\nAccess: ${widget.employees[index].access}",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
onTap: () {
updateEmployeePopUp(index, screenWidth);
},
);
},
);
}
}

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