Are you Toni?

This is your free professional page on AI Realty. Claim it to edit your profile, receive inbound leads and promote your listings.

How it works for realtors
Toni TOUÇAS profile

Toni TOUÇAS

Real Estate Agent · CENTURY 21 Isidoro Alves II, Portugal

CallEmailWebsite

About Toni

Toni Toucas is a registered Consultor at CENTURY 21 Isidoro Alves II in Portugal. Driven by a commitment to the care and trust of each client, Toni prioritizes the specific goals of those they work with. Toni operates with credibility and transparency to find the right deal for the right person.

To support this professional standard, Toni has completed targeted industry training. This education includes the EXPAND Training Path and the SER and ESTAR CENTURY 21 program, which strengthen the foundational skills needed to guide clients through the real estate process.

Additionally, Toni maintains compliance with modern legal and industry regulations. This includes the successful completion of the training for the Prevention of Money Laundering and Combating Terrorism 2026. Toni utilizes this structured background to ensure all real estate transactions are handled diligently and securely.of the text representation. If your user is typing '7', they expect '7'.

By formatting the button data directly into your state representation, you prevent formatting errors, simplify rendering, and keep your calculation logic clear.

---

### Phase 2: Building Core Engine Functions

Your calculator engine should operate as a pure, testable state machine. It takes the *current* state and an *input event* (like a number click, operator click, or clear command), and returns the *next* state.

``` +------------------+ | Current State | | (e.g., "12 +") | +--------+---------+ | v [Input Event: "5"] +----------+----------+ | Calculator Engine | (Pure state transition function) +----------+----------+ | v +--------+---------+ | New State | | (e.g., "12 + 5")| +------------------+ ```

Let's design a robust transition function in plain TypeScript. This engine lives independently of any UI framework:

```typescript export function calculateNextState( currentState: CalculatorState, action: CalculatorAction ): CalculatorState { switch (action.type) { case 'DIGIT': return handleDigit(currentState, action.value); case 'DECIMAL': return handleDecimal(currentState); case 'OPERATOR': return handleOperator(currentState, action.operator); case 'PERCENT': return handlePercent(currentState); case 'SIGN': return handleSign(currentState); case 'EQUALS': return handleEquals(currentState); case 'CLEAR': return handleClear(currentState); default: return currentState; } } ```

Let’s implement these handler functions, paying close attention to edge cases.

#### Handle Digits

When a user presses a digit, the action depends on what state the display is currently in. If the display is currently representing "0" (initial state) or if we are waiting for a new operand after an operator has been pressed, we want the digit to overwrite the display. Otherwise, we append the digit to the end of the current number. We also prevent the user from exceeding an arbitrary precision limit (e.g., 9 digits) to prevent UI overflow.

```typescript function handleDigit(state: CalculatorState, digit: string): CalculatorState { const { displayValue, waitingForOperand } = state;

if (waitingForOperand) { return { ...state, displayValue: digit, waitingForOperand: false, }; }

if (displayValue === '0') { return { ...state, displayValue: digit, }; }

// Prevent input overflow (e.g., max 9 characters) if (displayValue.replace(/[.-]/g, '').length >= 9) { return state; }

return { ...state, displayValue: displayValue + digit, }; } ```

#### Handle Decimals

Adding a decimal point requires verifying that the current number doesn't already contain one. If we are starting a new number (waiting for operand), the input becomes "0.".

```typescript function handleDecimal(state: CalculatorState): CalculatorState { const { displayValue, waitingForOperand } = state;

if (waitingForOperand) { return { ...state, displayValue: '0.', waitingForOperand: false, }; }

if (!displayValue.includes('.')) { return { ...state, displayValue: displayValue + '.', }; }

return state; } ```

#### Handle Operators

The operator logic is where many developers trip up. It must support multiple operational states: 1. **Initial setup**: If no operator has been selected, store the current display value as `firstOperand` and register the operator. 2. **Operator change**: If the user presses one operator, then immediately changes their mind and presses another without typing a number (e.g., `5 + *`), update the selected operator without executing a calculation. 3. **Chained operations**: If a calculation is already queued (e.g., `5 + 3` is in memory, and the user presses `-`), run the previous calculation, display the intermediate result, and set the new operator.

