From 5d75fcf42c1fd125b9de55cb334a53322dca66d5 Mon Sep 17 00:00:00 2001 From: ehc32 Date: Fri, 14 Feb 2025 10:46:42 -0500 Subject: [PATCH] Login y Registro --- package.json | 3 +- src/data/api.js | 63 +++++++++ src/pages/auth/ForgotPassword.jsx | 75 +++++++++++ src/pages/auth/ResetPassword.jsx | 109 +++++++++++++++ src/pages/auth/sign-in.jsx | 214 ++++++++++++++--------------- src/pages/auth/sign-up.jsx | 216 ++++++++++++++++++------------ src/routes.jsx | 9 ++ 7 files changed, 485 insertions(+), 204 deletions(-) create mode 100644 src/data/api.js create mode 100644 src/pages/auth/ForgotPassword.jsx create mode 100644 src/pages/auth/ResetPassword.jsx diff --git a/package.json b/package.json index 44f14fa6..674943f1 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@heroicons/react": "2.0.18", "@material-tailwind/react": "2.1.4", "apexcharts": "3.44.0", + "axios": "^1.7.9", "prop-types": "15.8.1", "react": "18.2.0", "react-apexcharts": "1.4.1", @@ -29,4 +30,4 @@ "tailwindcss": "3.3.4", "vite": "4.5.0" } -} \ No newline at end of file +} diff --git a/src/data/api.js b/src/data/api.js new file mode 100644 index 00000000..ef6db4f2 --- /dev/null +++ b/src/data/api.js @@ -0,0 +1,63 @@ +import axios from "axios" + +const API_BASE_URL = "http://127.0.0.1:8000/api/" + +const api = axios.create({ + baseURL: API_BASE_URL, + headers: { + "Content-Type": "application/json", + }, +}) + +export const Service = { + get: async (url) => { + try { + const response = await api.get(url) + return response.data + } catch (error) { + console.error("Error en GET:", error) + throw error + } + }, + + post: async (url, data) => { + try { + const response = await api.post(url, data) + return response.data + } catch (error) { + console.error("Error en POST:", error) + throw error + } + }, + + patch: async (url, data) => { + try { + const response = await api.patch(url, data) + return response.data + } catch (error) { + console.error("Error en PATCH:", error) + throw error + } + }, + + put: async (url, data) => { + try { + const response = await api.put(url, data) + return response.data + } catch (error) { + console.error("Error en PUT:", error) + throw error + } + }, + + delete: async (url) => { + try { + const response = await api.delete(url) + return response.data + } catch (error) { + console.error("Error en DELETE:", error) + throw error + } + }, +} + diff --git a/src/pages/auth/ForgotPassword.jsx b/src/pages/auth/ForgotPassword.jsx new file mode 100644 index 00000000..3adc99d7 --- /dev/null +++ b/src/pages/auth/ForgotPassword.jsx @@ -0,0 +1,75 @@ +"use client" + +import { useState } from "react" +import { Card, Input, Button, Typography } from "@material-tailwind/react" +import { EnvelopeIcon } from "@heroicons/react/24/outline" +import { Service } from "@/data/api" + +export function ForgotPassword() { + const [email, setEmail] = useState("") + const [notification, setNotification] = useState(null) + + const handleSubmit = async (e) => { + e.preventDefault() + try { + await Service.post("/auth/forgot-password", { email }) + showNotification("green", "Se ha enviado un código de recuperación a tu correo.") + } catch (error) { + console.error("Error al enviar el correo de recuperación:", error) + showNotification("red", "Error al enviar el correo. Por favor, intenta de nuevo.") + } + } + + const showNotification = (type, message) => { + setNotification({ type, message }) + setTimeout(() => setNotification(null), 5000) + } + + return ( +
+ +
+
+ + + Recuperar Contraseña + + + Ingresa tu correo electrónico para recibir un código de recuperación. + +
+
+ setEmail(e.target.value)} + required + /> +
+ + + ¿Recordaste tu contraseña?{" "} + + Iniciar sesión + + +
+
+ {notification && ( +
+ {notification.message} +
+ )} +
+ ) +} + +export default ForgotPassword + diff --git a/src/pages/auth/ResetPassword.jsx b/src/pages/auth/ResetPassword.jsx new file mode 100644 index 00000000..9d17aee7 --- /dev/null +++ b/src/pages/auth/ResetPassword.jsx @@ -0,0 +1,109 @@ +"use client" + +import { useState } from "react" +import { Card, Input, Button, Typography } from "@material-tailwind/react" +import { LockClosedIcon } from "@heroicons/react/24/outline" +import { Service } from "@/data/api" + +export function ResetPassword() { + const [formData, setFormData] = useState({ + code: "", + newPassword: "", + confirmPassword: "", + }) + const [notification, setNotification] = useState(null) + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }) + } + + const handleSubmit = async (e) => { + e.preventDefault() + if (formData.newPassword !== formData.confirmPassword) { + showNotification("red", "Las contraseñas no coinciden.") + return + } + try { + await Service.post("/auth/reset-password", { + code: formData.code, + newPassword: formData.newPassword, + }) + showNotification("green", "Tu contraseña ha sido actualizada exitosamente.") + } catch (error) { + console.error("Error al restablecer la contraseña:", error) + showNotification("red", "Error al restablecer la contraseña. Por favor, intenta de nuevo.") + } + } + + const showNotification = (type, message) => { + setNotification({ type, message }) + setTimeout(() => setNotification(null), 5000) + } + + return ( +
+ +
+
+ + + Restablecer Contraseña + + + Ingresa el código recibido y tu nueva contraseña. + +
+
+ + + +
+ + + ¿Recordaste tu contraseña?{" "} + + Iniciar sesión + + +
+
+ {notification && ( +
+ {notification.message} +
+ )} +
+ ) +} + +export default ResetPassword + diff --git a/src/pages/auth/sign-in.jsx b/src/pages/auth/sign-in.jsx index 3b3da41a..69e8fc8c 100644 --- a/src/pages/auth/sign-in.jsx +++ b/src/pages/auth/sign-in.jsx @@ -1,126 +1,106 @@ -import { - Card, - Input, - Checkbox, - Button, - Typography, -} from "@material-tailwind/react"; -import { Link } from "react-router-dom"; +"use client" +import { useState } from "react" +import { Card, Input, Checkbox, Button, Typography, Alert } from "@material-tailwind/react" +import { Link } from "react-router-dom" +import { Service } from "@/data/api" export function SignIn() { + const [correo, setEmail] = useState("") + const [contrasena, setPassword] = useState("") + const [rememberMe, setRememberMe] = useState(false) + const [notification, setNotification] = useState(null) + + const handleSignIn = async (e) => { + e.preventDefault() + try { + const response = await Service.post("/login/", { correo, contrasena }) + console.log("Inicio de sesión exitoso:", response) + setNotification({ + type: "green", + message: "Inicio de sesión exitoso. Redirigiendo...", + }) + setTimeout(() => { + window.location.href = "/dashboard/home" + }, 1000) + } catch (error) { + console.error("Error al iniciar sesión:", error) + setNotification({ + type: "red", + message: "Error al iniciar sesión. Por favor, verifica tus credenciales.", + }) + } + } + return ( -
-
-
- Sign In - Enter your email and password to Sign In. + +
+
+ + Iniciar Sesión + + + Ingresa tu correo y contraseña para acceder. +
- -
- - Your email - - - - Password - - -
- - I agree the  - - Terms and Conditions - - - } - containerProps={{ className: "-ml-2.5" }} + {notification && ( + setNotification(null), + }} + className="mb-4" + > + {notification.message} + + )} +
+ + Correo electrónico + + setEmail(e.target.value)} + placeholder="tucorreo@ejemplo.com" + required + fullWidth /> - - -
- - Subscribe me to newsletter - - } - containerProps={{ className: "-ml-2.5" }} - /> - - - Forgot Password - - -
-
- - -
- - Not registered? - Create account +
+
+ + Contraseña - - -
-
- -
- -
- ); + setPassword(e.target.value)} + placeholder="••••••••" + required + fullWidth + /> + +
+ setRememberMe(e.target.checked)} /> + + ¿Olvidaste tu contraseña? + +
+ +
+ + ¿No tienes una cuenta?{" "} + + Regístrate + + +
+ + + ) } -export default SignIn; +export default SignIn + diff --git a/src/pages/auth/sign-up.jsx b/src/pages/auth/sign-up.jsx index 5f040d04..390278ff 100644 --- a/src/pages/auth/sign-up.jsx +++ b/src/pages/auth/sign-up.jsx @@ -1,94 +1,138 @@ -import { - Card, - Input, - Checkbox, - Button, - Typography, -} from "@material-tailwind/react"; -import { Link } from "react-router-dom"; +"use client" +import { useState } from "react" +import { Card, Input, Checkbox, Button, Typography, Alert } from "@material-tailwind/react" +import { Link } from "react-router-dom" +import { Service } from "@/data/api" export function SignUp() { + const [formData, setFormData] = useState({ + correo: "", + nombres: "", + apellidos: "", + documento: "", + contrasena: "", + }) + const [aceptaTerminos, setAceptaTerminos] = useState(false) + const [notification, setNotification] = useState(null) + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }) + } + + const handleSubmit = async (e) => { + e.preventDefault() + if (!aceptaTerminos) { + setNotification({ + type: "red", + message: "Debes aceptar los términos y condiciones para registrarte.", + }) + return + } + try { + const response = await Service.post("/usuario/", { + ...formData, + estado: true, + }) + console.log("Registro exitoso:", response) + setNotification({ + type: "green", + message: "Registro exitoso. Por favor, inicia sesión.", + }) + // Aquí puedes redirigir al usuario a la página de inicio de sesión + } catch (error) { + console.error("Error al registrarse:", error) + setNotification({ + type: "red", + message: "Error al registrarse. Por favor, intenta de nuevo.", + }) + } + } + return ( -
-
- -
-
-
- Join Us Today - Enter your email and password to register. + +
+
+ + Regístrate + + + Ingresa tus datos para crear una cuenta. +
- -
- - Your email - - -
- - I agree the  - - Terms and Conditions - - - } - containerProps={{ className: "-ml-2.5" }} + {notification && ( + setNotification(null), + }} + className="mb-4" + > + {notification.message} + + )} +
+ - - -
- - -
- - Already have an account? - Sign in - - - -
-
- ); + + + + + + + Acepto los{" "} + +  términos y condiciones + + + } + containerProps={{ className: "-ml-2.5" }} + checked={aceptaTerminos} + onChange={(e) => setAceptaTerminos(e.target.checked)} + /> + + + ¿Ya tienes una cuenta? + + Inicia sesión + + + + + ) } -export default SignUp; +export default SignUp + diff --git a/src/routes.jsx b/src/routes.jsx index 3a5a8da0..81d640c5 100644 --- a/src/routes.jsx +++ b/src/routes.jsx @@ -8,6 +8,8 @@ import { } from "@heroicons/react/24/solid"; import { Home, Profile, Tables, Notifications } from "@/pages/dashboard"; import { SignIn, SignUp } from "@/pages/auth"; +import { element } from "prop-types"; +import ForgotPassword from "./pages/auth/ForgotPassword"; const icon = { className: "w-5 h-5 text-inherit", @@ -59,6 +61,13 @@ export const routes = [ path: "/sign-up", element: , }, + + { + icon: , + name: "forgot password", + path: "/forgot-password", + element : , + } ], }, ];