Ir al contenido principal

Componente React de lista dinámica (filtrada por una condición)

Esto es código pleno. Consta de un array llamado dummySuggestions, al cual se le aplica un método filter para simular una búsqueda, cuyo resultado se guarda en un array llamado suggestions. Después, aplicando el método map al array suggestions, se generan elementos "ul" de JSX, que es lo que finalmente va a ser la lista de elementos filtrados. Sin más, acá va el código:

import React, { useState, useEffect, useCallback } from 'react';
import { Input } from '@/Components/ui/input'; // Componente Input de shadcn/ui
import { Button } from '@/Components/ui/button'; // Componente Button de shadcn/ui
import { MapPin, Search } from 'lucide-react'; // Iconos de lucide-react

// Este es un componente conceptual. En un proyecto real,
// integrarías una librería como @react-google-maps/api o similar
// para el autocompletado y geocodificación real.

function AddressInputWithMap({ initialData = {}, onAddressChange }) {
// Estado para los campos del domicilio
const [address, setAddress] = useState(initialData.address || '');
const [country, setCountry] = useState(initialData.country || '');
const [province, setProvince] = useState(initialData.province || '');
const [city, setCity] = useState(initialData.city || '');
const [district, setDistrict] = useState(initialData.district || ''); // Partido
const [locality, setLocality] = useState(initialData.locality || ''); // Localidad

// Estado para las sugerencias de autocompletado (simulado)
const [suggestions, setSuggestions] = useState([]);
const [loading, setLoading] = useState(false);

// Simula una llamada a una API de geocodificación/autocompletado
const fetchAddressSuggestions = useCallback(async (query) => {
if (query.length < 3) {
setSuggestions([]);
return;
}
setLoading(true);
// En un proyecto real, aquí harías un fetch a la API de Google Places Autocomplete
// o a tu propio backend que interactúe con una API de geocodificación.
// Por simplicidad, simulamos una respuesta.
const dummySuggestions = [
{
fullAddress: 'Av. Corrientes 1234, CABA, Argentina',
components: {
address: 'Av. Corrientes 1234',
city: 'Buenos Aires',
province: 'Ciudad Autónoma de Buenos Aires',
country: 'Argentina',
district: 'Comuna 3', // Ejemplo de partido/comuna
locality: 'Balvanera', // Ejemplo de localidad/barrio
},
},
{
fullAddress: 'Calle Falsa 123, Springfield, Buenos Aires, Argentina',
components: {
address: 'Calle Falsa 123',
city: 'Springfield',
province: 'Buenos Aires',
country: 'Argentina',
district: 'Partido de La Matanza', // Otro ejemplo
locality: 'Villa Elisa', // Otro ejemplo
},
},
{
fullAddress: 'Ruta 3 km 25, San Justo, Buenos Aires, Argentina',
components: {
address: 'Ruta 3 km 25',
city: 'San Justo',
province: 'Buenos Aires',
country: 'Argentina',
district: 'Partido de La Matanza',
locality: 'San Justo',
},
},
];

// Simular un retardo de red
await new Promise(resolve => setTimeout(resolve, 500));

const filteredSuggestions = dummySuggestions.filter(s =>
s.fullAddress.toLowerCase().includes(query.toLowerCase())
);
setSuggestions(filteredSuggestions);
setLoading(false);
}, []);

// Manejador para el cambio del input de dirección
const handleAddressInputChange = (e) => {
const value = e.target.value;
setAddress(value);
fetchAddressSuggestions(value);
};

// Manejador cuando se selecciona una sugerencia
const handleSelectSuggestion = (suggestion) => {
setAddress(suggestion.fullAddress);
setCountry(suggestion.components.country || '');
setProvince(suggestion.components.province || '');
setCity(suggestion.components.city || '');
setDistrict(suggestion.components.district || '');
setLocality(suggestion.components.locality || '');
setSuggestions([]); // Limpiar sugerencias
// Notificar al componente padre sobre el cambio de dirección completa
onAddressChange(suggestion.components);
};

// Efecto para notificar cambios al padre si los campos se editan manualmente
useEffect(() => {
onAddressChange({ address, country, province, city, district, locality });
}, [address, country, province, city, district, locality, onAddressChange]);


return (
<div className="space-y-4 p-4 border rounded-lg bg-white dark:bg-gray-800 shadow-sm">
<h3 className="text-lg font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2">
<MapPin className="w-5 h-5 text-[#00A896]" />
Domicilio del Paciente
</h3>

{/* Campo de Dirección con Autocompletado */}
<div>
<label htmlFor="full-address" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Dirección Completa
</label>
<div className="relative">
<Input
id="full-address"
type="text"
value={address}
onChange={handleAddressInputChange}
placeholder="Ej: Av. Corrientes 1234"
className="w-full pr-10" // Espacio para el icono de búsqueda
/>
<Search className="absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
{loading && (
<div className="absolute top-full left-0 w-full bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-md shadow-lg mt-1 z-10 p-2 text-center text-sm text-gray-500 dark:text-gray-400">
Buscando...
</div>
)}
{suggestions.length > 0 && !loading && (
<ul className="absolute top-full left-0 w-full bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-md shadow-lg mt-1 z-10">
{suggestions.map((s, index) => (
<li
key={index}
className="px-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 text-sm"
onClick={() => handleSelectSuggestion(s)}
>
{s.fullAddress}
</li>
))}
</ul>
)}
</div>
</div>

{/* Campos rellenados automáticamente (o editables) */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label htmlFor="country" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
País
</label>
<Input
id="country"
type="text"
value={country}
onChange={(e) => setCountry(e.target.value)}
placeholder="País"
className="w-full"
/>
</div>
<div>
<label htmlFor="province" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Provincia
</label>
<Input
id="province"
type="text"
value={province}
onChange={(e) => setProvince(e.target.value)}
placeholder="Provincia"
className="w-full"
/>
</div>
<div>
<label htmlFor="city" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Ciudad
</label>
<Input
id="city"
type="text"
value={city}
onChange={(e) => setCity(e.target.value)}
placeholder="Ciudad"
className="w-full"
/>
</div>
<div>
<label htmlFor="district" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Partido
</label>
<Input
id="district"
type="text"
value={district}
onChange={(e) => setDistrict(e.target.value)}
placeholder="Partido (ej. Comuna, Condado)"
className="w-full"
/>
</div>
<div>
<label htmlFor="locality" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Localidad
</label>
<Input
id="locality"
type="text"
value={locality}
onChange={(e) => setLocality(e.target.value)}
placeholder="Localidad (ej. Barrio, Pueblo)"
className="w-full"
/>
</div>
</div>

{/* Un mapa visual (conceptual) */}
<div className="w-full aspect-video bg-gray-200 dark:bg-gray-700 rounded-md flex items-center justify-center text-gray-500 dark:text-gray-400 border border-gray-300 dark:border-gray-600">
{/* Aquí iría la integración real de un mapa (ej. Google Maps Embed) */}
<p>Mapa se mostraría aquí</p>
</div>

<Button className="w-full bg-blue-600 hover:bg-blue-700 text-white">
Guardar Domicilio
</Button>
</div>
);
}

// Ejemplo de cómo usarlo en un componente padre
function PatientForm() {
const [patientAddress, setPatientAddress] = useState({
address: 'Calle Inventada 456',
country: 'Argentina',
province: 'Córdoba',
city: 'Córdoba',
district: '',
locality: 'Nueva Córdoba'
});

const handleAddressUpdate = (newAddressComponents) => {
console.log('Dirección actualizada:', newAddressComponents);
setPatientAddress(newAddressComponents);
};

return (
<div className="p-8">
<h1 className="text-3xl font-bold text-center mb-8 text-gray-900 dark:text-white">
Formulario de Paciente
</h1>
<AddressInputWithMap initialData={patientAddress} onAddressChange={handleAddressUpdate} />
<div className="mt-6 p-4 border rounded-lg bg-gray-50 dark:bg-gray-900 text-gray-700 dark:text-gray-300 text-sm">
<h3 className="font-semibold mb-2">Datos del Domicilio guardados:</h3>
<pre>{JSON.stringify(patientAddress, null, 2)}</pre>
</div>
</div>
);
}

export default PatientForm;

Comentarios

Entradas populares de este blog

Crear proyecto de frontend con Vite, React, Tailwind, Typescript y JSX

 ¿Cómo se crea un proyecto exclusivo de frontend con Vite, React, Tailwind, Typescript y JSX? ¡Absolutamente! Entiendo que quieres la guía completa para pasar de cero a tener un proyecto de frontend moderno, vacío y listo para ser llenado con tu código. A continuación, te proporciono un archivo de guía detallada que incluye todos los comandos necesarios para inicializar el proyecto, configurar Tailwind CSS, y los pasos clave para empezar a "poblarlo". Voy a generar un documento Markdown con la guía paso a paso, incluyendo los comandos de terminal y las modificaciones esenciales a los archivos de configuración. Guía: Creación de un Proyecto Frontend Puro (Vite, React, TypeScript, Tailwind) Este documento detalla el proceso para inicializar un proyecto de frontend vacío y optimizado, utilizando Vite como empaquetador, React como librería, TypeScript para tipado y Tailwind CSS para estilizado. 1. Inicialización del Proyecto con Vite Vite es la herramienta más rápida para emp...

Tokens V2

Tokens: Programme to discover tokens, where there are not. Now available at  https://puszcza.gnu.org.ua/projects/tokens/ This is Version 2, for  version 1, go here . Synopsis: use TokensV2; sub printFile; my @FORMAT = ( ['<Message Date=".*?" Time=".*?" DateTime=".*?" SessionID=".*?"><From>(?:<User FriendlyName=".*?"/>)+</From><To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style=".*?")?>.*?</Text></Message>',   sub {     my $fh = $_[1];     my ($d, $t, $f, $s, $T) = $_[0] =~ m|<Message Date="(.*?)" Time="(.*?)" DateTime=".*?" SessionID=".*?">(<From>(?:<User FriendlyName=".*?"/>)+</From>)<To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style="(.*?)")?>(.*?)</Text></Message>|;     my $F = join '<br />', ...

Perl Net::LDAP::SimpleServer

Adaptaciones sobre el módulo LDAP Server para Windows (Strawberry Perl) Lista de adaptaciones (continúa más abajo): - Relajación de condiciones de bind:     - Cuenta principal (principal account)     - Validación de contraseñas Ubicación del archivo: %Strawberry_Perl%\site\lib\net\ldap\SimpleServer\ProtocolHandler.pm CPAN: http://search.cpan.org/~russoz/Net-LDAP-SimpleServer-0.0.17/lib/Net/LDAP/SimpleServer.pm Código: package Net::LDAP::SimpleServer::ProtocolHandler; use strict; use warnings; # ABSTRACT: LDAP protocol handler used with Net::LDAP::SimpleServer our $VERSION = '0.0.17';    # VERSION use Net::LDAP::Server; use base 'Net::LDAP::Server'; use fields qw(store root_dn root_pw allow_anon); use Carp; use Net::LDAP::LDIF; use Net::LDAP::Util qw{canonical_dn}; use Net::LDAP::FilterMatch; use Net::LDAP::Constant (     qw/LDAP_SUCCESS LDAP_AUTH_UNKNOWN LDAP_INVALID_CREDENTIALS/,   ...