diff --git a/Frontend/lib/mih_components/mih_inputs_and_buttons/mih_number_input.dart b/Frontend/lib/mih_components/mih_inputs_and_buttons/mih_number_input.dart new file mode 100644 index 00000000..dee3e614 --- /dev/null +++ b/Frontend/lib/mih_components/mih_inputs_and_buttons/mih_number_input.dart @@ -0,0 +1,203 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import '../../main.dart'; + +class MIHNumberField extends StatefulWidget { + final TextEditingController controller; + final String hintText; + final bool editable; + final bool required; + final bool enableDecimal; + final Iterable? autoFillHintGroup; + + const MIHNumberField({ + super.key, + required this.controller, + required this.hintText, + required this.editable, + required this.required, + required this.enableDecimal, + this.autoFillHintGroup, + }); + + @override + State createState() => _MIHNumberFieldState(); +} + +class _MIHNumberFieldState extends State { + bool startup = true; + final FocusNode _focus = FocusNode(); + + List allowDecimals() { + if (widget.enableDecimal) { + return [ + FilteringTextInputFormatter.allow(RegExp(r'^\d+(\.\d*)?')), + ]; + } else { + return [FilteringTextInputFormatter.digitsOnly]; + } + } + + bool makeEditable() { + if (widget.editable) { + return false; + } else { + return true; + } + } + + String? get _errorText { + final text = widget.controller.text; + String errorMessage = ''; + if (startup) { + return null; + } + if (!widget.required) { + return null; + } + if (text.isEmpty) { + return "${widget.hintText} is required"; + } + if (widget.hintText == "Email" && !isEmailValid(text)) { + errorMessage += "Enter a valid email address\n"; + } + // if (widget.hintText == "Username" && text.length < 8) { + // errorMessage += "• Username must contain at least 8 characters.\n"; + // } + if (widget.hintText == "Username" && !isUsernameValid(text)) { + errorMessage += "Let's create a great username for you!\n"; + errorMessage += "• Your username should start with a letter.\n"; + errorMessage += "• You can use letters, numbers, and/ or underscores.\n"; + errorMessage += "• Keep it between 6 and 30 characters.\n"; + errorMessage += "• Avoid special characters like @, #, or \$.\"\n"; + } + if (errorMessage.isEmpty) { + return null; + } + // If there are no error messages, the password is valid + return errorMessage; + } + + bool isUsernameValid(String username) { + return RegExp(r'^[a-zA-Z][a-zA-Z0-9_]{5,19}$').hasMatch(username); + } + + bool isEmailValid(String email) { + var regex = RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'); + return regex.hasMatch(email); + } + + void _onFocusChange() { + setState(() { + startup = false; + }); + } + + // List getAutoFillDetails(){ + // if(widget.autoFillHintGroup == null){ + // return []; + // } + // else{ + // return widget.autoFillHintGroup!; + // } + // } + + Widget setRequiredText() { + if (widget.required) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "*", + style: TextStyle( + color: MzanziInnovationHub.of(context)!.theme.errorColor()), + ), + const SizedBox( + width: 8.0, + ), + Text(widget.hintText, + style: TextStyle( + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor())), + ], + ); + } else { + return Text(widget.hintText, + style: TextStyle( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor())); + } + } + + @override + void dispose() { + _focus.dispose(); + super.dispose(); + } + + @override + void initState() { + _focus.addListener(_onFocusChange); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return TextField( + keyboardType: TextInputType.number, + inputFormatters: allowDecimals(), + autofillHints: widget.autoFillHintGroup, + style: TextStyle( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + controller: widget.controller, + focusNode: _focus, + readOnly: makeEditable(), + //enabled: !makeEditable(), + obscureText: false, + onChanged: (_) => setState(() { + startup = false; + }), + decoration: InputDecoration( + label: setRequiredText(), + //labelStyle: TextStyle(color: MzanziInnovationHub.of(context)!.theme.primaryColor()), + fillColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + filled: true, + errorText: _errorText, + errorStyle: TextStyle( + color: MzanziInnovationHub.of(context)!.theme.errorColor(), + fontWeight: FontWeight.bold), + //errorBorder: const InputBorder(), + //hintText: hintText, + //hintStyle: TextStyle(color: Colors.blueGrey[400]), + disabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + width: 2.0, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + width: 2.0, + ), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: MzanziInnovationHub.of(context)!.theme.errorColor(), + width: 2.0, + ), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: MzanziInnovationHub.of(context)!.theme.errorColor(), + width: 2.0, + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor()), + ), + ), + ); + } +} diff --git a/Frontend/lib/mih_packages/calculator/calculator.dart b/Frontend/lib/mih_packages/calculator/calculator.dart new file mode 100644 index 00000000..3da3edfc --- /dev/null +++ b/Frontend/lib/mih_packages/calculator/calculator.dart @@ -0,0 +1,194 @@ +import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_action.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_body.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_header.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_layout_builder.dart'; +import 'package:Mzansi_Innovation_Hub/mih_objects/arguments.dart'; +import 'package:Mzansi_Innovation_Hub/mih_packages/calculator/simple_calc.dart'; +import 'package:Mzansi_Innovation_Hub/mih_packages/calculator/tip_calc.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_swipe_detector/flutter_swipe_detector.dart'; + +class MIHCalculator extends StatefulWidget { + const MIHCalculator({super.key}); + + @override + State createState() => _MIHCalculatorState(); +} + +class _MIHCalculatorState extends State { + int _selectedIndex = 0; + + MIHAction getActionButton() { + return MIHAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + Navigator.of(context).pop(); + Navigator.of(context).popAndPushNamed( + '/', + arguments: AuthArguments(true, false), + ); + }, + ); + } + + MIHHeader getHeader() { + return const MIHHeader( + headerAlignment: MainAxisAlignment.center, + headerItems: [ + Text( + "", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + ), + ), + ], + ); + } + + MIHHeader getSecAction() { + return MIHHeader( + headerAlignment: MainAxisAlignment.end, + headerItems: [ + //============ Simple Calc ================ + Visibility( + visible: _selectedIndex != 0, + child: IconButton( + onPressed: () { + setState(() { + _selectedIndex = 0; + }); + }, + icon: const Icon( + Icons.calculate, + size: 35, + ), + ), + ), + Visibility( + visible: _selectedIndex == 0, + child: IconButton.filled( + iconSize: 35, + onPressed: () { + setState(() { + _selectedIndex = 0; + }); + }, + icon: const Icon( + Icons.calculate, + ), + ), + ), + //============ Tip Calc ================ + Visibility( + visible: _selectedIndex != 1, + child: IconButton( + onPressed: () { + setState(() { + _selectedIndex = 1; + }); + }, + icon: const Icon( + Icons.money, + size: 35, + ), + ), + ), + Visibility( + visible: _selectedIndex == 1, + child: IconButton.filled( + onPressed: () { + setState(() { + _selectedIndex = 1; + }); + }, + icon: const Icon( + Icons.money, + size: 35, + ), + ), + ), + // //============ Patient Files ================ + // Visibility( + // visible: _selectedIndex != 2, + // child: IconButton( + // onPressed: () { + // setState(() { + // _selectedIndex = 2; + // }); + // }, + // icon: const Icon( + // Icons.file_present, + // size: 35, + // ), + // ), + // ), + // Visibility( + // visible: _selectedIndex == 2, + // child: IconButton.filled( + // onPressed: () { + // setState(() { + // _selectedIndex = 2; + // }); + // }, + // icon: const Icon( + // Icons.file_present, + // size: 35, + // ), + // ), + // ), + ], + ); + } + + MIHBody getBody() { + return MIHBody( + borderOn: true, + bodyItems: [showSelection(_selectedIndex)], + ); + } + + Widget showSelection(int index) { + if (index == 0) { + return const SimpleCalc(); + } else if (index == 1) { + return const TipCalc(); + } else { + return const Placeholder(); + } + } + + @override + Widget build(BuildContext context) { + return SwipeDetector( + onSwipeLeft: (offset) { + if (_selectedIndex < 1) { + setState(() { + _selectedIndex += 1; + }); + } + //print("swipe left"); + }, + onSwipeRight: (offset) { + if (_selectedIndex > 0) { + setState(() { + _selectedIndex -= 1; + }); + } + //print("swipe right"); + }, + child: MIHLayoutBuilder( + actionButton: getActionButton(), + header: getHeader(), + secondaryActionButton: getSecAction(), + body: getBody(), + actionDrawer: null, + secondaryActionDrawer: null, + bottomNavBar: null, + pullDownToRefresh: false, + onPullDown: () async {}, + ), + ); + } +} diff --git a/Frontend/lib/mih_packages/calculator/simple_calc.dart b/Frontend/lib/mih_packages/calculator/simple_calc.dart new file mode 100644 index 00000000..24bc2f15 --- /dev/null +++ b/Frontend/lib/mih_packages/calculator/simple_calc.dart @@ -0,0 +1,283 @@ +import 'package:Mzansi_Innovation_Hub/main.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_button.dart'; +import 'package:flutter/material.dart'; +import 'package:math_expressions/math_expressions.dart'; + +class SimpleCalc extends StatefulWidget { + const SimpleCalc({super.key}); + + @override + State createState() => _SimpleCalcState(); +} + +class _SimpleCalcState extends State { + var userInput = ''; + var answer = '0'; + + // Array of button + final List buttons = [ + 'C', + '(', + ')', + 'Del', + '7', + '8', + '9', + '/', + '4', + '5', + '6', + 'x', + '1', + '2', + '3', + '-', + '0', + '.', + '=', + '+', + ]; + +// function to calculate the input operation + void equalPressed() { + String finaluserinput = userInput; + finaluserinput = userInput.replaceAll('x', '*'); + + Parser p = Parser(); + Expression exp = p.parse(finaluserinput); + ContextModel cm = ContextModel(); + double eval = exp.evaluate(EvaluationType.REAL, cm); + answer = eval.toString(); + } + + @override + Widget build(BuildContext context) { + double width = MediaQuery.sizeOf(context).width; + double height = MediaQuery.sizeOf(context).height; + var padding = MediaQuery.paddingOf(context); + double newheight = height - padding.top - padding.bottom; + print("width: $width"); + print("height: $height"); + print("newheight: $newheight"); + double calcWidth = 500; + if (MzanziInnovationHub.of(context)!.theme.screenType == "desktop") { + if (height < 700) { + calcWidth = 300; + } + } + return Column( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Simple Calculator", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + Divider(color: MzanziInnovationHub.of(context)!.theme.secondaryColor()), + const SizedBox(height: 10), + Container( + //color: Colors.white, + padding: const EdgeInsets.all(20), + alignment: Alignment.centerRight, + child: Text( + userInput, + style: TextStyle( + fontSize: 18, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ), + Container( + width: double.infinity, + //color: Colors.white, + padding: const EdgeInsets.all(15), + alignment: Alignment.centerRight, + child: Text( + answer, + style: TextStyle( + fontSize: 30, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + fontWeight: FontWeight.bold), + ), + ), + Container( + alignment: Alignment.centerRight, + child: SizedBox( + width: calcWidth, + child: GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + // padding: EdgeInsets.only( + // left: width / 10, + // right: width / 10, + // bottom: height / 15, + // //top: 20, + // ), + // shrinkWrap: true, + itemCount: buttons.length, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + //mainAxisExtent: 150, + ), + itemBuilder: (context, index) { + // Clear Button + if (index == 0) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: MIHButton( + onTap: () { + setState(() { + userInput = ''; + answer = '0'; + }); + }, + buttonText: buttons[index], + buttonColor: MzanziInnovationHub.of(context)! + .theme + .messageTextColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ); + } + + // +/- button + else if (index == 1) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: MIHButton( + onTap: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + buttonColor: MzanziInnovationHub.of(context)! + .theme + .messageTextColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ); + } + // % Button + else if (index == 2) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: MIHButton( + onTap: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + buttonColor: MzanziInnovationHub.of(context)! + .theme + .messageTextColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ); + } + // Delete Button + else if (index == 3) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: MIHButton( + onTap: () { + setState(() { + userInput = + userInput.substring(0, userInput.length - 1); + }); + }, + buttonText: buttons[index], + buttonColor: + MzanziInnovationHub.of(context)!.theme.errorColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ); + } + // Equal_to Button + else if (index == 18) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: MIHButton( + onTap: () { + setState(() { + equalPressed(); + }); + }, + buttonText: buttons[index], + buttonColor: + MzanziInnovationHub.of(context)!.theme.successColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ); + } + // +, -, / x buttons + else if (index == 7 || + index == 11 || + index == 15 || + index == 19) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: MIHButton( + onTap: () { + if (answer == "0") { + setState(() { + userInput += buttons[index]; + }); + } else { + setState(() { + userInput = answer; + answer = "0"; + userInput += buttons[index]; + }); + } + // setState(() { + // userInput += buttons[index]; + // }); + }, + buttonText: buttons[index], + buttonColor: MzanziInnovationHub.of(context)! + .theme + .messageTextColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ); + } + // other buttons + else { + return Padding( + padding: const EdgeInsets.all(4.0), + child: MIHButton( + onTap: () { + setState(() { + userInput += buttons[index]; + }); + }, + buttonText: buttons[index], + buttonColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ); + } + }, + ), + ), + ), + ], + ); + } +} diff --git a/Frontend/lib/mih_packages/calculator/tip_calc.dart b/Frontend/lib/mih_packages/calculator/tip_calc.dart new file mode 100644 index 00000000..8bb6efa8 --- /dev/null +++ b/Frontend/lib/mih_packages/calculator/tip_calc.dart @@ -0,0 +1,330 @@ +import 'package:Mzansi_Innovation_Hub/main.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_button.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_number_input.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_window.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:math_expressions/math_expressions.dart'; + +class TipCalc extends StatefulWidget { + const TipCalc({super.key}); + + @override + State createState() => _TipCalcState(); +} + +class _TipCalcState extends State { + TextEditingController billAmountController = TextEditingController(); + TextEditingController tipPercentageController = TextEditingController(); + TextEditingController splitBillController = TextEditingController(); + TextEditingController noPeopleController = TextEditingController(); + final ValueNotifier splitValue = ValueNotifier(""); + String tip = ""; + String total = ""; + String amountPerPerson = ""; + void splitSelected() { + if (splitBillController.text.isNotEmpty) { + splitValue.value = splitBillController.text; + } else { + splitValue.value = ""; + } + } + + void validateInput() async { + bool valid = false; + if (splitBillController.text.isNotEmpty && + splitBillController.text == "Yes") { + if (billAmountController.text.isEmpty || + tipPercentageController.text.isEmpty || + noPeopleController.text.isEmpty) { + valid = false; + } else { + valid = true; + } + } else if (splitBillController.text.isNotEmpty && + splitBillController.text == "No") { + if (billAmountController.text.isEmpty || + tipPercentageController.text.isEmpty) { + valid = false; + } else { + valid = true; + } + } else { + valid = false; + } + print("Is input valid: $valid"); + if (valid) { + calculatePressed(); + } else { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Input Error"); + }, + ); + } + } + + void calculatePressed() { + String tipCalc = + "${billAmountController.text}*(${tipPercentageController.text}/100)"; + Parser p = Parser(); + ContextModel cm = ContextModel(); + Expression exp = p.parse(tipCalc); + double eval = exp.evaluate(EvaluationType.REAL, cm); + tip = eval.toStringAsFixed(2); + //print("Tip: $tip"); + String totalCalc = "${billAmountController.text}+$tip"; + exp = p.parse(totalCalc); + eval = exp.evaluate(EvaluationType.REAL, cm); + total = eval.toStringAsFixed(2); + //print("Total Amount: $total"); + if (splitBillController.text == "Yes") { + String splitCalc = "$total/${noPeopleController.text}"; + exp = p.parse(splitCalc); + eval = exp.evaluate(EvaluationType.REAL, cm); + amountPerPerson = eval.toStringAsFixed(2); + } + + //print("Amount Per Person: $amountPerPerson"); + displayResult(); + } + + void clearInput() { + billAmountController.clear(); + tipPercentageController.clear(); + noPeopleController.clear(); + setState(() { + splitBillController.text = "No"; + }); + } + + @override + void dispose() { + billAmountController.dispose(); + tipPercentageController.dispose(); + splitBillController.dispose(); + noPeopleController.dispose(); + super.dispose(); + } + + void displayResult() { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => MIHWindow( + fullscreen: false, + windowTitle: "Calculation Results", + onWindowTapClose: () { + Navigator.pop(context); + }, + windowTools: const [], + windowBody: [ + // FaIcon( + // FontAwesomeIcons.moneyBills, + // color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + // size: 30, + // ), + // const Divider(), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.coins, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + size: 35, + ), + const SizedBox(width: 15), + Text( + "Tip", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ], + ), + Text( + tip, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + const Divider(), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.moneyBills, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + size: 35, + ), + const SizedBox(width: 15), + Text( + "Total", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ], + ), + Text( + total, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + const Divider(), + if (splitBillController.text == "Yes") + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.peopleGroup, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + size: 35, + ), + const SizedBox(width: 15), + Text( + "Total per Person", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ], + ), + if (splitBillController.text == "Yes") + Text( + amountPerPerson, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + // if (splitBillController.text == "Yes") const Divider(), + ], + ), + ); + } + + @override + void initState() { + super.initState(); + splitBillController.text = "No"; + splitBillController.addListener(splitSelected); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + "Tip Calculator", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + Divider(color: MzanziInnovationHub.of(context)!.theme.secondaryColor()), + const SizedBox(height: 10), + MIHNumberField( + controller: billAmountController, + hintText: "Bill Amount", + editable: true, + required: true, + enableDecimal: true, + ), + const SizedBox(height: 10), + MIHNumberField( + controller: tipPercentageController, + hintText: "Tip %", + editable: true, + required: true, + enableDecimal: false, + ), + const SizedBox(height: 10), + MIHDropdownField( + controller: splitBillController, + hintText: "Split Bill", + dropdownOptions: const ["Yes", "No"], + required: true, + editable: true, + ), + const SizedBox(height: 10), + ValueListenableBuilder( + valueListenable: splitValue, + builder: (BuildContext context, String value, Widget? child) { + return Visibility( + visible: value == "Yes", + child: Column( + children: [ + MIHNumberField( + controller: noPeopleController, + hintText: "No. of People", + editable: true, + required: true, + enableDecimal: false, + ), + const SizedBox(height: 10), + ], + ), + ); + }, + ), + SizedBox( + width: double.infinity, + height: 50, + child: MIHButton( + onTap: () { + validateInput(); + }, + buttonText: "Calculate", + buttonColor: MzanziInnovationHub.of(context)!.theme.successColor(), + textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ), + const SizedBox(height: 10), + SizedBox( + width: double.infinity, + height: 50, + child: MIHButton( + onTap: () { + clearInput(); + }, + buttonText: "Clear", + buttonColor: MzanziInnovationHub.of(context)!.theme.errorColor(), + textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ), + ], + ); + } +} diff --git a/Frontend/lib/mih_packages/mih_home/mih_home.dart b/Frontend/lib/mih_packages/mih_home/mih_home.dart index 7e9317e1..65416371 100644 --- a/Frontend/lib/mih_packages/mih_home/mih_home.dart +++ b/Frontend/lib/mih_packages/mih_home/mih_home.dart @@ -291,6 +291,31 @@ class _MIHHomeState extends State { s: getSec(), )); + tileList.add(MIHTile( + videoID: "", + onTap: () { + Navigator.of(context).pushNamed( + '/calculator', + //arguments: widget.signedInUser, + ); + }, + tileName: "Calculator", + tileIcon: Center( + child: FaIcon( + FontAwesomeIcons.calculator, + color: getSec(), + size: 200, + ), + ), + // Icon( + // Icons.info_outline, + // color: getSec(), + // size: 230, + // ), + p: getPrim(), + s: getSec(), + )); + tileList.add(MIHTile( videoID: "hbKhlmY_56U", onTap: () { @@ -929,7 +954,7 @@ class _MIHHomeState extends State { child: SizedBox( child: MIHSearchField( controller: searchController, - hintText: "Search Mzansi Apps", + hintText: "Search Mzansi Tiles", required: false, editable: true, onTap: () { diff --git a/Frontend/lib/mih_router/routeGenerator.dart b/Frontend/lib/mih_router/routeGenerator.dart index 39128829..8ea87309 100644 --- a/Frontend/lib/mih_router/routeGenerator.dart +++ b/Frontend/lib/mih_router/routeGenerator.dart @@ -1,3 +1,4 @@ +import 'package:Mzansi_Innovation_Hub/mih_packages/calculator/calculator.dart'; import 'package:Mzansi_Innovation_Hub/mih_packages/mih_policy_tos/mih_privacy_polocy.dart'; import 'package:Mzansi_Innovation_Hub/mih_packages/mih_policy_tos/mih_terms_of_service.dart'; import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_wallet/mzansi_wallet.dart'; @@ -266,6 +267,12 @@ class RouteGenerator { ); } return _errorRoute(); + case '/calculator': + return MaterialPageRoute( + settings: settings, + builder: (_) => const MIHCalculator(), + ); + default: return _errorRoute(); } diff --git a/Frontend/pubspec.lock b/Frontend/pubspec.lock index d6983355..a72646e3 100644 --- a/Frontend/pubspec.lock +++ b/Frontend/pubspec.lock @@ -717,6 +717,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.11.1" + math_expressions: + dependency: "direct main" + description: + name: math_expressions + sha256: e32d803d758ace61cc6c4bdfed1226ff60a6a23646b35685670d28b5616139f8 + url: "https://pub.dev" + source: hosted + version: "2.6.0" meta: dependency: transitive description: diff --git a/Frontend/pubspec.yaml b/Frontend/pubspec.yaml index e0e03ba9..e6d6d810 100644 --- a/Frontend/pubspec.yaml +++ b/Frontend/pubspec.yaml @@ -68,6 +68,7 @@ dependencies: url_launcher: ^6.3.1 fl_downloader: ^2.0.2 local_auth: ^2.3.0 + math_expressions: ^2.6.0 dev_dependencies: flutter_test: