diff --git a/package.json b/package.json
index 6dc3028..0fe4eca 100644
--- a/package.json
+++ b/package.json
@@ -14,13 +14,16 @@
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@material-tailwind/react": "^2.1.10",
+ "@mui/icons-material": "^6.1.6",
"@mui/lab": "^6.0.0-beta.10",
"@mui/material": "^6.1.2",
"@mui/system": "^6.1.2",
"@mui/x-date-pickers": "^7.19.0",
- "@react-google-maps/api": "^2.19.3",
+ "@react-google-maps/api": "^2.20.3",
"aws-sdk": "^2.1691.0",
"axios": "^1.7.7",
+ "browser-image-compression": "^2.0.2",
+ "compress.js": "1.1.2",
"date-fns": "2.29.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
diff --git a/src/components/ImageUpload.css b/src/components/ImageUpload.css
new file mode 100644
index 0000000..0b277c7
--- /dev/null
+++ b/src/components/ImageUpload.css
@@ -0,0 +1,43 @@
+.image-upload-container {
+ max-width: 800px;
+ margin: 0 auto;
+ }
+
+ .dropzone {
+ background-color: #f9fafb; /* Color de fondo más claro */
+ transition: background-color 0.2s;
+ }
+
+ .dropzone:hover {
+ background-color: #e5e7eb; /* Color de fondo al pasar el mouse */
+ }
+
+ .image-preview {
+ margin-top: 0.5rem;
+ width: 100%; /* Asegúrate de que ocupe todo el ancho de su contenedor */
+ height: 150px; /* Altura fija para todas las imágenes */
+ object-fit: cover; /* Mantener la relación de aspecto y recortar si es necesario */
+ }
+
+ .font-medium {
+ padding-left: 10px;
+ margin-bottom: 70px;
+ }
+ .absolute{
+ position: absolute;
+ border: none;
+ background-color: transparent;
+ }
+ .absolute:hover{
+ color: #666;
+ }
+ .flex{
+ display: flex flex-wrap;
+ }
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/ImageUpload2.jsx b/src/components/ImageUpload2.jsx
new file mode 100644
index 0000000..dfad842
--- /dev/null
+++ b/src/components/ImageUpload2.jsx
@@ -0,0 +1,114 @@
+import React, { useState } from 'react';
+import { useDropzone } from 'react-dropzone';
+import DeleteIcon from '@mui/icons-material/Cancel';
+import './ImageUpload.css';
+import logo from '../assets/logoo.png';
+import imageCompression from 'browser-image-compression'; // Importa la nueva librería
+
+function ImageUpload({ files, setFiles }) {
+ const [error, setError] = useState('');
+
+ const onDrop = async acceptedFiles => {
+ if (acceptedFiles.length + files.length > 5) {
+ setError('Solo se permiten un máximo de 5 imágenes');
+ return;
+ }
+
+ setError('');
+
+ const newFiles = await Promise.all(
+ acceptedFiles.map(async file => {
+ const options = {
+ maxSizeMB: 1, // Ajusta el tamaño máximo de la imagen
+ maxWidthOrHeight: 800, // Cambia el tamaño máximo
+ useWebWorker: true,
+ };
+ const compressedFile = await imageCompression(file, options);
+ return Object.assign(compressedFile, {
+ preview: URL.createObjectURL(compressedFile)
+ });
+ })
+ );
+
+ setFiles(prevFiles => [...prevFiles, ...newFiles]);
+ };
+
+ const { getRootProps, getInputProps } = useDropzone({
+ onDrop,
+ accept: 'image/jpeg, image/png',
+ maxFiles: 5,
+ maxSize: 5000000 // 5MB
+ });
+
+ return (
+
+
+
+
+
+
+
+
+ Hasta 5 imágenes en formato PNG o JPG
+
+
+
+
+
+ {/* Aquí es donde renderizamos las imágenes dentro del dropzone */}
+
+ {files.map((file, index) => (
+
+
+
+
+
+ ))}
+
+
+
+
+ {error &&
{error}
}
+
+ );
+}
+
+export default ImageUpload;
diff --git a/src/components/TailwinSvgIcons/CrossDeleteIcon2.jsx b/src/components/TailwinSvgIcons/CrossDeleteIcon2.jsx
new file mode 100644
index 0000000..31cca8d
--- /dev/null
+++ b/src/components/TailwinSvgIcons/CrossDeleteIcon2.jsx
@@ -0,0 +1,19 @@
+export default function CrossDeleteIcon() {
+ return (
+
+ );
+ }
+
\ No newline at end of file
diff --git a/src/pages/users/publicar.jsx b/src/pages/users/publicar.jsx
index f9ca89a..9497f01 100644
--- a/src/pages/users/publicar.jsx
+++ b/src/pages/users/publicar.jsx
@@ -3,7 +3,7 @@ import { Stepper, Step, StepLabel, Button, Typography, Box, Tab, Tabs, FormHelpe
import { Link } from 'react-router-dom';
import Navbar from '../../components/Navbar';
import Footer from '../../components/Footer';
-import ImageUpload from '../../components/ImageUpload';
+import ImageUpload from '../../components/ImageUpload2';
import TurismoForm from './zturismo.jsx';
import CentrosDeportivosForm from './zcentros.jsx';
import EventosForm from './zeventos.jsx';
diff --git a/src/pages/users/zcamping.jsx b/src/pages/users/zcamping.jsx
new file mode 100644
index 0000000..a3270d4
--- /dev/null
+++ b/src/pages/users/zcamping.jsx
@@ -0,0 +1,440 @@
+import '../../styles/users/zhospedaje.css';
+import { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+import {
+ TextField,
+ MenuItem,
+ FormControl,
+ InputLabel,
+ Select,
+ Button,
+ Checkbox,
+ FormControlLabel,
+ Grid,
+ Typography,
+} from '@mui/material';
+//------------new
+import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api'; // Importar componentes de Google Maps
+const mapContainerStyle = {
+ height: "400px",
+ width: "100%"
+};
+
+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
+};
+//-----------new
+
+
+const subcategories = [
+ { label: 'Arriendo', value: 'arriendo' },
+ { label: 'Cabaña', value: 'cabaña' },
+ { label: 'Departamento', value: 'departamento' },
+ { label: 'Casa', value: 'casa' },
+ { label: 'Hospedaje', value: 'hospedaje' },
+ { label: 'Hotel', value: 'hotel' }
+];
+
+function HospedajeForm({ onNext }) {
+ //-----------new
+ 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 handleMapClick = async (event) => {
+ const lat = event.latLng.lat();
+ const lng = event.latLng.lng();
+ setMarkerPosition({ lat, lng }); // Actualiza la posición del marcador
+ // Aquí puedes agregar lógica para convertir las coordenadas en una dirección si lo deseas
+ //const address = await getAddressFromLatLng(lat, lng); //new
+ setFormData((prev) => ({ ...prev, ubicacion: `Lat: ${lat}, Lng: ${lng}` })); // Actualiza el campo de ubicación
+ };
+
+ useEffect(() => {
+ // Obtener ubicación actual del usuario
+ if (navigator.geolocation) {
+ navigator.geolocation.getCurrentPosition(position => {
+ const newLocation = {
+ lat: position.coords.latitude,
+ lng: position.coords.longitude,
+ };
+ setUserLocation(newLocation);
+ setMarkerPosition(newLocation);
+ //setFormData(prev => ({ ...prev, ubicacion: address })); //new
+ setFormData(prev => ({ ...prev, ubicacion: `Lat: ${position.coords.latitude}, Lng: ${position.coords.longitude}` }));
+ }, () => {
+ alert("No se pudo obtener la ubicación.");
+ });
+ } else {
+ alert("Geolocalización no es soportada en este navegador.");
+ }
+ }, []);
+
+ /*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
+ } else {
+ return ''; // Retorna vacío si no se encuentra dirección
+ }
+ };*/
+ //-----------new
+
+ const [formData, setFormData] = useState({
+ subcategoria: '',
+ titulo: '',
+ descripcion: '',
+ ubicacion: '',
+ numeroUbicacion: '',
+ dormitorios: '',
+ camasSimples: '',
+ camasDobles: '',
+ cantidadMinima: '',
+ cantidadMaxima: '',
+ nombreContacto: '',
+ celularContacto: '',
+ mailContacto: '',
+ instagram: '',
+ facebook: '',
+ paginaWeb: '',
+ precioPorNoche: '',
+ disponible: false,
+ incluyeDesayuno: false,
+ incluyeToallasSabanas: false
+ });
+
+ const [errors, setErrors] = useState({});
+
+
+ const handleInputChange = (field, value) => {
+ setFormData(prev => ({ ...prev, [field]: value }));
+ if (errors[name]) {
+ setErrors((prevErrors) => ({ ...prevErrors, [name]: undefined }));
+ }
+ //setErrors(prev => ({ ...prev, [field]: '' })); // Reset error when value changes
+ };
+
+ const validateForm = () => {
+ const newErrors = {};
+
+ if (!formData.subcategoria) {newErrors.subcategoria = 'Selecciona un tipo de acomodación.';}
+ 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).';
+ } else if (!/^[\w\s,.-]+$/.test(formData.ubicacion)) { // Simple regex for address format
+ newErrors.ubicacion = 'Debes seguir el formato de dirección: Calle 123, Comuna, Ciudad.';
+ }
+
+ if (!formData.dormitorios) {newErrors.dormitorios = 'Ingresa cantidad de dormitorios.';}
+ if (!formData.camasSimples) {newErrors.camasSimples = 'Ingresa cantidad de camas simples.';}
+ if (!formData.camasDobles) {newErrors.camasDobles = 'Ingresa cantidad de camas dobles.';}
+ if (!formData.cantidadMaxima) {newErrors.cantidadMaxima = 'Ingresa cantidad máxima de personas para la acomodación.';}
+ if (!formData.cantidadMinima) {newErrors.cantidadMinima = 'Ingresa cantidad mínima de personas para la acomodación.';}
+
+ if (!formData.celularContacto && !formData.mailContacto) {
+ newErrors.contacto = 'Debes incluir al menos el número de celular de contacto o el mail de contacto.';
+ } else {
+ if (formData.celularContacto && !/^\d+$/.test(formData.celularContacto)) { // Validar que solo incluya números
+ newErrors.celularContacto = 'El número de celular debe contener solo números. Ej: 9 8765 4321.';
+ }
+ if (formData.mailContacto && !/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(formData.mailContacto)) { // Simple regex for email
+ newErrors.mailContacto = 'Escribir el email en su debido formato. Ej: usuario@dominio.com';
+ }
+ }
+ if (!formData.precioPorNoche) {
+ newErrors.precioPorNoche = 'Se debe escribir un precio por noche.';
+ }
+ if (formData.paginaWeb && !/^(https?:\/\/)?([\w\-]+\.)+[\w\-]{2,4}(\/[\w\-\.]*)*$/.test(formData.paginaWeb)) {
+ newErrors.paginaWeb = 'Debes escribir en el formato indicado de página web. Ej: https://www.ejemplo.com';
+ }
+
+ setErrors(newErrors);
+ return Object.keys(newErrors).length === 0;
+ };
+
+ //const handleSubmit = (e) => {
+ // e.preventDefault();
+ // if (validateForm()) {
+ // console.log('Formulario válido, proceder...');
+ // handleNext();
+ //} else {
+ // console.log('Errores en el formulario:', errors);
+ //}
+ //}
+ const handleSubmit = (event) => {
+ event.preventDefault();
+ if (validateForm()) {
+ // Aquí puedes manejar la lógica de envío del formulario
+ // Luego, llama a onNext para avanzar al siguiente paso
+ onNext();} else {
+ console.log('Errores en el formulario:', errors);
+ }
+};
+
+
+
+ return (
+
+ );
+}
+
+/*HospedajeForm.propTypes = {
+ handleNext: PropTypes.func.isRequired,
+};*/
+
+HospedajeForm.propTypes = {
+ onNext: PropTypes.func.isRequired,
+};
+export default HospedajeForm;
\ No newline at end of file
diff --git a/src/pages/users/zhospedaje.jsx b/src/pages/users/zhospedaje.jsx
index 5876326..a3270d4 100644
--- a/src/pages/users/zhospedaje.jsx
+++ b/src/pages/users/zhospedaje.jsx
@@ -13,6 +13,19 @@ import {
Grid,
Typography,
} from '@mui/material';
+//------------new
+import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api'; // Importar componentes de Google Maps
+const mapContainerStyle = {
+ height: "400px",
+ width: "100%"
+};
+
+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
+};
+//-----------new
+
const subcategories = [
{ label: 'Arriendo', value: 'arriendo' },
@@ -24,6 +37,51 @@ const subcategories = [
];
function HospedajeForm({ onNext }) {
+ //-----------new
+ 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 handleMapClick = async (event) => {
+ const lat = event.latLng.lat();
+ const lng = event.latLng.lng();
+ setMarkerPosition({ lat, lng }); // Actualiza la posición del marcador
+ // Aquí puedes agregar lógica para convertir las coordenadas en una dirección si lo deseas
+ //const address = await getAddressFromLatLng(lat, lng); //new
+ setFormData((prev) => ({ ...prev, ubicacion: `Lat: ${lat}, Lng: ${lng}` })); // Actualiza el campo de ubicación
+ };
+
+ useEffect(() => {
+ // Obtener ubicación actual del usuario
+ if (navigator.geolocation) {
+ navigator.geolocation.getCurrentPosition(position => {
+ const newLocation = {
+ lat: position.coords.latitude,
+ lng: position.coords.longitude,
+ };
+ setUserLocation(newLocation);
+ setMarkerPosition(newLocation);
+ //setFormData(prev => ({ ...prev, ubicacion: address })); //new
+ setFormData(prev => ({ ...prev, ubicacion: `Lat: ${position.coords.latitude}, Lng: ${position.coords.longitude}` }));
+ }, () => {
+ alert("No se pudo obtener la ubicación.");
+ });
+ } else {
+ alert("Geolocalización no es soportada en este navegador.");
+ }
+ }, []);
+
+ /*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
+ } else {
+ return ''; // Retorna vacío si no se encuentra dirección
+ }
+ };*/
+ //-----------new
+
const [formData, setFormData] = useState({
subcategoria: '',
titulo: '',
@@ -116,15 +174,7 @@ function HospedajeForm({ onNext }) {
}
};
- //
- const handleNext = () => {
- if (validateForm()) {
- onNext(); // Llama a la función para ir al siguiente paso si es válido
- }
- };
- //
-
-
+
return (