117 Commits

Author SHA1 Message Date
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
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
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
711 changed files with 5728 additions and 4152 deletions

BIN
.DS_Store vendored

Binary file not shown.

15
.gitignore vendored
View File

@@ -1,15 +1,12 @@
# *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

6
.vscode/launch.json vendored
View File

@@ -6,14 +6,14 @@
"configurations": [
{
"name": "Debug",
"cwd": "Frontend",
"cwd": "mih_ui",
"request": "launch",
"type": "dart",
"program": "lib/main_dev.dart"
},
{
"name": "Profile",
"cwd": "Frontend",
"cwd": "mih_ui",
"request": "launch",
"type": "dart",
"flutterMode": "profile",
@@ -21,7 +21,7 @@
},
{
"name": "Release",
"cwd": "Frontend",
"cwd": "mih_ui",
"request": "launch",
"type": "dart",
"flutterMode": "release",

View File

@@ -1,45 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "8defaa71a77c16e8547abdbfad2053ce3a6e2d5b"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: android
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: ios
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: linux
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: macos
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: web
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: windows
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#6641b2</color>
<!-- Women For Change -->
<color name="mih_icon_background">#6641b2</color>
<color name="mih_icon_foreground">#E0D1FF</color>
<!-- Original -->
<!-- <color name="mih_icon_background">#3A4454</color>
<color name="mih_icon_foreground">#bedcfe</color> -->
</resources>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -1,321 +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.4";
// 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"),
),
// Text selection / cursor color
textSelectionTheme: TextSelectionThemeData(
cursorColor: MihColors.getPrimaryColor(mode == "Dark"),
selectionColor:
MihColors.getPrimaryColor(mode == "Dark").withOpacity(0.25),
selectionHandleColor: MihColors.getPrimaryColor(mode == "Dark"),
),
tooltipTheme: TooltipThemeData(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(mode == "Dark"),
borderRadius: BorderRadius.circular(6),
border: Border.all(
width: 1.0,
color: MihColors.getPrimaryColor(mode == "Dark"),
),
boxShadow: [
BoxShadow(
color:
MihColors.getPrimaryColor(mode == "Dark").withOpacity(0.18),
blurRadius: 6,
offset: const Offset(0, 2),
),
],
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(mode == "Dark"),
fontSize: 13,
height: 1.2,
),
waitDuration: const Duration(milliseconds: 500),
showDuration: const Duration(seconds: 3),
preferBelow: true,
verticalOffset: 24,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
triggerMode: TooltipTriggerMode.longPress,
),
// // Input decoration (text fields) theme
// inputDecorationTheme: InputDecorationTheme(
// filled: true,
// fillColor: mode == "Dark"
// ? MihColors.getPrimaryColor(true).withOpacity(0.06)
// : MihColors.getPrimaryColor(false).withOpacity(0.03),
// contentPadding:
// const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(8),
// borderSide:
// BorderSide(color: MihColors.getSecondaryColor(mode == "Dark")),
// ),
// enabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(8),
// borderSide: BorderSide(
// color:
// MihColors.getSecondaryColor(mode == "Dark").withOpacity(0.6)),
// ),
// focusedBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(8),
// borderSide: BorderSide(
// color: MihColors.getSecondaryColor(mode == "Dark"), width: 2),
// ),
// hintStyle: TextStyle(
// color:
// MihColors.getSecondaryColor(mode == "Dark").withOpacity(0.7)),
// labelStyle:
// TextStyle(color: MihColors.getSecondaryColor(mode == "Dark")),
// errorStyle: TextStyle(color: MihColors.getRedColor(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_package_components/assets/images/loading_light.gif',
// );
// } else {
// loading = const AssetImage(
// 'lib/mih_package_components/assets/images/loading_dark.gif',
// );
// }
// return loading;
// }
// AssetImage altLoadingImage() {
// if (mode == "Dark") {
// loading = const AssetImage(
// 'lib/mih_package_components/assets/images/loading_dark.gif',
// );
// } else {
// loading = const AssetImage(
// 'lib/mih_package_components/assets/images/loading_light.gif',
// );
// }
// return loading;
// }
// String loadingImageLocation() {
// if (mode == "Dark") {
// loadingAssetText =
// 'lib/mih_package_components/assets/images/loading_light.gif';
// } else {
// loadingAssetText =
// 'lib/mih_package_components/assets/images/loading_dark.gif';
// }
// return loadingAssetText;
// }
// String altLoadingImageLocation() {
// if (mode == "Dark") {
// loadingAssetText =
// 'lib/mih_package_components/assets/images/loading_dark.gif';
// } else {
// loadingAssetText =
// 'lib/mih_package_components/assets/images/loading_light.gif';
// }
// return loadingAssetText;
// }
// AssetImage aiLogoImage() {
// if (mode == "Dark") {
// return const AssetImage(
// 'lib/mih_package_components/assets/images/mzansi_ai-dark.png',
// );
// } else {
// return const AssetImage(
// 'lib/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,248 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihDropdownField extends StatefulWidget {
final TextEditingController controller;
final String hintText;
final bool requiredText;
final List<String> dropdownOptions;
final bool editable;
final bool enableSearch;
final FormFieldValidator<String>? validator;
final Function(String?)? onSelected;
const MihDropdownField({
super.key,
required this.controller,
required this.hintText,
required this.dropdownOptions,
required this.requiredText,
required this.editable,
required this.enableSearch,
this.validator,
this.onSelected,
});
@override
State<MihDropdownField> createState() => _MihDropdownFieldState();
}
class _MihDropdownFieldState extends State<MihDropdownField> {
late List<DropdownMenuEntry<String>> menu;
List<DropdownMenuEntry<String>> buildMenuOptions(List<String> options) {
List<DropdownMenuEntry<String>> menuList = [];
for (final i in options) {
menuList.add(DropdownMenuEntry(
value: i,
label: i,
style: ButtonStyle(
foregroundColor: WidgetStatePropertyAll(MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
),
));
}
return menuList;
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
menu = buildMenuOptions(widget.dropdownOptions);
}
@override
void initState() {
super.initState();
menu = widget.dropdownOptions
.map((e) => DropdownMenuEntry(value: e, label: e))
.toList();
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.hintText,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
if (!widget.requiredText)
Text(
"(Optional)",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 4),
FormField<String>(
validator: widget.validator,
autovalidateMode: AutovalidateMode.onUserInteraction,
initialValue: widget.controller.text,
builder: (field) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Theme(
data: Theme.of(context).copyWith(
textSelectionTheme: TextSelectionThemeData(
cursorColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
selectionColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")
.withValues(alpha: 0.3),
selectionHandleColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
child: DropdownMenu(
controller: widget.controller,
dropdownMenuEntries: menu,
enableSearch: widget.enableSearch,
enableFilter: widget.enableSearch,
enabled: widget.editable,
textInputAction: widget.enableSearch
? TextInputAction.search
: TextInputAction.none,
requestFocusOnTap: widget.enableSearch,
menuHeight: 400,
expandedInsets: EdgeInsets.zero,
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.w500,
),
trailingIcon: Icon(
Icons.arrow_drop_down,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
selectedTrailingIcon: Icon(
Icons.arrow_drop_up,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
leadingIcon: IconButton(
onPressed: () {
widget.controller.clear();
field.didChange('');
},
icon: Icon(
Icons.delete_outline_rounded,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
onSelected: (String? selectedValue) {
field.didChange(selectedValue);
widget.onSelected?.call(selectedValue);
},
menuStyle: MenuStyle(
backgroundColor: WidgetStatePropertyAll(
MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
side: WidgetStatePropertyAll(
BorderSide(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 1.0),
),
shape: WidgetStatePropertyAll(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
10), // Increase for more roundness
),
),
),
inputDecorationTheme: InputDecorationTheme(
errorStyle: const TextStyle(height: 0, fontSize: 0),
contentPadding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 8.0),
filled: true,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: field.hasError
? MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")
: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 3.0,
),
),
),
),
),
if (field.hasError)
Padding(
padding: const EdgeInsets.only(left: 8.0, top: 4.0),
child: Text(
field.errorText ?? '',
style: TextStyle(
fontSize: 12,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.bold,
),
),
),
],
);
},
),
],
);
}
}

