Merge pull request #225 from yaso-meth/NEW--MIH-Authentication-Package

NEW--MIH-Authentication-Package
This commit is contained in:
yaso-meth
2025-07-02 18:37:56 +02:00
committed by GitHub
9 changed files with 1199 additions and 66 deletions

View File

@@ -13,6 +13,7 @@ import 'package:mzansi_innovation_hub/mih_packages/authentication/forgot_passwor
import 'package:mzansi_innovation_hub/mih_packages/authentication/reset_password.dart';
import 'package:mzansi_innovation_hub/mih_packages/calculator/mih_calculator.dart';
import 'package:mzansi_innovation_hub/mih_packages/calendar/mzansi_calendar.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_authentication.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/mzansi_ai.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/profile_business_add.dart';
@@ -38,6 +39,7 @@ class AppRoutes {
// Internal
static const String authCheck = '/';
static const String mihAuthentication = '/mih-authentication';
static const String notifications = '/notifications';
static const String forgotPassword = '/forgot-password';
static const String aboutMih = '/about';
@@ -105,6 +107,14 @@ class RouteGenerator {
}
break; // Use break and fall through to _errorRoute if argument type is wrong
case AppRoutes.mihAuthentication:
// if (args is AuthArguments) {
return MaterialPageRoute(
settings: settings,
builder: (_) => MihAuthentication(),
);
// }
// break; // Use break and fall through to _errorRoute if argument type is wrong
case AppRoutes.notifications:
if (args is NotificationArguments) {
return MaterialPageRoute(

View File

@@ -1,10 +1,10 @@
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_packages/authentication/biometric_check.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_authentication.dart';
import 'package:supertokens_flutter/supertokens.dart';
// import 'package:no_screenshot/no_screenshot.dart';
import 'signin_or_register.dart';
class AuthCheck extends StatefulWidget {
final bool personalSelected;
@@ -69,7 +69,7 @@ class _AuthCheckState extends State<AuthCheck> {
firstBoot: widget.firstBoot,
);
} else if (snapshot.data == false) {
return const SignInOrRegister();
return MihAuthentication();
} else {
return
// const SizedBox(width: 5, height: 5);

View File

@@ -46,14 +46,12 @@ class _SignInState extends State<SignIn> {
//sign user in
Future<void> signUserIn() async {
//var _backgroundColor = Colors.transparent;
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
try {
var response = await http.post(
Uri.parse("$baseAPI/auth/signin"),

View File

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

View File

@@ -0,0 +1,379 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.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_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:supertokens_flutter/http.dart' as http;
import 'package:supertokens_flutter/supertokens.dart';
class MihRegister extends StatefulWidget {
final void Function()? onExistingUserButtonTap;
const MihRegister({
super.key,
required this.onExistingUserButtonTap,
});
@override
State<MihRegister> createState() => _MihRegisterState();
}
class _MihRegisterState extends State<MihRegister> {
final emailController = TextEditingController();
final passwordController = TextEditingController();
final confirmPasswordController = TextEditingController();
final FocusNode _focusNode = FocusNode();
final _formKey = GlobalKey<FormState>();
final baseAPI = AppEnviroment.baseApiUrl;
Future<void> addUserAPICall(String email, String uid) async {
//await getOfficeIdByUser(docOfficeIdApiUrl + widget.userEmail);
//print(futureDocOfficeId.toString());
await MihUserServices().createUser(
email,
uid,
context,
);
// var response = await http.post(
// Uri.parse("$baseAPI/user/insert/"),
// headers: <String, String>{
// "Content-Type": "application/json; charset=UTF-8"
// },
// body: jsonEncode(<String, dynamic>{
// "email": email,
// "app_id": uid,
// }),
// );
// if (response.statusCode == 201) {
// Navigator.of(context).pushNamedAndRemoveUntil(
// '/',
// (route) => false,
// arguments: AuthArguments(
// true,
// true,
// ),
// );
// // signUpSuccess();
// // setState(() {
// // successfulSignUp = true;
// // });
// } else {
// internetConnectionPopUp();
// }
}
Future<void> signUserUp() async {
if (!validEmail()) {
emailError();
} else if (passwordController.text != confirmPasswordController.text) {
passwordError();
} else {
//var _backgroundColor = Colors.transparent;
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
try {
Uri uri = Uri.parse(
"$baseAPI/auth/emailpassword/email/exists?email=${emailController.text}");
//print("Here");
var response = await http.get(uri);
//print(response.body);
//print("response 1: ${response.statusCode}");
if (response.statusCode == 200) {
var userExists = jsonDecode(response.body);
if (userExists["exists"]) {
Navigator.of(context).pop();
signUpError();
} else {
var response2 = await http.post(
Uri.parse("$baseAPI/auth/signup"),
body:
'{"formFields": [{"id": "email","value": "${emailController.text}"}, {"id": "password","value": "${passwordController.text}"}]}',
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
"Authorization": "leatucczyixqwkqqdrhayiwzeofkltds"
},
);
//print("response 2: ${response2.statusCode}");
if (response2.statusCode == 200) {
//print("response 2: ${response2.body}");
var userCreated = jsonDecode(response2.body);
//print("Created user $userCreated");
if (userCreated["status"] == "OK") {
//print("Here1");
//Creat user in db
String uid = await SuperTokens.getUserId();
//print("uid: $uid");
addUserAPICall(emailController.text, uid);
Navigator.of(context).pop();
//print("Here1");
} else if (userCreated["status"] == "FIELD_ERROR") {
Navigator.of(context).pop();
passwordReqError();
} else {
Navigator.of(context).pop();
internetConnectionPopUp();
}
}
}
}
} on Exception catch (error) {
Navigator.of(context).pop();
loginError(error.toString());
emailController.clear();
passwordController.clear();
confirmPasswordController.clear();
}
}
}
void submitFormInput() async {
await signUserUp();
}
bool validEmail() {
String text = emailController.text;
var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$');
return regex.hasMatch(text);
}
void loginError(error) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(error),
);
},
);
}
void emailError() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Invalid Email");
},
);
}
void signUpError() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "User Exists");
},
);
}
void passwordError() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Password Match");
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void passwordReqError() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Password Requirements");
},
);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
if (_formKey.currentState!.validate()) {
submitFormInput();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
}
},
child: MihSingleChildScroll(
child: Padding(
padding:
MzanziInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.2)
: EdgeInsets.symmetric(horizontal: width * 0.075),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//logo
Icon(
Icons.lock,
size: 100,
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
//spacer
const SizedBox(height: 10),
//Heading
Text(
'Create an Account',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
//spacer
// const SizedBox(height: 20),
MihForm(
formKey: _formKey,
formFields: [
//email input
MihTextFormField(
fillColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
inputColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
controller: emailController,
multiLineInput: false,
requiredText: true,
hintText: "Email",
autofillHints: const [AutofillHints.email],
validator: (value) {
return MihValidationServices().validateEmail(value);
},
),
//spacer
const SizedBox(height: 10),
//password input
MihTextFormField(
fillColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
inputColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
controller: passwordController,
multiLineInput: false,
requiredText: true,
hintText: "Password",
passwordMode: true,
autofillHints: const [AutofillHints.password],
validator: (value) {
return MihValidationServices().validatePassword(value);
},
),
//spacer
const SizedBox(height: 10),
MihTextFormField(
fillColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
inputColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
controller: confirmPasswordController,
multiLineInput: false,
requiredText: true,
hintText: "Confirm Password",
passwordMode: true,
autofillHints: const [AutofillHints.password],
validator: (value) {
return MihValidationServices().validatePassword(value);
},
),
//spacer
const SizedBox(height: 20),
// sign up button
Center(
child: Wrap(
alignment: WrapAlignment.center,
runAlignment: WrapAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitFormInput();
} else {
MihAlertServices()
.formNotFilledCompletely(context);
}
},
buttonColor: MzanziInnovationHub.of(context)!
.theme
.successColor(),
width: 300,
child: Text(
"Create New Account",
style: TextStyle(
color: MzanziInnovationHub.of(context)!
.theme
.primaryColor(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
MihButton(
onPressed: widget.onExistingUserButtonTap,
buttonColor: MzanziInnovationHub.of(context)!
.theme
.secondaryColor(),
width: 300,
child: Text(
"I have an account",
style: TextStyle(
color: MzanziInnovationHub.of(context)!
.theme
.primaryColor(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
//here
],
)
],
),
),
),
);
}
}

View File

@@ -0,0 +1,489 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.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_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_install_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
class MihSignIn extends StatefulWidget {
final void Function()? onNewUserButtonTap;
const MihSignIn({
super.key,
required this.onNewUserButtonTap,
});
@override
State<MihSignIn> createState() => _MihSignInState();
}
class _MihSignInState extends State<MihSignIn> {
final emailController = TextEditingController();
final passwordController = TextEditingController();
final FocusNode _focusNode = FocusNode();
final _formKey = GlobalKey<FormState>();
bool successfulSignIn = false;
bool showProfiles = false;
final baseAPI = AppEnviroment.baseApiUrl;
late List<MIHTile> sandboxProfileList = [];
//sign user in
Future<void> signUserIn() async {
try {
successfulSignIn = await MihAuthenticationServices().signUserIn(
emailController.text,
passwordController.text,
context,
);
if (!successfulSignIn) {
loginError();
passwordController.clear();
}
} on Exception {
Navigator.of(context).pop();
loginError();
passwordController.clear();
}
}
void submitSignInForm() async {
await signUserIn();
if (successfulSignIn) {
Navigator.of(context).pushNamedAndRemoveUntil(
'/',
(route) => false,
arguments: AuthArguments(
true,
true,
),
);
}
}
void setSandboxProfiles(List<MIHTile> tileList) {
tileList.add(MIHTile(
onTap: () {
setState(() {
emailController.text = "testpatient@mzansi-innovation-hub.co.za";
passwordController.text = "Testprofile@1234";
});
if (_formKey.currentState!.validate()) {
submitSignInForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
tileName: "Patient",
tileIcon: Icon(
Icons.perm_identity_rounded,
color: getSec(),
size: 200,
),
p: getPrim(),
s: getSec(),
));
tileList.add(MIHTile(
onTap: () {
setState(() {
emailController.text = "testdoctor@mzansi-innovation-hub.co.za";
passwordController.text = "Testprofile@1234";
});
if (_formKey.currentState!.validate()) {
submitSignInForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
tileName: "Doctor",
tileIcon: Icon(
Icons.medical_services,
color: getSec(),
size: 200,
),
p: getPrim(),
s: getSec(),
));
//if (AppEnviroment.getEnv() == "Dev") {
tileList.add(MIHTile(
onTap: () {
setState(() {
emailController.text = "test-business@mzansi-innovation-hub.co.za";
passwordController.text = "Testprofile@1234";
});
if (_formKey.currentState!.validate()) {
submitSignInForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
tileName: "Business",
tileIcon: Icon(
Icons.business,
color: getSec(),
size: 200,
),
p: getPrim(),
s: getSec(),
));
tileList.add(MIHTile(
onTap: () {
setState(() {
emailController.text = "test@mzansi-innovation-hub.co.za";
passwordController.text = "Testprofile@1234";
});
if (_formKey.currentState!.validate()) {
submitSignInForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
tileName: "Test",
tileIcon: Icon(
Icons.warning_amber_rounded,
color: getSec(),
size: 200,
),
p: getPrim(),
s: getSec(),
));
//}
}
Color getPrim() {
return MzanziInnovationHub.of(context)!.theme.secondaryColor();
}
Color getSec() {
return MzanziInnovationHub.of(context)!.theme.primaryColor();
}
void loginError() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Invalid Credentials");
},
);
}
@override
void initState() {
super.initState();
setState(() {
setSandboxProfiles(sandboxProfileList);
});
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
if (_formKey.currentState!.validate()) {
submitSignInForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
}
},
child: MihSingleChildScroll(
child: Padding(
padding:
MzanziInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.2)
: EdgeInsets.symmetric(horizontal: width * 0.075),
child: AutofillGroup(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Visibility(
visible: MzanziInnovationHub.of(context)!
.theme
.getPlatform() ==
"Web",
child: Padding(
padding: const EdgeInsets.all(10.0),
child: MihButton(
onPressed: () {
MihInstallServices().installMihTrigger(context);
},
buttonColor: MzanziInnovationHub.of(context)!
.theme
.successColor(),
width: 150,
child: Text(
"Install MIH",
style: TextStyle(
color: MzanziInnovationHub.of(context)!
.theme
.primaryColor(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
//logo
Icon(
Icons.lock,
size: 100,
color:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
//spacer
const SizedBox(height: 10),
//Heading
Text(
'Sign In',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
//spacer
const SizedBox(height: 10),
MihForm(
formKey: _formKey,
formFields: [
MihTextFormField(
fillColor: MzanziInnovationHub.of(context)!
.theme
.secondaryColor(),
inputColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
controller: emailController,
multiLineInput: false,
requiredText: true,
hintText: "Email",
autofillHints: const [AutofillHints.email],
validator: (value) {
return MihValidationServices().validateEmail(value);
},
),
//spacer
const SizedBox(height: 10),
//password input
MihTextFormField(
fillColor: MzanziInnovationHub.of(context)!
.theme
.secondaryColor(),
inputColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
controller: passwordController,
multiLineInput: false,
requiredText: true,
hintText: "Password",
passwordMode: true,
autofillHints: const [AutofillHints.password],
validator: (value) {
return MihValidationServices().validatePassword(value);
},
),
const SizedBox(height: 10),
SizedBox(
// width: 500.0,
//height: 100.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: () {
Navigator.of(context).pushNamed(
'/forgot-password',
);
},
child: Text(
'Forgot Password?',
style: TextStyle(
fontSize: 15,
color: MzanziInnovationHub.of(context)!
.theme
.secondaryColor(),
fontWeight: FontWeight.bold,
),
),
),
],
),
),
//spacer
const SizedBox(height: 20),
// sign in button
Center(
child: Wrap(
alignment: WrapAlignment.center,
runAlignment: WrapAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitSignInForm();
} else {
MihAlertServices()
.formNotFilledCompletely(context);
}
},
buttonColor: MzanziInnovationHub.of(context)!
.theme
.successColor(),
width: 300,
child: Text(
"Sign In",
style: TextStyle(
color: MzanziInnovationHub.of(context)!
.theme
.primaryColor(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
MihButton(
onPressed: widget.onNewUserButtonTap,
buttonColor: MzanziInnovationHub.of(context)!
.theme
.secondaryColor(),
width: 300,
child: Text(
"Create New Account",
style: TextStyle(
color: MzanziInnovationHub.of(context)!
.theme
.primaryColor(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
//spacer
const SizedBox(height: 35),
Center(
child: SizedBox(
width: width,
//height: 100.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Flexible(
flex: 1,
child: Padding(
padding: EdgeInsets.only(right: 10.0),
child: Divider(),
),
),
Flexible(
flex: 1,
child: GestureDetector(
child: Text(
'Use Sandox Profile',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: MzanziInnovationHub.of(context)!
.theme
.secondaryColor()),
),
onTap: () {
setState(() {
showProfiles = !showProfiles;
});
},
),
),
const Flexible(
flex: 1,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Divider(),
),
),
],
),
),
),
const SizedBox(height: 10),
Center(
child: Visibility(
visible: showProfiles,
child: SizedBox(
width: 500,
child: Column(
//mainAxisSize: MainAxisSize.max,
children: [
GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: sandboxProfileList.length,
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
mainAxisSpacing: 10,
maxCrossAxisExtent: 100),
itemBuilder: (context, index) {
return sandboxProfileList[index];
},
),
// const SizedBox(height: 10),
Text(
"NB: These accounts are used for test purposes. Please do not store personal information on these profiles.",
textAlign: TextAlign.center,
style: TextStyle(
color: MzanziInnovationHub.of(context)!
.theme
.errorColor(),
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
],
),
],
),
),
),
),
);
}
}

View File

@@ -0,0 +1,153 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
// import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
import 'package:supertokens_flutter/http.dart' as http;
// import 'package:supertokens_flutter/supertokens.dart';
class MihAuthenticationServices {
final baseAPI = AppEnviroment.baseApiUrl;
// Future<void> signUserUp(
// TextEditingController emailController,
// TextEditingController passwordController,
// TextEditingController confirmPasswordController,
// BuildContext context,
// ) async {
// showDialog(
// context: context,
// builder: (context) {
// return const Mihloadingcircle();
// },
// );
// try {
// Uri uri = Uri.parse(
// "$baseAPI/auth/emailpassword/email/exists?email=${emailController.text}");
// var response = await http.get(uri);
// if (response.statusCode == 200) {
// var userExists = jsonDecode(response.body);
// if (userExists["exists"]) {
// Navigator.of(context).pop();
// signUpError(context);
// } else {
// var response2 = await http.post(
// Uri.parse("$baseAPI/auth/signup"),
// body:
// '{"formFields": [{"id": "email","value": "${emailController.text}"}, {"id": "password","value": "${passwordController.text}"}]}',
// headers: {
// 'Content-type': 'application/json',
// 'Accept': 'application/json',
// "Authorization": "leatucczyixqwkqqdrhayiwzeofkltds"
// },
// );
// //print("response 2: ${response2.statusCode}");
// if (response2.statusCode == 200) {
// //print("response 2: ${response2.body}");
// var userCreated = jsonDecode(response2.body);
// //print("Created user $userCreated");
// if (userCreated["status"] == "OK") {
// //print("Here1");
// //Creat user in db
// String uid = await SuperTokens.getUserId();
// //print("uid: $uid");
// await MihUserServices()
// .createUser(emailController.text, uid, context);
// // addUserAPICall(emailController.text, uid);
// Navigator.of(context).pop();
// //print("Here1");
// } else if (userCreated["status"] == "FIELD_ERROR") {
// Navigator.of(context).pop();
// passwordReqError(context);
// } else {
// Navigator.of(context).pop();
// internetConnectionPopUp(context);
// }
// }
// }
// }
// } on Exception catch (error) {
// Navigator.of(context).pop();
// loginError(error.toString(), context);
// emailController.clear();
// passwordController.clear();
// confirmPasswordController.clear();
// }
// }
Future<bool> signUserIn(
String email,
String password,
BuildContext context,
) async {
//var _backgroundColor = Colors.transparent;
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
var response = await http.post(
Uri.parse("$baseAPI/auth/signin"),
body:
'{"formFields": [{"id": "email","value": "$email"}, {"id": "password","value": "$password"}]}',
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
"Authorization": "leatucczyixqwkqqdrhayiwzeofkltds"
},
);
if (response.statusCode == 200) {
var userSignedin = jsonDecode(response.body);
if (userSignedin["status"] == "OK") {
Navigator.of(context).pop();
return true;
} else {
Navigator.of(context).pop();
return false;
}
} else {
return false;
}
}
void internetConnectionPopUp(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void loginError(String error, BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(error),
);
},
);
}
void passwordReqError(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Password Requirements");
},
);
}
void signUpError(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "User Exists");
},
);
}
}

View File

@@ -30,6 +30,39 @@ class MihUserServices {
}
}
Future<void> createUser(
String email,
String app_id,
BuildContext context,
) async {
var response = await http.post(
Uri.parse("$baseAPI/user/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"email": email,
"app_id": app_id,
}),
);
if (response.statusCode == 201) {
Navigator.of(context).pushNamedAndRemoveUntil(
'/',
(route) => false,
arguments: AuthArguments(
true,
true,
),
);
// signUpSuccess();
// setState(() {
// successfulSignUp = true;
// });
} else {
internetConnectionPopUp(context);
}
}
Future<AppUser?> getUserDetails(
String app_id,
BuildContext context,
@@ -60,33 +93,32 @@ class MihUserServices {
BuildContext context,
) async {
var fileName = profilePicture.replaceAll(RegExp(r' '), '-');
var filePath =
"${signedInUser.app_id}/profile_files/$fileName";
var filePath = "${signedInUser.app_id}/profile_files/$fileName";
String profileType;
if (isBusinessUser) {
profileType = "business";
} else {
profileType = "personal";
}
var response = await http.put(
Uri.parse("${AppEnviroment.baseApiUrl}/user/update/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"idusers": signedInUser.idUser,
"username": username,
"fnam": firstName,
"lname": lastName,
"type": profileType,
"pro_pic_path": filePath,
}),
);
if (response.statusCode == 200) {
return response.statusCode;
} else {
return response.statusCode;
}
var response = await http.put(
Uri.parse("${AppEnviroment.baseApiUrl}/user/update/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"idusers": signedInUser.idUser,
"username": username,
"fnam": firstName,
"lname": lastName,
"type": profileType,
"pro_pic_path": filePath,
}),
);
if (response.statusCode == 200) {
return response.statusCode;
} else {
return response.statusCode;
}
}
static Future<void> deleteAccount(
@@ -128,19 +160,6 @@ class MihUserServices {
}
}
// Future<void> signOut() async {
// await SuperTokens.signOut(completionHandler: (error) {
// print(error);
// });
// if (await SuperTokens.doesSessionExist() == false) {
// Navigator.of(context).pop();
// Navigator.of(context).popAndPushNamed(
// '/',
// arguments: AuthArguments(true, false),
// );
// }
// }
//================== POP UPS ==========================================================================
static void internetConnectionPopUp(BuildContext context) {

View File

@@ -169,34 +169,34 @@ services:
networks:
- MIH-network
# === Added section for NVIDIA GPU acceleration ===
# runtime: nvidia
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: all # or specify a number of GPUs
# capabilities: [ gpu ]
#============== Firebaase ====================================================================
# firebase:
# container_name: MIH-firebase-emulator
# build:
# context: ./Firebase-emulator
# environment:
# DATA_DIRECTORY: "firebase/data"
# FIREBASE_PROJECT: "mzansi-innovation-hub"
# ports:
# - 8082:8080 # FIRESTORE_PORT
# - 5005:5005 # FIRESTORE_WS_PORT
# - 4000:4000 # UI_PORT
# - 9099:9099 # AUTH_PORT
# - 5000:6001 # Hosting
# volumes:
# - ./Firebase-emulator:/srv/firebase:rw
# # - ./cache:/root/.cache/:rw
# # - ~/.config/:/root/.config
# - ./Firebase-emulator/firebase/data:/srv/firebase/data:rw
#============== Named Volumes ====================================================================
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all # or specify a number of GPUs
capabilities: [ gpu ]
#============== Firebaase ====================================================================
# firebase:
# container_name: MIH-firebase-emulator
# build:
# context: ./Firebase-emulator
# environment:
# DATA_DIRECTORY: "firebase/data"
# FIREBASE_PROJECT: "mzansi-innovation-hub"
# ports:
# - 8082:8080 # FIRESTORE_PORT
# - 5005:5005 # FIRESTORE_WS_PORT
# - 4000:4000 # UI_PORT
# - 9099:9099 # AUTH_PORT
# - 5000:6001 # Hosting
# volumes:
# - ./Firebase-emulator:/srv/firebase:rw
# # - ./cache:/root/.cache/:rw
# # - ~/.config/:/root/.config
# - ./Firebase-emulator/firebase/data:/srv/firebase/data:rw
#============== Named Volumes ====================================================================
volumes:
certbotConf:
certbotChall: