diff --git a/src/components/ImageUpload2.jsx b/src/components/ImageUpload2.jsx index b960c88..c0009f4 100644 --- a/src/components/ImageUpload2.jsx +++ b/src/components/ImageUpload2.jsx @@ -37,7 +37,7 @@ function ImageUpload({ files, setFiles }) { onDrop, accept: 'image/jpeg, image/png', maxFiles: 5, - maxSize: 5000000 // 5MB + maxSize: 50000000 // 5MB }); return ( @@ -51,7 +51,7 @@ function ImageUpload({ files, setFiles }) {
- Hasta 5 imágenes en formato PNG o JPG + Hasta 5 imágenes (máximo 1 MB cada una) en formato PNG o JPG
- Watermark - - {/* Diálogo de Términos y Condiciones */} TÉRMINOS Y CONDICIONES DE USO GEOMAP CONDICIONES GENERALES diff --git a/src/pages/users/publicaciones.jsx b/src/pages/users/publicaciones.jsx index 8a04220..d30b769 100644 --- a/src/pages/users/publicaciones.jsx +++ b/src/pages/users/publicaciones.jsx @@ -3,7 +3,6 @@ import { useNavigate } from 'react-router-dom'; import '../../styles/users/publicaciones.css'; import Navbar from '../../components/Navbar'; import Footer from '../../components/Footer'; -import MostrarPublicacion from './ymostrar.jsx'; function Publicaciones() { const navigate = useNavigate(); @@ -20,7 +19,7 @@ function Publicaciones() {

No tienes publicaciones aún. ¡Crea una nueva publicación para empezar!

- +
); diff --git a/src/pages/users/ymostrar.jsx b/src/pages/users/ymostrar.jsx index 5e8ceb8..f86d52c 100644 --- a/src/pages/users/ymostrar.jsx +++ b/src/pages/users/ymostrar.jsx @@ -2,27 +2,7 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; const MostrarPublicacion = ({ id }) => { - const [post, setPost] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - id = 1; - - useEffect(() => { - // Función para obtener la publicación - const fetchPost = async () => { - try { - const response = await axios.get(`http://localhost:8000/post/posts/${id}`); - setPost(response.data); - setLoading(false); - } catch (err) { - console.error('Error al obtener la publicación:', err); - setError('Error al obtener la publicación.'); - setLoading(false); - } - }; - - fetchPost(); - }, [id]); + if (loading) { return

Cargando publicación...

; @@ -34,13 +14,7 @@ const MostrarPublicacion = ({ id }) => { return (
-

{post.nombre}

-

Descripción: {post.descripcion}

-

Dirección: {post.direccion}

-

Precio: {post.precio}

-

Contacto: {post.contacto}

-

URL de contacto: {post.contacto_url}

-

Coordenadas: {post.latitude}, {post.longitude}

+

Publicacion

); }; diff --git a/src/pages/users/zgastronomia.jsx b/src/pages/users/zgastronomia.jsx index 20d4817..e3ce453 100644 --- a/src/pages/users/zgastronomia.jsx +++ b/src/pages/users/zgastronomia.jsx @@ -1,16 +1,12 @@ import '../../styles/users/zgastronomia.css'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import { TextField, - MenuItem, - FormControl, - InputLabel, - Select, - Button, - Checkbox, - FormControlLabel, + Box, Typography, + FormControlLabel, + Checkbox } from '@mui/material'; import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api'; @@ -20,103 +16,83 @@ const mapContainerStyle = { }; const center = { - lat: -33.4489, // Cambia esto a la latitud de tu ubicación inicial - lng: -70.6693 // Cambia esto a la longitud de tu ubicación inicial + lat: -33.4489, + lng: -70.6693 }; -const subcategories = [ - { label: 'Restaurant', value: 'Restaurant' }, - { label: 'Cafetería', value: 'Cafetería' }, - { label: 'Bar', value: 'Bar' }, - { label: 'Heladería', value: 'Heladería' } -]; +const googleApiKey = "AIzaSyAJuzF9SX5VP6CU38hq-lgRopJ66jYgb5E"; // Reemplaza con tu API Key -function GastronomiaForm({ handleNext }) { - const [markerPosition, setMarkerPosition] = useState(center); // Estado para la posición del marcador - const [userLocation, setUserLocation] = useState(null); // Estado para la ubicación del usuario - const [formData, setFormData] = useState({ - subcategoria: '', - titulo: '', - descripcion: '', - ubicacion: '', - nombreContacto: '', - celularContacto: '', - mailContacto: '', - instagram: '', - facebook: '', - paginaWeb: '', - disponible: false, - aptoVeganos: false, - aptoVegetarianos: false, - aptoCeliacos: false, - }); - const [errors, setErrors] = useState({}); +function GastronomiaForm({ formData, errors, onInputChange, onNext }) { + const [markerPosition, setMarkerPosition] = useState(center); + const autocompleteRef = useRef(null); + const inputRef = useRef(null); + const mapRef = useRef(null); - // Función para obtener la dirección a partir de coordenadas - const getAddressFromLatLng = async (lat, lng) => { - const apiKey = "AIzaSyAJuzF9SX5VP6CU38hq-lgRopJ66jYgb5E"; // Reemplaza con tu API key - const response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${apiKey}`); - const data = await response.json(); - if (data.results && data.results.length > 0) { - return data.results[0].formatted_address; + useEffect(() => { + // Configuración de Autocomplete con verificación + const initializeAutocomplete = () => { + if (window.google && inputRef.current) { + autocompleteRef.current = new window.google.maps.places.Autocomplete(inputRef.current, { + fields: ["formatted_address", "geometry"], + types: ["address"], + componentRestrictions: { country: ["cl"] } + }); + autocompleteRef.current.addListener("place_changed", handlePlaceSelect); + } + }; + + const intervalId = setInterval(() => { + if (window.google && window.google.maps && window.google.maps.places) { + clearInterval(intervalId); + initializeAutocomplete(); + } + }, 200); + + return () => clearInterval(intervalId); + }, []); + + const handlePlaceSelect = () => { + const place = autocompleteRef.current.getPlace(); + if (place.geometry && place.geometry.location) { + const location = place.geometry.location; + setMarkerPosition({ lat: location.lat(), lng: location.lng() }); + onInputChange('ubicacion', place.formatted_address); + + if (mapRef.current) { + mapRef.current.panTo(location); + mapRef.current.setZoom(15); + } } else { - return ''; + console.error("No se encontró la ubicación seleccionada."); } }; const handleMapClick = async (event) => { const lat = event.latLng.lat(); const lng = event.latLng.lng(); - setMarkerPosition({ lat, lng }); // Actualiza la posición del marcador + setMarkerPosition({ lat, lng }); - const address = await getAddressFromLatLng(lat, lng); // Obtiene la dirección - setFormData((prev) => ({ ...prev, ubicacion: address })); // Actualiza el campo de ubicación - }; - - useEffect(() => { - // Obtener ubicación actual del usuario - if (navigator.geolocation) { - navigator.geolocation.getCurrentPosition(async (position) => { - const newLocation = { - lat: position.coords.latitude, - lng: position.coords.longitude, - }; - setUserLocation(newLocation); - setMarkerPosition(newLocation); - - const address = await getAddressFromLatLng(newLocation.lat, newLocation.lng); // Obtiene la dirección de la ubicación actual - setFormData((prev) => ({ ...prev, ubicacion: address })); - }, () => { - alert("No se pudo obtener la ubicación."); - }); - } else { - alert("Geolocalización no es soportada en este navegador."); + const address = await getAddressFromLatLng(lat, lng); + if (address) { + onInputChange('ubicacion', address); } - }, []); + }; - const handleInputChange = (field, value) => { - setFormData(prev => ({ ...prev, [field]: value })); - setErrors(prev => ({ ...prev, [field]: '' })); // Reset error when value changes + const getAddressFromLatLng = async (lat, lng) => { + const response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${googleApiKey}`); + const data = await response.json(); + return data.results && data.results.length > 0 ? data.results[0].formatted_address : ''; }; - const validateForm = () => { - const newErrors = {}; - if (!formData.subcategoria) newErrors.subcategoria = 'Selecciona un tipo de establecimiento.'; - if (!formData.titulo) newErrors.titulo = 'Escribe un título.'; - if (!formData.descripcion) newErrors.descripcion = 'Escribe una descripción.'; - if (!formData.ubicacion) newErrors.ubicacion = 'Escribe una ubicación (Ej: Calle 123, Comuna, Ciudad).'; - if (!formData.celularContacto && !formData.mailContacto) { - newErrors.contacto = 'Debes incluir al menos el número de celular de contacto o el mail de contacto.'; - } - setErrors(newErrors); - return Object.keys(newErrors).length === 0; + const handleInputChange = (field, value) => { + onInputChange(field, value); }; const handleSubmit = (e) => { e.preventDefault(); if (validateForm()) { console.log('Formulario válido, proceder...'); - handleNext(); + onNext(); } else { console.log('Errores en el formulario:', errors); } @@ -127,88 +103,68 @@ function GastronomiaForm({ handleNext }) {

Restaurantes y Comida

Ingresa la información de tu publicación

- - Tipo de Establecimiento - - {errors.subcategoria && {errors.subcategoria} || 'Campo Obligatorio'} - - handleInputChange('titulo', e.target.value)} margin="normal" + multiline error={Boolean(errors.titulo)} - helperText={errors.titulo || 'Campo Obligatorio'} + helperText={errors.titulo} /> handleInputChange('descripcion', e.target.value)} margin="normal" multiline rows={4} error={Boolean(errors.descripcion)} - helperText={errors.descripcion || 'Campo Obligatorio'} + helperText={errors.descripcion} /> -
- handleInputChange('ubicacion', e.target.value)} - margin="normal" - error={Boolean(errors.ubicacion)} - helperText={errors.ubicacion || 'Campo Obligatorio'} - /> - handleInputChange('numeroUbicacion', e.target.value)} - margin="normal" - /> -
+ handleInputChange('ubicacion', e.target.value)} + margin="normal" + error={Boolean(errors.ubicacion)} + helperText={errors.ubicacion} + /> - {/* Reemplaza con tu API key */} + { mapRef.current = map; }} > - {/* Campos de contacto */} -
+ handleInputChange('nombreContacto', e.target.value)} margin="normal" + error={Boolean(errors.nombreContacto)} + helperText={errors.nombreContacto} /> - handleInputChange('celularContacto', e.target.value)} margin="normal" @@ -216,48 +172,74 @@ function GastronomiaForm({ handleNext }) { helperText={errors.celularContacto} type="number" /> - handleInputChange('mailContacto', e.target.value)} margin="normal" error={Boolean(errors.mailContacto)} helperText={errors.mailContacto} /> -
- - {errors.contacto && {errors.contacto} || 'Incluir al menos el número de celular o mail de contacto'} - - {/* Red social y opciones */} -
- handleInputChange('instagram', e.target.value)} margin="normal" /> - handleInputChange('facebook', e.target.value)} margin="normal" /> - handleInputChange('paginaWeb', e.target.value)} margin="normal" error={Boolean(errors.paginaWeb)} helperText={errors.paginaWeb} /> -
+ -
- handleInputChange('disponible', e.target.checked)} />} label="Actualmente Disponible" /> -
+ {errors.contacto && {errors.contacto}} -
- handleInputChange('aptoVeganos', e.target.checked)} />} label="Apto para Veganos" /> - handleInputChange('aptoVegetarianos', e.target.checked)} />} label="Apto para Vegetarianos" /> - handleInputChange('aptoCeliacos', e.target.checked)} />} label="Apto para Celíacos" /> -
- -
- -
+ + handleInputChange('instagram', e.target.value)} + margin="normal" + /> + handleInputChange('facebook', e.target.value)} + margin="normal" + /> + handleInputChange('paginaWeb', e.target.value)} + margin="normal" + error={Boolean(errors.paginaWeb)} + helperText={errors.paginaWeb} + /> + + + +
+ handleInputChange('aptoVeganos', e.target.checked)} />} + label="Apto para Veganos" + /> + handleInputChange('aptoVegetarianos', e.target.checked)} />} + label="Apto para Vegetarianos" + /> + handleInputChange('aptoCeliacos', e.target.checked)} />} + label="Apto para Celíacos" + /> +
+
); } GastronomiaForm.propTypes = { - handleNext: PropTypes.func.isRequired, + formData: PropTypes.object.isRequired, + errors: PropTypes.object.isRequired, + onInputChange: PropTypes.func.isRequired, + onNext: PropTypes.func.isRequired, }; export default GastronomiaForm; diff --git a/src/pages/users/zhospedaje.jsx b/src/pages/users/zhospedaje.jsx index 2557448..4d8e798 100644 --- a/src/pages/users/zhospedaje.jsx +++ b/src/pages/users/zhospedaje.jsx @@ -195,9 +195,12 @@ function HospedajeForm({ formData, errors, onInputChange, onNext }) { handleInputChange('nombreContacto', e.target.value)} margin="normal" + error={Boolean(errors.nombreContacto)} + helperText={errors.nombreContacto} /> onInputChange('nombreContacto', e.target.value)} + value={formData.mailContacto} + onChange={(e) => onInputChange('mailContacto', e.target.value)} margin="normal" - error={Boolean(errors.nombreContacto)} - helperText={errors.nombreContacto} + error={Boolean(errors.mailContacto)} + helperText={errors.mailContacto} /> @@ -242,34 +245,29 @@ function HospedajeForm({ formData, errors, onInputChange, onNext }) { > Privado Compartido - No tiene + No tiene -

*: Campos Obligatorios

+

*: Campos Obligatorios

- + onInputChange('disponible', e.target.checked)} />} label="Actualmente Disponible" /> - - - - - - + -

