Skip to content

Commit 1955dfb

Browse files
committed
Seguridad y logica actualizada
1 parent bd5e248 commit 1955dfb

File tree

3 files changed

+150
-170
lines changed

3 files changed

+150
-170
lines changed

backend/app.py

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
import os
22
from dotenv import load_dotenv
3-
from flask import Flask, jsonify, request, Response
3+
from flask import Flask, jsonify, request
44
from flask_cors import CORS
55
from flask_sqlalchemy import SQLAlchemy
66
from flask_migrate import Migrate
77
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
88
from datetime import datetime
99
from admin import setup_admin
1010
from models import db, Usuario, Cliente, Estado, TipoTrabajo, Trabajo
11-
from flask_socketio import SocketIO
12-
from flask_socketio import emit
1311
from werkzeug.security import check_password_hash
1412

1513
# Inicializa Flask
1614
app = Flask(__name__)
1715
CORS(app, cors_allowed_origins="*")
1816

19-
# Inicializa SocketIO
20-
socketio = SocketIO(app, cors_allowed_origins="*")
21-
22-
2317
load_dotenv()
2418

2519
# Configura la aplicación
@@ -55,7 +49,7 @@ def login():
5549
return jsonify({"token": token}), 200
5650

5751
return jsonify({"error": "Usuario o contraseña incorrectos"}), 401
58-
52+
5953
@app.route('/api/protected', methods=['GET'])
6054
@jwt_required()
6155
def protected():
@@ -114,11 +108,6 @@ def crear_cliente():
114108
try:
115109
db.session.add(nuevo_cliente)
116110
db.session.commit()
117-
118-
# Emitir evento de actualización de clientes
119-
clientes_actualizados = [cliente.serialize() for cliente in Cliente.query.all()]
120-
socketio.emit('actualizar_clientes', clientes_actualizados)
121-
122111
return jsonify(nuevo_cliente.serialize()), 201
123112
except Exception as e:
124113
db.session.rollback()
@@ -336,5 +325,4 @@ def obtener_ultimo_numero_trabajo():
336325

337326

338327
if __name__ == '__main__':
339-
socketio.run(app,host="0.0.0.0", debug=True, port=3001, use_reloader=True)
340-
328+
app.run(debug=True, port=3001)

frontend/src/components/Clientes.jsx

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import React, { useEffect, useState } from "react";
22
import { Link } from "react-router-dom";
3-
import { io } from "socket.io-client";
43
import ModalCliente from "./ModalCliente";
54

6-
// Establece la conexión de Socket.IO utilizando WebSocket
7-
const socket = io("https://app-agenda-sdc-backend.onrender.com", {
8-
transports: ["websocket"], // Usa solo WebSocket
9-
});
10-
115
const Clientes = () => {
126
// URL del backend, configurable con una variable de entorno
137
const apiUrl = process.env.BACKEND_URL || 'https://app-agenda-sdc-backend.onrender.com';
@@ -39,17 +33,6 @@ const Clientes = () => {
3933
useEffect(() => {
4034
// Fetch inicial de los clientes
4135
fetchClientes();
42-
43-
// Configurar el socket para escuchar cambios en la lista de clientes
44-
socket.on("actualizar_clientes", (data) => {
45-
console.log("Clientes actualizados recibidos:", data); // Para depurar
46-
setClientes(data); // Actualiza los datos de clientes en el estado
47-
});
48-
49-
// Desuscribir el evento al desmontar el componente
50-
return () => {
51-
socket.off("actualizar_clientes");
52-
};
5336
}, []); // El efecto se ejecuta solo una vez cuando el componente se monta
5437

5538
return (
Lines changed: 147 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,162 +1,171 @@
1-
// ModalCliente.jsx
21
import React, { useState } from 'react';
32

43
const ModalCliente = () => {
5-
const [nombre, setNombre] = useState("");
6-
const [apellido, setApellido] = useState("");
7-
const [cedula, setCedula] = useState("");
8-
const [direccion, setDireccion] = useState("");
9-
const [telefono, setTelefono] = useState("");
10-
const [loading, setLoading] = useState("");
11-
const [error, setError] = useState("");
4+
const [nombre, setNombre] = useState("");
5+
const [apellido, setApellido] = useState("");
6+
const [cedula, setCedula] = useState("");
7+
const [direccion, setDireccion] = useState("");
8+
const [telefono, setTelefono] = useState("");
9+
const [loading, setLoading] = useState(false);
10+
const [error, setError] = useState("");
1211

13-
const apiUrl = process.env.BACKEND_URL || 'https://app-agenda-sdc-backend.onrender.com';
12+
const apiUrl = process.env.BACKEND_URL || 'https://app-agenda-sdc-backend.onrender.com';
1413

15-
const handleSubmit = async (e) => {
16-
e.preventDefault();
14+
const handleSubmit = async (e) => {
15+
e.preventDefault();
1716

18-
// Mostrar el spinner
19-
setLoading(true);
20-
setError(""); // Limpiar cualquier error previo
17+
// Mostrar el spinner
18+
setLoading(true);
19+
setError(""); // Limpiar cualquier error previo
2120

22-
// Enviar los datos al backend
23-
try {
24-
const response = await fetch(`${apiUrl}/api/clientes`, {
25-
method: "POST",
26-
headers: {
27-
"Content-Type": "application/json",
28-
},
29-
body: JSON.stringify({
30-
nombre,
31-
apellido,
32-
cedula,
33-
direccion,
34-
telefono,
35-
}),
36-
});
21+
// Enviar los datos al backend
22+
try {
23+
const response = await fetch(`${apiUrl}/api/clientes`, {
24+
method: "POST",
25+
headers: {
26+
"Content-Type": "application/json",
27+
},
28+
body: JSON.stringify({
29+
nombre,
30+
apellido,
31+
cedula,
32+
direccion,
33+
telefono,
34+
}),
35+
});
3736

38-
const data = await response.json();
37+
const data = await response.json();
3938

40-
if (response.ok){
41-
alert("Cliente creado exitosamente");
42-
setNombre("");
43-
setApellido("");
44-
setCedula("");
45-
setDireccion("");
46-
setTelefono("");
47-
}else{
48-
setError(data.Error || "Hubo un problema al creare el cliente");
39+
if (response.ok) {
40+
alert("Cliente creado exitosamente");
41+
setNombre("");
42+
setApellido("");
43+
setCedula("");
44+
setDireccion("");
45+
setTelefono("");
46+
} else {
47+
setError(data.Error || "Hubo un problema al crear el cliente");
48+
}
49+
} catch {
50+
setError("Hubo un problema de conexión");
51+
} finally {
52+
setLoading(false);
4953
}
50-
}catch{
51-
setError("Hubo un problema de conexion")
52-
} finally {
53-
setLoading(false)
54-
}
55-
};
56-
return (
57-
<div
58-
className="modal fade"
59-
id="modalAgregarCliente"
60-
tabIndex="-1"
61-
aria-labelledby="modalAgregarClienteLabel"
62-
aria-hidden="true"
63-
>
64-
<div className="modal-dialog">
65-
<div className="modal-content">
66-
<div className="modal-header">
67-
<h5 className="modal-title" id="modalAgregarClienteLabel">Agregar Cliente</h5>
68-
<button
69-
type="button"
70-
className="btn-close"
71-
data-bs-dismiss="modal"
72-
aria-label="Cerrar"
73-
></button>
74-
</div>
75-
<div className="modal-body">
76-
{/* Mostrar mensaje de error si ocurre */}
77-
{error && <div className="alert alert-danger">{error}</div>}
54+
};
7855

79-
{/* Formulario de cliente */}
80-
<form onSubmit={handleSubmit}>
81-
<div className="row mb-3">
82-
<div className="col-md-6">
83-
<label htmlFor="clienteNombre" className="form-label">Nombre</label>
84-
<input
85-
type="text"
86-
className="form-control"
87-
id="clienteNombre"
88-
value={nombre}
89-
onChange={(e) => setNombre(e.target.value)}
90-
required
91-
/>
92-
</div>
93-
<div className="col-md-6">
94-
<label htmlFor="clienteApellido" className="form-label">Apellido</label>
95-
<input
96-
type="text"
97-
className="form-control"
98-
id="clienteApellido"
99-
value={apellido}
100-
onChange={(e) => setApellido(e.target.value)}
101-
required
102-
/>
103-
</div>
104-
<div className="col-md-6">
105-
<label htmlFor="clienteCedula" className="form-label">Cédula</label>
106-
<input
107-
type="text"
108-
className="form-control"
109-
id="clienteCedula"
110-
value={cedula}
111-
onChange={(e) => setCedula(e.target.value)}
112-
113-
/>
56+
const handleCloseModal = () => {
57+
window.location.reload(); // Recargar la página cuando se cierre el modal
58+
};
59+
60+
return (
61+
<div
62+
className="modal fade"
63+
id="modalAgregarCliente"
64+
tabIndex="-1"
65+
aria-labelledby="modalAgregarClienteLabel"
66+
aria-hidden="true"
67+
>
68+
<div className="modal-dialog">
69+
<div className="modal-content">
70+
<div className="modal-header">
71+
<h5 className="modal-title" id="modalAgregarClienteLabel">Agregar Cliente</h5>
72+
<button
73+
type="button"
74+
className="btn-close"
75+
data-bs-dismiss="modal"
76+
aria-label="Cerrar"
77+
onClick={handleCloseModal} // Añadido para recargar al cerrar
78+
></button>
79+
</div>
80+
<div className="modal-body">
81+
{/* Mostrar mensaje de error si ocurre */}
82+
{error && <div className="alert alert-danger">{error}</div>}
83+
84+
{/* Formulario de cliente */}
85+
<form onSubmit={handleSubmit}>
86+
<div className="row mb-3">
87+
<div className="col-md-6">
88+
<label htmlFor="clienteNombre" className="form-label">Nombre</label>
89+
<input
90+
type="text"
91+
className="form-control"
92+
id="clienteNombre"
93+
value={nombre}
94+
onChange={(e) => setNombre(e.target.value)}
95+
required
96+
/>
97+
</div>
98+
<div className="col-md-6">
99+
<label htmlFor="clienteApellido" className="form-label">Apellido</label>
100+
<input
101+
type="text"
102+
className="form-control"
103+
id="clienteApellido"
104+
value={apellido}
105+
onChange={(e) => setApellido(e.target.value)}
106+
required
107+
/>
108+
</div>
109+
<div className="col-md-6">
110+
<label htmlFor="clienteCedula" className="form-label">Cédula</label>
111+
<input
112+
type="text"
113+
className="form-control"
114+
id="clienteCedula"
115+
value={cedula}
116+
onChange={(e) => setCedula(e.target.value)}
117+
/>
118+
</div>
119+
<div className="col-md-6">
120+
<label htmlFor="clienteDireccion" className="form-label">Dirección o localidad</label>
121+
<input
122+
type="text"
123+
className="form-control"
124+
id="clienteDireccion"
125+
value={direccion}
126+
onChange={(e) => setDireccion(e.target.value)}
127+
required
128+
/>
129+
</div>
114130
</div>
115-
<div className="col-md-6">
116-
<label htmlFor="clienteDireccion" className="form-label">Dirección o localidad</label>
131+
<div className="mb-3">
132+
<label htmlFor="clienteTelefono" className="form-label">Teléfono</label>
117133
<input
118-
type="text"
134+
type="tel"
119135
className="form-control"
120-
id="clienteDireccion"
121-
value={direccion}
122-
onChange={(e) => setDireccion(e.target.value)}
136+
id="clienteTelefono"
137+
value={telefono}
138+
onChange={(e) => setTelefono(e.target.value)}
123139
required
124140
/>
125141
</div>
126-
</div>
127-
<div className="mb-3">
128-
<label htmlFor="clienteTelefono" className="form-label">Teléfono</label>
129-
<input
130-
type="tel"
131-
className="form-control"
132-
id="clienteTelefono"
133-
value={telefono}
134-
onChange={(e) => setTelefono(e.target.value)}
135-
required
136-
/>
137-
</div>
138142

139-
{/* Botón de guardar */}
140-
<button type="submit" className="btn btn-success w-100" disabled={loading}>
141-
{loading ? (
142-
<div className="spinner-border spinner-border-sm" role="status">
143-
<span className="visually-hidden">Cargando...</span>
144-
</div>
145-
) : (
146-
"Guardar Cliente"
147-
)}
143+
{/* Botón de guardar */}
144+
<button type="submit" className="btn btn-success w-100" disabled={loading}>
145+
{loading ? (
146+
<div className="spinner-border spinner-border-sm" role="status">
147+
<span className="visually-hidden">Cargando...</span>
148+
</div>
149+
) : (
150+
"Guardar Cliente"
151+
)}
152+
</button>
153+
</form>
154+
</div>
155+
<div className="modal-footer">
156+
<button
157+
type="button"
158+
className="btn btn-secondary"
159+
data-bs-dismiss="modal"
160+
onClick={handleCloseModal} // Añadido para recargar al cerrar
161+
>
162+
Cerrar
148163
</button>
149-
</form>
150-
</div>
151-
<div className="modal-footer">
152-
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">
153-
Cerrar
154-
</button>
164+
</div>
155165
</div>
156166
</div>
157167
</div>
158-
</div>
159-
);
168+
);
160169
};
161170

162-
export default ModalCliente;
171+
export default ModalCliente;

0 commit comments

Comments
 (0)