NEW: Add user and business count to about MIH

This commit is contained in:
2025-09-23 11:43:27 +02:00
parent 5548a23f69
commit ffcee3b7a7
5 changed files with 221 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
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_business_details_services.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';
@@ -11,7 +12,9 @@ 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:mzansi_innovation_hub/mih_services/mih_user_services.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:redacted/redacted.dart';
import 'package:share_plus/share_plus.dart';
class MihInfo extends StatefulWidget {
@@ -22,6 +25,8 @@ class MihInfo extends StatefulWidget {
}
class _MihInfoState extends State<MihInfo> {
late Future<int> _futureUserCount;
late Future<int> _futureBusinessCount;
final Uri _tiktokUrl =
Uri.parse('https://www.tiktok.com/@mzansi.innovation.hub');
final Uri _whatsappUrl =
@@ -144,7 +149,7 @@ class _MihInfoState extends State<MihInfo> {
textAlign: TextAlign.center,
style: const TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 15,
fontSize: 17,
),
),
],
@@ -178,7 +183,7 @@ class _MihInfoState extends State<MihInfo> {
textAlign: TextAlign.center,
style: const TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 15,
fontSize: 17,
),
),
],
@@ -506,6 +511,121 @@ class _MihInfoState extends State<MihInfo> {
);
}
Widget displayBusinessCount() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
FutureBuilder<int>(
future: _futureBusinessCount,
builder: (context, snapshot) {
bool isLoading = true;
String userCount = "⚠️";
if (snapshot.connectionState == ConnectionState.waiting) {
isLoading = true;
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasError) {
isLoading = false;
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
isLoading = false;
userCount = snapshot.data.toString();
} else {
isLoading = true;
}
return SizedBox(
child: Text(
userCount,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 23,
),
),
).redacted(
context: context,
redact: isLoading,
configuration: RedactedConfiguration(
defaultBorderRadius: BorderRadius.circular(5),
redactedColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
),
),
);
},
),
Text(
"Businesses",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.normal,
fontSize: 20,
),
),
],
);
}
Widget displayUserCount() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
FutureBuilder<int>(
future: _futureUserCount,
builder: (context, snapshot) {
bool isLoading = true;
String userCount = "⚠️";
if (snapshot.connectionState == ConnectionState.waiting) {
isLoading = true;
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasError) {
isLoading = false;
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
isLoading = false;
userCount = snapshot.data.toString();
} else {
isLoading = true;
}
return SizedBox(
child: Text(
userCount,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 23,
),
),
).redacted(
context: context,
redact: isLoading,
configuration: RedactedConfiguration(
defaultBorderRadius: BorderRadius.circular(5),
redactedColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
),
),
);
},
),
Text(
"Users",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.normal,
fontSize: 20,
),
),
],
);
}
@override
void initState() {
super.initState();
_futureUserCount = MihUserServices().fetchUserCount();
_futureBusinessCount = MihBusinessDetailsServices().fetchBusinessCount();
}
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
@@ -555,6 +675,30 @@ class _MihInfoState extends State<MihInfo> {
// const SizedBox(
// height: 10,
// ),
Text(
"The MIH Family",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
Wrap(
alignment: WrapAlignment.spaceEvenly,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 25,
runSpacing: 10,
children: [
displayUserCount(),
displayBusinessCount(),
],
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Divider(),
),
// const SizedBox(
// height: 10,
// ),
Wrap(
alignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,

View File

@@ -9,6 +9,21 @@ import '../mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:supertokens_flutter/http.dart' as http;
class MihBusinessDetailsServices {
Future<int> fetchBusinessCount() async {
var response = await http.get(
Uri.parse("${AppEnviroment.baseApiUrl}/business/count/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
);
if (response.statusCode == 200) {
var jsonBody = jsonDecode(response.body);
return jsonBody['count'];
} else {
return 0;
}
}
Future<List<String>> fetchAllBusinessTypes() async {
var response = await http.get(
Uri.parse("${AppEnviroment.baseApiUrl}/business/types/"),

View File

@@ -33,6 +33,21 @@ class MihUserServices {
}
}
Future<int> fetchUserCount() async {
var response = await http.get(
Uri.parse("${AppEnviroment.baseApiUrl}/users/count/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
);
if (response.statusCode == 200) {
var jsonBody = jsonDecode(response.body);
return jsonBody['count'];
} else {
return 0;
}
}
Future<void> createUser(
String email,
String app_id,

View File

@@ -6,6 +6,7 @@ import mih_database.mihDbConnections
from mih_database.mihDbObjects import User, Business, BusinessRating, BookmarkedBusiness
from sqlalchemy import desc, or_
from sqlalchemy.orm import Session
from sqlalchemy.sql import func
#SuperToken Auth from front end
from supertokens_python.recipe.session.framework.fastapi import verify_session
from supertokens_python.recipe.session import SessionContainer
@@ -62,6 +63,24 @@ class businessUpdateRequestV2(BaseModel):
rating: str
mission_vision: str
@router.get("/business/count/", tags=["MIH Business"])
async def read_business_by_business_id(): #, session: SessionContainer = Depends(verify_session())
dbEngine = mih_database.mihDbConnections.dbAllConnect()
dbSession = Session(dbEngine)
try:
queryResults = dbSession.query(func.count(Business.business_id)).scalar()
response_data = {"count": queryResults}
return response_data
except Exception as e:
print(f"An error occurred during the ORM query: {e}")
if dbSession.is_active:
dbSession.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve records due to an internal server error."
)
finally:
dbSession.close()
# Get List of all files
@router.get("/business/types/", tags=["MIH Business"])

View File

@@ -1,7 +1,12 @@
from fastapi import APIRouter, HTTPException
from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel
#from ..mih_database import dbConnection
import mih_database
import mih_database.mihDbConnections
from mih_database.mihDbObjects import User, Business, BusinessRating, BookmarkedBusiness
from sqlalchemy import desc, or_
from sqlalchemy.orm import Session
from sqlalchemy.sql import func
#SuperToken Auth from front end
from supertokens_python.recipe.session.framework.fastapi import verify_session
from supertokens_python.recipe.session import SessionContainer
@@ -67,6 +72,26 @@ class userDeleteRequest(BaseModel):
# return items[0]
@router.get("/users/count/", tags=["MIH Users"])
async def read_users_by_app_id(): #, session: SessionContainer = Depends(verify_session())
dbEngine = mih_database.mihDbConnections.dbAllConnect()
dbSession = Session(dbEngine)
try:
queryResults = dbSession.query(func.count(User.app_id)).scalar()
response_data = {"count": queryResults}
return response_data
except Exception as e:
print(f"An error occurred during the ORM query: {e}")
if dbSession.is_active:
dbSession.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve records due to an internal server error."
)
finally:
dbSession.close()
# Get List of all files
@router.get("/users/search/{search}", tags=["MIH Users"])
async def read_all_users(search: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())