Este hospedaje incluye:

+

Este hospedaje incluye:

- + diff --git a/src/pages/users/znegocios.jsx b/src/pages/users/znegocios.jsx index 7f94a82..8681005 100644 --- a/src/pages/users/znegocios.jsx +++ b/src/pages/users/znegocios.jsx @@ -1,11 +1,9 @@ import '../../styles/users/zservicios.css'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import { TextField, - Button, - Checkbox, - FormControlLabel, + Box, Typography, } from '@mui/material'; import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api'; @@ -16,92 +14,84 @@ const mapContainerStyle = { }; const center = { - lat: -33.4489, // Cambia esto a la latitud de tu ubicación inicial - lng: -70.6693 // Cambia esto a la longitud de tu ubicación inicial + lat: -33.4489, + lng: -70.6693 }; -function NegociosForm({ handleNext }) { - const [markerPosition, setMarkerPosition] = useState(center); // Estado para la posición del marcador - const [userLocation, setUserLocation] = useState(null); // Estado para la ubicación del usuario - const [formData, setFormData] = useState({ - titulo: '', - descripcion: '', - ubicacion: '', - numeroUbicacion: '', - nombreContacto: '', - celularContacto: '', - mailContacto: '', - instagram: '', - facebook: '', - paginaWeb: '', - disponible: false, - }); - const [errors, setErrors] = useState({}); - - // Función para obtener la dirección a partir de coordenadas - const getAddressFromLatLng = async (lat, lng) => { - const apiKey = "AIzaSyAJuzF9SX5VP6CU38hq-lgRopJ66jYgb5E"; // Reemplaza con tu API key - const response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${apiKey}`); - const data = await response.json(); - if (data.results && data.results.length > 0) { - return data.results[0].formatted_address; // Retorna la primera dirección formateada +const googleApiKey = "AIzaSyAJuzF9SX5VP6CU38hq-lgRopJ66jYgb5E"; // Reemplaza con tu API Key + +function NegociosForm({ formData, errors, onInputChange, onNext }) { + const [markerPosition, setMarkerPosition] = useState(center); + const autocompleteRef = useRef(null); + const inputRef = useRef(null); + const mapRef = useRef(null); + + useEffect(() => { + // Configura el Autocomplete cuando la API de Google esté lista + const initializeAutocomplete = () => { + if (window.google && inputRef.current) { + autocompleteRef.current = new window.google.maps.places.Autocomplete(inputRef.current, { + fields: ["formatted_address", "geometry"], + types: ["address"], + componentRestrictions: { country: ["cl"] } + }); + autocompleteRef.current.addListener("place_changed", handlePlaceSelect); + } + }; + + // Espera hasta que Google Maps esté disponible, revisa cada 200ms + const intervalId = setInterval(() => { + if (window.google && window.google.maps && window.google.maps.places) { + clearInterval(intervalId); + initializeAutocomplete(); + } + }, 200); + + return () => clearInterval(intervalId); + }, []); + + const handlePlaceSelect = () => { + const place = autocompleteRef.current.getPlace(); + if (place.geometry && place.geometry.location) { + const location = place.geometry.location; + setMarkerPosition({ lat: location.lat(), lng: location.lng() }); + onInputChange('ubicacion', place.formatted_address); + + if (mapRef.current) { + mapRef.current.panTo(location); + mapRef.current.setZoom(15); + } } else { - return ''; // Retorna vacío si no se encuentra dirección + console.error("No se encontró la ubicación seleccionada."); } }; const handleMapClick = async (event) => { const lat = event.latLng.lat(); const lng = event.latLng.lng(); - setMarkerPosition({ lat, lng }); // Actualiza la posición del marcador - - const address = await getAddressFromLatLng(lat, lng); // Obtiene la dirección - setFormData((prev) => ({ ...prev, ubicacion: address })); // Actualiza el campo de ubicación - }; + setMarkerPosition({ lat, lng }); - useEffect(() => { - // Obtener ubicación actual del usuario - if (navigator.geolocation) { - navigator.geolocation.getCurrentPosition(async (position) => { - const newLocation = { - lat: position.coords.latitude, - lng: position.coords.longitude, - }; - setUserLocation(newLocation); - setMarkerPosition(newLocation); - - const address = await getAddressFromLatLng(newLocation.lat, newLocation.lng); // Obtiene la dirección de la ubicación actual - setFormData((prev) => ({ ...prev, ubicacion: address })); - }, () => { - alert("No se pudo obtener la ubicación."); - }); - } else { - alert("Geolocalización no es soportada en este navegador."); + const address = await getAddressFromLatLng(lat, lng); + if (address) { + onInputChange('ubicacion', address); } - }, []); + }; - const handleInputChange = (field, value) => { - setFormData(prev => ({ ...prev, [field]: value })); - setErrors(prev => ({ ...prev, [field]: '' })); // Reset error when value changes + const getAddressFromLatLng = async (lat, lng) => { + const response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${googleApiKey}`); + const data = await response.json(); + return data.results && data.results.length > 0 ? data.results[0].formatted_address : ''; }; - const validateForm = () => { - const newErrors = {}; - if (!formData.titulo) newErrors.titulo = 'Escribe un título.'; - if (!formData.descripcion) newErrors.descripcion = 'Escribe una descripción.'; - if (!formData.ubicacion) newErrors.ubicacion = 'Escribe una ubicación (Ej: Calle 123, Comuna, Ciudad).'; - if (!formData.celularContacto && !formData.mailContacto) { - newErrors.contacto = 'Debes incluir al menos el número de celular de contacto o el mail de contacto.'; - } - setErrors(newErrors); - return Object.keys(newErrors).length === 0; + const handleInputChange = (field, value) => { + onInputChange(field, value); }; const handleSubmit = (e) => { e.preventDefault(); if (validateForm()) { console.log('Formulario válido, proceder...'); - handleNext(); + onNext(); } else { console.log('Errores en el formulario:', errors); } @@ -114,68 +104,66 @@ function NegociosForm({ handleNext }) { handleInputChange('titulo', e.target.value)} error={Boolean(errors.titulo)} - helperText={errors.titulo || 'Campo Obligatorio'} + helperText={errors.titulo} /> handleInputChange('descripcion', e.target.value)} error={Boolean(errors.descripcion)} - helperText={errors.descripcion || 'Campo Obligatorio'} + helperText={errors.descripcion} /> -
- handleInputChange('ubicacion', e.target.value)} - error={Boolean(errors.ubicacion)} - helperText={errors.ubicacion || 'Campo Obligatorio'} - /> - handleInputChange('numeroUbicacion', e.target.value)} - margin="normal" - /> -
+ handleInputChange('ubicacion', e.target.value)} + error={Boolean(errors.ubicacion)} + helperText={errors.ubicacion} + /> - + { mapRef.current = map; }} > -
+ handleInputChange('nombreContacto', e.target.value)} + error={Boolean(errors.nombreContacto)} + helperText={errors.nombreContacto} /> handleInputChange('celularContacto', e.target.value)} type="number" @@ -184,66 +172,55 @@ function NegociosForm({ handleNext }) { /> handleInputChange('mailContacto', e.target.value)} error={Boolean(errors.mailContacto)} helperText={errors.mailContacto} /> -
+
- {errors.contacto && {errors.contacto} || 'Incluir al menos el número de celular o mail de contacto'} + {errors.contacto && {errors.contacto}} -
+ handleInputChange('instagram', e.target.value)} /> handleInputChange('facebook', e.target.value)} /> handleInputChange('paginaWeb', e.target.value)} error={Boolean(errors.paginaWeb)} helperText={errors.paginaWeb} /> -
- -
- handleInputChange('disponible', e.target.checked)} - /> - } - label="Actualmente Disponible" - /> -
- -
- -
+
); } NegociosForm.propTypes = { - handleNext: PropTypes.func.isRequired, + formData: PropTypes.object.isRequired, + errors: PropTypes.object.isRequired, + onInputChange: PropTypes.func.isRequired, + onNext: PropTypes.func.isRequired, }; export default NegociosForm;