View File

@@ -1,113 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:provider/provider.dart';
class BuildMinesweeperLeaderboardList extends StatefulWidget {
const BuildMinesweeperLeaderboardList({super.key});
@override
State<BuildMinesweeperLeaderboardList> createState() =>
_BuildMinesweeperLeaderboardListState();
}
class _BuildMinesweeperLeaderboardListState
extends State<BuildMinesweeperLeaderboardList> {
Color getMedalColor(int index) {
switch (index) {
case (0):
return MihColors.getGoldColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
case (1):
return MihColors.getSilverColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
case (2):
return MihColors.getBronze(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
default:
return MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
}
}
@override
Widget build(BuildContext context) {
final double width = MediaQuery.sizeOf(context).width;
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider,
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: mineSweeperProvider.leaderboard!.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: Row(
children: [
Text(
"#${index + 1}",
style: TextStyle(
fontSize: 25,
color: getMedalColor(index),
),
),
const SizedBox(width: 10),
MihCircleAvatar(
key: UniqueKey(),
imageFile:
mineSweeperProvider.leaderboardUserPictures.isNotEmpty
? mineSweeperProvider.leaderboardUserPictures[index]
: null,
width: 80,
editable: false,
fileNameController: null,
userSelectedfile: null,
frameColor: getMedalColor(index),
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: () {},
),
const SizedBox(width: 10),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${mineSweeperProvider.leaderboard![index].username}${profileProvider.user!.username == mineSweeperProvider.leaderboard![index].username ? " (You)" : ""}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: getMedalColor(index),
),
),
Text(
"Score: ${mineSweeperProvider.leaderboard![index].game_score}\nTime: ${mineSweeperProvider.leaderboard![index].game_time}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 18,
// fontWeight: FontWeight.bold,
color: getMedalColor(index),
),
),
],
)
],
),
);
},
);
},
);
}
}

View File

@@ -1,204 +0,0 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:provider/provider.dart';
class MihMineSweeperLeaderBoard extends StatefulWidget {
const MihMineSweeperLeaderBoard({super.key});
@override
State<MihMineSweeperLeaderBoard> createState() =>
_MihMineSweeperLeaderBoardState();
}
class _MihMineSweeperLeaderBoardState extends State<MihMineSweeperLeaderBoard> {
TextEditingController filterController = TextEditingController();
bool isLoading = true;
Future<void> initialiseLeaderboard() async {
MihMineSweeperProvider mineSweeperProvider =
context.read<MihMineSweeperProvider>();
filterController.text = mineSweeperProvider.difficulty;
KenLogger.success("getting data");
await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider);
List<ImageProvider<Object>?> userPictures = [];
String userPicUrl = "";
for (final ranking in mineSweeperProvider.leaderboard!) {
userPicUrl = await MihFileApi.getMinioFileUrl(ranking.proPicUrl);
userPictures.add(NetworkImage(userPicUrl));
}
mineSweeperProvider.setLeaderboardUserPictures(
leaderboardUserPictures: userPictures);
setState(() {
isLoading = false;
});
}
void refreshLeaderBoard(
MihMineSweeperProvider mineSweeperProvider, String difficulty) {
setState(() {
isLoading = true;
});
mineSweeperProvider.setDifficulty(difficulty);
mineSweeperProvider.setLeaderboard(leaderboard: null);
mineSweeperProvider.setMyScoreboard(myScoreboard: null);
initialiseLeaderboard();
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
await initialiseLeaderboard();
});
}
@override
Widget build(BuildContext context) {
final double width = MediaQuery.sizeOf(context).width;
return Consumer<MihMineSweeperProvider>(
builder: (BuildContext context,
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
return RefreshIndicator(
onRefresh: () async {
refreshLeaderBoard(mineSweeperProvider, filterController.text);
},
child: MihPackageToolBody(
borderOn: false,
bodyItem: getBody(width),
),
);
},
);
}
Widget getBody(double width) {
return Consumer<MihMineSweeperProvider>(
builder: (BuildContext context,
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
if (isLoading) {
return Center(
child: Mihloadingcircle(),
);
} else {
return SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: MihDropdownField(
controller: filterController,
hintText: "Leaderboards",
dropdownOptions: const [
"Very Easy",
"Easy",
"Intermediate",
"Hard",
],
requiredText: true,
editable: true,
enableSearch: false,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
onSelected: (selection) {
refreshLeaderBoard(mineSweeperProvider, selection!);
},
),
),
],
),
),
const SizedBox(height: 10),
!isLoading && mineSweeperProvider.leaderboard!.isEmpty
? Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mineSweeper,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"Be the first on the leaderboard.",
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(
FontAwesomeIcons.bomb,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
TextSpan(text: " and start a new game"),
],
),
),
),
],
),
)
: BuildMinesweeperLeaderboardList(),
],
),
);
}
},
);
}
}