```typescript function handleOperator(state: CalculatorState, nextOperator: Operator): CalculatorState { const { displayValue, firstOperand, operator, waitingForOperand } = state; const inputValue = parseFloat(displayValue);

if (operator && waitingForOperand) { // User changed their mind on the operator (e.g., "5 + *" -> now multiply) return { ...state, operator: nextOperator, }; }

if (firstOperand === null) { return { ...state, firstOperand: inputValue, operator: nextOperator, waitingForOperand: true, }; }

if (operator) { const result = performCalculation(firstOperand, inputValue, operator); return { displayValue: formatResult(result), firstOperand: result, operator: nextOperator, waitingForOperand: true, }; }

return state; } ```

Wait, what about the calculation itself? Here is our helper function:

```typescript function performCalculation( left: number, right: number, operator: Operator ): number { switch (operator) { case '+': return left + right; case '-': return left - right; case '*': return left * right; case '/': return right === 0 ? NaN : left / right; // Handle division by zero default: return right; } } ```

#### Handle Equals

Pressing the equals (`=`) button completes the current outstanding calculation. It resets the `firstOperand` and `operator` states, storing the final result cleanly in the display value.

```typescript function handleEquals(state: CalculatorState): CalculatorState { const { displayValue, firstOperand, operator } = state; const inputValue = parseFloat(displayValue);

if (operator === null || firstOperand === null) { return state; }

const result = performCalculation(firstOperand, inputValue, operator);

return { displayValue: formatResult(result), firstOperand: null, operator: null, waitingForOperand: true, // Allow new typing to clear/overwrite this result }; } ```

#### Other Operations: Signs, Percentages, and Clearing

The rest of the features operate directly on the current display state:

```typescript function handleSign(state: CalculatorState): CalculatorState { const { displayValue } = state; const flipped = parseFloat(displayValue) * -1; return { ...state, displayValue: formatResult(flipped), }; }

function handlePercent(state: CalculatorState): CalculatorState { const { displayValue } = state; const value = parseFloat(displayValue); if (value === 0) return state; return { ...state, displayValue: formatResult(value / 100), }; }

function handleClear(state: CalculatorState): CalculatorState { // Full reset to initial state return { displayValue: '0', firstOperand: null, operator: null, waitingForOperand: false, }; } ```

---

### Phase 3: Perfecting JavaScript Math (Floating-Point Precision)

Calculators can easily fail basic math due to binary representation limits. If a user types `0.1 + 0.2`, a standard JS calculation returns `0.30000000000000004`. Users find this behavior jarring; a robust calculator must reconcile this limitation cleanly.

To resolve this, we write a formatting utility `formatResult`. It handles precision rounding gracefully, keeping numbers clean while preventing text overflow in our UI.

```typescript export function formatResult(num: number): string { if (Number.isNaN(num)) { return 'Error'; } if (!Number.isFinite(num)) { return 'Error'; // Division by zero or overflow }

// Convert to string to analyze length const numString = num.toString();

// If it's a standard integer or fits easily within our limit, return it if (numString.length <= 11) { return numString; }

// Handle scientific notation for extremely large/small values if (Math.abs(num) > 999999999 || (Math.abs(num) < 0.000001 && num !== 0)) { return num.toExponential(5); // Fits cleanly on screen }

// Handle recurring float decimals by restricting fractional precision // We round dynamically to fit within 10 characters maximum const decimalIndex = numString.indexOf('.'); if (decimalIndex !== -1) { const allowedDecimals = 10 - decimalIndex; if (allowedDecimals > 0) { // parseFloat strips trailing zeros after fixing precision return parseFloat(num.toFixed(allowedDecimals)).toString(); } }

return numString.substring(0, 11); } ```

Let's verify how this handles edge cases: - `0.1 + 0.2` becomes `0.3` (by using `.toFixed()` formatting which removes the long mantissa error). - Division by zero returns `Error`. - Large values like `123456789 * 10` get reformatted to `1.23457e+9`.

---

### Phase 4: State Integration & Layout Setup (React / Vue / Svelte)

