Basic Calc functions

This commit is contained in:
Malte Schröder
2025-12-19 18:55:59 +01:00
commit a8103a7c6e
11 changed files with 6800 additions and 0 deletions

16
src/main.rs Normal file
View File

@@ -0,0 +1,16 @@
use dioxus::prelude::*;
mod ui;
const MAIN_CSS: Asset = asset!("/assets/main.css");
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
rsx! {
document::Link { rel: "stylesheet", href: MAIN_CSS }
ui::Calculator {}
}
}

219
src/ui.rs Normal file
View File

@@ -0,0 +1,219 @@
use dioxus::prelude::*;
/// The main calculator component.
/// We use `allow(non_snake_case)` because Dioxus components are typically CamelCase.
#[allow(non_snake_case)]
#[component]
pub fn Calculator() -> Element {
// --- State Management ---
// `first_num`: Stores the first number entered.
// `second_num`: Stores the second number entered.
// `operator`: Stores the current operator (+, -, *, /).
let mut first_num = use_signal(String::new);
let mut second_num = use_signal(String::new);
let mut operator = use_signal(String::new);
rsx! {
// Main container for the calculator
div { class: "app-container",
div { class: "calculator-wrap",
// Display Screen
div { class: "display-area",
div { class: "display-text",
// Logic: If first number is empty, show "0"
if first_num().is_empty() {
"0"
} else {
"{first_num}"
}
" "
span { class: "operator-symbol", "{operator}" }
" "
"{second_num}"
}
}
// Button Grid
div { class: "keypad-grid",
// --- Row 1 ---
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "7"),
"7"
}
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "8"),
"8"
}
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "9"),
"9"
}
button {
class: "calc-btn btn-operator",
onclick: move |_| handle_operator(first_num, second_num, operator, "/"),
"/"
}
// --- Row 2 ---
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "4"),
"4"
}
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "5"),
"5"
}
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "6"),
"6"
}
button {
class: "calc-btn btn-operator",
onclick: move |_| handle_operator(first_num, second_num, operator, "*"),
"*"
}
// --- Row 3 ---
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "1"),
"1"
}
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "2"),
"2"
}
button {
class: "calc-btn btn-number",
onclick: move |_| input_digit(first_num, second_num, operator, "3"),
"3"
}
button {
class: "calc-btn btn-operator",
onclick: move |_| handle_operator(first_num, second_num, operator, "-"),
"-"
}
// --- Row 4 ---
button {
class: "calc-btn btn-number btn-zero",
onclick: move |_| input_digit(first_num, second_num, operator, "0"),
"0"
}
button {
class: "calc-btn btn-clear",
onclick: move |_| {
first_num.set(String::new());
second_num.set(String::new());
operator.set(String::new());
},
"C"
}
button {
class: "calc-btn btn-operator",
onclick: move |_| handle_operator(first_num, second_num, operator, "+"),
"+"
}
// --- Row 5 (Equals) ---
button {
class: "calc-btn btn-equals",
onclick: move |_| calculate_result(first_num, second_num, operator),
"="
}
}
}
}
}
}
/// Helper function to add a digit to the current number
fn input_digit(
mut first_num: Signal<String>,
mut second_num: Signal<String>,
operator: Signal<String>,
digit: &str,
) {
if operator().is_empty() {
first_num.write().push_str(digit);
} else {
second_num.write().push_str(digit);
}
}
/// Helper logic for operators
fn handle_operator(
first_num: Signal<String>,
second_num: Signal<String>,
mut operator: Signal<String>,
op: &str,
) {
if !first_num().is_empty() && second_num().is_empty() {
operator.set(op.to_string());
} else if !second_num().is_empty() {
// If we already have two numbers, calculate first, then set new operator
calculate_result(first_num, second_num, operator);
operator.set(op.to_string());
}
}
/// Performs the calculation based on current state
fn calculate_result(
mut first_num: Signal<String>,
mut second_num: Signal<String>,
mut operator: Signal<String>,
) {
// Parse numbers
let num1_str = first_num();
let num2_str = second_num();
let op = operator();
// If we don't have a second number, we can't calculate
if num2_str.is_empty() {
return;
}
// Try to parse strings to floats
let n1 = match num1_str.parse::<f64>() {
Ok(n) => n,
Err(_) => return, // Invalid number
};
let n2 = match num2_str.parse::<f64>() {
Ok(n) => n,
Err(_) => return, // Invalid number
};
// Calculate result
let result = match op.as_str() {
"+" => (n1 + n2).to_string(),
"-" => (n1 - n2).to_string(),
"*" => (n1 * n2).to_string(),
"/" => {
if n2 == 0.0 {
"Error".to_string()
} else {
(n1 / n2).to_string()
}
}
_ => return, // Unknown operator
};
// Update state with result
if result == "Error" {
first_num.set(String::new());
} else {
first_num.set(result);
}
// Reset others
second_num.set(String::new());
operator.set(String::new());
}