Merge pull request #240 from yaso-meth/NEW--Bookmark-Business
NEW--Bookmark-Business
@@ -71,8 +71,6 @@ class _MzansiInnovationHubState extends State<MzansiInnovationHub> {
|
|||||||
double width = MediaQuery.sizeOf(context).width;
|
double width = MediaQuery.sizeOf(context).width;
|
||||||
theme.setScreenType(width);
|
theme.setScreenType(width);
|
||||||
precacheImage(theme.loadingImage(), context);
|
precacheImage(theme.loadingImage(), context);
|
||||||
precacheImage(theme.logoImage(), context);
|
|
||||||
precacheImage(theme.logoFrame(), context);
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: getTitle(),
|
title: getTitle(),
|
||||||
themeMode: ThemeMode.dark,
|
themeMode: ThemeMode.dark,
|
||||||
|
|||||||
@@ -229,13 +229,15 @@ class MzansiAiArguments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MzansiDirectoryArguments {
|
class MzansiDirectoryArguments {
|
||||||
final String? startUpSearch;
|
|
||||||
final bool personalSearch;
|
final bool personalSearch;
|
||||||
|
final int? packageIndex;
|
||||||
|
final String? startSearchText;
|
||||||
|
|
||||||
MzansiDirectoryArguments(
|
MzansiDirectoryArguments({
|
||||||
this.startUpSearch,
|
required this.personalSearch,
|
||||||
this.personalSearch,
|
this.packageIndex,
|
||||||
);
|
required this.startSearchText,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestArguments {
|
class TestArguments {
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
class BookmarkedBusiness {
|
||||||
|
final int idbookmarked_businesses;
|
||||||
|
final String app_id;
|
||||||
|
final String business_id;
|
||||||
|
final String business_name;
|
||||||
|
final String created_date;
|
||||||
|
|
||||||
|
BookmarkedBusiness({
|
||||||
|
required this.idbookmarked_businesses,
|
||||||
|
required this.app_id,
|
||||||
|
required this.business_id,
|
||||||
|
required this.business_name,
|
||||||
|
required this.created_date,
|
||||||
|
});
|
||||||
|
factory BookmarkedBusiness.fromJson(Map<String, dynamic> json) {
|
||||||
|
return switch (json) {
|
||||||
|
{
|
||||||
|
"idbookmarked_businesses": int idbookmarked_businesses,
|
||||||
|
"app_id": String app_id,
|
||||||
|
"business_id": String business_id,
|
||||||
|
"business_name": String business_name,
|
||||||
|
"created_date": String created_date,
|
||||||
|
} =>
|
||||||
|
BookmarkedBusiness(
|
||||||
|
idbookmarked_businesses: idbookmarked_businesses,
|
||||||
|
app_id: app_id,
|
||||||
|
business_id: business_id,
|
||||||
|
business_name: business_name,
|
||||||
|
created_date: created_date,
|
||||||
|
),
|
||||||
|
_ => throw const FormatException(
|
||||||
|
'Failed to load bookmarked business objects'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,8 @@ class BusinessReview {
|
|||||||
date_time: date_time,
|
date_time: date_time,
|
||||||
reviewer: reviewer,
|
reviewer: reviewer,
|
||||||
),
|
),
|
||||||
_ => throw const FormatException('Failed to load loyalty card objects'),
|
_ =>
|
||||||
|
throw const FormatException('Failed to load Business Review objects'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
|
|||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart';
|
||||||
// import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart';
|
// import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
|
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
|
||||||
@@ -30,6 +31,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
|
|||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_field.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_field.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart';
|
||||||
|
import 'package:redacted/redacted.dart';
|
||||||
|
|
||||||
class PackageToolOne extends StatefulWidget {
|
class PackageToolOne extends StatefulWidget {
|
||||||
final AppUser user;
|
final AppUser user;
|
||||||
@@ -291,16 +293,34 @@ class _PackageToolOneState extends State<PackageToolOne> {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
// MihBusinessCard(
|
Text("This text should be redacted").redacted(
|
||||||
// businessid: "123456",
|
context: context,
|
||||||
// businessName: "Mzansi Innovation Hub",
|
redact: true,
|
||||||
// cellNumber: "0788300006",
|
),
|
||||||
// email: "yasien.meth@mzansi-innovation-hub.co.za",
|
MihBusinessCard(
|
||||||
// gpsLocation: "-26.1853611, 28.134664",
|
business: Business(
|
||||||
// website:
|
"business_id",
|
||||||
// "https://app.mzansi-innovation-hub.co.za/privacy.html",
|
"Name",
|
||||||
// rating: 3.25,
|
"type",
|
||||||
// ),
|
"registration_no",
|
||||||
|
"logo_name",
|
||||||
|
"logo_path",
|
||||||
|
"contact_no",
|
||||||
|
"bus_email",
|
||||||
|
"app_id",
|
||||||
|
"gps_location",
|
||||||
|
"practice_no",
|
||||||
|
"vat_no",
|
||||||
|
"website",
|
||||||
|
"rating",
|
||||||
|
"mission_vision",
|
||||||
|
),
|
||||||
|
startUpSearch: '',
|
||||||
|
width: 300,
|
||||||
|
).redacted(
|
||||||
|
context: context,
|
||||||
|
redact: true,
|
||||||
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Divider(
|
Divider(
|
||||||
color:
|
color:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 54 KiB |
@@ -44,7 +44,7 @@ class _MihPackageState extends State<MihPackage>
|
|||||||
int nextPage =
|
int nextPage =
|
||||||
currentPage + 1 < widget.appBody.length ? currentPage + 1 : currentPage;
|
currentPage + 1 < widget.appBody.length ? currentPage + 1 : currentPage;
|
||||||
if (nextPage != currentPage) {
|
if (nextPage != currentPage) {
|
||||||
await Future.delayed(const Duration(milliseconds: 300));
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
await _pageController.animateTo(
|
await _pageController.animateTo(
|
||||||
currentOffset + peakOffset,
|
currentOffset + peakOffset,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
@@ -86,10 +86,24 @@ class _MihPackageState extends State<MihPackage>
|
|||||||
vsync: this,
|
vsync: this,
|
||||||
duration: const Duration(milliseconds: 400),
|
duration: const Duration(milliseconds: 400),
|
||||||
);
|
);
|
||||||
|
// if (!MzansiInnovationHub.of(context)!.theme.kIsWeb) {
|
||||||
|
// // Trigger the peak animation on start (or call this elsewhere)
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// _peakAnimation();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
if (!MzansiInnovationHub.of(context)!.theme.kIsWeb) {
|
if (!MzansiInnovationHub.of(context)!.theme.kIsWeb) {
|
||||||
// Trigger the peak animation on start (or call this elsewhere)
|
// Trigger the peak animation only AFTER the route transition is complete
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_peakAnimation();
|
final ModalRoute? currentRoute = ModalRoute.of(context);
|
||||||
|
if (currentRoute != null) {
|
||||||
|
currentRoute.animation?.addStatusListener((status) {
|
||||||
|
if (status == AnimationStatus.completed && mounted) {
|
||||||
|
// Ensure the widget is still mounted and the animation is completed
|
||||||
|
_peakAnimation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ class _MihSearchBarState extends State<MihSearchBar> {
|
|||||||
color: widget.fillColor,
|
color: widget.fillColor,
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
// Keep AnimatedContainer for width/height transitions
|
// Keep AnimatedContainer for width/height transitions
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
width: widget.width,
|
width: widget.width,
|
||||||
height: widget.height ?? 50,
|
height: widget.height ?? 50,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
@@ -123,6 +124,7 @@ class _MihSearchBarState extends State<MihSearchBar> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
textAlignVertical: TextAlignVertical.center,
|
||||||
controller: widget.controller, // Assign the controller
|
controller: widget.controller, // Assign the controller
|
||||||
focusNode: widget.searchFocusNode,
|
focusNode: widget.searchFocusNode,
|
||||||
autocorrect: true,
|
autocorrect: true,
|
||||||
@@ -134,17 +136,20 @@ class _MihSearchBarState extends State<MihSearchBar> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: widget.hintColor,
|
color: widget.hintColor,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
cursorColor: widget.hintColor,
|
cursorColor: widget.hintColor,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
isDense: true,
|
||||||
hintText: widget.hintText,
|
hintText: widget.hintText,
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
color: widget.hintColor,
|
color: widget.hintColor,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 12.0),
|
const EdgeInsets.symmetric(horizontal: 10.0, vertical: 15.0),
|
||||||
prefixIcon: GestureDetector(
|
prefixIcon: GestureDetector(
|
||||||
onTap: widget.onPrefixIconTap,
|
onTap: widget.onPrefixIconTap,
|
||||||
child: getPrefixIcon(),
|
child: getPrefixIcon(),
|
||||||
@@ -152,12 +157,15 @@ class _MihSearchBarState extends State<MihSearchBar> {
|
|||||||
suffixIcon: Row(
|
suffixIcon: Row(
|
||||||
// Use a Row for multiple suffix icons
|
// Use a Row for multiple suffix icons
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
// Optional suffix tools
|
// Optional suffix tools
|
||||||
if (widget.suffixTools != null) ...widget.suffixTools!,
|
if (widget.suffixTools != null) ...widget.suffixTools!,
|
||||||
// Clear Icon (conditionally visible)
|
// Clear Icon (conditionally visible)
|
||||||
if (_showClearIcon) // Only show if input is not empty
|
if (_showClearIcon) // Only show if input is not empty
|
||||||
IconButton(
|
IconButton(
|
||||||
|
iconSize: 35,
|
||||||
icon: Icon(Icons.clear,
|
icon: Icon(Icons.clear,
|
||||||
color: widget.hintColor), // Clear icon
|
color: widget.hintColor), // Clear icon
|
||||||
onPressed: widget.onClearIconTap ??
|
onPressed: widget.onClearIconTap ??
|
||||||
|
|||||||
@@ -163,54 +163,6 @@ class MihTheme {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetImage logoFrame() {
|
|
||||||
if (mode == "Dark") {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/frame_dark.png',
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/frame_light.png',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AssetImage altLogoFrame() {
|
|
||||||
if (mode == "Light") {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/frame_dark.png',
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/frame_light.png',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AssetImage logoImage() {
|
|
||||||
if (mode == "Dark") {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/logo_dark.png',
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/logo_light.png',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AssetImage altLogoImage() {
|
|
||||||
if (mode == "Light") {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/logo_dark.png',
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const AssetImage(
|
|
||||||
'lib/mih_components/mih_package_components/assets/images/logo_light.png',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AssetImage loadingImage() {
|
AssetImage loadingImage() {
|
||||||
if (mode == "Dark") {
|
if (mode == "Dark") {
|
||||||
loading = const AssetImage(
|
loading = const AssetImage(
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ class _MihInfoState extends State<MihInfo> {
|
|||||||
bio += "(University of the Western Cape)\n";
|
bio += "(University of the Western Cape)\n";
|
||||||
bio +=
|
bio +=
|
||||||
"6 Year of banking experience with one of the big 5 banks of South Africa.";
|
"6 Year of banking experience with one of the big 5 banks of South Africa.";
|
||||||
ImageProvider logoFrame =
|
|
||||||
MzansiInnovationHub.of(context)!.theme.altLogoFrame();
|
|
||||||
return Wrap(
|
return Wrap(
|
||||||
alignment: WrapAlignment.center,
|
alignment: WrapAlignment.center,
|
||||||
crossAxisAlignment: WrapCrossAlignment.center,
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
@@ -61,18 +59,22 @@ class _MihInfoState extends State<MihInfo> {
|
|||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
fit: StackFit.loose,
|
fit: StackFit.loose,
|
||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
Padding(
|
||||||
backgroundColor:
|
padding: const EdgeInsets.only(left: 4.0),
|
||||||
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
child: CircleAvatar(
|
||||||
backgroundImage: const AssetImage(
|
backgroundColor:
|
||||||
"lib/mih_components/mih_package_components/assets/images/founder.jpg"),
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
//'https://media.licdn.com/dms/image/D4D03AQGd1-QhjtWWpA/profile-displayphoto-shrink_400_400/0/1671698053061?e=2147483647&v=beta&t=a3dJI5yxs5-KeXjj10LcNCFuC9IOfa8nNn3k_Qyr0CA'),
|
backgroundImage: const AssetImage(
|
||||||
radius: 75,
|
"lib/mih_components/mih_package_components/assets/images/founder.jpg"),
|
||||||
|
//'https://media.licdn.com/dms/image/D4D03AQGd1-QhjtWWpA/profile-displayphoto-shrink_400_400/0/1671698053061?e=2147483647&v=beta&t=a3dJI5yxs5-KeXjj10LcNCFuC9IOfa8nNn3k_Qyr0CA'),
|
||||||
|
radius: 75,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
MihIcons.mihRing,
|
||||||
|
size: 165,
|
||||||
|
color: MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
||||||
),
|
),
|
||||||
SizedBox(
|
|
||||||
width: 165,
|
|
||||||
child: Image(image: logoFrame),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -61,35 +61,6 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
|
|||||||
backgroundColor:
|
backgroundColor:
|
||||||
MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
||||||
),
|
),
|
||||||
// MIHProfilePicture(
|
|
||||||
// profilePictureFile: widget.propicFile,
|
|
||||||
// proPicController: proPicController,
|
|
||||||
// proPic: null,
|
|
||||||
// width: 60,
|
|
||||||
// radius: 27,
|
|
||||||
// drawerMode: true,
|
|
||||||
// editable: false,
|
|
||||||
// frameColor: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
|
||||||
// onChange: (newProPic) {},
|
|
||||||
// ),
|
|
||||||
|
|
||||||
// Stack(
|
|
||||||
// alignment: Alignment.center,
|
|
||||||
// fit: StackFit.loose,
|
|
||||||
// children: [
|
|
||||||
// CircleAvatar(
|
|
||||||
// backgroundColor:
|
|
||||||
// MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
|
||||||
// backgroundImage: widget.propicFile,
|
|
||||||
// //'https://media.licdn.com/dms/image/D4D03AQGd1-QhjtWWpA/profile-displayphoto-shrink_400_400/0/1671698053061?e=2147483647&v=beta&t=a3dJI5yxs5-KeXjj10LcNCFuC9IOfa8nNn3k_Qyr0CA'),
|
|
||||||
// radius: 27,
|
|
||||||
// ),
|
|
||||||
// SizedBox(
|
|
||||||
// width: 60,
|
|
||||||
// child: Image(image: logoFrame),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,24 +86,22 @@ class _MIHHomeLegacyState extends State<MIHHomeLegacy> {
|
|||||||
// );
|
// );
|
||||||
|
|
||||||
void setAppsNewPersonal(List<MIHTile> tileList) {
|
void setAppsNewPersonal(List<MIHTile> tileList) {
|
||||||
ImageProvider logo = MzansiInnovationHub.of(context)!.theme.logoImage();
|
|
||||||
|
|
||||||
if (widget.signedInUser.fname == "") {
|
if (widget.signedInUser.fname == "") {
|
||||||
tileList.add(MIHTile(
|
// tileList.add(MIHTile(
|
||||||
videoID: "jFV3NN65DtQ",
|
// videoID: "jFV3NN65DtQ",
|
||||||
onTap: () {
|
// onTap: () {
|
||||||
Navigator.of(context).pushNamed('/mzansi-profile',
|
// Navigator.of(context).pushNamed('/mzansi-profile',
|
||||||
arguments: AppProfileUpdateArguments(
|
// arguments: AppProfileUpdateArguments(
|
||||||
widget.signedInUser, widget.propicFile));
|
// widget.signedInUser, widget.propicFile));
|
||||||
},
|
// },
|
||||||
tileName: "Setup Profie",
|
// tileName: "Setup Profie",
|
||||||
tileIcon: Padding(
|
// tileIcon: Padding(
|
||||||
padding: const EdgeInsets.all(15.0),
|
// padding: const EdgeInsets.all(15.0),
|
||||||
child: Image(image: logo),
|
// child: Image(image: logo),
|
||||||
),
|
// ),
|
||||||
p: getPrim(),
|
// p: getPrim(),
|
||||||
s: getSec(),
|
// s: getSec(),
|
||||||
));
|
// ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,27 +126,26 @@ class _MIHHomeLegacyState extends State<MIHHomeLegacy> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setAppsPersonal(List<MIHTile> tileList) {
|
void setAppsPersonal(List<MIHTile> tileList) {
|
||||||
ImageProvider logo = MzansiInnovationHub.of(context)!.theme.logoImage();
|
|
||||||
ImageProvider aiLogo = MzansiInnovationHub.of(context)!.theme.aiLogoImage();
|
ImageProvider aiLogo = MzansiInnovationHub.of(context)!.theme.aiLogoImage();
|
||||||
tileList.add(MIHTile(
|
// tileList.add(MIHTile(
|
||||||
videoID: "P2bM9eosJ_A",
|
// videoID: "P2bM9eosJ_A",
|
||||||
onTap: () {
|
// onTap: () {
|
||||||
Navigator.of(context).pushNamed(
|
// Navigator.of(context).pushNamed(
|
||||||
'/mzansi-profile',
|
// '/mzansi-profile',
|
||||||
arguments: AppProfileUpdateArguments(
|
// arguments: AppProfileUpdateArguments(
|
||||||
widget.signedInUser,
|
// widget.signedInUser,
|
||||||
widget.propicFile,
|
// widget.propicFile,
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
tileName: "Mzansi Profile",
|
// tileName: "Mzansi Profile",
|
||||||
tileIcon: Padding(
|
// tileIcon: Padding(
|
||||||
padding: const EdgeInsets.all(15.0),
|
// padding: const EdgeInsets.all(15.0),
|
||||||
child: Image(image: logo),
|
// child: Image(image: logo),
|
||||||
),
|
// ),
|
||||||
p: getPrim(),
|
// p: getPrim(),
|
||||||
s: getSec(),
|
// s: getSec(),
|
||||||
));
|
// ));
|
||||||
tileList.add(MIHTile(
|
tileList.add(MIHTile(
|
||||||
videoID: "6l8h0sjt08k",
|
videoID: "6l8h0sjt08k",
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart';
|
||||||
|
|
||||||
|
class BuildFavouriteBusinessesList extends StatefulWidget {
|
||||||
|
final List<Business?> favouriteBusinesses;
|
||||||
|
final String? myLocation;
|
||||||
|
const BuildFavouriteBusinessesList({
|
||||||
|
super.key,
|
||||||
|
required this.favouriteBusinesses,
|
||||||
|
required this.myLocation,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<BuildFavouriteBusinessesList> createState() =>
|
||||||
|
_BuildFavouriteBusinessesListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BuildFavouriteBusinessesListState
|
||||||
|
extends State<BuildFavouriteBusinessesList> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListView.separated(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemCount: widget.favouriteBusinesses.length,
|
||||||
|
separatorBuilder: (BuildContext context, index) {
|
||||||
|
return Divider(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final Business? business = widget.favouriteBusinesses[index];
|
||||||
|
|
||||||
|
if (business == null) {
|
||||||
|
return const SizedBox(); // Or a placeholder if a business couldn't be loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
return Material(
|
||||||
|
color: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
'/business-profile/view',
|
||||||
|
arguments: BusinessViewArguments(
|
||||||
|
business,
|
||||||
|
business.Name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
splashColor: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.secondaryColor()
|
||||||
|
.withOpacity(0.2),
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 25,
|
||||||
|
),
|
||||||
|
child: MihBusinessProfilePreview(
|
||||||
|
business: business, myLocation: widget.myLocation),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart';
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
|
||||||
|
|
||||||
class MzansiDirectory extends StatefulWidget {
|
class MzansiDirectory extends StatefulWidget {
|
||||||
final MzansiDirectoryArguments arguments;
|
final MzansiDirectoryArguments arguments;
|
||||||
@@ -18,9 +21,22 @@ class MzansiDirectory extends StatefulWidget {
|
|||||||
|
|
||||||
class _MzansiDirectoryState extends State<MzansiDirectory> {
|
class _MzansiDirectoryState extends State<MzansiDirectory> {
|
||||||
int _selcetedIndex = 0;
|
int _selcetedIndex = 0;
|
||||||
|
late Future<Position?> futurePosition =
|
||||||
|
MIHLocationAPI().getGPSPosition(context);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.arguments.packageIndex == null) {
|
||||||
|
_selcetedIndex = 0;
|
||||||
|
} else {
|
||||||
|
_selcetedIndex = widget.arguments.packageIndex!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
print('MzansiDirectory build method called!');
|
||||||
return MihPackage(
|
return MihPackage(
|
||||||
appActionButton: getAction(),
|
appActionButton: getAction(),
|
||||||
appTools: getTools(),
|
appTools: getTools(),
|
||||||
@@ -37,12 +53,41 @@ class _MzansiDirectoryState extends State<MzansiDirectory> {
|
|||||||
|
|
||||||
List<Widget> getToolBody() {
|
List<Widget> getToolBody() {
|
||||||
List<Widget> toolBodies = [
|
List<Widget> toolBodies = [
|
||||||
MihSearchMzansi(
|
FutureBuilder(
|
||||||
startUpSearch: widget.arguments.startUpSearch,
|
future: futurePosition,
|
||||||
personalSearch: widget.arguments.personalSearch,
|
builder: (context, asyncSnapshot) {
|
||||||
),
|
String myLocation = "";
|
||||||
|
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
myLocation = "Getting Your GPS Location Ready";
|
||||||
|
} else {
|
||||||
|
myLocation = asyncSnapshot.data
|
||||||
|
.toString()
|
||||||
|
.replaceAll("Latitude: ", "")
|
||||||
|
.replaceAll("Longitude: ", "");
|
||||||
|
}
|
||||||
|
return MihSearchMzansi(
|
||||||
|
personalSearch: widget.arguments.personalSearch,
|
||||||
|
myLocation: myLocation,
|
||||||
|
startSearchText: widget.arguments.startSearchText,
|
||||||
|
);
|
||||||
|
}),
|
||||||
// MihContacts(),
|
// MihContacts(),
|
||||||
// MihFavouriteBusinesses(),
|
FutureBuilder(
|
||||||
|
future: futurePosition,
|
||||||
|
builder: (context, asyncSnapshot) {
|
||||||
|
String myLocation = "";
|
||||||
|
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
myLocation = "Getting Your GPS Location Ready";
|
||||||
|
} else {
|
||||||
|
myLocation = asyncSnapshot.data
|
||||||
|
.toString()
|
||||||
|
.replaceAll("Latitude: ", "")
|
||||||
|
.replaceAll("Longitude: ", "");
|
||||||
|
}
|
||||||
|
return MihFavouriteBusinesses(
|
||||||
|
myLocation: myLocation,
|
||||||
|
);
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
return toolBodies;
|
return toolBodies;
|
||||||
}
|
}
|
||||||
@@ -70,11 +115,11 @@ class _MzansiDirectoryState extends State<MzansiDirectory> {
|
|||||||
// _selcetedIndex = 1;
|
// _selcetedIndex = 1;
|
||||||
// });
|
// });
|
||||||
// };
|
// };
|
||||||
// temp[const Icon(Icons.business_center)] = () {
|
temp[const Icon(Icons.business_center)] = () {
|
||||||
// setState(() {
|
setState(() {
|
||||||
// _selcetedIndex = 2;
|
_selcetedIndex = 1;
|
||||||
// });
|
});
|
||||||
// };
|
};
|
||||||
return MihPackageTools(
|
return MihPackageTools(
|
||||||
tools: temp,
|
tools: temp,
|
||||||
selcetedIndex: _selcetedIndex,
|
selcetedIndex: _selcetedIndex,
|
||||||
@@ -84,8 +129,8 @@ class _MzansiDirectoryState extends State<MzansiDirectory> {
|
|||||||
List<String> getToolTitle() {
|
List<String> getToolTitle() {
|
||||||
List<String> toolTitles = [
|
List<String> toolTitles = [
|
||||||
"Mzansi Search",
|
"Mzansi Search",
|
||||||
"Contacts",
|
|
||||||
"Favourite Businesses",
|
"Favourite Businesses",
|
||||||
|
"Contacts",
|
||||||
];
|
];
|
||||||
return toolTitles;
|
return toolTitles;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ class _MzansiDirectoryTileState extends State<MzansiDirectoryTile> {
|
|||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
'/mzansi-directory',
|
'/mzansi-directory',
|
||||||
arguments: MzansiDirectoryArguments(
|
arguments: MzansiDirectoryArguments(
|
||||||
null, // startUpSearch
|
personalSearch: true,
|
||||||
true, // personalSearch
|
startSearchText: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,24 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
|
||||||
|
import 'package:supertokens_flutter/supertokens.dart';
|
||||||
|
|
||||||
class MihFavouriteBusinesses extends StatefulWidget {
|
class MihFavouriteBusinesses extends StatefulWidget {
|
||||||
const MihFavouriteBusinesses({super.key});
|
final String? myLocation;
|
||||||
|
const MihFavouriteBusinesses({
|
||||||
|
super.key,
|
||||||
|
required this.myLocation,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MihFavouriteBusinesses> createState() => _MihFavouriteBusinessesState();
|
State<MihFavouriteBusinesses> createState() => _MihFavouriteBusinessesState();
|
||||||
@@ -15,6 +28,70 @@ class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
|
|||||||
final TextEditingController businessSearchController =
|
final TextEditingController businessSearchController =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
final FocusNode searchFocusNode = FocusNode();
|
final FocusNode searchFocusNode = FocusNode();
|
||||||
|
late Future<List<BookmarkedBusiness>> boookmarkedBusinessListFuture;
|
||||||
|
List<BookmarkedBusiness> listBookmarkedBusinesses = [];
|
||||||
|
final ValueNotifier<List<Business?>> searchBookmarkedBusinesses =
|
||||||
|
ValueNotifier([]);
|
||||||
|
late Future<Map<String, Business?>> businessDetailsMapFuture;
|
||||||
|
Map<String, Business?> _businessDetailsMap = {};
|
||||||
|
Timer? _debounce;
|
||||||
|
|
||||||
|
Future<Map<String, Business?>>
|
||||||
|
getAndMapAllBusinessDetailsForBookmarkedBusinesses() async {
|
||||||
|
String user_id = await SuperTokens.getUserId();
|
||||||
|
List<BookmarkedBusiness> bookmarked = await MihMzansiDirectoryServices()
|
||||||
|
.getAllUserBookmarkedBusiness(user_id);
|
||||||
|
listBookmarkedBusinesses = bookmarked;
|
||||||
|
Map<String, Business?> businessMap = {};
|
||||||
|
List<Future<Business?>> detailFutures = [];
|
||||||
|
for (var item in bookmarked) {
|
||||||
|
detailFutures.add(MihBusinessDetailsServices()
|
||||||
|
.getBusinessDetailsByBusinessId(item.business_id));
|
||||||
|
}
|
||||||
|
List<Business?> details = await Future.wait(detailFutures);
|
||||||
|
for (int i = 0; i < bookmarked.length; i++) {
|
||||||
|
businessMap[bookmarked[i].business_id] = details[i];
|
||||||
|
}
|
||||||
|
_businessDetailsMap = businessMap;
|
||||||
|
_filterAndSetBusinesses();
|
||||||
|
return businessMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _filterAndSetBusinesses() {
|
||||||
|
List<Business?> businessesToDisplay = [];
|
||||||
|
String query = businessSearchController.text.toLowerCase();
|
||||||
|
for (var bookmarked in listBookmarkedBusinesses) {
|
||||||
|
if (bookmarked.business_name.toLowerCase().contains(query)) {
|
||||||
|
if (_businessDetailsMap.containsKey(bookmarked.business_id)) {
|
||||||
|
businessesToDisplay.add(_businessDetailsMap[bookmarked.business_id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchBookmarkedBusinesses.value = businessesToDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
businessSearchController.dispose();
|
||||||
|
searchFocusNode.dispose();
|
||||||
|
searchBookmarkedBusinesses.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
businessDetailsMapFuture =
|
||||||
|
getAndMapAllBusinessDetailsForBookmarkedBusinesses();
|
||||||
|
businessSearchController.addListener(() {
|
||||||
|
if (_debounce?.isActive ?? false) {
|
||||||
|
_debounce!.cancel();
|
||||||
|
}
|
||||||
|
_debounce = Timer(const Duration(milliseconds: 200), () {
|
||||||
|
_filterAndSetBusinesses();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -44,6 +121,130 @@ class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
|
FutureBuilder<Map<String, Business?>>(
|
||||||
|
future: businessDetailsMapFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return Mihloadingcircle(
|
||||||
|
message: "Getting your favourites",
|
||||||
|
);
|
||||||
|
} else if (snapshot.connectionState == ConnectionState.done) {
|
||||||
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
|
// No need to re-filter here, _filterAndSetBusinesses is called in initState
|
||||||
|
// and by the text controller listener.
|
||||||
|
return ValueListenableBuilder<List<Business?>>(
|
||||||
|
valueListenable:
|
||||||
|
searchBookmarkedBusinesses, // Listen to changes in this
|
||||||
|
builder: (context, businesses, child) {
|
||||||
|
// Display message if no results after search
|
||||||
|
if (businesses.isEmpty &&
|
||||||
|
businessSearchController.text.isNotEmpty) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 50),
|
||||||
|
Icon(
|
||||||
|
Icons
|
||||||
|
.search_off_rounded, // A different icon for "no results"
|
||||||
|
size: 150,
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.secondaryColor(),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 500,
|
||||||
|
child: Text(
|
||||||
|
"No businesses found for '${businessSearchController.text}'", // Specific message for no search results
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else if (businesses.isEmpty) {
|
||||||
|
// Initial empty state
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 50),
|
||||||
|
Icon(
|
||||||
|
Icons.business_center_rounded,
|
||||||
|
size: 150,
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.secondaryColor(),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 500,
|
||||||
|
child: Text(
|
||||||
|
"No favourites yet, use Mzansi Search to find and bookmark businesses you like",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return BuildFavouriteBusinessesList(
|
||||||
|
favouriteBusinesses:
|
||||||
|
businesses, // Pass the filtered list from ValueNotifier
|
||||||
|
myLocation: widget.myLocation,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// This block handles the case where there are no bookmarked businesses initially
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 50),
|
||||||
|
Icon(
|
||||||
|
Icons.business_center_rounded,
|
||||||
|
size: 150,
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.secondaryColor(),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 500,
|
||||||
|
child: Text(
|
||||||
|
"No favourites yet, use Mzansi Search to find and bookmark businesses you like",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
"Error loading bookmarked businesses: ${snapshot.error}"), // Show specific error
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Fallback for unexpected states
|
||||||
|
return Center(
|
||||||
|
child: Text("An unknown error occurred."),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:geolocator/geolocator.dart';
|
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
|
||||||
@@ -10,17 +11,19 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
|
|||||||
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.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_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_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_business_details_services.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
|
|
||||||
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
|
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
|
||||||
|
|
||||||
class MihSearchMzansi extends StatefulWidget {
|
class MihSearchMzansi extends StatefulWidget {
|
||||||
final String? startUpSearch;
|
|
||||||
final bool personalSearch;
|
final bool personalSearch;
|
||||||
|
final String? myLocation;
|
||||||
|
final String? startSearchText;
|
||||||
const MihSearchMzansi({
|
const MihSearchMzansi({
|
||||||
super.key,
|
super.key,
|
||||||
required this.startUpSearch,
|
|
||||||
required this.personalSearch,
|
required this.personalSearch,
|
||||||
|
required this.myLocation,
|
||||||
|
required this.startSearchText,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -29,14 +32,62 @@ class MihSearchMzansi extends StatefulWidget {
|
|||||||
|
|
||||||
class _MihSearchMzansiState extends State<MihSearchMzansi> {
|
class _MihSearchMzansiState extends State<MihSearchMzansi> {
|
||||||
final TextEditingController mzansiSearchController = TextEditingController();
|
final TextEditingController mzansiSearchController = TextEditingController();
|
||||||
|
final TextEditingController businessTypeController = TextEditingController();
|
||||||
final FocusNode searchFocusNode = FocusNode();
|
final FocusNode searchFocusNode = FocusNode();
|
||||||
late bool userSearch;
|
late bool userSearch;
|
||||||
Future<List<AppUser>?> futureUserSearchResults = Future.value();
|
Future<List<AppUser>?> futureUserSearchResults = Future.value();
|
||||||
Future<List<Business>?> futureBusinessSearchResults = Future.value();
|
Future<List<Business>?> futureBusinessSearchResults = Future.value();
|
||||||
late Future<Position?> futurePosition =
|
|
||||||
MIHLocationAPI().getGPSPosition(context);
|
|
||||||
List<AppUser> userSearchResults = [];
|
List<AppUser> userSearchResults = [];
|
||||||
List<Business> businessSearchResults = [];
|
List<Business> businessSearchResults = [];
|
||||||
|
late Future<List<String>> availableBusinessTypes;
|
||||||
|
bool filterOn = false;
|
||||||
|
|
||||||
|
void swapPressed() {
|
||||||
|
setState(() {
|
||||||
|
userSearch = !userSearch;
|
||||||
|
if (filterOn) {
|
||||||
|
filterOn = !filterOn;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (businessTypeController.text.isNotEmpty) {
|
||||||
|
setState(() {
|
||||||
|
futureBusinessSearchResults = Future.value();
|
||||||
|
businessTypeController.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
searchPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearAll() {
|
||||||
|
setState(() {
|
||||||
|
futureUserSearchResults = Future.value();
|
||||||
|
futureBusinessSearchResults = Future.value();
|
||||||
|
mzansiSearchController.clear();
|
||||||
|
businessTypeController.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void searchPressed() {
|
||||||
|
setState(() {
|
||||||
|
// userSearch = !userSearch;
|
||||||
|
if (userSearch && mzansiSearchController.text.isNotEmpty) {
|
||||||
|
futureUserSearchResults =
|
||||||
|
MihUserServices().searchUsers(mzansiSearchController.text, context);
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
// mzansiSearchController.text.isNotEmpty &&
|
||||||
|
businessTypeController.text.isNotEmpty) {
|
||||||
|
futureBusinessSearchResults = MihBusinessDetailsServices()
|
||||||
|
.searchBusinesses(mzansiSearchController.text,
|
||||||
|
businessTypeController.text, context);
|
||||||
|
} else if (mzansiSearchController.text.isNotEmpty) {
|
||||||
|
futureBusinessSearchResults = MihBusinessDetailsServices()
|
||||||
|
.searchBusinesses(mzansiSearchController.text,
|
||||||
|
businessTypeController.text, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@@ -49,13 +100,13 @@ class _MihSearchMzansiState extends State<MihSearchMzansi> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
setState(() {
|
setState(() {
|
||||||
userSearch = widget.personalSearch;
|
userSearch = widget.personalSearch;
|
||||||
mzansiSearchController.text = widget.startUpSearch ?? "";
|
availableBusinessTypes =
|
||||||
if (userSearch) {
|
MihBusinessDetailsServices().fetchAllBusinessTypes();
|
||||||
futureUserSearchResults =
|
if (widget.startSearchText != null) {
|
||||||
MihUserServices().searchUsers(mzansiSearchController.text, context);
|
mzansiSearchController.text = widget.startSearchText!;
|
||||||
|
searchPressed();
|
||||||
} else {
|
} else {
|
||||||
futureBusinessSearchResults = MihBusinessDetailsServices()
|
mzansiSearchController.text = "";
|
||||||
.searchBusinesses(mzansiSearchController.text, context);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -76,76 +127,132 @@ class _MihSearchMzansiState extends State<MihSearchMzansi> {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||||
child: MihSearchBar(
|
child: Row(
|
||||||
controller: mzansiSearchController,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
hintText: "Search Mzansi",
|
children: [
|
||||||
prefixIcon: Icons.search,
|
Expanded(
|
||||||
prefixAltIcon: userSearch ? Icons.person : Icons.business,
|
child: MihSearchBar(
|
||||||
suffixTools: [
|
controller: mzansiSearchController,
|
||||||
IconButton(
|
hintText: "Search Mzansi",
|
||||||
|
prefixIcon: Icons.search,
|
||||||
|
prefixAltIcon: userSearch ? Icons.person : Icons.business,
|
||||||
|
suffixTools: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
swapPressed();
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.swap_horiz_rounded,
|
||||||
|
size: 35,
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.primaryColor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
fillColor:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
||||||
|
hintColor:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
onPrefixIconTap: () {
|
||||||
|
searchPressed();
|
||||||
|
},
|
||||||
|
onClearIconTap: () {
|
||||||
|
clearAll();
|
||||||
|
},
|
||||||
|
searchFocusNode: searchFocusNode,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: !userSearch,
|
||||||
|
child: const SizedBox(width: 10),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: !userSearch,
|
||||||
|
child: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
if (filterOn) {
|
||||||
|
clearAll();
|
||||||
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
// searchTypeVisibility = !searchTypeVisibility;
|
filterOn = !filterOn;
|
||||||
userSearch = !userSearch;
|
|
||||||
if (userSearch) {
|
|
||||||
futureUserSearchResults = MihUserServices()
|
|
||||||
.searchUsers(
|
|
||||||
mzansiSearchController.text, context);
|
|
||||||
} else {
|
|
||||||
futureBusinessSearchResults =
|
|
||||||
MihBusinessDetailsServices().searchBusinesses(
|
|
||||||
mzansiSearchController.text, context);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.swap_horiz_rounded,
|
!filterOn
|
||||||
|
? Icons.filter_list_rounded
|
||||||
|
: Icons.filter_list_off_rounded,
|
||||||
size: 35,
|
size: 35,
|
||||||
color:
|
color: MzansiInnovationHub.of(context)!
|
||||||
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
.theme
|
||||||
))
|
.secondaryColor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
fillColor:
|
|
||||||
MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
|
||||||
hintColor: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
|
||||||
onPrefixIconTap: () {
|
|
||||||
if (userSearch) {
|
|
||||||
setState(() {
|
|
||||||
futureUserSearchResults = MihUserServices()
|
|
||||||
.searchUsers(mzansiSearchController.text, context);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setState(() {
|
|
||||||
futureBusinessSearchResults = MihBusinessDetailsServices()
|
|
||||||
.searchBusinesses(mzansiSearchController.text, context);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClearIconTap: () {
|
|
||||||
setState(() {
|
|
||||||
futureUserSearchResults = Future.value();
|
|
||||||
futureBusinessSearchResults = Future.value();
|
|
||||||
mzansiSearchController.clear();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
searchFocusNode: searchFocusNode,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: futurePosition,
|
future: availableBusinessTypes,
|
||||||
builder: (context, asyncSnapshot) {
|
builder: (context, asyncSnapshot) {
|
||||||
String myLocation = "";
|
List<String> options = [];
|
||||||
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
|
if (asyncSnapshot.connectionState == ConnectionState.done) {
|
||||||
myLocation = "Getting Your GPS Location Ready";
|
options.addAll(asyncSnapshot.data!);
|
||||||
} else {
|
|
||||||
myLocation = asyncSnapshot.data
|
|
||||||
.toString()
|
|
||||||
.replaceAll("Latitude: ", "")
|
|
||||||
.replaceAll("Longitude: ", "");
|
|
||||||
}
|
}
|
||||||
return displaySearchResults(userSearch, myLocation);
|
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 Filter",
|
||||||
|
dropdownOptions: options,
|
||||||
|
requiredText: true,
|
||||||
|
editable: true,
|
||||||
|
enableSearch: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
MihButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (businessTypeController.text.isNotEmpty) {
|
||||||
|
searchPressed();
|
||||||
|
} else {
|
||||||
|
MihAlertServices().errorAlert(
|
||||||
|
"Business Type Not Selected",
|
||||||
|
"Please ensure you have selected a Business Type before seareching for Businesses of Mzansi",
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttonColor: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.successColor(),
|
||||||
|
elevation: 10,
|
||||||
|
child: Text(
|
||||||
|
"Search",
|
||||||
|
style: TextStyle(
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.primaryColor(),
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
displaySearchResults(userSearch, widget.myLocation ?? ""),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
|
||||||
|
import 'package:supertokens_flutter/supertokens.dart';
|
||||||
|
|
||||||
|
class MihAddBookmarkAlert extends StatefulWidget {
|
||||||
|
final Business business;
|
||||||
|
const MihAddBookmarkAlert({
|
||||||
|
super.key,
|
||||||
|
required this.business,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MihAddBookmarkAlert> createState() => _MihAddBookmarkAlertState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MihAddBookmarkAlertState extends State<MihAddBookmarkAlert> {
|
||||||
|
Future<void> addBookmark(String business_id) async {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return const Mihloadingcircle();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
String user_id = await SuperTokens.getUserId();
|
||||||
|
await MihMzansiDirectoryServices()
|
||||||
|
.addBookmarkedBusiness(user_id, business_id)
|
||||||
|
.then((statusCode) {
|
||||||
|
if (statusCode == 201) {
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
'/mzansi-directory',
|
||||||
|
ModalRoute.withName('/'),
|
||||||
|
arguments: MzansiDirectoryArguments(
|
||||||
|
personalSearch: false, // personalSearch
|
||||||
|
packageIndex: 1,
|
||||||
|
startSearchText: widget.business.Name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
MihAlertServices().successAlert(
|
||||||
|
"Successfully Bookmarked Business!",
|
||||||
|
"${widget.business.Name} has successfully been added to favourite businessess in the Mzansi Directory.",
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
MihAlertServices().errorAlert(
|
||||||
|
"Error Adding Bookmark",
|
||||||
|
"An error occured while add ${widget.business.Name} to you Mzansi Directory, Please try again later.",
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MihPackageAlert(
|
||||||
|
alertColour: MihColors.getSecondaryColor(context),
|
||||||
|
alertIcon: Icon(
|
||||||
|
Icons.warning_rounded,
|
||||||
|
size: 100,
|
||||||
|
color: MihColors.getSecondaryColor(context),
|
||||||
|
),
|
||||||
|
alertTitle: "Bookmark Business",
|
||||||
|
alertBody: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Are you sure you want to save ${widget.business.Name} to your Mzansi Directory?",
|
||||||
|
style: TextStyle(
|
||||||
|
color: MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
Wrap(
|
||||||
|
spacing: 10,
|
||||||
|
runSpacing: 10,
|
||||||
|
children: [
|
||||||
|
MihButton(
|
||||||
|
width: 300,
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
buttonColor:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.errorColor(),
|
||||||
|
child: Text(
|
||||||
|
"Cancel",
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
MihButton(
|
||||||
|
width: 300,
|
||||||
|
onPressed: () {
|
||||||
|
addBookmark(widget.business.business_id);
|
||||||
|
},
|
||||||
|
buttonColor:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.successColor(),
|
||||||
|
child: Text(
|
||||||
|
"Bookmark Business",
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,38 +1,26 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
|
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart';
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
|
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
|
||||||
|
import 'package:redacted/redacted.dart';
|
||||||
import 'package:supertokens_flutter/supertokens.dart';
|
import 'package:supertokens_flutter/supertokens.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class MihBusinessCard extends StatefulWidget {
|
class MihBusinessCard extends StatefulWidget {
|
||||||
final Business business;
|
final Business business;
|
||||||
final String? startUpSearch;
|
final String? startUpSearch;
|
||||||
// final String businessid;
|
|
||||||
// final String businessName;
|
|
||||||
// final String cellNumber;
|
|
||||||
// final String email;
|
|
||||||
// final String gpsLocation;
|
|
||||||
// final String? website;
|
|
||||||
// final double rating;
|
|
||||||
final double width;
|
final double width;
|
||||||
const MihBusinessCard({
|
const MihBusinessCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.business,
|
required this.business,
|
||||||
required this.startUpSearch,
|
required this.startUpSearch,
|
||||||
// required this.businessid,
|
|
||||||
// required this.businessName,
|
|
||||||
// required this.cellNumber,
|
|
||||||
// required this.email,
|
|
||||||
// required this.gpsLocation,
|
|
||||||
// required this.rating,
|
|
||||||
// this.website,
|
|
||||||
required this.width,
|
required this.width,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,6 +29,16 @@ class MihBusinessCard extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MihBusinessCardState extends State<MihBusinessCard> {
|
class _MihBusinessCardState extends State<MihBusinessCard> {
|
||||||
|
Future<BusinessReview?>? _businessReviewFuture;
|
||||||
|
Future<BookmarkedBusiness?>? _bookmarkedBusinessFuture;
|
||||||
|
|
||||||
|
RedactedConfiguration getRedactedConfiguration() {
|
||||||
|
return RedactedConfiguration(
|
||||||
|
// redactedColor: Colors.pink,
|
||||||
|
redactedColor: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _makePhoneCall(String phoneNumber) async {
|
Future<void> _makePhoneCall(String phoneNumber) async {
|
||||||
final Uri url = Uri(scheme: 'tel', path: phoneNumber);
|
final Uri url = Uri(scheme: 'tel', path: phoneNumber);
|
||||||
if (await canLaunchUrl(url)) {
|
if (await canLaunchUrl(url)) {
|
||||||
@@ -269,6 +267,7 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
String subLabel,
|
String subLabel,
|
||||||
IconData icon,
|
IconData icon,
|
||||||
Color? iconColor,
|
Color? iconColor,
|
||||||
|
bool redacted,
|
||||||
Function()? ontap,
|
Function()? ontap,
|
||||||
) {
|
) {
|
||||||
return Material(
|
return Material(
|
||||||
@@ -288,16 +287,25 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
|
width: 45,
|
||||||
|
height: 45,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: iconColor,
|
color: iconColor,
|
||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(15),
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: Icon(
|
child: FittedBox(
|
||||||
icon,
|
child: Icon(
|
||||||
size: 35,
|
icon,
|
||||||
color: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
// size: 35,
|
||||||
|
color:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
).redacted(
|
||||||
|
context: context,
|
||||||
|
redact: redacted,
|
||||||
|
configuration: getRedactedConfiguration(),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -316,6 +324,10 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
.primaryColor(),
|
.primaryColor(),
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
),
|
),
|
||||||
|
).redacted(
|
||||||
|
context: context,
|
||||||
|
redact: redacted,
|
||||||
|
configuration: getRedactedConfiguration(),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
subLabel,
|
subLabel,
|
||||||
@@ -326,6 +338,10 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
.theme
|
.theme
|
||||||
.primaryColor(),
|
.primaryColor(),
|
||||||
),
|
),
|
||||||
|
).redacted(
|
||||||
|
context: context,
|
||||||
|
redact: redacted,
|
||||||
|
configuration: getRedactedConfiguration(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -345,6 +361,27 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<BookmarkedBusiness?> getUserBookmark() async {
|
||||||
|
String user_id = await SuperTokens.getUserId();
|
||||||
|
return await MihMzansiDirectoryServices().getUserBookmarkOfBusiness(
|
||||||
|
user_id,
|
||||||
|
widget.business.business_id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValidGps(String coordinateString) {
|
||||||
|
final RegExp gpsRegex = RegExp(
|
||||||
|
r"^-?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*-?(1[0-7]\d(\.\d+)?|180(\.0+)?|\d{1,2}(\.\d+)?)$");
|
||||||
|
return gpsRegex.hasMatch(coordinateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_businessReviewFuture = getUserReview();
|
||||||
|
_bookmarkedBusinessFuture = getUserBookmark();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// double screenWidth = MediaQuery.of(context).size.width;
|
// double screenWidth = MediaQuery.of(context).size.width;
|
||||||
@@ -369,6 +406,7 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
"Give us a quick call.",
|
"Give us a quick call.",
|
||||||
Icons.phone,
|
Icons.phone,
|
||||||
MihColors.getGreenColor(context),
|
MihColors.getGreenColor(context),
|
||||||
|
false,
|
||||||
() {
|
() {
|
||||||
// print("Calling ${widget.cellNumber}");
|
// print("Calling ${widget.cellNumber}");
|
||||||
_makePhoneCall(widget.business.contact_no);
|
_makePhoneCall(widget.business.contact_no);
|
||||||
@@ -382,6 +420,7 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
"Send us an email.",
|
"Send us an email.",
|
||||||
Icons.email,
|
Icons.email,
|
||||||
MihColors.getPinkColor(context),
|
MihColors.getPinkColor(context),
|
||||||
|
false,
|
||||||
() {
|
() {
|
||||||
// print("Emailing ${widget.email}");
|
// print("Emailing ${widget.email}");
|
||||||
_launchEmail(
|
_launchEmail(
|
||||||
@@ -391,58 +430,182 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Divider(
|
Visibility(
|
||||||
color: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
visible: isValidGps(widget.business.gps_location),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Divider(
|
||||||
|
color:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
),
|
||||||
|
_buildContactInfo(
|
||||||
|
"Location",
|
||||||
|
"Come visit us.",
|
||||||
|
Icons.location_on,
|
||||||
|
MihColors.getOrangeColor(context),
|
||||||
|
false,
|
||||||
|
() {
|
||||||
|
final latitude = double.parse(
|
||||||
|
widget.business.gps_location.split(',')[0]);
|
||||||
|
final longitude = double.parse(
|
||||||
|
widget.business.gps_location.split(',')[1]);
|
||||||
|
_launchGoogleMapsWithUrl(
|
||||||
|
latitude: latitude,
|
||||||
|
longitude: longitude,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
_buildContactInfo(
|
Visibility(
|
||||||
"Location",
|
visible: widget.business.website.isNotEmpty &&
|
||||||
"Come visit us.",
|
widget.business.website != "",
|
||||||
Icons.location_on,
|
child: Column(
|
||||||
MihColors.getOrangeColor(context),
|
children: [
|
||||||
() {
|
Divider(
|
||||||
final latitude =
|
color:
|
||||||
double.parse(widget.business.gps_location.split(',')[0]);
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
final longitude =
|
),
|
||||||
double.parse(widget.business.gps_location.split(',')[1]);
|
_buildContactInfo(
|
||||||
_launchGoogleMapsWithUrl(
|
"Website",
|
||||||
latitude: latitude,
|
"Find out more about us.",
|
||||||
longitude: longitude,
|
Icons.vpn_lock,
|
||||||
);
|
MihColors.getRedColor(context),
|
||||||
|
false,
|
||||||
|
() {
|
||||||
|
_launchWebsite(widget.business.website);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: _businessReviewFuture,
|
||||||
|
builder: (context, asyncSnapshot) {
|
||||||
|
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
// return const SizedBox.shrink();
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||||
|
child: Divider(
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.primaryColor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child: _buildContactInfo(
|
||||||
|
"Loading Rating",
|
||||||
|
"Loading your rating.",
|
||||||
|
Icons.star_rate_rounded,
|
||||||
|
MihColors.getYellowColor(context),
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
).redacted(context: context, redact: true),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
BusinessReview? businessReview = asyncSnapshot.data;
|
||||||
|
String ratingDisplayTitle = "";
|
||||||
|
if (businessReview == null) {
|
||||||
|
ratingDisplayTitle = "Rate Us";
|
||||||
|
} else {
|
||||||
|
ratingDisplayTitle = "Update Rating";
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||||
|
child: Divider(
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.primaryColor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildContactInfo(
|
||||||
|
ratingDisplayTitle,
|
||||||
|
"Let us know how we are doing.",
|
||||||
|
Icons.star_rate_rounded,
|
||||||
|
MihColors.getYellowColor(context),
|
||||||
|
false,
|
||||||
|
() {
|
||||||
|
businessReviewRatingWindow(
|
||||||
|
businessReview, true, widget.width);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Visibility(
|
FutureBuilder(
|
||||||
visible: widget.business.website.isNotEmpty &&
|
future: _bookmarkedBusinessFuture,
|
||||||
widget.business.website != "",
|
builder: (context, asyncSnapshot) {
|
||||||
child: Divider(
|
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
|
||||||
color: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
// return const SizedBox.shrink();
|
||||||
),
|
return Column(
|
||||||
),
|
children: [
|
||||||
Visibility(
|
Padding(
|
||||||
visible: widget.business.website.isNotEmpty &&
|
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||||
widget.business.website != "",
|
child: Divider(
|
||||||
child: _buildContactInfo(
|
color: MzansiInnovationHub.of(context)!
|
||||||
"Website",
|
.theme
|
||||||
"Find out more about us.",
|
.primaryColor(),
|
||||||
Icons.vpn_lock,
|
),
|
||||||
MihColors.getRedColor(context),
|
),
|
||||||
() {
|
Container(
|
||||||
_launchWebsite(widget.business.website);
|
child: _buildContactInfo(
|
||||||
},
|
"Loading Bookmark",
|
||||||
),
|
"Loading your bookmark.",
|
||||||
),
|
Icons.bookmark_add_rounded,
|
||||||
Padding(
|
MihColors.getBluishPurpleColor(context),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
true,
|
||||||
child: Divider(
|
null,
|
||||||
color: MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
_buildContactInfo(
|
);
|
||||||
"Rate Us",
|
} else {
|
||||||
"Let us know how we are doing.",
|
BookmarkedBusiness? bookmarkBusiness = asyncSnapshot.data;
|
||||||
Icons.star_rate_rounded,
|
String bookmarkDisplayTitle = "";
|
||||||
MihColors.getYellowColor(context),
|
if (bookmarkBusiness == null) {
|
||||||
() {
|
bookmarkDisplayTitle = "Bookmark Us";
|
||||||
businessReviewRatingWindow(true, widget.width);
|
} else {
|
||||||
|
bookmarkDisplayTitle = "Remove Bookmark";
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||||
|
child: Divider(
|
||||||
|
color: MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.primaryColor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildContactInfo(
|
||||||
|
bookmarkDisplayTitle,
|
||||||
|
"Save us for later.",
|
||||||
|
bookmarkBusiness == null
|
||||||
|
? Icons.bookmark_add_rounded
|
||||||
|
: Icons.bookmark_remove_rounded,
|
||||||
|
MihColors.getBluishPurpleColor(context),
|
||||||
|
false,
|
||||||
|
() {
|
||||||
|
// _launchWebsite(widget.website);
|
||||||
|
if (bookmarkBusiness == null) {
|
||||||
|
showAddBookmarkAlert();
|
||||||
|
} else {
|
||||||
|
showDeleteBookmarkAlert(bookmarkBusiness);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// Padding(
|
// Padding(
|
||||||
@@ -455,7 +618,7 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
// "Bookmark",
|
// "Bookmark",
|
||||||
// "Save us for later.",
|
// "Save us for later.",
|
||||||
// Icons.bookmark_add_rounded,
|
// Icons.bookmark_add_rounded,
|
||||||
// MihColors.getBluishPurpleColor(context),
|
// MihColors.getBluishPurpleColor(context),
|
||||||
// () {
|
// () {
|
||||||
// // _launchWebsite(widget.website);
|
// // _launchWebsite(widget.website);
|
||||||
// print("Saving ${widget.business.Name} to Directory");
|
// print("Saving ${widget.business.Name} to Directory");
|
||||||
@@ -476,115 +639,34 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> businessReviewRatingWindow(
|
Future<void> businessReviewRatingWindow(
|
||||||
bool previouslyRated, double width) async {
|
BusinessReview? myReview, bool previouslyRated, double width) async {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => FutureBuilder(
|
builder: (context) => MihReviewBusinessWindow(
|
||||||
future: getUserReview(),
|
business: widget.business,
|
||||||
builder: (context, asyncSnapshot) {
|
businessReview: myReview,
|
||||||
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
|
screenWidth: width,
|
||||||
return const Mihloadingcircle(
|
readOnly: false,
|
||||||
message: "Checking for previous reviews...",
|
|
||||||
);
|
|
||||||
} else if (asyncSnapshot.connectionState == ConnectionState.done) {
|
|
||||||
return MihReviewBusinessWindow(
|
|
||||||
business: widget.business,
|
|
||||||
businessReview: asyncSnapshot.data,
|
|
||||||
screenWidth: width,
|
|
||||||
readOnly: false,
|
|
||||||
startUpSearch: widget.startUpSearch,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return MihPackageAlert(
|
|
||||||
alertColour: MzansiInnovationHub.of(context)!.theme.errorColor(),
|
|
||||||
alertIcon: Icon(
|
|
||||||
Icons.warning_rounded,
|
|
||||||
size: 100,
|
|
||||||
color: MzansiInnovationHub.of(context)!.theme.errorColor(),
|
|
||||||
),
|
|
||||||
alertTitle: "Error Pulling Data",
|
|
||||||
alertBody: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Please ensure you are connectede top the internet and you are running the latest version of MIH then try again.",
|
|
||||||
style: TextStyle(
|
|
||||||
color: MzansiInnovationHub.of(context)!
|
|
||||||
.theme
|
|
||||||
.secondaryColor(),
|
|
||||||
fontSize: 15,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showBookmarkAlert() {
|
void showAddBookmarkAlert() {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => MihPackageAlert(
|
builder: (context) => MihAddBookmarkAlert(
|
||||||
alertColour: MihColors.getSecondaryColor(context),
|
business: widget.business,
|
||||||
alertIcon: Icon(
|
|
||||||
Icons.warning_rounded,
|
|
||||||
size: 100,
|
|
||||||
color: MihColors.getSecondaryColor(context),
|
|
||||||
),
|
|
||||||
alertTitle: "Bookmark Business",
|
|
||||||
alertBody: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Are you sure you want to save ${widget.business.Name} to your Mzansi Directory?",
|
|
||||||
style: TextStyle(
|
|
||||||
color: MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
|
||||||
fontSize: 15,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 25),
|
|
||||||
Wrap(
|
|
||||||
spacing: 10,
|
|
||||||
runSpacing: 10,
|
|
||||||
children: [
|
|
||||||
MihButton(
|
|
||||||
width: 300,
|
|
||||||
onPressed: () async {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
buttonColor:
|
|
||||||
MzansiInnovationHub.of(context)!.theme.errorColor(),
|
|
||||||
child: Text(
|
|
||||||
"Cancel",
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
MihButton(
|
|
||||||
width: 300,
|
|
||||||
onPressed: () {},
|
|
||||||
buttonColor:
|
|
||||||
MzansiInnovationHub.of(context)!.theme.successColor(),
|
|
||||||
child: Text(
|
|
||||||
"Save Business",
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showDeleteBookmarkAlert(BookmarkedBusiness? bookmarkBusiness) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => MihDeleteBookmarkAlert(
|
||||||
|
business: widget.business,
|
||||||
|
bookmarkBusiness: bookmarkBusiness,
|
||||||
|
startUpSearch: widget.startUpSearch,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
|
||||||
|
|
||||||
|
class MihDeleteBookmarkAlert extends StatefulWidget {
|
||||||
|
final Business business;
|
||||||
|
final BookmarkedBusiness? bookmarkBusiness;
|
||||||
|
final String? startUpSearch;
|
||||||
|
const MihDeleteBookmarkAlert({
|
||||||
|
super.key,
|
||||||
|
required this.business,
|
||||||
|
required this.bookmarkBusiness,
|
||||||
|
required this.startUpSearch,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MihDeleteBookmarkAlert> createState() => _MihDeleteBookmarkAlertState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MihDeleteBookmarkAlertState extends State<MihDeleteBookmarkAlert> {
|
||||||
|
Future<void> deleteBookmark(int idbookmarked_businesses) async {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return const Mihloadingcircle();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await MihMzansiDirectoryServices()
|
||||||
|
.deleteBookmarkedBusiness(idbookmarked_businesses)
|
||||||
|
.then((statusCode) {
|
||||||
|
if (statusCode == 200) {
|
||||||
|
// Navigator.of(context).pop(); //Remove loading circle
|
||||||
|
// Navigator.of(context).pop(); //Remove window
|
||||||
|
// Navigator.of(context).pop(); //Remove profile
|
||||||
|
// Navigator.of(context).pop(); //Remove directory
|
||||||
|
// Navigator.of(context).pushNamed(
|
||||||
|
// '/mzansi-directory',
|
||||||
|
// arguments: MzansiDirectoryArguments(
|
||||||
|
// startUpSearch: widget.startUpSearch, // startUpSearch
|
||||||
|
// personalSearch: false, // personalSearch
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
'/mzansi-directory',
|
||||||
|
ModalRoute.withName('/'),
|
||||||
|
arguments: MzansiDirectoryArguments(
|
||||||
|
personalSearch: false, // personalSearch
|
||||||
|
packageIndex: 1,
|
||||||
|
startSearchText: widget.business.Name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
MihAlertServices().successAlert(
|
||||||
|
"Successfully Removed Bookmark!",
|
||||||
|
"${widget.business.Name} has successfully been removed your favourite businessess in the Mzansi Directory.",
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
//error messagek
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
MihAlertServices().errorAlert(
|
||||||
|
"Error Adding Bookmark",
|
||||||
|
"An error occured while add ${widget.business.Name} to you Mzansi Directory, Please try again later.",
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MihPackageAlert(
|
||||||
|
alertColour: MihColors.getSecondaryColor(context),
|
||||||
|
alertIcon: Icon(
|
||||||
|
Icons.warning_rounded,
|
||||||
|
size: 100,
|
||||||
|
color: MihColors.getSecondaryColor(context),
|
||||||
|
),
|
||||||
|
alertTitle: "Remove Bookmark",
|
||||||
|
alertBody: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Are you sure you want to remove ${widget.business.Name} from your Mzansi Directory?",
|
||||||
|
style: TextStyle(
|
||||||
|
color: MzansiInnovationHub.of(context)!.theme.secondaryColor(),
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
Wrap(
|
||||||
|
spacing: 10,
|
||||||
|
runSpacing: 10,
|
||||||
|
children: [
|
||||||
|
MihButton(
|
||||||
|
width: 300,
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
buttonColor:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.successColor(),
|
||||||
|
child: Text(
|
||||||
|
"Cancel",
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
MihButton(
|
||||||
|
width: 300,
|
||||||
|
onPressed: () {
|
||||||
|
// todo: remove bookmark
|
||||||
|
deleteBookmark(
|
||||||
|
widget.bookmarkBusiness!.idbookmarked_businesses);
|
||||||
|
},
|
||||||
|
buttonColor:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.errorColor(),
|
||||||
|
child: Text(
|
||||||
|
"Remove Business",
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
MzansiInnovationHub.of(context)!.theme.primaryColor(),
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,14 +23,12 @@ class MihReviewBusinessWindow extends StatefulWidget {
|
|||||||
final BusinessReview? businessReview;
|
final BusinessReview? businessReview;
|
||||||
final double screenWidth;
|
final double screenWidth;
|
||||||
final bool readOnly;
|
final bool readOnly;
|
||||||
final String? startUpSearch;
|
|
||||||
const MihReviewBusinessWindow({
|
const MihReviewBusinessWindow({
|
||||||
super.key,
|
super.key,
|
||||||
required this.business,
|
required this.business,
|
||||||
required this.businessReview,
|
required this.businessReview,
|
||||||
required this.screenWidth,
|
required this.screenWidth,
|
||||||
required this.readOnly,
|
required this.readOnly,
|
||||||
required this.startUpSearch,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -101,8 +99,8 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
|
|||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
'/mzansi-directory',
|
'/mzansi-directory',
|
||||||
arguments: MzansiDirectoryArguments(
|
arguments: MzansiDirectoryArguments(
|
||||||
widget.startUpSearch, // startUpSearch
|
personalSearch: false, // personalSearch
|
||||||
false, // personalSearch
|
startSearchText: widget.business.Name,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
MihAlertServices().successAlert(
|
MihAlertServices().successAlert(
|
||||||
@@ -191,8 +189,8 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
|
|||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
'/mzansi-directory',
|
'/mzansi-directory',
|
||||||
arguments: MzansiDirectoryArguments(
|
arguments: MzansiDirectoryArguments(
|
||||||
widget.startUpSearch, // startUpSearch
|
personalSearch: false, // personalSearch
|
||||||
false, // personalSearch
|
startSearchText: widget.business.Name,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
MihAlertServices().successAlert(
|
MihAlertServices().successAlert(
|
||||||
@@ -227,8 +225,8 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
|
|||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
'/mzansi-directory',
|
'/mzansi-directory',
|
||||||
arguments: MzansiDirectoryArguments(
|
arguments: MzansiDirectoryArguments(
|
||||||
widget.startUpSearch, // startUpSearch
|
personalSearch: false, // personalSearch
|
||||||
false, // personalSearch
|
startSearchText: widget.business.Name,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
MihAlertServices().successAlert(
|
MihAlertServices().successAlert(
|
||||||
@@ -386,7 +384,8 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
|
|||||||
emptyColor: MzansiInnovationHub.of(context)!
|
emptyColor: MzansiInnovationHub.of(context)!
|
||||||
.theme
|
.theme
|
||||||
.secondaryColor(),
|
.secondaryColor(),
|
||||||
halfFilledColor: MihColors.getYellowColor(context), isHalfAllowed: true,
|
halfFilledColor: MihColors.getYellowColor(context),
|
||||||
|
isHalfAllowed: true,
|
||||||
initialRating: widget.businessReview != null
|
initialRating: widget.businessReview != null
|
||||||
? double.parse(_reviewScoreController.text)
|
? double.parse(_reviewScoreController.text)
|
||||||
: 1,
|
: 1,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
|
||||||
@@ -98,6 +99,11 @@ class _MzansiBusinessProfileState extends State<MzansiBusinessProfile> {
|
|||||||
_selcetedIndex = 3;
|
_selcetedIndex = 3;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
temp[const Icon(Icons.star_rate_rounded)] = () {
|
||||||
|
setState(() {
|
||||||
|
_selcetedIndex = 4;
|
||||||
|
});
|
||||||
|
};
|
||||||
return MihPackageTools(
|
return MihPackageTools(
|
||||||
tools: temp,
|
tools: temp,
|
||||||
selcetedIndex: _selcetedIndex,
|
selcetedIndex: _selcetedIndex,
|
||||||
@@ -149,6 +155,7 @@ class _MzansiBusinessProfileState extends State<MzansiBusinessProfile> {
|
|||||||
// MihBusinessProfile(arguments: widget.arguments),
|
// MihBusinessProfile(arguments: widget.arguments),
|
||||||
MihMyBusinessTeam(arguments: widget.arguments),
|
MihMyBusinessTeam(arguments: widget.arguments),
|
||||||
MihBusinessUserSearch(arguments: widget.arguments),
|
MihBusinessUserSearch(arguments: widget.arguments),
|
||||||
|
MihBusinessReviews(business: widget.arguments.business!),
|
||||||
];
|
];
|
||||||
return toolBodies;
|
return toolBodies;
|
||||||
}
|
}
|
||||||
@@ -159,6 +166,7 @@ class _MzansiBusinessProfileState extends State<MzansiBusinessProfile> {
|
|||||||
"User",
|
"User",
|
||||||
"Team",
|
"Team",
|
||||||
"Add Member",
|
"Add Member",
|
||||||
|
"Reviews",
|
||||||
];
|
];
|
||||||
return toolTitles;
|
return toolTitles;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ class _MihBusinessReviewsState extends State<MihBusinessReviews> {
|
|||||||
businessReview: businessReview,
|
businessReview: businessReview,
|
||||||
screenWidth: width,
|
screenWidth: width,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
startUpSearch: null,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -59,6 +58,7 @@ class _MihBusinessReviewsState extends State<MihBusinessReviews> {
|
|||||||
} else if (asyncSnapshot.connectionState == ConnectionState.done &&
|
} else if (asyncSnapshot.connectionState == ConnectionState.done &&
|
||||||
asyncSnapshot.hasData) {
|
asyncSnapshot.hasData) {
|
||||||
List<BusinessReview> reviews = asyncSnapshot.data!;
|
List<BusinessReview> reviews = asyncSnapshot.data!;
|
||||||
|
print("Reviews: ${reviews.length}");
|
||||||
if (reviews.isEmpty) {
|
if (reviews.isEmpty) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -133,11 +133,16 @@ class _MihBusinessReviewsState extends State<MihBusinessReviews> {
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Visibility(
|
||||||
"${reviews[index].rating_description.substring(0, reviews[index].rating_description.length >= descriptionDisplayCOunt ? descriptionDisplayCOunt : reviews[index].rating_description.length - 1)}${reviews[index].rating_description.length >= descriptionDisplayCOunt ? "..." : ""}",
|
visible: reviews[index].rating_description.isNotEmpty,
|
||||||
style: TextStyle(
|
child: Text(
|
||||||
fontSize: 18,
|
reviews[index].rating_description.isEmpty
|
||||||
fontWeight: FontWeight.normal,
|
? ""
|
||||||
|
: "${reviews[index].rating_description.substring(0, reviews[index].rating_description.length >= descriptionDisplayCOunt ? descriptionDisplayCOunt : reviews[index].rating_description.length - 1)}${reviews[index].rating_description.length >= descriptionDisplayCOunt ? "..." : ""}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@@ -150,6 +150,9 @@ class _MihCardDisplayState extends State<MihCardDisplay> {
|
|||||||
case "fresmart":
|
case "fresmart":
|
||||||
return Image.asset(
|
return Image.asset(
|
||||||
'lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/fresmart-min.png');
|
'lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/fresmart-min.png');
|
||||||
|
case "total energies":
|
||||||
|
return Image.asset(
|
||||||
|
'lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/total_energies-min.png');
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ class _MihCardsState extends State<MihCards> {
|
|||||||
"Spar",
|
"Spar",
|
||||||
"Spur",
|
"Spur",
|
||||||
"TFG Group",
|
"TFG Group",
|
||||||
|
"Total Energies",
|
||||||
"Toys R Us",
|
"Toys R Us",
|
||||||
"Woermann Brock",
|
"Woermann Brock",
|
||||||
"Woolworths"
|
"Woolworths"
|
||||||
@@ -367,7 +368,7 @@ class _MihCardsState extends State<MihCards> {
|
|||||||
builder: (BuildContext context,
|
builder: (BuildContext context,
|
||||||
List<MIHLoyaltyCard> value, Widget? child) {
|
List<MIHLoyaltyCard> value, Widget? child) {
|
||||||
return BuildLoyaltyCardList(
|
return BuildLoyaltyCardList(
|
||||||
cardList: searchShopName.value,
|
cardList: value,
|
||||||
signedInUser: widget.signedInUser,
|
signedInUser: widget.signedInUser,
|
||||||
navIndex: 0,
|
navIndex: 0,
|
||||||
bannerAd: _bannerAd,
|
bannerAd: _bannerAd,
|
||||||
|
|||||||
@@ -9,12 +9,42 @@ import '../mih_components/mih_pop_up_messages/mih_error_message.dart';
|
|||||||
import 'package:supertokens_flutter/http.dart' as http;
|
import 'package:supertokens_flutter/http.dart' as http;
|
||||||
|
|
||||||
class MihBusinessDetailsServices {
|
class MihBusinessDetailsServices {
|
||||||
|
Future<List<String>> fetchAllBusinessTypes() async {
|
||||||
|
var response = await http.get(
|
||||||
|
Uri.parse("${AppEnviroment.baseApiUrl}/business/types/"),
|
||||||
|
headers: <String, String>{
|
||||||
|
"Content-Type": "application/json; charset=UTF-8"
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
List<dynamic> jsonList = jsonDecode(response.body);
|
||||||
|
List<String> businessTypes =
|
||||||
|
jsonList.map((item) => item['type'].toString()).toList();
|
||||||
|
return businessTypes;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<Business>> searchBusinesses(
|
Future<List<Business>> searchBusinesses(
|
||||||
String searchText,
|
String searchText,
|
||||||
|
String searchType,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
) async {
|
) async {
|
||||||
|
String newSearchText = "All";
|
||||||
|
if (searchText.isNotEmpty) {
|
||||||
|
newSearchText = searchText;
|
||||||
|
}
|
||||||
|
String newSearchType = "All";
|
||||||
|
if (searchType.isNotEmpty) {
|
||||||
|
newSearchType = searchType;
|
||||||
|
}
|
||||||
|
if (searchText.isEmpty && searchType.isEmpty) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
var response = await http.get(
|
var response = await http.get(
|
||||||
Uri.parse("${AppEnviroment.baseApiUrl}/businesses/search/$searchText"),
|
Uri.parse(
|
||||||
|
"${AppEnviroment.baseApiUrl}/business/search/$newSearchType/$newSearchText"),
|
||||||
headers: <String, String>{
|
headers: <String, String>{
|
||||||
"Content-Type": "application/json; charset=UTF-8"
|
"Content-Type": "application/json; charset=UTF-8"
|
||||||
},
|
},
|
||||||
@@ -29,7 +59,7 @@ class MihBusinessDetailsServices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Business?> getBusinessDetails(
|
Future<Business?> getBusinessDetailsByUser(
|
||||||
String app_id,
|
String app_id,
|
||||||
) async {
|
) async {
|
||||||
var response = await http.get(
|
var response = await http.get(
|
||||||
@@ -47,6 +77,25 @@ class MihBusinessDetailsServices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Business?> getBusinessDetailsByBusinessId(
|
||||||
|
String business_id,
|
||||||
|
) async {
|
||||||
|
var response = await http.get(
|
||||||
|
Uri.parse(
|
||||||
|
"${AppEnviroment.baseApiUrl}/business/business_id/$business_id"),
|
||||||
|
headers: <String, String>{
|
||||||
|
"Content-Type": "application/json; charset=UTF-8"
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
String body = response.body;
|
||||||
|
var jsonBody = jsonDecode(body);
|
||||||
|
return Business.fromJson(jsonBody);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<Response> createBusinessDetails(
|
Future<Response> createBusinessDetails(
|
||||||
String appId,
|
String appId,
|
||||||
String busineName,
|
String busineName,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart';
|
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||||
import 'package:supertokens_flutter/http.dart' as http;
|
import 'package:supertokens_flutter/http.dart' as http;
|
||||||
@@ -6,6 +7,10 @@ import 'package:supertokens_flutter/http.dart' as http;
|
|||||||
class MihMzansiDirectoryServices {
|
class MihMzansiDirectoryServices {
|
||||||
final baseAPI = AppEnviroment.baseApiUrl;
|
final baseAPI = AppEnviroment.baseApiUrl;
|
||||||
|
|
||||||
|
//########################################################
|
||||||
|
//# Business Ratings #
|
||||||
|
//########################################################
|
||||||
|
|
||||||
Future<BusinessReview?> getUserReviewOfBusiness(
|
Future<BusinessReview?> getUserReviewOfBusiness(
|
||||||
String app_id,
|
String app_id,
|
||||||
String business_id,
|
String business_id,
|
||||||
@@ -33,10 +38,9 @@ class MihMzansiDirectoryServices {
|
|||||||
List<BusinessReview> businessReviews = List<BusinessReview>.from(
|
List<BusinessReview> businessReviews = List<BusinessReview>.from(
|
||||||
l.map((model) => BusinessReview.fromJson(model)));
|
l.map((model) => BusinessReview.fromJson(model)));
|
||||||
return businessReviews;
|
return businessReviews;
|
||||||
} else if (response.statusCode == 404){
|
} else if (response.statusCode == 404) {
|
||||||
return [];
|
return [];
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw Exception('failed to fetch Business Reviews');
|
throw Exception('failed to fetch Business Reviews');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,4 +132,84 @@ class MihMzansiDirectoryServices {
|
|||||||
return response.statusCode;
|
return response.statusCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//########################################################
|
||||||
|
//# Bookmarked Business #
|
||||||
|
//########################################################
|
||||||
|
|
||||||
|
Future<BookmarkedBusiness?> getUserBookmarkOfBusiness(
|
||||||
|
String app_id,
|
||||||
|
String business_id,
|
||||||
|
) async {
|
||||||
|
final response = await http.get(Uri.parse(
|
||||||
|
"${AppEnviroment.baseApiUrl}/mzansi-directory/bookmarked-business/$app_id/$business_id"));
|
||||||
|
// print(response.statusCode);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
String body = response.body;
|
||||||
|
var jsonBody = jsonDecode(body);
|
||||||
|
BookmarkedBusiness? BookmarkedBus = BookmarkedBusiness.fromJson(jsonBody);
|
||||||
|
return BookmarkedBus;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<BookmarkedBusiness>> getAllUserBookmarkedBusiness(
|
||||||
|
String app_id,
|
||||||
|
) async {
|
||||||
|
final response = await http.get(Uri.parse(
|
||||||
|
"${AppEnviroment.baseApiUrl}/mzansi-directory/bookmarked-business/user/all/$app_id"));
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
Iterable l = jsonDecode(response.body);
|
||||||
|
List<BookmarkedBusiness> businessReviews = List<BookmarkedBusiness>.from(
|
||||||
|
l.map((model) => BookmarkedBusiness.fromJson(model)));
|
||||||
|
return businessReviews;
|
||||||
|
} else if (response.statusCode == 404) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
throw Exception('failed to fetch User Bookmarked Business');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> addBookmarkedBusiness(
|
||||||
|
String app_id,
|
||||||
|
String business_id,
|
||||||
|
) async {
|
||||||
|
var response = await http.post(
|
||||||
|
Uri.parse(
|
||||||
|
"${AppEnviroment.baseApiUrl}/mzansi-directory/bookmarked-business/insert/"),
|
||||||
|
headers: <String, String>{
|
||||||
|
"Content-Type": "application/json; charset=UTF-8"
|
||||||
|
},
|
||||||
|
body: jsonEncode(<String, dynamic>{
|
||||||
|
"app_id": app_id,
|
||||||
|
"business_id": business_id,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if (response.statusCode == 201) {
|
||||||
|
return response.statusCode;
|
||||||
|
} else {
|
||||||
|
return response.statusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> deleteBookmarkedBusiness(
|
||||||
|
int idbookmarked_businesses,
|
||||||
|
) async {
|
||||||
|
var response = await http.delete(
|
||||||
|
Uri.parse(
|
||||||
|
"${AppEnviroment.baseApiUrl}/mzansi-directory/bookmarked-business/delete/"),
|
||||||
|
headers: <String, String>{
|
||||||
|
"Content-Type": "application/json; charset=UTF-8"
|
||||||
|
},
|
||||||
|
body: jsonEncode(<String, dynamic>{
|
||||||
|
"idbookmarked_businesses": idbookmarked_businesses,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
return response.statusCode;
|
||||||
|
} else {
|
||||||
|
return response.statusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ class MIHApiCalls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get Businessdata
|
// Get Businessdata
|
||||||
Business? business = await MihBusinessDetailsServices().getBusinessDetails(
|
Business? business =
|
||||||
|
await MihBusinessDetailsServices().getBusinessDetailsByUser(
|
||||||
uid,
|
uid,
|
||||||
);
|
);
|
||||||
if (business != null) {
|
if (business != null) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY requirements.txt ./
|
COPY requirements.txt ./
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
pip install -r requirements.txt
|
pip --default-timeout=120 install -r requirements.txt
|
||||||
|
|
||||||
# COPY . ./app
|
# COPY . ./app
|
||||||
|
|
||||||
|
|||||||
@@ -64,10 +64,21 @@ class BusinessRating(Base):
|
|||||||
rating_description = Column(String(256), nullable=False, server_default="")
|
rating_description = Column(String(256), nullable=False, server_default="")
|
||||||
rating_score = Column(String(45), nullable=False, server_default="")
|
rating_score = Column(String(45), nullable=False, server_default="")
|
||||||
date_time = Column(DateTime, nullable=True)
|
date_time = Column(DateTime, nullable=True)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return (
|
return (
|
||||||
f"<BusinessRating(idbusiness_ratings={self.idbusiness_ratings}, app_id='{self.app_id}', "
|
f"<BusinessRating(idbusiness_ratings={self.idbusiness_ratings}, app_id='{self.app_id}', "
|
||||||
f"business_id='{self.business_id}', rating_title='{self.rating_title}', rating_description='{self.rating_description}', "
|
f"business_id='{self.business_id}', rating_title='{self.rating_title}', rating_description='{self.rating_description}', "
|
||||||
f"rating_score='{self.rating_score}', date_time='{self.date_time}')>"
|
f"rating_score='{self.rating_score}', date_time='{self.date_time}')>"
|
||||||
|
)
|
||||||
|
class BookmarkedBusiness(Base):
|
||||||
|
__tablename__ = 'bookmarked_businesses'
|
||||||
|
__table_args__ = {'schema': 'mzansi_directory'}
|
||||||
|
idbookmarked_businesses = Column(Integer, primary_key=True)
|
||||||
|
app_id = Column(String(128), nullable=False, server_default="")
|
||||||
|
business_id = Column(String(128), nullable=False, server_default="")
|
||||||
|
created_date = Column(DateTime, nullable=True)
|
||||||
|
def __repr__(self):
|
||||||
|
return (
|
||||||
|
f"<BusinessRating(idbookmarked_businesses={self.idbookmarked_businesses}, app_id='{self.app_id}', "
|
||||||
|
f"business_id='{self.business_id}', created_date='{self.created_date}')>"
|
||||||
)
|
)
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException, status
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
#from ..mih_database import dbConnection
|
#from ..mih_database import dbConnection
|
||||||
import mih_database
|
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
|
||||||
#SuperToken Auth from front end
|
#SuperToken Auth from front end
|
||||||
from supertokens_python.recipe.session.framework.fastapi import verify_session
|
from supertokens_python.recipe.session.framework.fastapi import verify_session
|
||||||
from supertokens_python.recipe.session import SessionContainer
|
from supertokens_python.recipe.session import SessionContainer
|
||||||
@@ -60,90 +64,162 @@ class businessUpdateRequestV2(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
# Get List of all files
|
# Get List of all files
|
||||||
@router.get("/businesses/search/{search}", tags=["MIH Business"])
|
@router.get("/business/types/", tags=["MIH Business"])
|
||||||
async def read_all_businesses(search: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
|
async def read_business_by_business_id(session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
|
||||||
db = mih_database.dbConnection.dbAppDataConnect()
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
cursor = db.cursor()
|
dbSession = Session(dbEngine)
|
||||||
query = "SELECT business.business_id, business.Name, business.type, business.registration_no, "
|
try:
|
||||||
query += "business.logo_name, business.logo_path, business.contact_no, business.bus_email, "
|
queryResults = dbSession.query(Business.type).distinct().order_by(Business.type).all()
|
||||||
query += "business.gps_location, "
|
response_data = [{"type": t[0]} for t in queryResults]
|
||||||
query += "practice_no, vat_no, "
|
return response_data
|
||||||
query += "website, rating, mission_vision "
|
except Exception as e:
|
||||||
query += "FROM business "
|
print(f"An error occurred during the ORM query: {e}")
|
||||||
query += "WHERE LOWER(business.Name) LIKE %s OR LOWER(business.type) LIKE %s "
|
if dbSession.is_active:
|
||||||
query += "OR LOWER(business.bus_email) LIKE %s OR LOWER(business.mission_vision) LIKE %s"
|
dbSession.rollback()
|
||||||
search_term = f"%{search.lower()}%" # Add wildcards and lowercase
|
raise HTTPException(
|
||||||
cursor.execute(query, (search_term, search_term, search_term, search_term))
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
items = [
|
detail="Failed to retrieve records due to an internal server error."
|
||||||
{
|
)
|
||||||
"business_id": item[0],
|
finally:
|
||||||
"Name": item[1],
|
dbSession.close()
|
||||||
"type": item[2],
|
|
||||||
"registration_no": item[3],
|
# Get List of all files
|
||||||
"logo_name": item[4],
|
@router.get("/business/search/{type}/{search}", tags=["MIH Business"])
|
||||||
"logo_path": item[5],
|
async def read_all_businesses(search: str, type: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
|
||||||
"contact_no": item[6],
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
"bus_email": item[7],
|
dbSession = Session(dbEngine)
|
||||||
"app_id": "",
|
try:
|
||||||
"gps_location": item[8],
|
queryResults = dbSession.query(Business)
|
||||||
"practice_no": item[9],
|
type_term_with_wildcards = ""
|
||||||
"vat_no": item[10],
|
if type != "All":
|
||||||
"website": item[11],
|
type_term_with_wildcards = f"%{type.lower()}%"
|
||||||
"rating": item[12],
|
queryResults = queryResults.filter(
|
||||||
"mission_vision": item[13],
|
Business.type.ilike(type_term_with_wildcards)
|
||||||
}
|
)
|
||||||
for item in cursor.fetchall()
|
search_term_with_wildcards = ""
|
||||||
]
|
if search != "All":
|
||||||
cursor.close()
|
search_term_with_wildcards = f"%{search.lower()}%"
|
||||||
db.close()
|
queryResults = queryResults.filter(
|
||||||
return items
|
or_(
|
||||||
|
Business.Name.ilike(search_term_with_wildcards),
|
||||||
|
Business.bus_email.ilike(search_term_with_wildcards),
|
||||||
|
Business.mission_vision.ilike(search_term_with_wildcards),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
queryResults = queryResults.all()
|
||||||
|
response_data = []
|
||||||
|
for business in queryResults:
|
||||||
|
response_data.append({
|
||||||
|
"business_id": business.business_id,
|
||||||
|
"Name": business.Name,
|
||||||
|
"type": business.type,
|
||||||
|
"registration_no": business.registration_no,
|
||||||
|
"logo_name": business.logo_name,
|
||||||
|
"logo_path": business.logo_path,
|
||||||
|
"contact_no": business.contact_no,
|
||||||
|
"bus_email": business.bus_email,
|
||||||
|
"app_id": "",
|
||||||
|
"gps_location": business.gps_location,
|
||||||
|
"practice_no": business.practice_no,
|
||||||
|
"vat_no": business.vat_no,
|
||||||
|
"website": business.website,
|
||||||
|
"rating": business.rating,
|
||||||
|
"mission_vision": business.mission_vision,
|
||||||
|
})
|
||||||
|
|
||||||
|
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()
|
||||||
|
# db = mih_database.dbConnection.dbAppDataConnect()
|
||||||
|
# cursor = db.cursor()
|
||||||
|
# query = "SELECT business.business_id, business.Name, business.type, business.registration_no, "
|
||||||
|
# query += "business.logo_name, business.logo_path, business.contact_no, business.bus_email, "
|
||||||
|
# query += "business.gps_location, "
|
||||||
|
# query += "practice_no, vat_no, "
|
||||||
|
# query += "website, rating, mission_vision "
|
||||||
|
# query += "FROM business "
|
||||||
|
# query += "WHERE LOWER(business.Name) LIKE %s OR LOWER(business.type) LIKE %s "
|
||||||
|
# query += "OR LOWER(business.bus_email) LIKE %s OR LOWER(business.mission_vision) LIKE %s"
|
||||||
|
# search_term = f"%{search.lower()}%" # Add wildcards and lowercase
|
||||||
|
# cursor.execute(query, (search_term, search_term, search_term, search_term))
|
||||||
|
# items = [
|
||||||
|
# {
|
||||||
|
# "business_id": item[0],
|
||||||
|
# "Name": item[1],
|
||||||
|
# "type": item[2],
|
||||||
|
# "registration_no": item[3],
|
||||||
|
# "logo_name": item[4],
|
||||||
|
# "logo_path": item[5],
|
||||||
|
# "contact_no": item[6],
|
||||||
|
# "bus_email": item[7],
|
||||||
|
# "app_id": "",
|
||||||
|
# "gps_location": item[8],
|
||||||
|
# "practice_no": item[9],
|
||||||
|
# "vat_no": item[10],
|
||||||
|
# "website": item[11],
|
||||||
|
# "rating": item[12],
|
||||||
|
# "mission_vision": item[13],
|
||||||
|
# }
|
||||||
|
# for item in cursor.fetchall()
|
||||||
|
# ]
|
||||||
|
# cursor.close()
|
||||||
|
# db.close()
|
||||||
|
# return items
|
||||||
|
|
||||||
# Get List of all files
|
# Get List of all files
|
||||||
@router.get("/business/business_id/{business_id}", tags=["MIH Business"])
|
@router.get("/business/business_id/{business_id}", tags=["MIH Business"])
|
||||||
async def read_business_by_business_id(business_id: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
|
async def read_business_by_business_id(business_id: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
|
||||||
db = mih_database.dbConnection.dbAppDataConnect()
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
cursor = db.cursor()
|
dbSession = Session(dbEngine)
|
||||||
query = "SELECT business.business_id, business.Name, business.type, business.registration_no, "
|
|
||||||
query += "business.logo_name, business.logo_path, business.contact_no, business.bus_email, "
|
|
||||||
query += "business_users.app_id, business.gps_location, "
|
|
||||||
query += "practice_no, vat_no, "
|
|
||||||
query += "website, rating, mission_vision "
|
|
||||||
query += "FROM business "
|
|
||||||
query += "inner join business_users "
|
|
||||||
query += "on business.business_id=business_users.business_id "
|
|
||||||
query += "where business.business_id = %s"
|
|
||||||
try:
|
try:
|
||||||
cursor.execute(query, (business_id,))
|
queryResults = dbSession.query(Business).\
|
||||||
except Exception as error:
|
filter(
|
||||||
raise HTTPException(status_code=404, detail="Failed to pull records")
|
Business.business_id == business_id,
|
||||||
items = [
|
).first()
|
||||||
{
|
if queryResults:
|
||||||
"business_id": item[0],
|
return {
|
||||||
"Name": item[1],
|
"business_id": queryResults.business_id,
|
||||||
"type": item[2],
|
"Name": queryResults.Name,
|
||||||
"registration_no": item[3],
|
"type": queryResults.type,
|
||||||
"logo_name": item[4],
|
"registration_no": queryResults.registration_no,
|
||||||
"logo_path": item[5],
|
"logo_name": queryResults.logo_name,
|
||||||
"contact_no": item[6],
|
"logo_path": queryResults.logo_path,
|
||||||
"bus_email": item[7],
|
"contact_no": queryResults.contact_no,
|
||||||
"app_id": item[8],
|
"bus_email": queryResults.bus_email,
|
||||||
"gps_location": item[9],
|
"app_id": "",
|
||||||
"practice_no": item[10],
|
"gps_location": queryResults.gps_location,
|
||||||
"vat_no": item[11],
|
"practice_no": queryResults.practice_no,
|
||||||
"website": item[12],
|
"vat_no": queryResults.vat_no,
|
||||||
"rating": item[13],
|
"website": queryResults.website,
|
||||||
"mission_vision": item[14],
|
"rating": queryResults.rating,
|
||||||
}
|
"mission_vision": queryResults.mission_vision,
|
||||||
for item in cursor.fetchall()
|
}
|
||||||
]
|
else:
|
||||||
#
|
raise HTTPException(
|
||||||
cursor.close()
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
db.close()
|
detail="Business not found for the given business_id."
|
||||||
if(len(items)!= 0):
|
)
|
||||||
return items[0]
|
except HTTPException as http_exc:
|
||||||
else:
|
# Re-raise HTTPException directly if it was raised within the try block
|
||||||
raise HTTPException(status_code=404, detail="No record found")
|
raise http_exc
|
||||||
|
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
|
# Get List of all files
|
||||||
@router.get("/business/app_id/{app_id}", tags=["MIH Business"])
|
@router.get("/business/app_id/{app_id}", tags=["MIH Business"])
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from sqlalchemy.orm import Session
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import mih_database.mihDbConnections
|
import mih_database.mihDbConnections
|
||||||
from mih_database.mihDbObjects import User, Business, BusinessRating
|
from mih_database.mihDbObjects import User, Business, BusinessRating, BookmarkedBusiness
|
||||||
from supertokens_python.recipe.session.framework.fastapi import verify_session
|
from supertokens_python.recipe.session.framework.fastapi import verify_session
|
||||||
from supertokens_python.recipe.session import SessionContainer
|
from supertokens_python.recipe.session import SessionContainer
|
||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
@@ -40,6 +40,17 @@ class BusinessRatingUpdateRequest(BaseModel):
|
|||||||
rating_old_score: str
|
rating_old_score: str
|
||||||
current_rating: str
|
current_rating: str
|
||||||
|
|
||||||
|
class BookmarkedBusinessInsertRequest(BaseModel):
|
||||||
|
app_id: str
|
||||||
|
business_id: str
|
||||||
|
|
||||||
|
class BookmarkedBusinessDeleteRequest(BaseModel):
|
||||||
|
idbookmarked_businesses: int
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# Business Ratings #
|
||||||
|
########################################################
|
||||||
|
|
||||||
@router.get("/mzansi-directory/business-ratings/user/{app_id}/{business_id}", tags=["Mzansi Directory"])
|
@router.get("/mzansi-directory/business-ratings/user/{app_id}/{business_id}", tags=["Mzansi Directory"])
|
||||||
async def read_all_ratings_by_business_id(app_id: str,business_id: str, session: SessionContainer = Depends(verify_session())): # , session: SessionContainer = Depends(verify_session())
|
async def read_all_ratings_by_business_id(app_id: str,business_id: str, session: SessionContainer = Depends(verify_session())): # , session: SessionContainer = Depends(verify_session())
|
||||||
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
@@ -295,4 +306,154 @@ async def UpdatePatient(itemRequest : BusinessRatingUpdateRequest, session: Sess
|
|||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
dbSession.close()
|
dbSession.close()
|
||||||
return {"message": "Successfully wUpdated Record"}
|
return {"message": "Successfully wUpdated Record"}
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# Bookmarked Business #
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
@router.get("/mzansi-directory/bookmarked-business/{app_id}/{business_id}", tags=["Mzansi Directory"])
|
||||||
|
async def read_all_ratings_by_business_id(app_id: str,business_id: str, session: SessionContainer = Depends(verify_session())): # , session: SessionContainer = Depends(verify_session())
|
||||||
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
|
dbSession = Session(dbEngine)
|
||||||
|
try:
|
||||||
|
queryResults = dbSession.query(BookmarkedBusiness, Business).\
|
||||||
|
join(Business, BookmarkedBusiness.business_id == Business.business_id).\
|
||||||
|
filter(
|
||||||
|
BookmarkedBusiness.business_id == business_id,
|
||||||
|
BookmarkedBusiness.app_id == app_id,
|
||||||
|
).order_by(
|
||||||
|
desc(BookmarkedBusiness.created_date)
|
||||||
|
).first()
|
||||||
|
if queryResults:
|
||||||
|
bookmark_obj, bus_obj = queryResults
|
||||||
|
return {
|
||||||
|
"idbookmarked_businesses": bookmark_obj.idbookmarked_businesses,
|
||||||
|
"app_id": bookmark_obj.app_id,
|
||||||
|
"business_id": bookmark_obj.business_id,
|
||||||
|
"business_name": bus_obj.Name,
|
||||||
|
"created_date": bookmark_obj.created_date,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
# Return an empty response or a specific message
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Bookmarked Business rating not found for the given app_id & business_id."
|
||||||
|
)
|
||||||
|
except HTTPException as http_exc:
|
||||||
|
# Re-raise HTTPException directly if it was raised within the try block
|
||||||
|
raise http_exc
|
||||||
|
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()
|
||||||
|
|
||||||
|
@router.get("/mzansi-directory/bookmarked-business/user/all/{app_id}/", tags=["Mzansi Directory"])
|
||||||
|
async def read_all_ratings_by_business_id(app_id: str, session: SessionContainer = Depends(verify_session())): # , session: SessionContainer = Depends(verify_session())
|
||||||
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
|
dbSession = Session(dbEngine)
|
||||||
|
try:
|
||||||
|
queryResults = dbSession.query(BookmarkedBusiness, Business).\
|
||||||
|
join(Business, BookmarkedBusiness.business_id == Business.business_id).\
|
||||||
|
filter(
|
||||||
|
BookmarkedBusiness.app_id == app_id,
|
||||||
|
).order_by(
|
||||||
|
desc(BookmarkedBusiness.created_date)
|
||||||
|
).all()
|
||||||
|
response_data = []
|
||||||
|
for rating_obj, bus_obj in queryResults:
|
||||||
|
response_data.append({
|
||||||
|
"idbookmarked_businesses": rating_obj.idbookmarked_businesses,
|
||||||
|
"app_id": rating_obj.app_id,
|
||||||
|
"business_id": rating_obj.business_id,
|
||||||
|
"business_name": bus_obj.Name,
|
||||||
|
"created_date": rating_obj.created_date,
|
||||||
|
})
|
||||||
|
if len(response_data) > 0:
|
||||||
|
return response_data
|
||||||
|
else:
|
||||||
|
# Return an empty response or a specific message
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Bookmarked Business not found for the given app_id."
|
||||||
|
)
|
||||||
|
except HTTPException as http_exc:
|
||||||
|
# Re-raise HTTPException directly if it was raised within the try block
|
||||||
|
raise http_exc
|
||||||
|
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()
|
||||||
|
|
||||||
|
@router.post("/mzansi-directory/bookmarked-business/insert/", tags=["Mzansi Directory"], status_code=201)
|
||||||
|
async def insert_loyalty_card(itemRequest : BookmarkedBusinessInsertRequest): #, session: SessionContainer = Depends(verify_session())
|
||||||
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
|
nowDateTime = datetime.now()
|
||||||
|
formatedDateTime = nowDateTime.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
dbSession = Session(dbEngine)
|
||||||
|
try:
|
||||||
|
# add business rating
|
||||||
|
new_bookmarked_business = BookmarkedBusiness(
|
||||||
|
app_id=itemRequest.app_id,
|
||||||
|
business_id=itemRequest.business_id,
|
||||||
|
created_date=formatedDateTime
|
||||||
|
)
|
||||||
|
dbSession.add(new_bookmarked_business)
|
||||||
|
dbSession.flush() # Ensure the new rating is added to the session
|
||||||
|
dbSession.commit() # Commit the session to save changes
|
||||||
|
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 insert records due to an internal server error."
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
dbSession.close()
|
||||||
|
return {"message": "Successfully Created Record"}
|
||||||
|
|
||||||
|
@router.delete("/mzansi-directory/bookmarked-business/delete/", tags=["Mzansi Directory"])
|
||||||
|
async def Delete_loyalty_card(itemRequest : BookmarkedBusinessDeleteRequest, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
|
||||||
|
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||||
|
dbSession = Session(dbEngine)
|
||||||
|
try:
|
||||||
|
# delete business rating
|
||||||
|
rating_to_delete = dbSession.query(BookmarkedBusiness).\
|
||||||
|
get(
|
||||||
|
itemRequest.idbookmarked_businesses
|
||||||
|
)
|
||||||
|
if not rating_to_delete:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=f"Bookmarked Business with ID {itemRequest.idbusiness_ratings} not found."
|
||||||
|
)
|
||||||
|
dbSession.delete(rating_to_delete)
|
||||||
|
dbSession.flush() # Ensure the new rating is added to the session
|
||||||
|
dbSession.commit() # Commit the session to save changes
|
||||||
|
except HTTPException as http_exc:
|
||||||
|
# Re-raise HTTPException directly if it was raised within the try block
|
||||||
|
raise http_exc
|
||||||
|
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 insert records due to an internal server error."
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
dbSession.close()
|
||||||
|
return {"message": "Successfully Deleted Record"}
|
||||||
|
|||||||