View File

@@ -1,209 +0,0 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_my_scoreboard_list.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:provider/provider.dart';
class MyScoreBoard extends StatefulWidget {
const MyScoreBoard({super.key});
@override
State<MyScoreBoard> createState() => _MihMineSweeperLeaderBoardState();
}
class _MihMineSweeperLeaderBoardState extends State<MyScoreBoard> {
TextEditingController filterController = TextEditingController();
Future<void> initialiseLeaderboard() async {
MzansiProfileProvider profileProvider =
context.read<MzansiProfileProvider>();
MihMineSweeperProvider mineSweeperProvider =
context.read<MihMineSweeperProvider>();
filterController.text = mineSweeperProvider.difficulty;
KenLogger.success("getting data");
await MihMinesweeperServices()
.getMyScoreboard(profileProvider, mineSweeperProvider);
KenLogger.success("${mineSweeperProvider.myScoreboard}");
}
void refreshLeaderBoard(
MihMineSweeperProvider mineSweeperProvider, String difficulty) {
mineSweeperProvider.setDifficulty(difficulty);
mineSweeperProvider.setLeaderboard(leaderboard: null);
mineSweeperProvider.setMyScoreboard(myScoreboard: null);
initialiseLeaderboard();
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
await initialiseLeaderboard();
});
}
@override
Widget build(BuildContext context) {
final double width = MediaQuery.sizeOf(context).width;
return Consumer<MihMineSweeperProvider>(
builder: (BuildContext context,
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
return RefreshIndicator(
onRefresh: () async {
refreshLeaderBoard(mineSweeperProvider, filterController.text);
},
child: MihPackageToolBody(
borderOn: false,
bodyItem: getBody(width),
),
);
},
);
}
Widget getBody(double width) {
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider,
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
if (mineSweeperProvider.myScoreboard == null) {
return Center(
child: Mihloadingcircle(),
);
} else {
return SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
Center(
child: MihCircleAvatar(
imageFile: profileProvider.userProfilePicture,
width: 150,
editable: false,
fileNameController: null,
userSelectedfile: null,
frameColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: (selectedImage) {},
key: ValueKey(profileProvider.userProfilePicUrl),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: MihDropdownField(
controller: filterController,
hintText: "Scoreboards",
dropdownOptions: const [
"Very Easy",
"Easy",
"Intermediate",
"Hard",
],
requiredText: true,
editable: true,
enableSearch: false,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
onSelected: (selection) {
refreshLeaderBoard(mineSweeperProvider, selection!);
},
),
),
],
),
),
const SizedBox(height: 10),
mineSweeperProvider.myScoreboard!.isEmpty
? Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mineSweeper,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"You have played and ${mineSweeperProvider.difficulty} yet.",
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(
FontAwesomeIcons.bomb,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
),
TextSpan(text: " and start a new game"),
],
),
),
),
],
),
)
: BuildMyScoreBoardList(),
],
),
);
}
},
);
}
}

View File

@@ -1,556 +0,0 @@
import 'package:flutter/material.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.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';
import 'package:provider/provider.dart';
class MihSearchMzansi extends StatefulWidget {
const MihSearchMzansi({
super.key,
});
@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();
List<AppUser> userSearchResults = [];
List<Business> businessSearchResults = [];
late Future<List<String>> availableBusinessTypes;
bool filterOn = false;
bool loadingSearchResults = false;
Future<void> swapPressed(MzansiProfileProvider profileProvider,
MzansiDirectoryProvider directoryProvider) async {
directoryProvider.setPersonalSearch(!directoryProvider.personalSearch);
setState(() {
if (filterOn) {
filterOn = !filterOn;
}
});
if (businessTypeController.text.isNotEmpty) {
setState(() {
businessTypeController.clear();
});
}
await searchPressed(profileProvider, directoryProvider);
}
void clearAll(MzansiDirectoryProvider directoryProvider) {
directoryProvider.setSearchedBusinesses(searchedBusinesses: []);
directoryProvider.setSearchedUsers(searchedUsers: []);
directoryProvider.setSearchTerm(searchTerm: "");
setState(() {
mzansiSearchController.clear();
businessTypeController.clear();
});
}
Future<void> searchPressed(MzansiProfileProvider profileProvider,
MzansiDirectoryProvider directoryProvider) async {
setState(() {
loadingSearchResults = true;
});
directoryProvider.setSearchTerm(searchTerm: mzansiSearchController.text);
directoryProvider.setBusinessTypeFilter(
businessTypeFilter: businessTypeController.text);
if (directoryProvider.personalSearch &&
directoryProvider.searchTerm.isNotEmpty) {
final userResults = await MihUserServices()
.searchUsers(profileProvider, directoryProvider.searchTerm, context);
directoryProvider.setSearchedUsers(searchedUsers: userResults);
} else {
List<Business>? businessSearchResults = [];
if (directoryProvider.businessTypeFilter.isNotEmpty) {
businessSearchResults = await MihBusinessDetailsServices()
.searchBusinesses(directoryProvider.searchTerm,
directoryProvider.businessTypeFilter, context);
} else if (directoryProvider.searchTerm.isNotEmpty) {
businessSearchResults = await MihBusinessDetailsServices()
.searchBusinesses(directoryProvider.searchTerm,
directoryProvider.businessTypeFilter, context);
}
directoryProvider.setSearchedBusinesses(
searchedBusinesses: businessSearchResults);
}
setState(() {
loadingSearchResults = false;
});
}
@override
void dispose() {
super.dispose();
businessTypeController.dispose();
mzansiSearchController.dispose();
}
@override
void initState() {
super.initState();
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
availableBusinessTypes =
MihBusinessDetailsServices().fetchAllBusinessTypes();
mzansiSearchController.text = "";
WidgetsBinding.instance.addPostFrameCallback((_) async {
directoryProvider.setSearchedUsers(searchedUsers: []);
});
}
@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 Consumer2<MzansiProfileProvider, MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider,
MzansiDirectoryProvider directoryProvider, Widget? child) {
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: directoryProvider.personalSearch
? Icons.person
: Icons.business,
suffixTools: [
IconButton(
onPressed: () {
swapPressed(profileProvider, directoryProvider);
},
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(profileProvider, directoryProvider);
},
onClearIconTap: () {
clearAll(directoryProvider);
},
searchFocusNode: searchFocusNode,
),
),
Visibility(
visible: !directoryProvider.personalSearch,
child: const SizedBox(width: 10),
),
Visibility(
visible: !directoryProvider.personalSearch,
child: IconButton(
onPressed: () {
if (filterOn) {
clearAll(directoryProvider);
}
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(
profileProvider, directoryProvider);
} else {
MihAlertServices().errorBasicAlert(
"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(directoryProvider),
],
),
);
},
);
}
Widget displayBusinessSearchResults(
MzansiDirectoryProvider directoryProvider) {
KenLogger.success(
"Searched Businesses: ${directoryProvider.searchedBusinesses}");
if (directoryProvider.searchedBusinesses == null || loadingSearchResults) {
return Center(
child: const Mihloadingcircle(),
);
} else if (directoryProvider.searchedBusinesses!.isNotEmpty) {
// return Text("Pulled Data successfully");
directoryProvider.searchedBusinesses!
.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: directoryProvider.searchedBusinesses!,
),
],
);
} else if (directoryProvider.searchedBusinesses!.isEmpty &&
directoryProvider.searchTerm.isNotEmpty) {
// 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 (directoryProvider.searchedBusinesses!.isEmpty &&
directoryProvider.searchTerm.isEmpty) {
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/${directoryProvider.searchTerm}",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.center,
),
);
}
}
Widget displayPersonalSearchResults(
MzansiDirectoryProvider directoryProvider) {
if (directoryProvider.searchedUsers == null || loadingSearchResults) {
return Center(
child: const Mihloadingcircle(),
);
} else if (directoryProvider.searchedUsers!.isNotEmpty) {
// return Text("Pulled Data successfully");
directoryProvider.searchedUsers!
.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: directoryProvider.searchedUsers!),
],
);
} else if (directoryProvider.searchedUsers!.isEmpty &&
directoryProvider.searchTerm.isEmpty) {
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"),
],
),
),
),
],
),
);
} else if (directoryProvider.searchedUsers!.isEmpty &&
directoryProvider.searchTerm.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"),
),
),
],
);
} else {
return Center(
child: Text(
"Error pulling Patients Data\n/users/search/${directoryProvider.searchTerm}",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.center,
),
);
}
}
Widget displaySearchResults(MzansiDirectoryProvider directoryProvider) {
if (directoryProvider.personalSearch) {
return displayPersonalSearchResults(directoryProvider);
} else {
return displayBusinessSearchResults(directoryProvider);
}
}
}

