Are you Toni?
This is your page on AI Realty. We invest our own budget in advertising listings from top realtors. Claim your profile to see your AI Realty Score and how visible you are in AI search, and to submit your listings to the investment program.
- AI Realty Score:
- available once you claim your profile
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.
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. Contact Toni TOUÇAS directly from this page, or browse other verified realtors in Portugal in the directory.
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.
Is this your page? With Premium, other realtors aren't shown here. Learn more →
More agents in Portugal
Olga Fionik
Real Estate Agent
My name is Olga Fionik, and I’ve been in Portugal for over 15 years. My journey in real estate began with personal investment projects based on a system and calculations. Now I help others. I work at one of Portugal’s largest agencies, @zome.pt, and I have a strong team of professionals behind me. My specialization is the secondary market and properties for investment and restoration, as well as new buildings. The main locations are Lisbon and the surrounding area, Cascais, Mafra, Setúbal. For other regions, I work based on the client’s request. I fully understand the client’s goals and provide comprehensive support throughout the process of purchasing the right property, whether it’s an investment or a home for living. I work professionally, clearly, and without unnecessary emotions, using the necessary professional tools, and focus on achieving results, which is why relationships with clients and partners last for many years. For me, my work is not a tedious routine, as each new request is different from the previous one, and I have to solve new problems. Currently, I manage 16 income‑generating units, including my own and those of my investors. I constantly communicate with tenants and know how to conduct the selection process in such a way that there are no problems later on.
Dimitri Pushkar
Real Estate Agent
Online property viewing, airport pickup, premium service. Get a mortgage estimate (mortgages are issued to U.S. citizens) Not About Volume. About Value. COIN Real Estate is a boutique agency specialising in premium and luxury property in Cascais, Estoril and the Lisbon Coast. The agency's portfolio includes apartments and villas in prime coastal locations by the ocean, near the marina and in the heart of Cascais. COIN's clients are international buyers from the United States, Germany and across Europe who choose Portugal for lifestyle, relocation or investment. The agency works with a limited number of properties and clients ensuring precise market positioning, strong negotiation and full transaction transparency. Every deal, from the first consultation to the final signature, is built on clarity, legal security and long-term value.
Elena Tsvet
Real Estate Agent
Elena Tsvet - Real Estate Consultant, MA Properties. She working across both sales and rentals throughout Portugal. Her portfolio ranges from spacious villas with private pools in the Lisbon area (Mafra) to compact rental apartments in the heart of the capital (Parque das Nações) and Cascais, as well as coastal apartments in Figueira da Foz. Elena guides clients through every stage of a transaction from finding the right property for their budget and goals (whether for living, leisure, or investment) to handling the paperwork operating under license AMI 11631, registered to Mauniverse Investments, Unipessoal Lda.
Alexandra Viveiros
Broker Associate/Team Leader
Alexandra Viveiros is a Broker Associate and Team Leader at RE/MAX Expo who works in Lisbon, Portugal. Holding Registered Realtor License Nº 1544, she has been certified by RE/MAX University from 2003-present and certified by RE/MAX Collection since 2005. She has been a member of the 100% Club International since 2004, and she currently has 12 properties to buy. Her academic credentials include a BSc. Major in Chemistry, with Distinction, from McGill University (1985), a Minor in Photography from Concordia University (1986), and a Minor in Greek Studies from Université de Montreal (1986). She holds a Masters in Marketing & International Studies from INDEG- ISCTE (1995-1996), and studied Mandarin & Chinese Business at ISEG (2014). She also studied Luxury Management at Católica University (2021) and Leadership and Management at AESE Business School (2024-2025). Additionally, she holds executive degrees in Social Media Marketing (2014), Luxury Products from the Louis Vuitton Group (2015), Team Leadership (2016), and Resilience in turbulent times (2019). Her specialties are Luxury Management, Investment Opportunities, Team Leadership, and Social Media Marketing. She speaks English, Portuguese, French, Italian, Greek, and Mandarin.
Igor Meshchaninov
Real Estate Agent
Top 10 real estate agents in Portugal (Cascais, Lisbon, Setúbal) - Russian-english speaking. Investment Commercial Residential Purchase / Sale / Rent Mortgage Portugal Keys 8 years of experience, +150 clients, worked for a year at RE/MAX. License 23055 3 brokers in the team, working areas: Lisbon, Cascais, Setubal, Oeiras Igor Meschaninov (Portugal Keys) is a real estate agent based in Lisboa, Portugal, helping local and international buyers and sellers navigate the Lisbon property market with clear, practical guidance. From first viewing to closing, Igor focuses on transparent communication, accurate pricing context and a smooth transaction process. Whether you are searching for an apartment in central Lisbon, a family home in the wider metropolitan area, or looking to sell a property with confidence, Igor combines local neighborhood knowledge with a structured, client-first approach. Specialties: residential sales, buyer representation, relocation support, local market analysis. Service area: Lisboa, Portugal and surrounding municipalities. Languages: English, Russian, Portuguese. Contact Igor Meschaninov directly through AI Realty to discuss your property goals in Lisboa. Website: https://www.portugal-keys.com Игорь Мещанинов входит в топ-10 агентов недвижимости Португалии (Лиссабон, Кашкайш, Сетубал). - русскоязычных Portugal Keys более 8 лет помогает купить или продать недвижимость в Португалии. С клиентами работают 3 брокера, специализирующихся на жилой, инвестиционной и коммерческой недвижимости. Команда говорит на русском, английском, португальском и французском языках. Подбираем квартиры, дома, виллы, новостройки, коммерческие объекты и готовый бизнес. Для инвесторов анализируем потенциальную доходность, ликвидность, риски и сценарии выхода, а перед покупкой готовим понятный отчёт по объекту. Сопровождаем подбор, переговоры, ипотеку, проверку документов и юридическую часть сделки. Также помогаем новым резидентам разобраться с районами, школами, инфраструктурой, переездом и бытовыми вопросами. Первая консультация — бесплатно.
Olena Bykovets
An all-in-one relocation service for families and businesses in Portugal!
Olena Bykovets is the founder of RelyOn Relocation, a Portugal-based relocation company specializing in helping American individuals and families successfully move to Portugal. With offices in Portugal and Miami, FL, RelyOn provides end-to-end support including residency & citizenship, tax optimization (NHR/IFICI regimes), property assistance, insurance, and full settling-in services. Key strengths: Founder-led service — every client works directly with Olena TOP 10 relocation company in Portugal First-page Google presence for relocation services Results-based payment model (50% upfront, 50% after document submission) €150 paid consultation (deductible from full service) with personalized action plan Ideal clients: Remote professionals, entrepreneurs, early retirees, and families from the US who value professional guidance over DIY approaches. Core advantages of Portugal for Americans: One of the safest countries in the world Cost of living ~2× lower than the US (lifestyle upgrade) Free public healthcare for residents
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 directoryFor realtors
We invest our own budget in advertising listings from realtors with a high AI Realty Score. Claim your profile, and everything else happens on WhatsApp: you add listings and deals, climb the rating and submit listings to the investment program. We handle the ads and initial lead qualification, and you pay for advertising only when a deal closes.
