update package structure and add package tile

This commit is contained in:
2025-03-26 09:28:25 +02:00
parent 7e9ac5e317
commit f2326bc109
4 changed files with 41 additions and 2 deletions

View File

@@ -0,0 +1,304 @@
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_layout/mih_single_child_scroll.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih-app_tool_body.dart';
import 'package:flutter/material.dart';
import 'package:math_expressions/math_expressions.dart';
class SimpleCalc extends StatefulWidget {
const SimpleCalc({super.key});
@override
State<SimpleCalc> createState() => _SimpleCalcState();
}
class _SimpleCalcState extends State<SimpleCalc> {
var userInput = '';
var answer = '0';
// Array of button
final List<String> buttons = [
'C',
'(',
')',
'D',
'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) {
return MihAppToolBody(
borderOn: true,
bodyItem: getBody(),
);
}
Widget getBody() {
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 MihSingleChildScroll(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
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(),
),
);
}
},
),
),
),
],
),
);
}
}

View File

@@ -0,0 +1,363 @@
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_single_child_scroll.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_window.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih-app_tool_body.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<TipCalc> createState() => _TipCalcState();
}
class _TipCalcState extends State<TipCalc> {
TextEditingController billAmountController = TextEditingController();
TextEditingController tipPercentageController = TextEditingController();
TextEditingController splitBillController = TextEditingController();
TextEditingController noPeopleController = TextEditingController();
final ValueNotifier<String> 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(),
),
),
Text(
"~ ${double.parse(total).ceil()}.00",
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")
Text(
"~ ${double.parse(amountPerPerson).ceil()}.00",
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 MihAppToolBody(
borderOn: true,
bodyItem: getBody(),
);
}
Widget getBody() {
return MihSingleChildScroll(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
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,
enableSearch: false,
),
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(),
),
),
],
),
);
}
}