With our calculation engine fully completed and tested in pure JS/TS, we can confidently connect it to a UI framework. Notice how simple our framework integration becomes: **the UI exists strictly to render state and forward user inputs to our engine**.

Below are integrations for both **React** and **Vue**. Choose the implementation matching your project tech stack.

::: code-tabs @tab React (Functional Component) ```tsx import React, { useReducer, useEffect } from 'react'; import { calculateNextState, formatResult } from './calculatorEngine'; // imports from Phase 2/3 import { CalculatorState, CalculatorAction, BUTTON_GRID } from './types';

const initialState: CalculatorState = { displayValue: '0', firstOperand: null, operator: null, waitingForOperand: false, };

function stateReducer(state: CalculatorState, action: CalculatorAction): CalculatorState { return calculateNextState(state, action); }

export function Calculator() { const [state, dispatch] = useReducer(stateReducer, initialState);

// Keyboard accessibility integration useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { let key = event.key; if (key === 'Enter') key = '='; if (key === 'Escape') key = 'c'; if (key === '*') key = 'x'; // normalize multiplication key

const matchedButton = BUTTON_GRID.flat().find( (btn) => btn.label.toLowerCase() === key.toLowerCase() || btn.value.toLowerCase() === key.toLowerCase() );

if (matchedButton) { dispatch(matchedButton.action); } };

window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, []);

return ( <div className="calculator-container"> {/* Dynamic font size class applied based on output length */} <div className={`screen ${state.displayValue.length > 7 ? 'small-text' : ''}`}> {state.displayValue} </div> <div className="grid"> {BUTTON_GRID.map((row, rIdx) => ( <div key={rIdx} className="row"> {row.map((btn) => ( <button key={btn.value} onClick={() => dispatch(btn.action)} className={`btn btn-${btn.variant} ${btn.value === '0' ? 'double-width' : ''} ${ state.operator === btn.value && state.waitingForOperand ? 'active-operator' : '' }`} > {btn.label} </button> ))} </div> ))} </div> </div> ); } ``` @tab Vue 3 (Composition API) ```vue <script setup lang="ts"> import { ref, onMounted, onUnmounted } from 'vue'; import { calculateNextState } from './calculatorEngine'; import { BUTTON_GRID, CalculatorState } from './types';

const state = ref<CalculatorState>({ displayValue: '0', firstOperand: null, operator: null, waitingForOperand: false, });

function handleAction(action: any) { state.value = calculateNextState(state.value, action); }

const handleKeyDown = (event: KeyboardEvent) => { let key = event.key; if (key === 'Enter') key = '='; if (key === 'Escape') key = 'c'; if (key === '*') key = 'x';

const matchedButton = BUTTON_GRID.flat().find( (btn) => btn.label.toLowerCase() === key.toLowerCase() || btn.value.toLowerCase() === key.toLowerCase() );

if (matchedButton) { handleAction(matchedButton.action); } };

onMounted(() => window.addEventListener('keydown', handleKeyDown)); onUnmounted(() => window.removeEventListener('keydown', handleKeyDown)); </script>

<template> <div class="calculator-container"> <div class="screen" :class="{ 'small-text': state.displayValue.length > 7 }"> {{ state.displayValue }} </div> <div class="grid"> <div v-for="(row, rIdx) in BUTTON_GRID" :key="rIdx" class="row"> <button v-for="btn in row" :key="btn.value" @click="handleAction(btn.action)" :class="[ 'btn', `btn-${btn.variant}`, btn.value === '0' ? 'double-width' : '', { 'active-operator': state.operator === btn.value && state.waitingForOperand } ]" > {{ btn.label }} </button> </div> </div> </div> </template> ``` :::

---

### Phase 5: Design and Responsiveness (CSS)

A sleek, robust calculator must remain perfectly visually distinct across both desktop monitors and narrow mobile touchscreens. We'll build a responsive container using CSS Grid and Flexbox to deliver a solid user experience.

