Agents Directory/Portugal/Catarina Neves

Are you Catarina?

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
Catarina Neves profile

Catarina Neves

Real Estate Agent · CENTURY 21 P.M. Paiva & Associados II · Portugal

CallEmailWebsite

About Catarina

Catarina Neves is a professional Real Estate Agent working with CENTURY 21 P.M. Paiva & Associados II in Portugal. Committed to maintaining industry standards and professional competence, she has completed specialized training paths including the "Caminho Formativo EXPAND" and "SER&ESTAR CENTURY 21."

In addition to her core real estate training, Catarina has successfully completed training on AML/CFT (Prevenção de Branqueamento de Capitais e Combate ao Terrorismo). This education ensures she is fully prepared to handle real estate transactions with a strong understanding of anti-money laundering and counter-terrorist financing prevention regulations.

Listings

Properties

3 photos€550,000

R. Caetanos 2, Lisbon, Portugal

Apartment for sale · 1 rooms · 1 bathrooms · 81.56 m². Features: near bank, near amenities, near police, near pharmacy, near metro, near taxi rank.

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?

Catarina Neves 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.

More agents in Portugal

Joaquim da Silva

Joaquim da Silva

ws_agent

SS

Sandra Silva

ws_agent

Emília Montenegro

Emília Montenegro

ws_agent

Emilia Montenegro is a professional Real Estate Agent working with CENTURY 21 Arquitectos in Portugal. She has completed specialized industry training programs to develop her skills, including the CREATE 21 Golden Edition: Etapa Presencial Porto and the Ser&Estar training course. To ensure compliance with financial regulations and industry standards, Emilia has also completed the training program PREVENCAO DE BRANQUEAMENTO DE CAPITAIS E COMBATE AO TERRORISMO 2024. Based on client testimonials, she serves clients across several locations in North Portugal. Her brokerage services cover Porto, Avintes, Ermesinde, and Santa Maria da Feira.

João Fialho

João Fialho

ws_agent

João Fialho is a professional real estate agent associated with CENTURY 21 Home Vintage in Portugal. He has completed specialized industry training to develop his professional skills and knowledge within the real estate sector. His formal training includes the completion of the AVALIAÇÃO IMOBILIÁRIA (Real Estate Valuation) course and the Ser&Estar training program. Additionally, he has completed the Caminho Formativo EXPAND (EXPAND Training Path).

Ana Peralta

Ana Peralta

ws_agent

Ana Peralta is a professional real estate consultant (Consultores) at CENTURY 21 Via in Portugal. She is dedicated to serving her clients in the property market by utilizing the structured training and methodologies of the CENTURY 21 network. To develop her skills and industry knowledge, Ana has successfully completed specialized real estate training programs. Her qualifications include the completion of the Caminho Formativo EXPAND training program and the SER&ESTAR CENTURY 21 training program.

Toni TOUÇAS

Toni TOUÇAS

ws_agent

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.

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