Are you Luciano?

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
Luciano Leal profile

Luciano Leal

Real Estate Agent · CENTURY 21 Polo Central II · Portugal

CallEmailWebsite

About Luciano

Luciano Leal is a professional real estate consultant (Consultor Imobiliario) working at CENTURY 21 Polo Central II in Portugal. He has completed several certified training programs to support his practice, including the Code of Ethics and Conduct (Codigo de Etica e Conduta - CEC) and the CREATE 21 Golden Edition: Etapa Presencial Lisboa.

Furthering his professional education, Luciano has completed the Ser&Estar training, as well as the 2024 course on the Prevention of Money Laundering and Combating the Financing of Terrorism (Prevencao de Branqueamento de Capitais e Combate ao Terrorismo 2024). His performance in the industry has been recognized with the 2025 MASTER RUBY PRODUCER award.

Listings

Properties

3 photos€750,000

R. Casal do Alfaiate 2, 2665-565 Venda do Pinheiro, Portugal

House for sale · 3 rooms · 2 bathrooms · 238.6 m². Features: video intercom, country view, city view, mountain view, wooden floor, stone floor.

Reviews

What clients say

"I would like to thank you for your service as a real estate consultant. First of all you didn’t give up although I took a long time to choose and make a final decision to close the deal. Your suggestion to take this apartment was timely and correct. It was a good decision! "
Daniel RHAKSHOURIFebruary 2026
" foi excelente o seu trabalho obrigado"
António FerroSeptember 2025
Gostámos muito da visita, obtivemos resposta a todas as nossas dúvidas e a sua postura foi muito profissional e atenta.
Filipe e SóniaSeptember 2025
Muito obrigado, mais uma vez, pela forma tão cordial, profissional e disponível com que nos recebeu durante a visita ao apartamento.
Eduardo e JoanaSeptember 2025

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?

Luciano Leal 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

Miguel Portela

Miguel Portela

ws_agent

Miguel Portela is a Consultor at CENTURY 21 Realty Art M&J, located in Portugal. He has completed the CREATE 21 Golden Edition: Etapa Presencial Lisboa training program to develop his skills in the real estate sector. Additionally, Miguel has completed the Ser&Estar training program. He utilizes this combination of professional training in his role as a real estate agent with the agency.

Diogo Malha

Diogo Malha

ws_agent

Adriano Marchesini

Adriano Marchesini

ws_agent

Adriano Marchesini is an arquiteto e consultor imobiliario at CENTURY 21 Realty Art Foz in Portugal. His professional career has been developed across the fields of architecture, rehabilitation, and property sales. He holds a Bachelor's degree in Architecture and Urbanism from UNESA in Rio de Janeiro, Brazil, a Master's degree in Interior Design from the Accademia D'Arte e Design Leonetto Cappiello in Florence, Italy, and a Post-graduate degree in Rehabilitation of Built Heritage from the Faculty of Engineering of the University of Porto. To support his real estate practice, Adriano has completed extensive specialized training. This includes the CREATE 21 Golden Edition training (Porto In-person stage), as well as dedicated courses in Empreendimento Bloom Marinha, Leasing Imobiliario, and Ser&Estar CENTURY 21. Additionally, he completed training in the Prevention of Money Laundering and Combating Terrorism in 2021. Adriano has consistently achieved recognition for his performance within the CENTURY 21 network. He won the Master Emerald Producer award in 2021, the Master Ruby Producer award in 2022, and the Master Diamond Producer award in 2023. Most recently, he won the Centurion Producer award in 2024 and the CENTURION PRODUCER award in 2025.

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.

Luisa Rodrigues

Luisa Rodrigues

ws_agent

Luisa Rodrigues is a professional Real Estate Agent with CENTURY 21 Evolution in Portugal, bringing 15 years of experience to the sector. Throughout her career, she has completed a comprehensive suite of professional training programs, including CREATE 21 Golden Edition, SER&ESTAR CENTURY 21, Trans 21, and Como Angariar Imóveis Vendáveis. She has also completed specialized training in Prevenção de Branqueamento de Capitais e Combate ao Terrorismo 2021. Her performance and dedication in the industry have been recognized with multiple professional awards. Luisa received the Ruby Award in 2012, 2013, 2016, 2017, and 2018. Additionally, she was honored with the Diamond Award in 2014.

Ismael Castro

Ismael Castro

ws_agent

Ismael Castro is a Consultor at CENTURY 21 Inca Linha in Portugal. He assists clients in achieving their real estate goals, whether they are buying, selling, or leasing a home, store, or office. In preparation for his role, Ismael has completed specialized professional training. This includes the SER&ESTAR CENTURY 21 training program as well as training in the Code of Ethics and Conduct (CEC).

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