View File

@@ -1,182 +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_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart';
import 'package:provider/provider.dart';
class MihPersonalProfile extends StatefulWidget {
const MihPersonalProfile({super.key});
@override
State<MihPersonalProfile> createState() => _MihPersonalProfileState();
}
class _MihPersonalProfileState extends State<MihPersonalProfile> {
TextEditingController proPicController = TextEditingController();
PlatformFile? newSelectedProPic;
void editProfileWindow(double width) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Consumer<MzansiProfileProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
return MihEditPersonalProfileWindow();
},
),
);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return Consumer<MzansiProfileProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
if (mzansiProfileProvider.user == null) {
//Change to new user flow
return Center(
child: Mihloadingcircle(),
);
} else {
return MihSingleChildScroll(
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: [
Center(
child: MihCircleAvatar(
imageFile: mzansiProfileProvider.userProfilePicture,
width: 150,
editable: false,
fileNameController: proPicController,
userSelectedfile: newSelectedProPic,
frameColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
onChange: (selectedImage) {
setState(() {
newSelectedProPic = selectedImage;
});
},
key: ValueKey(mzansiProfileProvider.userProfilePicUrl),
),
),
FittedBox(
child: Text(
mzansiProfileProvider.user!.username.isNotEmpty
? mzansiProfileProvider.user!.username
: "username",
style: TextStyle(
fontSize: 35,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
FittedBox(
child: Text(
mzansiProfileProvider.user!.fname.isNotEmpty
? "${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}"
: "Name Surname",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
FittedBox(
child: Text(
mzansiProfileProvider.user!.type == "business"
? "Business".toUpperCase()
: "Personal".toUpperCase(),
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
const SizedBox(height: 10.0),
Center(
child: SizedBox(
width: 700,
child: Text(
mzansiProfileProvider.user!.purpose.isNotEmpty
? mzansiProfileProvider.user!.purpose
: "No Personal Mission added yet",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
),
const SizedBox(height: 30.0),
Center(
child: MihButton(
onPressed: () {
// Connect with the user
editProfileWindow(width);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
mzansiProfileProvider.user!.username.isEmpty
? "Set Up Profile"
: "Edit Profile",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
}
},
);
}
}

View File

@@ -1,328 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart';
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_providers/ollama_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
class MzansiAiProvider extends ChangeNotifier {
bool ttsOn;
int toolIndex;
String? startUpQuestion;
late OllamaProvider ollamaProvider;
MzansiAiProvider({
this.toolIndex = 0,
this.ttsOn = false,
}) {
ollamaProvider = OllamaProvider(
baseUrl: "${AppEnviroment.baseAiUrl}/api",
model: AppEnviroment.getEnv() == "Prod" ? 'gemma3n:e4b' : "gemma3:1b",
systemPrompt: "You are Mzansi AI, a helpful and friendly AI assistant running on the 'MIH App'.\n" +
"The MIH App was created by 'Mzansi Innovation Hub', a South African-based startup company." +
"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" +
"Maintain a casual and friendly tone, but always remain professional.\n" +
"Strive for a balance between being empathetic and delivering factual information accurately.\n" +
"You may use lighthearted or playful language if the context is appropriate and enhances the user experience.\n" +
"You operate within the knowledge domain of the 'MIH App'.\n" +
"Here is a description of the MIH App and its features:\n" +
"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" +
"Key Features:\n" +
"- Mzansi Profile: Central hub for managing personal and business information, including business team details." +
"- Mzansi Wallet: Digitally store loyalty cards.\n" +
"- Patient Manager (For Medical Practices): Seamless patient appointment scheduling and data management.\n" +
"- Mzansi AI: Your friendly AI assistant for quick answers and support (that's you!).\n" +
"- Mzansi Directory: A place to search and find out more about the people and businesses across Mzansi.\n" +
"- Calendar: Integrated calendar for managing personal and business appointments.\n" +
"- Calculator: Simple calculator with tip and forex calculation functionality.\n" +
"- MIH Minesweeper: The first game from MIH! It's the classic brain-teaser ready to entertain you no matter where you are.\n" +
"- MIH Access: Manage and view profile access security.\n" +
"**Core Rules and Guidelines:**\n" +
"- **Accuracy First:** Always prioritize providing correct information.\n" +
"- **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" +
"- **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" +
"- **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" +
"- **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" +
"- **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",
)..addListener(() {
notifyListeners(); // Forward OllamaProvider notifications
});
}
void reset() {
toolIndex = 0;
startUpQuestion = null;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
void setTTSstate(bool ttsOn) {
this.ttsOn = ttsOn;
notifyListeners();
}
void setStartUpQuestion(String? question) {
startUpQuestion = question;
notifyListeners();
}
void clearStartUpQuestion() {
startUpQuestion = null;
}
MarkdownStyleSheet getLlmChatMarkdownStyle(BuildContext context) {
TextStyle body = TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 16,
fontWeight: FontWeight.w400,
);
TextStyle heading1 = TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 24,
fontWeight: FontWeight.w400,
);
TextStyle heading2 = TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.w400,
);
TextStyle code = TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 16,
fontWeight: FontWeight.w400,
);
BoxDecoration codeBlock = BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
color: MihColors.getHighlightColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
);
return MarkdownStyleSheet(
a: body,
blockquote: body,
checkbox: body,
del: body,
em: body.copyWith(fontStyle: FontStyle.italic),
h1: heading1,
h2: heading2,
h3: body.copyWith(fontWeight: FontWeight.bold),
h4: body,
h5: body,
h6: body,
listBullet: body,
img: body,
strong: body.copyWith(fontWeight: FontWeight.bold),
p: body,
tableBody: body,
tableHead: body,
code: code,
codeblockDecoration: codeBlock,
);
}
LlmChatViewStyle? getChatStyle(BuildContext context) {
return LlmChatViewStyle(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
progressIndicatorColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
menuColor: Colors.black,
// MihColors.getGreenColor(
// MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
disabledButtonStyle: ActionButtonStyle(
icon: MihIcons.mzansiAi,
iconColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
),
recordButtonStyle: ActionButtonStyle(
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
submitButtonStyle: ActionButtonStyle(
icon: Icons.send,
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
stopButtonStyle: ActionButtonStyle(
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
actionButtonBarDecoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
// Mzansi AI Chat Style
llmMessageStyle: LlmMessageStyle(
icon: MihIcons.mzansiAi,
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(25),
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
markdownStyle: getLlmChatMarkdownStyle(context),
),
// User Chat Style
userMessageStyle: UserMessageStyle(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
textStyle: TextStyle(
fontSize: 16,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
// User Input Style
chatInputStyle: ChatInputStyle(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
hintStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
hintText: "Ask Mzansi AI...",
),
// Suggestions Style
suggestionStyle: SuggestionStyle(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
copyButtonStyle: ActionButtonStyle(
iconColor: MihColors.getSecondaryInvertedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
editButtonStyle: ActionButtonStyle(
iconColor: MihColors.getSecondaryInvertedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
cancelButtonStyle: ActionButtonStyle(
iconDecoration: BoxDecoration(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
iconColor: MihColors.getSecondaryInvertedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1,48 +1,103 @@
#============== MIH Network ====================================================================
networks:
mih-network:
driver: bridge
#============== MIH Containers ====================================================================
services:
#============== API Hub ====================================================================
api:
build:
context: ./backend
target: builder
container_name: MIH-API-Hub
#command: sh -c "sleep 10s; uvicorn backend.main:app --reload --port=8080 --host=0.0.0.0"
#============Dev=================
# command: sh -c "sleep 10s; fastapi dev main.py --port 8080"
#============prod=================
#command: sh -c "sleep 10s; fastapi run backend/main.py --proxy-headers --port 8080"
#============== Nginx Proxy Server Old ====================================================================
# nginx:
# container_name: nginx
# restart: unless-stopped
# image: nginx
# ports:
# - 80:80
# - 443:443
# volumes:
# - ./nginx/nginx.conf:/etc/nginx/nginx.conf
# - certbotConf:/etc/letsencrypt
# - certbotChall:/var/www/certbot
# depends_on:
# - mih-ux
# networks:
# - mih-network
# profiles: [ 'prod' ]
#============== Cert Bot Old ====================================================================
# certbot:
# image: certbot/certbot
# container_name: certbot
# volumes:
# - certbotConf:/etc/letsencrypt
# - certbotChall:/var/www/certbot
# #command: certonly --test-cert --webroot -w /var/www/certbot --force-renewal --email yasienmeth@gmail.com -d mzansi-innovation-hub.co.za -d www.mzansi-innovation-hub.co.za --agree-tos
# command: certonly --webroot -w /var/www/certbot --force-renewal --email ${CERTBOT_EMAIL} -d ${CERTBOT_APP_DOMAIN} -d ${CERTBOT_API_DOMAIN} -d ${CERTBOT_STORAGE_DOMAIN} -d ${CERTBOT_MONITOR_DOMAIN} -d ${CERTBOT_AI_DOMAIN} --agree-tos
# networks:
# - mih-network
# depends_on:
# - nginx
# profiles: [ 'withCert' ]
#============== Nginx Proxy Manager ====================================================================
mih-nginx:
container_name: mih-nginx
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- 8080:80
- '80:80' # Public HTTP
- '443:443' # Public HTTPS
- '81:81' # Admin Web Port
volumes:
- ./backend:/app
- ./mih_nginx/data:/data
- ./mih_nginx/letsencrypt:/etc/letsencrypt
networks:
- MIH-network
- mih-network
#============== GITEA ====================================================================
mih-gitea:
image: gitea/gitea:latest
container_name: mih-gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=mih-gitea-db:3306
- GITEA__database__NAME=${GITEA_SQL_DB}
- GITEA__database__USER=${GITEA_SQL_USER}
- GITEA__database__PASSWD=${GITEA_SQL_PW}
restart: always
networks:
- mih-network
volumes:
- ./mih_git/gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- mysqldb
#============== My SQL DB ====================================================================
mysqldb:
#build: ./database/
platform: linux/amd64
image: mysql:5.7
container_name: MIH-Database
mih-gitea-db:
condition: service_healthy
mih-gitea-db:
image: mysql:8.0
container_name: mih-gitea-db
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${SQL_ROOT_PW}
MYSQL_USER: ${SQL_USER}
MYSQL_PASSWORD: ${SQL_USER_PW}
MYSQL_DATABASE: ${SUPERTOKENS_DB}
- MYSQL_ROOT_PASSWORD=${GITEA_SQL_ROOT_PW}
- MYSQL_USER=${GITEA_SQL_USER}
- MYSQL_PASSWORD=${GITEA_SQL_PW}
- MYSQL_DATABASE=${GITEA_SQL_DB}
networks:
- MIH-network
ports:
- '3306:3306'
- mih-network
volumes:
- ./database:/var/lib/mysql
- ./mih_git/mysql:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
#============== Super Token Auth ====================================================================
supertokens:
container_name: MIH-SuperTokens
mih-supertokens:
container_name: mih-supertokens
image: supertokens/supertokens-mysql:latest
# image: registry.supertokens.io/supertokens/supertokens-mysql
depends_on:
- mysqldb
- mih-db
ports:
- 3567:3567
environment:
@@ -51,12 +106,12 @@ services:
PASSWORD_RESET_TOKEN_LIFETIME: '7200000'
MYSQL_USER: ${SQL_USER}
MYSQL_PASSWORD: ${SQL_USER_PW}
MYSQL_HOST: mysqldb
MYSQL_HOST: mih-db
MYSQL_PORT: 3306
MYSQL_DATABASE_NAME: ${SUPERTOKENS_DB}
API_KEYS: ${SUPERTOKENS_API_KEY}
networks:
- MIH-network
- mih-network
restart: unless-stopped
healthcheck:
test: >
@@ -64,103 +119,130 @@ services:
interval: 10s
timeout: 5s
retries: 5
#============== MIH WordPress ====================================================================
mih-wordpress:
container_name: mih-wordpress
image: wordpress
restart: always
ports:
- 8081:80
environment:
WORDPRESS_DB_HOST: mih-wp-db
WORDPRESS_DB_USER: ${WP_SQL_USER}
WORDPRESS_DB_PASSWORD: ${WP_SQL_USER_PW}
WORDPRESS_DB_NAME: ${WP_SQL_DB}
volumes:
- ./mih_wp/ui:/var/www/html
networks:
- mih-network
mih-wp-db:
container_name: mih-wp-db
image: mariadb:10.11
restart: always
environment:
MARIADB_DATABASE: ${WP_SQL_DB}
MARIADB_USER: ${WP_SQL_USER}
MARIADB_PASSWORD: ${WP_SQL_USER_PW}
MARIADB_RANDOM_ROOT_PASSWORD: '1'
volumes:
- ./mih_wp/database:/var/lib/mysql
networks:
- mih-network
#============== MIH-UX Flutter ====================================================================
mih-ux:
container_name: mih-ux
build:
context: ./mih_ui
ports:
- "83:83"
networks:
- mih-network
depends_on:
- mih-api-hub
#============== API Hub ====================================================================
mih-api-hub:
build:
context: ./mih_api_hub
target: builder
container_name: mih-api-hub
ports:
- 8080:80
volumes:
- ./mih_api_hub:/app
networks:
- mih-network
depends_on:
- mih-db
#============== My SQL DB ====================================================================
mih-db:
platform: linux/amd64
image: mysql:5.7
container_name: mih-db
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${SQL_ROOT_PW}
MYSQL_USER: ${SQL_USER}
MYSQL_PASSWORD: ${SQL_USER_PW}
MYSQL_DATABASE: ${SUPERTOKENS_DB}
networks:
- mih-network
ports:
- '3306:3306'
volumes:
- ./mih_db:/var/lib/mysql
#============== PHP My Admin ====================================================================
# phpmyadmin:
# platform: linux/amd64
# image: phpmyadmin/phpmyadmin
# container_name: MIH-phpmyadmin
# environment:
# PMA_HOST: mysqlDB
# PMA_HOST: mih-db
# PMA_PORT: 3306
# PMA_ARBITRARY:
# networks:
# - MIH-network
# - mih-network
# restart: always
# ports:
# - 8081:80
# depends_on:
# - mysqldb
#============== Nginx Proxy Server ====================================================================
nginx:
container_name: nginx
restart: unless-stopped
image: nginx
ports:
- 80:80
- 443:443
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- certbotConf:/etc/letsencrypt
- certbotChall:/var/www/certbot
depends_on:
- user-interface
networks:
- MIH-network
profiles: [ 'prod' ]
#============== MIH-UX Flutter ====================================================================
user-interface:
container_name: MIH-UX
build:
context: ./Frontend
ports:
- "83:83"
networks:
- MIH-network
depends_on:
- api
#============== Cert Bot ====================================================================
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbotConf:/etc/letsencrypt
- certbotChall:/var/www/certbot
#command: certonly --test-cert --webroot -w /var/www/certbot --force-renewal --email yasienmeth@gmail.com -d mzansi-innovation-hub.co.za -d www.mzansi-innovation-hub.co.za --agree-tos
command: certonly --webroot -w /var/www/certbot --force-renewal --email ${CERTBOT_EMAIL} -d ${CERTBOT_APP_DOMAIN} -d ${CERTBOT_API_DOMAIN} -d ${CERTBOT_STORAGE_DOMAIN} -d ${CERTBOT_MONITOR_DOMAIN} -d ${CERTBOT_AI_DOMAIN} --agree-tos
networks:
- MIH-network
depends_on:
- nginx
profiles: [ 'withCert' ]
# - mih-db
#============== Minio File Storage ====================================================================
minio:
mih-minio:
platform: linux/amd64
container_name: MIH-Minio
hostname: minio
# image: docker.io/bitnami/minio:2022
container_name: mih-minio
hostname: mih-minio
image: minio/minio
ports:
- '9000:9000'
- '9001:9001'
volumes:
- './File_Storage:/data'
- './mih_minio:/data'
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PW}
networks:
- MIH-network
- mih-network
command: ["server", "/data", "--console-address", ":9001"]
#============== MIH-Monitor Portainer ====================================================================
portainer:
container_name: MIH-Monitor
mih-monitor:
container_name: mih-monitor
image: portainer/portainer-ce:2.20.3
ports:
- 9444:9443
volumes:
- data:/data
- ./mih_monitor/data:/data
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stopped
networks:
- MIH-network
- mih-network
#============== MIH-AI Ollama ====================================================================
ollama:
container_name: MIH-AI
mih-ai:
container_name: mih-ai
image: ollama/ollama:latest
ports:
- 11434:11434
volumes:
# - ./Mzansi_AI:/code
- ./Mzansi_AI/ollama/ollama:/root/.ollama
- ./mih_ai/ollama/ollama:/root/.ollama
pull_policy: always
tty: true
restart: always
@@ -169,16 +251,16 @@ services:
- OLLAMA_KEEP_ALIVE=24h
- OLLAMA_HOST=0.0.0.0
networks:
- MIH-network
- mih-network
# === Added section for NVIDIA GPU acceleration ===
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all # or specify a number of GPUs
capabilities: [ gpu ]
# runtime: nvidia
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: all # or specify a number of GPUs
# capabilities: [ gpu ]
#============== Firebaase ====================================================================
# firebase:
# container_name: MIH-firebase-emulator
@@ -198,11 +280,3 @@ services:
# # - ./cache:/root/.cache/:rw
# # - ~/.config/:/root/.config
# - ./Firebase-emulator/firebase/data:/srv/firebase/data:rw
#============== Named Volumes ====================================================================
volumes:
certbotConf:
certbotChall:
data: #============== MIH Network ====================================================================
networks:
MIH-network:
driver: bridge

Binary file not shown.

View File

@@ -9,7 +9,7 @@ minioSecret = os.getenv("MINIO_SECRET_KEY")
def minioConnect(env):
if(env == "Dev"):
return Minio(
"minio:9000",
endpoint="mih-minio:9000",
# "minio.mzansi-innovation-hub.co.za",
access_key=minioAccess,
secret_key=minioSecret,
@@ -17,8 +17,8 @@ def minioConnect(env):
)
else:
return Minio(
#"minio:9000",
"minio.mzansi-innovation-hub.co.za",
# endpoint="mih-minio:9000",
endpoint="minio.mzansi-innovation-hub.co.za",
access_key=minioAccess,
secret_key=minioSecret,
secure=True

View File

@@ -54,7 +54,7 @@ init(
),
supertokens_config=SupertokensConfig(
# https://try.supertokens.com is for demo purposes. Replace this with the address of your core instance (sign up on supertokens.com), or self host a core.
connection_uri="http://MIH-SuperTokens:3567/",
connection_uri="http://mih-supertokens:3567/",
api_key="leatucczyixqwkqqdrhayiwzeofkltds"
),
framework='fastapi',

View File

@@ -8,7 +8,7 @@ dbPass = os.getenv("DB_PASSWD")
def dbPatientManagerConnect():
return mysql.connector.connect(
host="mysqldb",
host="mih-db",
user=dbUser,
passwd=dbPass,
database="patient_manager"
@@ -16,7 +16,7 @@ def dbPatientManagerConnect():
def dbAppDataConnect():
return mysql.connector.connect(
host="mysqldb",
host="mih-db",
user=dbUser,
passwd=dbPass,
database="app_data"
@@ -24,7 +24,7 @@ def dbAppDataConnect():
def dbDataAccessConnect():
return mysql.connector.connect(
host="mysqldb",
host="mih-db",
user=dbUser,
passwd=dbPass,
database="data_access"
@@ -32,7 +32,7 @@ def dbDataAccessConnect():
def dbMzansiWalletConnect():
return mysql.connector.connect(
host="mysqldb",
host="mih-db",
user=dbUser,
passwd=dbPass,
database="mzansi_wallet"
@@ -40,7 +40,7 @@ def dbMzansiWalletConnect():
def dbMzansiDirectoryConnect():
return mysql.connector.connect(
host="mysqldb",
host="mih-db",
user=dbUser,
passwd=dbPass,
database="mzansi_directory"
@@ -48,7 +48,7 @@ def dbMzansiDirectoryConnect():
def dbMzansiCalendarConnect():
return mysql.connector.connect(
host="mysqldb",
host="mih-db",
user=dbUser,
passwd=dbPass,
database="mzansi_calendar"
@@ -56,7 +56,7 @@ def dbMzansiCalendarConnect():
def dbAllConnect():
return mysql.connector.connect(
host="mysqldb",
host="mih-db",
user=dbUser,
passwd=dbPass,
)

View File

@@ -7,7 +7,7 @@ from dotenv import load_dotenv
load_dotenv()
dbUser = os.getenv("DB_USER")
dbPass = os.getenv("DB_PASSWD")
dbHost = "mysqldb"
dbHost = "mih-db"
dbPort = 3306
encoded_dbPass = quote_plus(dbPass)
base_connect_url = f"mysql+mysqlconnector://{dbUser}:{encoded_dbPass}@{dbHost}:{dbPort}/"
@@ -15,7 +15,7 @@ base_connect_url = f"mysql+mysqlconnector://{dbUser}:{encoded_dbPass}@{dbHost}:{
def dbPatientManagerConnect():
return create_engine(base_connect_url+"patient_manager", echo=False, pool_recycle=3600)
# return mysql.connector.connect(
# host="mysqldb",
# host="mih-db",
# user=dbUser,
# passwd=dbPass,
# database="patient_manager"
@@ -24,7 +24,7 @@ def dbPatientManagerConnect():
def dbAppDataConnect():
return create_engine(base_connect_url+"app_data", echo=False, pool_recycle=3600)
# return mysql.connector.connect(
# host="mysqldb",
# host="mih-db",
# user=dbUser,
# passwd=dbPass,
# database="app_data"
@@ -33,7 +33,7 @@ def dbAppDataConnect():
def dbDataAccessConnect():
return create_engine(base_connect_url+"data_access", echo=False, pool_recycle=3600)
# return mysql.connector.connect(
# host="mysqldb",
# host="mih-db",
# user=dbUser,
# passwd=dbPass,
# database="data_access"
@@ -42,7 +42,7 @@ def dbDataAccessConnect():
def dbMzansiWalletConnect():
return create_engine(base_connect_url+"mzansi_wallet", echo=False, pool_recycle=3600)
# return mysql.connector.connect(
# host="mysqldb",
# host="mih-db",
# user=dbUser,
# passwd=dbPass,
# database="mzansi_wallet"
@@ -51,7 +51,7 @@ def dbMzansiWalletConnect():
def dbMzansiDirectoryConnect():
return create_engine(base_connect_url+"mzansi_directory", echo=False, pool_recycle=3600)
# return mysql.connector.connect(
# host="mysqldb",
# host="mih-db",
# user=dbUser,
# passwd=dbPass,
# database="mzansi_directory"
@@ -60,7 +60,7 @@ def dbMzansiDirectoryConnect():
def dbMzansiCalendarConnect():
return create_engine(base_connect_url+"mzansi_calendar", echo=False, pool_recycle=3600)
# return mysql.connector.connect(
# host="mysqldb",
# host="mih-db",
# user=dbUser,
# passwd=dbPass,
# database="mzansi_calendar"
@@ -69,7 +69,7 @@ def dbMzansiCalendarConnect():
def dbAllConnect():
return create_engine(base_connect_url, echo=False, pool_recycle=3600)
# return mysql.connector.connect(
# host="mysqldb",
# host="mih-db",
# user=dbUser,
# passwd=dbPass,
# )

View File

@@ -9,4 +9,5 @@ watchfiles
python-multipart
python-dotenv
xlrd
supertokens-python==0.29.2
supertokens-python
sniffio

View File

@@ -22,6 +22,7 @@ from supertokens_python.recipe.session import SessionContainer
from fastapi import Depends
import Minio_Storage.minioConnection
from datetime import timedelta
router = APIRouter()
@@ -110,13 +111,21 @@ class claimStatementUploud(BaseModel):
@router.get("/minio/pull/file/{env}/{app_id}/{folder}/{file_name}", tags=["Minio"])
async def pull_File_from_user(app_id: str, folder: str, file_name: str, env: str): #, session: SessionContainer = Depends(verify_session())
path = app_id + "/" + folder + "/" + file_name
print(path)
try:
# print(f"env: {env}")
# uploudFile(app_id, file.filename, extension[1], content)
client = Minio_Storage.minioConnection.minioConnect(env)
miniourl = client.presigned_get_object("mih", path)
# buckets = client.list_buckets()
# print("Connected to MinIO successfully!")
# print("Available buckets:", [bucket.name for bucket in buckets])
miniourl = client.presigned_get_object(
bucket_name="mih",
object_name=path,
expires=timedelta(minutes=60)
)
print("Generated presigned URL:", miniourl)
# if(env == "Dev"):
# miniourl.replace("minio", "localhost")
# temp = minioResponse.data#.encode('utf-8').strip()
@@ -125,7 +134,7 @@ async def pull_File_from_user(app_id: str, folder: str, file_name: str, env: str
# temp = temp.decode('utf-8')
#print(miniourl)
except Exception as error:
raise HTTPException(status_code=404, detail=miniourl)
raise HTTPException(status_code=404, detail=f"MinIO connection failed: {str(error)}")
# return {"message": error}
if(env == "Dev"):
return {
@@ -144,7 +153,7 @@ async def upload_File_to_user(file: UploadFile = File(...), app_id: str= Form(..
try:
uploudFile(app_id, env, folder, file.filename.replace(" ", "-"), extension[1], content)
except Exception as error:
raise HTTPException(status_code=404, detail="Failed to Uploud Record")
raise HTTPException(status_code=404, detail=str(error))
return {"message": f"Successfully Uploaded {file.filename}"}
# return {
@@ -161,7 +170,10 @@ async def delete_File_of_user(requestItem: minioDeleteRequest, session: SessionC
# uploudFile(app_id, file.filename, extension[1], content)
client = Minio_Storage.minioConnection.minioConnect(requestItem.env)
minioError = client.remove_object("mih", path)
minioError = client.remove_object(
bucket_name="mih",
object_name=path
)
except Exception as error:
raise HTTPException(status_code=404, detail=minioError)
# return {"message": error}
@@ -191,15 +203,16 @@ async def upload_perscription_to_user(requestItem: claimStatementUploud, session
def uploudFile(app_id, env, folder, fileName, extension, content):
client = Minio_Storage.minioConnection.minioConnect(env)
found = client.bucket_exists("mih")
found = client.bucket_exists(bucket_name="mih")
if not found:
client.make_bucket("mih")
client.make_bucket(bucket_name="mih")
else:
print("Bucket already exists")
fname = app_id + "/" + folder + "/" + fileName
client.put_object("mih",
fname,
content,
client.put_object(
bucket_name="mih",
object_name=fname,
data=content,
length=-1,
part_size=10*1024*1024,
content_type=f"application/{extension}")
@@ -208,9 +221,9 @@ def uploudMedCert(requestItem: medCertUploud):
client = Minio_Storage.minioConnection.minioConnect(requestItem.env)
generateMedCertPDF(requestItem)
today = datetime.today().strftime('%Y-%m-%d')
found = client.bucket_exists("mih")
found = client.bucket_exists(bucket_name="mih")
if not found:
client.make_bucket("mih")
client.make_bucket(bucket_name="mih")
else:
print("Bucket already exists")
fileName = f"{requestItem.app_id}/patient_files/{requestItem.fileName}"
@@ -285,9 +298,9 @@ def uploudPerscription(requestItem: perscriptionList):
client = Minio_Storage.minioConnection.minioConnect(requestItem.env)
generatePerscriptionPDF(requestItem)
today = datetime.today().strftime('%Y-%m-%d')
found = client.bucket_exists("mih")
found = client.bucket_exists(bucket_name="mih")
if not found:
client.make_bucket("mih")
client.make_bucket(bucket_name="mih")
else:
print("Bucket already exists")
fileName = f"{requestItem.app_id}/patient_files/{requestItem.fileName}"
@@ -391,9 +404,9 @@ def uploudClaimStatement(requestItem: claimStatementUploud):
generateClaimStatementPDF(requestItem)
today = datetime.today().strftime('%Y-%m-%d')
found = client.bucket_exists("mih")
found = client.bucket_exists(bucket_name="mih")
if not found:
client.make_bucket("mih")
client.make_bucket(bucket_name="mih")
else:
print("Bucket already exists")
fileName = f"{requestItem.patient_app_id}/claims-statements/{requestItem.fileName}"

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