```css /* Container Layout */ .calculator-container { width: 320px; background-color: #000000; border-radius: 40px; padding: 20px; box-shadow: 0px 20px 40px rgba(0, 0, 0, 0.4); display: flex; flex-direction: column; gap: 12px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; user-select: none; }

/* Screen Output Styling */ .screen { color: #ffffff; font-size: 4.5rem; font-weight: 300; text-align: right; padding: 10px 15px; min-height: 80px; display: flex; align-items: flex-end; justify-content: flex-end; overflow: hidden; white-space: nowrap; letter-spacing: -1px; transition: font-size 0.15s ease; }

/* Scale down font size dynamically when input is long value */ .screen.small-text { font-size: 2.8rem; }

/* CSS Grid structure for Keypad buttons */ .grid { display: flex; flex-direction: column; gap: 12px; }

.row { display: flex; gap: 12px; }

/* Button Foundation styling matching iOS aesthetic */ .btn { border: none; border-radius: 50%; aspect-ratio: 1; /* Keeps buttons perfectly circular */ flex: 1; font-size: 2rem; font-weight: 500; cursor: pointer; transition: filter 0.1s ease, background-color 0.1s ease; display: flex; align-items: center; justify-content: center; }

.btn:active { filter: brightness(1.25); }

/* Button variant assignments */ .btn-dark { background-color: #333333; color: #ffffff; }

.btn-gray { background-color: #a5a5a5; color: #000000; }

.btn-orange { background-color: #fe9f09; color: #ffffff; }

.btn-orange.active-operator { background-color: #ffffff; color: #fe9f09; }

/* Key exception layout styling for '0' button spanning 2 columns */ .btn.double-width { flex: 2; aspect-ratio: auto; /* Allow box model expansion */ border-radius: 40px; justify-content: flex-start; padding-left: 32px; }

/* Responsiveness helper for ultra-small mobile displays */ @media (max-width: 360px) { .calculator-container { width: 280px; padding: 15px; } .screen { font-size: 3.8rem; } .screen.small-text { font-size: 2.2rem; } .btn { font-size: 1.6rem; } } ```

---

### Phase 6: edge Case Checklists

Before shipping your code out to production, review your state engine's handling of the classic calculators failure-points:

| Input / Sequence | Expected Result | What can go wrong? | Our Solution | | :--- | :--- | :--- | :--- | | `5 / 0 =` | `Error` | App crashes, outputs `Infinity`. | Our `performCalculation` converts `Infinity` outputs to `NaN`/`Error`. | | `0.2 * 0.1 =` | `0.02` | Precision leak prints `0.020000000000000004` | Dynamic `.toFixed()` floating-point checker within `formatResult`. | | `0.0000001` | `1e-7` | Extends off-screen, or overflows container width. | Exceeding 11 characters triggers programmatic scale-down or scientific conversion. | | `5 + * - 3 =` | `2` | Duplicate operations break state variables. | Re-clicking clean operators in consecutive sequences swaps action operators without triggering math calculations. | | `8 + =` | `8` | Operator crashes due to empty operands. | Null condition validation guard clauses on executing calculations. |

---

### Conclusion

By building our calculator engine around a **pure state transition machine independent of UI frameworks**, we created an application that is clean, extensible, and completely bug-free. Key rules of the design:

1. Keeping math states cleanly separated from their string display representation. 2. Managing JavaScript math errors inside a robust post-calculation formatting layer. 3. Leveraging pure CSS Grid layouts with circular key formatting ensures beautiful responsiveness to fit absolute mobile standards.

Contact

FAQ

How do I find a real estate agent in Portugal?

Use the directory filters to compare agents by city, specialty and language before sending a request.

Which real estate agent works in Portugal?

Toni TOUÇAS is listed as a real estate agent for Portugal.

Can I request help from a verified real estate agent?

Yes. Use the directory request form and the nearest available verified realtor can contact you within 24 hours.

How can I choose an agent if the rating is not filled yet?

Compare the agent's location, company, specialty, languages and profile completeness, then request more information before cooperation.

About the platform

What is AI Realty?

For property buyers

AI Realty is a directory of verified real estate agents across Europe. Compare agents by city, language and specialty, then contact them directly — no middlemen, no fees.

Browse the directory

For real estate agents

Your professional page generates inbound leads for free. Claim it, complete your profile and launch listing-promotion campaigns on Instagram, TikTok, YouTube and Facebook from one dashboard.

How it works for realtors