Spaces:
Build error
Build error
despliegue
Browse files- .eslintrc.cjs +20 -0
- .gitignore +25 -0
- Dockerfile +23 -0
- index.html +13 -0
- package-lock.json +0 -0
- package.json +32 -0
- postcss.config.js +6 -0
- public/logo.svg +10 -0
- public/vite.svg +1 -0
- src/App.jsx +82 -0
- src/Carrito.jsx +81 -0
- src/Catalogo.jsx +106 -0
- src/NavBar.jsx +42 -0
- src/Prescripcion.jsx +392 -0
- src/assets/lentes-prueba.png +0 -0
- src/assets/lunas.jpg +0 -0
- src/assets/lunas.webp +0 -0
- src/assets/react.svg +1 -0
- src/components/BarraBusquedaCliente.jsx +36 -0
- src/components/CarritoItem.jsx +119 -0
- src/components/CarritoItemLunas.jsx +48 -0
- src/components/CatalogoMonturaCard.jsx +81 -0
- src/components/DatosCliente.jsx +31 -0
- src/components/DetalleClienteModalPrescripcion.jsx +20 -0
- src/components/DetalleTablaMedidas.jsx +94 -0
- src/components/DropdownClientesItem.jsx +23 -0
- src/components/ErrorMessage.jsx +11 -0
- src/components/Modal.jsx +128 -0
- src/components/ModalBoleta.jsx +145 -0
- src/components/ModalPrescripcion.jsx +83 -0
- src/components/ModalVerCarrito.jsx +84 -0
- src/components/TablaMedidas.jsx +247 -0
- src/index.css +9 -0
- src/lib/conexionApi.js +134 -0
- src/lib/funciones.js +22 -0
- src/main.jsx +13 -0
- tailwind.config.js +9 -0
- vite.config.js +7 -0
.eslintrc.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
module.exports = {
|
| 2 |
+
root: true,
|
| 3 |
+
env: { browser: true, es2020: true },
|
| 4 |
+
extends: [
|
| 5 |
+
'eslint:recommended',
|
| 6 |
+
'plugin:react/recommended',
|
| 7 |
+
'plugin:react/jsx-runtime',
|
| 8 |
+
'plugin:react-hooks/recommended',
|
| 9 |
+
],
|
| 10 |
+
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
| 11 |
+
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
| 12 |
+
settings: { react: { version: '18.2' } },
|
| 13 |
+
plugins: ['react-refresh'],
|
| 14 |
+
rules: {
|
| 15 |
+
'react-refresh/only-export-components': [
|
| 16 |
+
'warn',
|
| 17 |
+
{ allowConstantExport: true },
|
| 18 |
+
],
|
| 19 |
+
},
|
| 20 |
+
}
|
.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Logs
|
| 2 |
+
logs
|
| 3 |
+
*.log
|
| 4 |
+
npm-debug.log*
|
| 5 |
+
yarn-debug.log*
|
| 6 |
+
yarn-error.log*
|
| 7 |
+
pnpm-debug.log*
|
| 8 |
+
lerna-debug.log*
|
| 9 |
+
|
| 10 |
+
node_modules
|
| 11 |
+
dist
|
| 12 |
+
dist-ssr
|
| 13 |
+
*.local
|
| 14 |
+
|
| 15 |
+
# Editor directories and files
|
| 16 |
+
.vscode/*
|
| 17 |
+
!.vscode/extensions.json
|
| 18 |
+
.idea
|
| 19 |
+
.DS_Store
|
| 20 |
+
*.suo
|
| 21 |
+
*.ntvs*
|
| 22 |
+
*.njsproj
|
| 23 |
+
*.sln
|
| 24 |
+
*.sw?
|
| 25 |
+
.env
|
Dockerfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Usa la imagen de Node con la etiqueta 20.10-alpine3.18 como base
|
| 2 |
+
FROM node:20.10-alpine3.18
|
| 3 |
+
|
| 4 |
+
# Establece el directorio de trabajo en la aplicación
|
| 5 |
+
WORKDIR /usr/src/app
|
| 6 |
+
|
| 7 |
+
# Copia los archivos de configuración y el package.json a la imagen
|
| 8 |
+
COPY package*.json ./
|
| 9 |
+
|
| 10 |
+
# Instala las dependencias
|
| 11 |
+
RUN npm install
|
| 12 |
+
|
| 13 |
+
# Copia el resto de la aplicación a la imagen
|
| 14 |
+
COPY . .
|
| 15 |
+
|
| 16 |
+
# Otorga permisos de lectura, escritura y ejecución a todos los archivos y directorios
|
| 17 |
+
RUN chmod -R 777 /usr/src/app
|
| 18 |
+
|
| 19 |
+
# Expone el puerto 7860 (ajusta según sea necesario)
|
| 20 |
+
EXPOSE 7860
|
| 21 |
+
|
| 22 |
+
# Comando para ejecutar la aplicación
|
| 23 |
+
CMD ["npm", "run", "dev"]
|
index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 7 |
+
<title>Arte Visual</title>
|
| 8 |
+
</head>
|
| 9 |
+
<body>
|
| 10 |
+
<div id="root"></div>
|
| 11 |
+
<script type="module" src="/src/main.jsx"></script>
|
| 12 |
+
</body>
|
| 13 |
+
</html>
|
package-lock.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "intento5",
|
| 3 |
+
"private": true,
|
| 4 |
+
"version": "0.0.0",
|
| 5 |
+
"type": "module",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"dev": "vite --port 7860 --host 0.0.0.0",
|
| 8 |
+
"build": "vite build",
|
| 9 |
+
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
| 10 |
+
"preview": "vite preview"
|
| 11 |
+
},
|
| 12 |
+
"dependencies": {
|
| 13 |
+
"react": "^18.2.0",
|
| 14 |
+
"react-dom": "^18.2.0",
|
| 15 |
+
"react-router": "^6.20.1",
|
| 16 |
+
"react-router-dom": "6.20.1"
|
| 17 |
+
},
|
| 18 |
+
"devDependencies": {
|
| 19 |
+
"@types/react": "^18.2.37",
|
| 20 |
+
"@types/react-dom": "^18.2.15",
|
| 21 |
+
"@vitejs/plugin-react": "^4.2.0",
|
| 22 |
+
"autoprefixer": "^10.4.16",
|
| 23 |
+
"eslint": "^8.53.0",
|
| 24 |
+
"eslint-plugin-react": "^7.33.2",
|
| 25 |
+
"eslint-plugin-react-hooks": "^4.6.0",
|
| 26 |
+
"eslint-plugin-react-refresh": "^0.4.4",
|
| 27 |
+
"postcss": "^8.4.32",
|
| 28 |
+
"standard": "^17.1.0",
|
| 29 |
+
"tailwindcss": "^3.3.5",
|
| 30 |
+
"vite": "^5.0.0"
|
| 31 |
+
}
|
| 32 |
+
}
|
postcss.config.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export default {
|
| 2 |
+
plugins: {
|
| 3 |
+
tailwindcss: {},
|
| 4 |
+
autoprefixer: {},
|
| 5 |
+
},
|
| 6 |
+
}
|
public/logo.svg
ADDED
|
|
public/vite.svg
ADDED
|
|
src/App.jsx
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Route, Routes } from "react-router-dom";
|
| 2 |
+
import { NavBar } from "./NavBar";
|
| 3 |
+
import { Prescripcion } from "./Prescripcion";
|
| 4 |
+
import { Catalogo } from "./Catalogo";
|
| 5 |
+
import { useEffect, useState } from "react";
|
| 6 |
+
import { Carrito } from "./Carrito";
|
| 7 |
+
import { obtenerGet } from "./lib/conexionApi";
|
| 8 |
+
|
| 9 |
+
const Home = () => {
|
| 10 |
+
return <div>Home</div>;
|
| 11 |
+
};
|
| 12 |
+
|
| 13 |
+
const Pedidos = () => {
|
| 14 |
+
return <div>Pedidos</div>;
|
| 15 |
+
};
|
| 16 |
+
|
| 17 |
+
const fecha = new Date();
|
| 18 |
+
let dia = fecha.getDate();
|
| 19 |
+
let mes = fecha.getMonth() + 1; // Los meses en JavaScript empiezan desde 0
|
| 20 |
+
let año = fecha.getFullYear();
|
| 21 |
+
|
| 22 |
+
// Asegurándose de que el día y el mes sean de dos dígitos
|
| 23 |
+
if (dia < 10) dia = '0' + dia;
|
| 24 |
+
if (mes < 10) mes = '0' + mes;
|
| 25 |
+
|
| 26 |
+
const fechaFormateada = dia + '/' + mes + '/' + año;
|
| 27 |
+
|
| 28 |
+
export default function App() {
|
| 29 |
+
const [carrito, setCarrito] = useState([]);
|
| 30 |
+
const [monturas, setMonturas] = useState([]);
|
| 31 |
+
const [errorConsultaMonturas, setsetErrorConsultaMonturas] = useState(false);
|
| 32 |
+
const [precioTotal, setPrecioTotal] = useState(0);
|
| 33 |
+
const [prescripcion, setPrescripcion] = useState([]);
|
| 34 |
+
const [fecha, setFecha] = useState('')
|
| 35 |
+
|
| 36 |
+
useEffect(() => {
|
| 37 |
+
obtenerGet("monturas", setMonturas, setsetErrorConsultaMonturas);
|
| 38 |
+
}, []);
|
| 39 |
+
|
| 40 |
+
useEffect(() => {
|
| 41 |
+
setFecha(fechaFormateada)
|
| 42 |
+
}, []);
|
| 43 |
+
|
| 44 |
+
return (
|
| 45 |
+
<div className="flex flex-col items-center h-screen">
|
| 46 |
+
<NavBar />
|
| 47 |
+
<Routes>
|
| 48 |
+
<Route path="/" element={<Home />} />
|
| 49 |
+
<Route path="/pedidos" element={<Pedidos />} />
|
| 50 |
+
<Route path="/prescripcion" element={<Prescripcion />} />
|
| 51 |
+
<Route
|
| 52 |
+
path="/catalogo"
|
| 53 |
+
element={
|
| 54 |
+
<Catalogo
|
| 55 |
+
setCarrito={setCarrito}
|
| 56 |
+
carrito={carrito}
|
| 57 |
+
monturas={monturas}
|
| 58 |
+
setMonturas={setMonturas}
|
| 59 |
+
setPrecioTotal={setPrecioTotal}
|
| 60 |
+
setPrescripcion={setPrescripcion}
|
| 61 |
+
prescripcion={prescripcion}
|
| 62 |
+
/>
|
| 63 |
+
}
|
| 64 |
+
/>
|
| 65 |
+
<Route
|
| 66 |
+
path="/carrito"
|
| 67 |
+
element={
|
| 68 |
+
<Carrito
|
| 69 |
+
setCarrito={setCarrito}
|
| 70 |
+
carrito={carrito}
|
| 71 |
+
precioTotal={precioTotal}
|
| 72 |
+
setPrecioTotal={setPrecioTotal}
|
| 73 |
+
fecha={fecha}
|
| 74 |
+
prescripcion={prescripcion}
|
| 75 |
+
setPrescripcion={setPrescripcion}
|
| 76 |
+
/>
|
| 77 |
+
}
|
| 78 |
+
/>
|
| 79 |
+
</Routes>
|
| 80 |
+
</div>
|
| 81 |
+
);
|
| 82 |
+
}
|
src/Carrito.jsx
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useEffect, useState } from 'react'
|
| 2 |
+
import { CarritoItem } from './components/CarritoItem'
|
| 3 |
+
import { actualizarPut, cargarApi, obtenerEspecifico, registrarPost, obtenerGet } from "./lib/conexionApi";
|
| 4 |
+
import ModalBoleta from './components/ModalBoleta';
|
| 5 |
+
import {CarritoItemLunas} from './components/CarritoItemLunas';
|
| 6 |
+
|
| 7 |
+
export const Carrito = ({setCarrito, carrito, precioTotal, setPrecioTotal, fecha, prescripcion, setPrescripcion}) => {
|
| 8 |
+
|
| 9 |
+
const [modalBoleta, setModalBoleta] = useState(false)
|
| 10 |
+
const [adelanto, setAdelanto] = useState('')
|
| 11 |
+
const [precioLunas, setPrecioLunas] = useState('')
|
| 12 |
+
const [error, setError] = useState('')
|
| 13 |
+
const [errorPrecioLuna, setErrorPrecioLuna] = useState('')
|
| 14 |
+
|
| 15 |
+
const [precioTotalMostrado, setPrecioTotalMostrado] = useState(0)
|
| 16 |
+
|
| 17 |
+
useEffect(() => {
|
| 18 |
+
setPrecioTotal(carrito.reduce((total, carritoItem) => total + (carritoItem["cantidad"]*carritoItem["monturaInventario"]["precio_unit"]), 0))
|
| 19 |
+
}, [])
|
| 20 |
+
|
| 21 |
+
const handleContinuarClick = () => {
|
| 22 |
+
if (adelanto === '' || precioLunas === '') {
|
| 23 |
+
setError('todos los campos son obligatorios')
|
| 24 |
+
} else if (isNaN(parseFloat(adelanto)) || isNaN(parseFloat(precioLunas))) {
|
| 25 |
+
setError('Ingresar campos válidos')
|
| 26 |
+
} else if (adelanto < (precioTotal+parseFloat(precioLunas))*0.3) {
|
| 27 |
+
setError('El adelanto debe ser mayor al 30% del total')
|
| 28 |
+
} else {
|
| 29 |
+
setModalBoleta(true)
|
| 30 |
+
setError('')
|
| 31 |
+
setErrorPrecioLuna('')
|
| 32 |
+
}
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
return (
|
| 36 |
+
<div className='w-3/5'>
|
| 37 |
+
<div className='flex justify-between'>
|
| 38 |
+
<h1 className="my-10 text-4xl font-semibold text-center">Carrito de compras</h1>
|
| 39 |
+
|
| 40 |
+
<button className='bg-slate-700 text-white my-8 rounded-lg hover:bg-slate-800 uppercase text-xl font-semibold px-5' onClick={handleContinuarClick}>
|
| 41 |
+
Continuar
|
| 42 |
+
</button>
|
| 43 |
+
</div>
|
| 44 |
+
<div className='border-t border-black w-full'>
|
| 45 |
+
{(carrito.length > 0) && carrito.map((item) => {
|
| 46 |
+
return <CarritoItem key={item["monturaInventario"]["codigo"]} carritoItem={item} setCarrito={setCarrito} precioTotal={precioTotal} setPrecioTotal={setPrecioTotal} carrito={carrito} />
|
| 47 |
+
})}
|
| 48 |
+
{ prescripcion.length !== 0 && <CarritoItemLunas prescripcion={prescripcion} precioLunas={precioLunas} setPrecioLunas={setPrecioLunas} setPrecioTotal={setPrecioTotal} precioTotal={precioTotal} />}
|
| 49 |
+
</div>
|
| 50 |
+
<div className='flex justify-end mt-10 items-center'>
|
| 51 |
+
<label htmlFor="input-buscar-cliente" className='mr-2 font-semibold'>Adelanto: S/.</label>
|
| 52 |
+
<input
|
| 53 |
+
className="border w-[6rem] py-2 px-3 rounded-md text-right"
|
| 54 |
+
id="input-buscar-cliente "
|
| 55 |
+
type="text"
|
| 56 |
+
placeholder="00.00"
|
| 57 |
+
onChange={(e) => {
|
| 58 |
+
setAdelanto(e.target.value)
|
| 59 |
+
}}
|
| 60 |
+
value={adelanto}
|
| 61 |
+
/>
|
| 62 |
+
</div>
|
| 63 |
+
{(modalBoleta && precioTotal !== 0) && (
|
| 64 |
+
<ModalBoleta
|
| 65 |
+
fecha={fecha}
|
| 66 |
+
setModalBoleta={setModalBoleta}
|
| 67 |
+
precioTotal={precioTotal+parseFloat(precioLunas)}
|
| 68 |
+
carrito={carrito}
|
| 69 |
+
prescripcion={prescripcion}
|
| 70 |
+
adelanto={adelanto}
|
| 71 |
+
precioLunas={precioLunas}
|
| 72 |
+
setPrescripcion={setPrescripcion}
|
| 73 |
+
setPrecioTotal={setPrecioTotal}
|
| 74 |
+
setCarrito={setCarrito}
|
| 75 |
+
/>
|
| 76 |
+
)}
|
| 77 |
+
{errorPrecioLuna && <p className="text-red-500 text-xl">{errorPrecioLuna}</p>}
|
| 78 |
+
{error && <p className="text-red-500 text-xl">{error}</p>}
|
| 79 |
+
</div>
|
| 80 |
+
)
|
| 81 |
+
}
|
src/Catalogo.jsx
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useEffect, useState } from "react";
|
| 2 |
+
import CatalogoMonturaCard from "./components/CatalogoMonturaCard";
|
| 3 |
+
import {
|
| 4 |
+
actualizarPut,
|
| 5 |
+
cargarApi,
|
| 6 |
+
obtenerEspecifico,
|
| 7 |
+
registrarPost,
|
| 8 |
+
obtenerGet,
|
| 9 |
+
prescripcionPdff,
|
| 10 |
+
} from "./lib/conexionApi";
|
| 11 |
+
import ModalVerCarrito from "./components/ModalVerCarrito";
|
| 12 |
+
import { Navigate } from "react-router";
|
| 13 |
+
|
| 14 |
+
export const Catalogo = ({ setCarrito, carrito, monturas, setMonturas, setPrecioTotal, setPrescripcion, prescripcion }) => {
|
| 15 |
+
// Se obtienen primero los detalles de cada montura
|
| 16 |
+
|
| 17 |
+
// se obtienen los datos de precio, stock y código
|
| 18 |
+
const [monturasInventario, setmonturasInventario] = useState([]);
|
| 19 |
+
|
| 20 |
+
const [montura, setMontura] = useState({})
|
| 21 |
+
const [monturaInventario, setMonturaInventario] = useState({})
|
| 22 |
+
|
| 23 |
+
const [errorConsultaMonturasInv, setsetErrorConsultaMonturasInv] =
|
| 24 |
+
useState(false);
|
| 25 |
+
|
| 26 |
+
const [errorUltimaPrescripcion, setsetErrorUltimaPrescripcion] =
|
| 27 |
+
useState(false);
|
| 28 |
+
|
| 29 |
+
const [btnBuscarMonturaCodigo, setbtnBuscarMonturaCodigo] = useState(false);
|
| 30 |
+
|
| 31 |
+
const [modalVerCarrito, setModalVerCarrito] = useState(false)
|
| 32 |
+
|
| 33 |
+
const [irAlCarrito, setIrAlCarrito] = useState(false)
|
| 34 |
+
|
| 35 |
+
useEffect(() => {
|
| 36 |
+
|
| 37 |
+
}, []);
|
| 38 |
+
|
| 39 |
+
// obtener catalogo de monturas
|
| 40 |
+
useEffect(() => {
|
| 41 |
+
obtenerGet(
|
| 42 |
+
"monturas_inventario",
|
| 43 |
+
setmonturasInventario,
|
| 44 |
+
setsetErrorConsultaMonturasInv
|
| 45 |
+
);
|
| 46 |
+
}, []);
|
| 47 |
+
|
| 48 |
+
useEffect(() => {
|
| 49 |
+
const pdfPrescripcion = async () => {
|
| 50 |
+
await obtenerGet("prescripciones/ultimoregistro", setPrescripcion, setsetErrorUltimaPrescripcion);
|
| 51 |
+
await prescripcionPdff(prescripcion[0]["id_prescripcion"])
|
| 52 |
+
}
|
| 53 |
+
pdfPrescripcion()
|
| 54 |
+
}, []);
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
return (
|
| 59 |
+
<div className="mx-20 mt-5">
|
| 60 |
+
|
| 61 |
+
<div className="flex flex-col justify-center items-center">
|
| 62 |
+
<h1 className="my-10 text-5xl font-semibold text-center">Catálogo de monturas</h1>
|
| 63 |
+
{/* <div className="flex flex-row gap-2 mb-2 w-1/3">
|
| 64 |
+
<input
|
| 65 |
+
className="border w-3/4 py-2 px-3 rounded-md"
|
| 66 |
+
id="input-buscar-cliente "
|
| 67 |
+
type="text"
|
| 68 |
+
placeholder="Código de montura"
|
| 69 |
+
/>
|
| 70 |
+
<button className="rounded-md w-1/4 bg-slate-700 hover:bg-slate-800 text-white font-semibold px-2 text-center">
|
| 71 |
+
Buscar
|
| 72 |
+
</button>
|
| 73 |
+
</div> */}
|
| 74 |
+
</div>
|
| 75 |
+
<div className="mt-5 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2">
|
| 76 |
+
{monturasInventario.map((monturaInventario) => {
|
| 77 |
+
const montura = monturas.find(
|
| 78 |
+
(montura) =>
|
| 79 |
+
montura["id_montura"] === monturaInventario["id_montura"]
|
| 80 |
+
);
|
| 81 |
+
return (
|
| 82 |
+
<CatalogoMonturaCard
|
| 83 |
+
key={montura["id_montura"]}
|
| 84 |
+
montura={montura}
|
| 85 |
+
monturaInventario={monturaInventario}
|
| 86 |
+
setModalVerCarrito={setModalVerCarrito}
|
| 87 |
+
setMontura={setMontura}
|
| 88 |
+
setMonturaInventario={setMonturaInventario}
|
| 89 |
+
setCarrito={setCarrito}
|
| 90 |
+
carrito={carrito}
|
| 91 |
+
setPrecioTotal={setPrecioTotal}
|
| 92 |
+
/>
|
| 93 |
+
);
|
| 94 |
+
})}
|
| 95 |
+
</div>
|
| 96 |
+
{modalVerCarrito && (
|
| 97 |
+
<ModalVerCarrito montura={montura} monturaInventario={monturaInventario} setModalVerCarrito={setModalVerCarrito} carrito={carrito} setMontura={setMontura} setMonturaInventario={setMonturaInventario} setIrAlCarrito={setIrAlCarrito} />
|
| 98 |
+
)}
|
| 99 |
+
|
| 100 |
+
{irAlCarrito && (
|
| 101 |
+
<Navigate to="/carrito" replace={true}/>
|
| 102 |
+
)}
|
| 103 |
+
|
| 104 |
+
</div>
|
| 105 |
+
);
|
| 106 |
+
};
|
src/NavBar.jsx
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
import { NavLink } from "react-router-dom";
|
| 3 |
+
|
| 4 |
+
export const NavBar = () => {
|
| 5 |
+
return (
|
| 6 |
+
<header className="w-full mb-10">
|
| 7 |
+
<div className="bg-slate-500 text-white text-center pt-20 pb-10">
|
| 8 |
+
<h1 className="text-4xl font-semibold ">Óptica Arte Visual</h1>
|
| 9 |
+
<p className="mt-5">La mejor calidad en monturas con modelos exclusivos y resinas de alta calidad</p>
|
| 10 |
+
</div>
|
| 11 |
+
<nav className="bg-slate-700">
|
| 12 |
+
<ul id="nav-ul" className="flex flex-row justify-center text-xl">
|
| 13 |
+
<NavLink className="w-1/5 text-center" to="/">
|
| 14 |
+
<li className="hover:bg-slate-800 text-white py-2 hover:font-semibold">
|
| 15 |
+
Home
|
| 16 |
+
</li>
|
| 17 |
+
</NavLink>
|
| 18 |
+
<NavLink className="w-1/5 text-center" to="/pedidos">
|
| 19 |
+
<li className="hover:bg-slate-800 text-white py-2 hover:font-semibold">
|
| 20 |
+
Pedidos
|
| 21 |
+
</li>
|
| 22 |
+
</NavLink>
|
| 23 |
+
<NavLink className="w-1/5 text-center" to="/prescripcion">
|
| 24 |
+
<li className="hover:bg-slate-800 text-white py-2 hover:font-semibold">
|
| 25 |
+
Emitir Prescripción
|
| 26 |
+
</li>
|
| 27 |
+
</NavLink>
|
| 28 |
+
<NavLink className="w-1/5 text-center" to="/catalogo">
|
| 29 |
+
<li className="hover:bg-slate-800 text-white py-2 hover:font-semibold">
|
| 30 |
+
Catálogo
|
| 31 |
+
</li>
|
| 32 |
+
</NavLink>
|
| 33 |
+
<NavLink className="w-1/5 text-center" to="/carrito">
|
| 34 |
+
<li className="hover:bg-slate-800 text-white py-2 hover:font-semibold">
|
| 35 |
+
Carrito de compras
|
| 36 |
+
</li>
|
| 37 |
+
</NavLink>
|
| 38 |
+
</ul>
|
| 39 |
+
</nav>
|
| 40 |
+
</header>
|
| 41 |
+
);
|
| 42 |
+
};
|
src/Prescripcion.jsx
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useEffect, useState } from "react";
|
| 2 |
+
import { actualizarPut, cargarApi, obtenerEspecifico, registrarPost } from "./lib/conexionApi";
|
| 3 |
+
import Modal from "./components/Modal";
|
| 4 |
+
import ModalPrescripcion from "./components/ModalPrescripcion";
|
| 5 |
+
import TablaMedidas from "./components/TablaMedidas";
|
| 6 |
+
import BarraBusquedaCliente from "./components/BarraBusquedaCliente";
|
| 7 |
+
import DatosCliente from "./components/DatosCliente";
|
| 8 |
+
import { Navigate } from "react-router-dom";
|
| 9 |
+
import ErrorMessage from "./components/ErrorMessage";
|
| 10 |
+
|
| 11 |
+
const fecha = new Date();
|
| 12 |
+
let dia = fecha.getDate();
|
| 13 |
+
let mes = fecha.getMonth() + 1; // Los meses en JavaScript empiezan desde 0
|
| 14 |
+
let año = fecha.getFullYear();
|
| 15 |
+
|
| 16 |
+
// Asegurándose de que el día y el mes sean de dos dígitos
|
| 17 |
+
if (dia < 10) dia = '0' + dia;
|
| 18 |
+
if (mes < 10) mes = '0' + mes;
|
| 19 |
+
|
| 20 |
+
const fechaFormateada = dia + '/' + mes + '/' + año;
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
export const Prescripcion = () => {
|
| 24 |
+
// States para la búsqueda de clientes
|
| 25 |
+
const [clienteBusqueda, setClienteBusqueda] = useState("");
|
| 26 |
+
const [btnBuscarClick, setBtnBuscarClick] = useState(false);
|
| 27 |
+
const [clientes, setClientes] = useState([]);
|
| 28 |
+
const [cliente, setCliente] = useState({});
|
| 29 |
+
const [openModal, setOpenModal] = useState(false);
|
| 30 |
+
const [openModalPrescripcion, setOpenModalPrescripcion] = useState(false)
|
| 31 |
+
|
| 32 |
+
// States para medidas
|
| 33 |
+
const [medidas, setMedidas] = useState([]);
|
| 34 |
+
const [medidasEncontradas, setMedidasEncontradas] = useState(false);
|
| 35 |
+
const [asignacionNuevasMedidas, setAsignacionNuevasMedidas] = useState(false)
|
| 36 |
+
const [actualizacionMedidas, setActualizacionMedidas] = useState(false)
|
| 37 |
+
|
| 38 |
+
// lejos
|
| 39 |
+
const [esferaODlejos, setEsferaODLejos] = useState(0);
|
| 40 |
+
const [cilindroODlejos, setCilindroODlejos] = useState(0);
|
| 41 |
+
const [ejeODlejos, setEjeODlejos] = useState(0);
|
| 42 |
+
const [agudezavisualODlejos, setAgudezavisualODlejos] = useState(0);
|
| 43 |
+
const [esferaOIlejos, setEsferaOIlejos] = useState(0);
|
| 44 |
+
const [cilindroOIlejos, setCilindroOIlejos] = useState(0);
|
| 45 |
+
const [ejeOIlejos, setEjeOIlejos] = useState(0);
|
| 46 |
+
const [agudezavisualOIlejos, setAgudezavisualOIlejos] = useState(0);
|
| 47 |
+
|
| 48 |
+
// cerca
|
| 49 |
+
const [esferaODcerca, setEsferaODcerca] = useState(0);
|
| 50 |
+
const [cilindroODcerca, setCilindroODcerca] = useState(0);
|
| 51 |
+
const [ejeODcerca, setEjeODcerca] = useState(0);
|
| 52 |
+
const [agudezavisualODcerca, setAgudezavisualODcerca] = useState(0);
|
| 53 |
+
const [esferaOIcerca, setEsferaOIcerca] = useState(0);
|
| 54 |
+
const [cilindroOIcerca, setCilindroOIcerca] = useState(0);
|
| 55 |
+
const [ejeOIcerca, setEjeOIcerca] = useState(0);
|
| 56 |
+
const [agudezavisualOIcerca, setAgudezavisualOIcerca] = useState(0);
|
| 57 |
+
|
| 58 |
+
// States para crear nuevo cliente
|
| 59 |
+
const [nombresYApellidos, setNombresYApellidos] = useState("");
|
| 60 |
+
const [edad, setEdad] = useState("");
|
| 61 |
+
const [telefono, setTelefono] = useState("");
|
| 62 |
+
const [direccion, setDireccion] = useState("");
|
| 63 |
+
|
| 64 |
+
// States para crear nueva prescripción
|
| 65 |
+
const [notaAdicional, setNotaAdicional] = useState("");
|
| 66 |
+
const [prescripcionLista, setPrescripcionLista] = useState(false)
|
| 67 |
+
const [prescripcionRegistrada, setPrescripcionRegistrada] = useState(false)
|
| 68 |
+
|
| 69 |
+
// errores
|
| 70 |
+
const [error, setError] = useState(false)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
useEffect(() => {
|
| 74 |
+
cargarApi()
|
| 75 |
+
}, []);
|
| 76 |
+
|
| 77 |
+
useEffect(() => {
|
| 78 |
+
if (btnBuscarClick) {
|
| 79 |
+
obtenerEspecifico(
|
| 80 |
+
"clientes/busqueda",
|
| 81 |
+
{ nombres_y_apellidos: clienteBusqueda },
|
| 82 |
+
setClientes, setError
|
| 83 |
+
);
|
| 84 |
+
|
| 85 |
+
} else return;
|
| 86 |
+
}, [btnBuscarClick]);
|
| 87 |
+
|
| 88 |
+
useEffect(() => {
|
| 89 |
+
if (Object.keys(cliente).length !== 0 || asignacionNuevasMedidas) {
|
| 90 |
+
obtenerEspecifico(
|
| 91 |
+
"medidas/busqueda",
|
| 92 |
+
{ "id_cliente": parseInt(cliente["id_cliente"]) },
|
| 93 |
+
setMedidas, setError
|
| 94 |
+
);
|
| 95 |
+
console.log('medidas encontradas');
|
| 96 |
+
} else return;
|
| 97 |
+
}, [cliente, asignacionNuevasMedidas]);
|
| 98 |
+
|
| 99 |
+
useEffect(() => {
|
| 100 |
+
if (Object.keys(cliente).length !== 0 || actualizacionMedidas) {
|
| 101 |
+
obtenerEspecifico(
|
| 102 |
+
"medidas/busqueda",
|
| 103 |
+
{ "id_cliente": parseInt(cliente["id_cliente"]) },
|
| 104 |
+
setMedidas, setError
|
| 105 |
+
);
|
| 106 |
+
console.log('medidas encontradas');
|
| 107 |
+
} else return
|
| 108 |
+
}, [actualizacionMedidas])
|
| 109 |
+
|
| 110 |
+
useEffect(() => {
|
| 111 |
+
if (medidas.length !== 0) {
|
| 112 |
+
setMedidasEncontradas(true);
|
| 113 |
+
setEsferaODLejos(medidas[0]["Esfera_OD_lejos"]);
|
| 114 |
+
setCilindroODlejos(medidas[0]["Cilindro_OD_lejos"]);
|
| 115 |
+
setEjeODlejos(medidas[0]["Eje_OD_lejos"]);
|
| 116 |
+
setAgudezavisualODlejos(medidas[0]["Agudeza_visual_OD_lejos"]);
|
| 117 |
+
setEsferaOIlejos(medidas[0]["Esfera_OI_lejos"]);
|
| 118 |
+
setCilindroOIlejos(medidas[0]["Cilindro_OI_lejos"]);
|
| 119 |
+
setEjeOIlejos(medidas[0]["Eje_OI_lejos"]);
|
| 120 |
+
setAgudezavisualOIlejos(medidas[0]["Agudeza_visual_OI_lejos"]);
|
| 121 |
+
|
| 122 |
+
setEsferaODcerca(medidas[0]["Esfera_OD_cerca"]);
|
| 123 |
+
setCilindroODcerca(medidas[0]["Cilindro_OD_cerca"]);
|
| 124 |
+
setEjeODcerca(medidas[0]["Eje_OD_cerca"]);
|
| 125 |
+
setAgudezavisualODcerca(medidas[0]["Agudeza_visual_OD_cerca"]);
|
| 126 |
+
setEsferaOIcerca(medidas[0]["Esfera_OI_cerca"]);
|
| 127 |
+
setCilindroOIcerca(medidas[0]["Cilindro_OI_cerca"]);
|
| 128 |
+
setEjeOIcerca(medidas[0]["Eje_OI_cerca"]);
|
| 129 |
+
setAgudezavisualOIcerca(medidas[0]["Agudeza_visual_OI_cerca"]);
|
| 130 |
+
} else {
|
| 131 |
+
setMedidasEncontradas(false);
|
| 132 |
+
setEsferaODLejos(0);
|
| 133 |
+
setCilindroODlejos(0);
|
| 134 |
+
setEjeODlejos(0);
|
| 135 |
+
setAgudezavisualODlejos(0);
|
| 136 |
+
setEsferaOIlejos(0);
|
| 137 |
+
setCilindroOIlejos(0);
|
| 138 |
+
setEjeOIlejos(0);
|
| 139 |
+
setAgudezavisualOIlejos(0);
|
| 140 |
+
|
| 141 |
+
setEsferaODcerca(0);
|
| 142 |
+
setCilindroODcerca(0);
|
| 143 |
+
setEjeODcerca(0);
|
| 144 |
+
setAgudezavisualODcerca(0);
|
| 145 |
+
setEsferaOIcerca(0);
|
| 146 |
+
setCilindroOIcerca(0);
|
| 147 |
+
setEjeOIcerca(0);
|
| 148 |
+
setAgudezavisualOIcerca(0);
|
| 149 |
+
}
|
| 150 |
+
}, [medidas]);
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
const handleButtonBuscarCliente = (e) => {
|
| 154 |
+
e.preventDefault();
|
| 155 |
+
if (clienteBusqueda !== "") {
|
| 156 |
+
setBtnBuscarClick(true);
|
| 157 |
+
} else setBtnBuscarClick(false);
|
| 158 |
+
//console.log(clientes);
|
| 159 |
+
};
|
| 160 |
+
|
| 161 |
+
const handleSubmitEmitirPrescripcion = (e) => {
|
| 162 |
+
e.preventDefault()
|
| 163 |
+
if (Object.keys(cliente).length !== 0) {
|
| 164 |
+
const nuevoMonturas = {
|
| 165 |
+
"Esfera_OD_lejos": parseFloat(esferaODlejos),
|
| 166 |
+
"Cilindro_OD_lejos": parseFloat(cilindroODlejos),
|
| 167 |
+
"Eje_OD_lejos": parseFloat(ejeODlejos),
|
| 168 |
+
"Agudeza_visual_OD_lejos": parseFloat(agudezavisualODlejos),
|
| 169 |
+
"Esfera_OI_lejos": parseFloat(esferaOIlejos),
|
| 170 |
+
"Cilindro_OI_lejos": parseFloat(cilindroOIlejos),
|
| 171 |
+
"Eje_OI_lejos": parseFloat(ejeOIlejos),
|
| 172 |
+
"Agudeza_visual_OI_lejos": parseFloat(agudezavisualOIlejos),
|
| 173 |
+
"Esfera_OD_cerca": parseFloat(esferaODcerca),
|
| 174 |
+
"Cilindro_OD_cerca": parseFloat(cilindroODcerca),
|
| 175 |
+
"Eje_OD_cerca": parseFloat(ejeODcerca),
|
| 176 |
+
"Agudeza_visual_OD_cerca": parseFloat(agudezavisualODcerca),
|
| 177 |
+
"Esfera_OI_cerca": parseFloat(esferaOIcerca),
|
| 178 |
+
"Cilindro_OI_cerca": parseFloat(cilindroOIcerca),
|
| 179 |
+
"Eje_OI_cerca": parseFloat(ejeOIcerca),
|
| 180 |
+
"Agudeza_visual_OI_cerca": parseFloat(agudezavisualOIcerca),
|
| 181 |
+
"id_cliente": cliente["id_cliente"],
|
| 182 |
+
};
|
| 183 |
+
|
| 184 |
+
if (!medidasEncontradas ) {
|
| 185 |
+
registrarPost('medidas', nuevoMonturas)
|
| 186 |
+
console.log('medidas registradas');
|
| 187 |
+
setAsignacionNuevasMedidas(true)
|
| 188 |
+
console.log('medidas encontradas');
|
| 189 |
+
} else {
|
| 190 |
+
if (medidas.length !== 0) {
|
| 191 |
+
const actualizarMonturas = {
|
| 192 |
+
"id_medidas": medidas[0]["id_medidas"],
|
| 193 |
+
"Esfera_OD_lejos": parseFloat(esferaODlejos),
|
| 194 |
+
"Cilindro_OD_lejos": parseFloat(cilindroODlejos),
|
| 195 |
+
"Eje_OD_lejos": parseFloat(ejeODlejos),
|
| 196 |
+
"Agudeza_visual_OD_lejos": parseFloat(agudezavisualODlejos),
|
| 197 |
+
"Esfera_OI_lejos": parseFloat(esferaOIlejos),
|
| 198 |
+
"Cilindro_OI_lejos": parseFloat(cilindroOIlejos),
|
| 199 |
+
"Eje_OI_lejos": parseFloat(ejeOIlejos),
|
| 200 |
+
"Agudeza_visual_OI_lejos": parseFloat(agudezavisualOIlejos),
|
| 201 |
+
"Esfera_OD_cerca": parseFloat(esferaODcerca),
|
| 202 |
+
"Cilindro_OD_cerca": parseFloat(cilindroODcerca),
|
| 203 |
+
"Eje_OD_cerca": parseFloat(ejeODcerca),
|
| 204 |
+
"Agudeza_visual_OD_cerca": parseFloat(agudezavisualODcerca),
|
| 205 |
+
"Esfera_OI_cerca": parseFloat(esferaOIcerca),
|
| 206 |
+
"Cilindro_OI_cerca": parseFloat(cilindroOIcerca),
|
| 207 |
+
"Eje_OI_cerca": parseFloat(ejeOIcerca),
|
| 208 |
+
"Agudeza_visual_OI_cerca": parseFloat(agudezavisualOIcerca),
|
| 209 |
+
"id_cliente": cliente["id_cliente"],
|
| 210 |
+
};
|
| 211 |
+
actualizarPut("medidas",actualizarMonturas)
|
| 212 |
+
setActualizacionMedidas(true)
|
| 213 |
+
}
|
| 214 |
+
}
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
setOpenModalPrescripcion(true)
|
| 218 |
+
|
| 219 |
+
console.log('submit');
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
return (
|
| 223 |
+
<div className=" w-3/5 flex flex-row my-5 p-5 h-auto">
|
| 224 |
+
<div className="w-2/5">
|
| 225 |
+
{(btnBuscarClick && error) && <ErrorMessage mensaje={'No se encontraron resultados'}/>}
|
| 226 |
+
<div className=" flex flex-row">
|
| 227 |
+
<div className="w-full pr-5">
|
| 228 |
+
{/* BARRA DE BÚSQUEDA DE CLIENTE */}
|
| 229 |
+
<BarraBusquedaCliente
|
| 230 |
+
clienteBusqueda = {clienteBusqueda}
|
| 231 |
+
setClienteBusqueda = {setClienteBusqueda}
|
| 232 |
+
setBtnBuscarClick = {setBtnBuscarClick}
|
| 233 |
+
setAsignacionNuevasMedidas = {setAsignacionNuevasMedidas}
|
| 234 |
+
handleButtonBuscarCliente = {handleButtonBuscarCliente}
|
| 235 |
+
setError = {setError}
|
| 236 |
+
/>
|
| 237 |
+
|
| 238 |
+
{/* DROPDOWN DE CLIENTES ENCONTRADOS */}
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
{clientes && clienteBusqueda !== "" && btnBuscarClick !== false
|
| 243 |
+
? <ul>
|
| 244 |
+
{clientes.map((cli) => {
|
| 245 |
+
return (
|
| 246 |
+
<li
|
| 247 |
+
key={cli["id_cliente"]}
|
| 248 |
+
onClick={() => {
|
| 249 |
+
setBtnBuscarClick(false);
|
| 250 |
+
setClienteBusqueda("");
|
| 251 |
+
setCliente(cli);
|
| 252 |
+
setNotaAdicional("");
|
| 253 |
+
}}
|
| 254 |
+
className="cursor-pointer hover:font-semibold hover:bg-slate-50 p-2 "
|
| 255 |
+
>
|
| 256 |
+
<p>{cli["nombres_y_apellidos"]}</p>
|
| 257 |
+
<p className="text-sm text-slate-400">{cli["edad"]}</p>
|
| 258 |
+
<p className="text-sm text-slate-400">{cli["telefono"]}</p>
|
| 259 |
+
<p className="text-sm text-slate-400">{cli["direccion"]}</p>
|
| 260 |
+
</li>
|
| 261 |
+
);
|
| 262 |
+
})}
|
| 263 |
+
</ul>
|
| 264 |
+
: ""}
|
| 265 |
+
|
| 266 |
+
</div>
|
| 267 |
+
|
| 268 |
+
<svg
|
| 269 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 270 |
+
className="icon icon-tabler icon-tabler-user-plus cursor-pointer hover:stroke-slate-800 mr-5"
|
| 271 |
+
width="40"
|
| 272 |
+
height="40"
|
| 273 |
+
viewBox="0 0 24 24"
|
| 274 |
+
strokeWidth="2.5"
|
| 275 |
+
stroke="#334155"
|
| 276 |
+
fill="none"
|
| 277 |
+
strokeLinecap="round"
|
| 278 |
+
strokeLinejoin="round"
|
| 279 |
+
/* ABRIR MODAL PARA AGREGAR CLIENTE */
|
| 280 |
+
onClick={() => {
|
| 281 |
+
console.log("agregar");
|
| 282 |
+
setOpenModal(true);
|
| 283 |
+
}}
|
| 284 |
+
>
|
| 285 |
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
| 286 |
+
<path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" />
|
| 287 |
+
<path d="M16 19h6" />
|
| 288 |
+
<path d="M19 16v6" />
|
| 289 |
+
<path d="M6 21v-2a4 4 0 0 1 4 -4h4" />
|
| 290 |
+
</svg>
|
| 291 |
+
|
| 292 |
+
</div>
|
| 293 |
+
</div>
|
| 294 |
+
|
| 295 |
+
{/* MOSTRAR CLIENTE SELECCIONADO */}
|
| 296 |
+
{Object.keys(cliente).length !== 0 ? (
|
| 297 |
+
<form onSubmit={handleSubmitEmitirPrescripcion} className="px-5 flex flex-col w-3/5 h-full pb-5 border-l-2">
|
| 298 |
+
<DatosCliente
|
| 299 |
+
cliente={cliente}
|
| 300 |
+
notaAdicional={notaAdicional}
|
| 301 |
+
setNotaAdicional={setNotaAdicional}
|
| 302 |
+
/>
|
| 303 |
+
|
| 304 |
+
{!medidasEncontradas && (
|
| 305 |
+
<p className="mt-5 text-center text-xl text-gray-500">
|
| 306 |
+
Llena las medidas del nuevo cliente
|
| 307 |
+
</p>
|
| 308 |
+
)}
|
| 309 |
+
|
| 310 |
+
<TablaMedidas
|
| 311 |
+
esferaODlejos={esferaODlejos}
|
| 312 |
+
setEsferaODLejos={setEsferaODLejos}
|
| 313 |
+
cilindroODlejos={cilindroODlejos}
|
| 314 |
+
setCilindroODlejos={setCilindroODlejos}
|
| 315 |
+
ejeODlejos={ejeODlejos}
|
| 316 |
+
setEjeODlejos={setEjeODlejos}
|
| 317 |
+
agudezavisualODlejos={agudezavisualODlejos}
|
| 318 |
+
setAgudezavisualODlejos={setAgudezavisualODlejos}
|
| 319 |
+
esferaOIlejos={esferaOIlejos}
|
| 320 |
+
setEsferaOIlejos={setEsferaOIlejos}
|
| 321 |
+
cilindroOIlejos={cilindroOIlejos}
|
| 322 |
+
setCilindroOIlejos={setCilindroOIlejos}
|
| 323 |
+
ejeOIlejos={ejeOIlejos}
|
| 324 |
+
setEjeOIlejos={setEjeOIlejos}
|
| 325 |
+
agudezavisualOIlejos={agudezavisualOIlejos}
|
| 326 |
+
setAgudezavisualOIlejos={setAgudezavisualOIlejos}
|
| 327 |
+
esferaODcerca={esferaODcerca}
|
| 328 |
+
setEsferaODcerca={setEsferaODcerca}
|
| 329 |
+
cilindroODcerca={cilindroODcerca}
|
| 330 |
+
setCilindroODcerca={setCilindroODcerca}
|
| 331 |
+
ejeODcerca={ejeODcerca}
|
| 332 |
+
setEjeODcerca={setEjeODcerca}
|
| 333 |
+
agudezavisualODcerca={agudezavisualODcerca}
|
| 334 |
+
setAgudezavisualODcerca={setAgudezavisualODcerca}
|
| 335 |
+
esferaOIcerca={esferaOIcerca}
|
| 336 |
+
setEsferaOIcerca={setEsferaOIcerca}
|
| 337 |
+
cilindroOIcerca={cilindroOIcerca}
|
| 338 |
+
setCilindroOIcerca={setCilindroOIcerca}
|
| 339 |
+
ejeOIcerca={ejeOIcerca}
|
| 340 |
+
setEjeOIcerca={setEjeOIcerca}
|
| 341 |
+
agudezavisualOIcerca={agudezavisualOIcerca}
|
| 342 |
+
setAgudezavisualOIcerca={setAgudezavisualOIcerca}
|
| 343 |
+
/>
|
| 344 |
+
|
| 345 |
+
<button type="submit" className="rounded-md w-full py-3 mt-10 bg-slate-700 hover:bg-slate-800 text-white font-semibold uppercase ">
|
| 346 |
+
Emitir Prescripción
|
| 347 |
+
</button>
|
| 348 |
+
</form>
|
| 349 |
+
) : (
|
| 350 |
+
<div className="px-5 flex flex-col w-3/5 h-full pb-20 border-l-2">
|
| 351 |
+
<p className="text-gray-400 text-2xl font-semibold">
|
| 352 |
+
No se ha seleccionado ningún cliente
|
| 353 |
+
</p>
|
| 354 |
+
</div>
|
| 355 |
+
)}
|
| 356 |
+
|
| 357 |
+
{openModal && (
|
| 358 |
+
<Modal
|
| 359 |
+
openModal={openModal}
|
| 360 |
+
setOpenModal={setOpenModal}
|
| 361 |
+
nombresYApellidos={nombresYApellidos}
|
| 362 |
+
setNombresYApellidos={setNombresYApellidos}
|
| 363 |
+
edad={edad}
|
| 364 |
+
setEdad={setEdad}
|
| 365 |
+
telefono={telefono}
|
| 366 |
+
setTelefono={setTelefono}
|
| 367 |
+
direccion={direccion}
|
| 368 |
+
setDireccion={setDireccion}
|
| 369 |
+
setError={setError}
|
| 370 |
+
setClienteBusqueda={setClienteBusqueda}
|
| 371 |
+
/>
|
| 372 |
+
)}
|
| 373 |
+
{openModalPrescripcion && (
|
| 374 |
+
<ModalPrescripcion
|
| 375 |
+
setOpenModalPrescripcion={setOpenModalPrescripcion}
|
| 376 |
+
setPrescripcionLista={setPrescripcionLista}
|
| 377 |
+
cliente={cliente}
|
| 378 |
+
medidas={medidas}
|
| 379 |
+
fechaFormateada={fechaFormateada}
|
| 380 |
+
notaAdicional={notaAdicional}
|
| 381 |
+
setActualizacionMedidas={setActualizacionMedidas}
|
| 382 |
+
setAsignacionNuevasMedidas={setAsignacionNuevasMedidas}
|
| 383 |
+
setPrescripcionRegistrada={setPrescripcionRegistrada}
|
| 384 |
+
/>
|
| 385 |
+
)}
|
| 386 |
+
{prescripcionRegistrada && (
|
| 387 |
+
<Navigate to="/catalogo" replace={true} />
|
| 388 |
+
)}
|
| 389 |
+
|
| 390 |
+
</div>
|
| 391 |
+
);
|
| 392 |
+
}
|
src/assets/lentes-prueba.png
ADDED
|
src/assets/lunas.jpg
ADDED
|
src/assets/lunas.webp
ADDED
|
src/assets/react.svg
ADDED
|
|
src/components/BarraBusquedaCliente.jsx
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
|
| 3 |
+
const BarraBusquedaCliente = ({
|
| 4 |
+
clienteBusqueda,
|
| 5 |
+
setClienteBusqueda,
|
| 6 |
+
setBtnBuscarClick,
|
| 7 |
+
setAsignacionNuevasMedidas,
|
| 8 |
+
handleButtonBuscarCliente,
|
| 9 |
+
setError
|
| 10 |
+
}) => {
|
| 11 |
+
return (
|
| 12 |
+
<li className="flex flex-row gap-2 mb-2">
|
| 13 |
+
<input
|
| 14 |
+
className="border w-3/4 py-2 px-3 rounded-md"
|
| 15 |
+
id="input-buscar-cliente "
|
| 16 |
+
type="text"
|
| 17 |
+
placeholder="Nombre del cliente"
|
| 18 |
+
onChange={(e) => {
|
| 19 |
+
setClienteBusqueda(e.target.value);
|
| 20 |
+
setBtnBuscarClick(false);
|
| 21 |
+
setAsignacionNuevasMedidas(false);
|
| 22 |
+
setError(false)
|
| 23 |
+
}}
|
| 24 |
+
value={clienteBusqueda}
|
| 25 |
+
/>
|
| 26 |
+
<button
|
| 27 |
+
className="rounded-md w-1/4 bg-slate-700 hover:bg-slate-800 text-white font-semibold px-2 text-center"
|
| 28 |
+
onClick={handleButtonBuscarCliente}
|
| 29 |
+
>
|
| 30 |
+
Buscar
|
| 31 |
+
</button>
|
| 32 |
+
</li>
|
| 33 |
+
);
|
| 34 |
+
};
|
| 35 |
+
|
| 36 |
+
export default BarraBusquedaCliente;
|
src/components/CarritoItem.jsx
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useState } from "react";
|
| 2 |
+
import { formatearStringUrlImagen } from "../lib/funciones";
|
| 3 |
+
|
| 4 |
+
export const CarritoItem = ({
|
| 5 |
+
carritoItem,
|
| 6 |
+
setCarrito,
|
| 7 |
+
precioTotal,
|
| 8 |
+
setPrecioTotal,
|
| 9 |
+
carrito,
|
| 10 |
+
}) => {
|
| 11 |
+
const imagen = carritoItem["montura"]["imagen"];
|
| 12 |
+
|
| 13 |
+
const { src, alt, border } = formatearStringUrlImagen(imagen);
|
| 14 |
+
|
| 15 |
+
const [cantidad, setCantidad] = useState(carritoItem["cantidad"]);
|
| 16 |
+
|
| 17 |
+
return (
|
| 18 |
+
<div className="w-full p-10 flex justify-between items-center border-b border-black">
|
| 19 |
+
<div className="">
|
| 20 |
+
<img width={200} src={src} alt={alt} border={border} />
|
| 21 |
+
</div>
|
| 22 |
+
<div className="block w-[350px]">
|
| 23 |
+
<p className="truncate uppercase text-xl font-semibold">
|
| 24 |
+
{carritoItem["montura"]["nombre_montura"]}
|
| 25 |
+
</p>
|
| 26 |
+
<p className="mb-3 text-gray-500">{carritoItem["montura"]["marca"]}</p>
|
| 27 |
+
<p>
|
| 28 |
+
Material:{" "}
|
| 29 |
+
<span className="uppercase">
|
| 30 |
+
{carritoItem["montura"]["material"]}
|
| 31 |
+
</span>
|
| 32 |
+
</p>
|
| 33 |
+
<p>
|
| 34 |
+
Color:{" "}
|
| 35 |
+
<span className="uppercase">{carritoItem["montura"]["color"]}</span>
|
| 36 |
+
</p>
|
| 37 |
+
</div>
|
| 38 |
+
<div className="w-[80px] text-center">
|
| 39 |
+
S/.{carritoItem["monturaInventario"]["precio_unit"]} c/u
|
| 40 |
+
</div>
|
| 41 |
+
<div className="flex">
|
| 42 |
+
<button
|
| 43 |
+
className="bg-gray-200 h-8 w-8 text-lg hover:bg-gray-300 disabled:cursor-default disabled:text-gray-400 disabled:hover:bg-gray-200"
|
| 44 |
+
onClick={() => {
|
| 45 |
+
// falta eliminar
|
| 46 |
+
carritoItem["cantidad"] = cantidad - 1;
|
| 47 |
+
setCantidad(cantidad - 1);
|
| 48 |
+
console.log(carritoItem);
|
| 49 |
+
setPrecioTotal(
|
| 50 |
+
carrito.reduce(
|
| 51 |
+
(total, carritoItem) =>
|
| 52 |
+
total +
|
| 53 |
+
carritoItem["cantidad"] *
|
| 54 |
+
carritoItem["monturaInventario"]["precio_unit"],
|
| 55 |
+
0
|
| 56 |
+
)
|
| 57 |
+
);
|
| 58 |
+
}}
|
| 59 |
+
disabled={cantidad === 1}
|
| 60 |
+
>
|
| 61 |
+
-
|
| 62 |
+
</button>
|
| 63 |
+
<p className="mx-2 h-8 w-10 text-center">{cantidad}</p>
|
| 64 |
+
<button
|
| 65 |
+
className="bg-gray-200 h-8 w-8 text-lg hover:bg-gray-300 disabled:cursor-default disabled:text-gray-400 disabled:hover:bg-gray-200"
|
| 66 |
+
onClick={() => {
|
| 67 |
+
// falta eliminar
|
| 68 |
+
carritoItem["cantidad"] = cantidad + 1;
|
| 69 |
+
setCantidad(cantidad + 1);
|
| 70 |
+
console.log(carritoItem);
|
| 71 |
+
setPrecioTotal(
|
| 72 |
+
carrito.reduce(
|
| 73 |
+
(total, carritoItem) =>
|
| 74 |
+
total +
|
| 75 |
+
carritoItem["cantidad"] *
|
| 76 |
+
carritoItem["monturaInventario"]["precio_unit"],
|
| 77 |
+
0
|
| 78 |
+
)
|
| 79 |
+
);
|
| 80 |
+
}}
|
| 81 |
+
disabled={cantidad === carritoItem["monturaInventario"]["stock"]}
|
| 82 |
+
>
|
| 83 |
+
+
|
| 84 |
+
</button>
|
| 85 |
+
</div>
|
| 86 |
+
<div className="w-[80px] text-center text-sm font-semibold">
|
| 87 |
+
S/.{" "}
|
| 88 |
+
<span className="text-2xl">
|
| 89 |
+
{cantidad * carritoItem["monturaInventario"]["precio_unit"]}
|
| 90 |
+
</span>
|
| 91 |
+
</div>
|
| 92 |
+
<div>
|
| 93 |
+
<svg
|
| 94 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 95 |
+
className="icon icon-tabler icon-tabler-trash cursor-pointer"
|
| 96 |
+
width="30"
|
| 97 |
+
height="30"
|
| 98 |
+
viewBox="0 0 24 24"
|
| 99 |
+
strokeWidth="1"
|
| 100 |
+
stroke="#ff0000"
|
| 101 |
+
fill="none"
|
| 102 |
+
strokeLinecap="round"
|
| 103 |
+
strokeLinejoin="round"
|
| 104 |
+
onClick={() => {
|
| 105 |
+
setCarrito(carrito.filter((carritoItemFiltrado) => carritoItemFiltrado["monturaInventario"]["codigo"] !== carritoItem["monturaInventario"]["codigo"]));
|
| 106 |
+
setPrecioTotal(precioTotal - (carritoItem["cantidad"]*carritoItem["monturaInventario"]["precio_unit"]))
|
| 107 |
+
}}
|
| 108 |
+
>
|
| 109 |
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
| 110 |
+
<path d="M4 7l16 0" />
|
| 111 |
+
<path d="M10 11l0 6" />
|
| 112 |
+
<path d="M14 11l0 6" />
|
| 113 |
+
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
|
| 114 |
+
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
|
| 115 |
+
</svg>
|
| 116 |
+
</div>
|
| 117 |
+
</div>
|
| 118 |
+
);
|
| 119 |
+
};
|
src/components/CarritoItemLunas.jsx
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react'
|
| 2 |
+
// cantidad 1 prescripcion[0]["detalle_lunas"] input precio precio*cantidad
|
| 3 |
+
export const CarritoItemLunas = ({ prescripcion, precioLunas, setPrecioLunas, setPrecioTotal, precioTotal }) => {
|
| 4 |
+
return (
|
| 5 |
+
<div className="w-full p-10 flex justify-between items-center border-b border-black">
|
| 6 |
+
<div className="">
|
| 7 |
+
<img width={200} src="../src/assets/lunas.jpg" alt="lunas" border="0" />
|
| 8 |
+
</div>
|
| 9 |
+
<div className="block w-[350px]">
|
| 10 |
+
<p className="truncate text-xl ">
|
| 11 |
+
Detalle de lunas: <span className='font-semibold uppercase'>{ prescripcion.length !== 0 && prescripcion[0]["detalle_lunas"] }</span>
|
| 12 |
+
</p>
|
| 13 |
+
</div>
|
| 14 |
+
|
| 15 |
+
<div className="flex">
|
| 16 |
+
<button
|
| 17 |
+
className="bg-gray-200 h-8 w-8 text-lg hover:bg-gray-300 disabled:cursor-default disabled:text-gray-400 disabled:hover:bg-gray-200"
|
| 18 |
+
onClick={() => {
|
| 19 |
+
|
| 20 |
+
}}
|
| 21 |
+
disabled={true}
|
| 22 |
+
>
|
| 23 |
+
-
|
| 24 |
+
</button>
|
| 25 |
+
<p className="mx-2 h-8 w-10 text-center">{1}</p>
|
| 26 |
+
<button
|
| 27 |
+
className="bg-gray-200 h-8 w-8 text-lg hover:bg-gray-300 disabled:cursor-default disabled:text-gray-400 disabled:hover:bg-gray-200"
|
| 28 |
+
onClick={() => {
|
| 29 |
+
|
| 30 |
+
}}
|
| 31 |
+
disabled={true}
|
| 32 |
+
>
|
| 33 |
+
+
|
| 34 |
+
</button>
|
| 35 |
+
</div>
|
| 36 |
+
<div className="w-[80px] flex items-end">
|
| 37 |
+
<p className='text-sm'>S/.</p>
|
| 38 |
+
<input className='text-2xl border w-20 text-center ml-2' type="text" placeholder='00.00' value={precioLunas} onChange={e => {
|
| 39 |
+
setPrecioLunas(e.target.value)
|
| 40 |
+
//setPrecioTotal(pre)
|
| 41 |
+
}} />
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
</div>
|
| 45 |
+
|
| 46 |
+
</div>
|
| 47 |
+
)
|
| 48 |
+
}
|
src/components/CatalogoMonturaCard.jsx
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { formatearStringUrlImagen } from "../lib/funciones";
|
| 2 |
+
|
| 3 |
+
const CatalogoMonturaCard = ({
|
| 4 |
+
montura = {
|
| 5 |
+
"id_montura": 10,
|
| 6 |
+
"nombre_montura": "Nombre monturaaaaaaaaaaaaaaaaaaa",
|
| 7 |
+
"imagen":
|
| 8 |
+
'<img src="https://i.ibb.co/jHWcz8B/EBJ8-NK3-Ko81-301-C5-Frontal.png" alt="EBJ8-NK3-Ko81-301-C5-Frontal" border="0">',
|
| 9 |
+
"marca": "Marca montura",
|
| 10 |
+
"color": "Color montura",
|
| 11 |
+
"material": "Material Montura",
|
| 12 |
+
},
|
| 13 |
+
monturaInventario = {
|
| 14 |
+
"id_montura_inventario": 10,
|
| 15 |
+
"id_montura": 8,
|
| 16 |
+
"precio_unit": 90,
|
| 17 |
+
"stock": 20,
|
| 18 |
+
"codigo": "montura8",
|
| 19 |
+
},
|
| 20 |
+
setModalVerCarrito,
|
| 21 |
+
setMontura,
|
| 22 |
+
setMonturaInventario,
|
| 23 |
+
setCarrito,
|
| 24 |
+
carrito,
|
| 25 |
+
setPrecioTotal
|
| 26 |
+
}) => {
|
| 27 |
+
const { src, alt, border } = formatearStringUrlImagen(montura["imagen"]);
|
| 28 |
+
|
| 29 |
+
return (
|
| 30 |
+
<div className="p-5 hover:bg-slate-50 w-[360px]">
|
| 31 |
+
<div className="w-30 h-[150px] p-5">
|
| 32 |
+
<img src={src} alt={alt} border={border} className=" mb-5" />
|
| 33 |
+
</div>
|
| 34 |
+
<div className="flex flex-col items-center">
|
| 35 |
+
<h3 className="text-center px-6 w-full uppercase text-xl font-semibold truncate ">{montura["nombre_montura"]}</h3>
|
| 36 |
+
<div className="flex flex-row gap-2 items-center">
|
| 37 |
+
<p className="text-sm ">S/.
|
| 38 |
+
<span className="text-2xl">
|
| 39 |
+
{monturaInventario["precio_unit"]}
|
| 40 |
+
</span>
|
| 41 |
+
</p>
|
| 42 |
+
<div className="hover:bg-slate-300 rounded-full p-2">
|
| 43 |
+
<svg
|
| 44 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 45 |
+
className="icon icon-tabler icon-tabler-shopping-cart-plus"
|
| 46 |
+
width="30"
|
| 47 |
+
height="30"
|
| 48 |
+
viewBox="0 0 24 24"
|
| 49 |
+
strokeWidth="1.5"
|
| 50 |
+
stroke="#000000"
|
| 51 |
+
fill="none"
|
| 52 |
+
strokeLinecap="round"
|
| 53 |
+
strokeLinejoin="round"
|
| 54 |
+
onClick={(e) => {
|
| 55 |
+
e.preventDefault();
|
| 56 |
+
setMontura(montura);
|
| 57 |
+
setMonturaInventario(monturaInventario);
|
| 58 |
+
setModalVerCarrito(true)
|
| 59 |
+
setCarrito([...carrito, {
|
| 60 |
+
"montura":montura,
|
| 61 |
+
"monturaInventario":monturaInventario,
|
| 62 |
+
"cantidad":1,
|
| 63 |
+
}])
|
| 64 |
+
|
| 65 |
+
}}
|
| 66 |
+
>
|
| 67 |
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
| 68 |
+
<path d="M4 19a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
| 69 |
+
<path d="M12.5 17h-6.5v-14h-2" />
|
| 70 |
+
<path d="M6 5l14 1l-.86 6.017m-2.64 .983h-10.5" />
|
| 71 |
+
<path d="M16 19h6" />
|
| 72 |
+
<path d="M19 16v6" />
|
| 73 |
+
</svg>
|
| 74 |
+
</div>
|
| 75 |
+
</div>
|
| 76 |
+
</div>
|
| 77 |
+
</div>
|
| 78 |
+
);
|
| 79 |
+
};
|
| 80 |
+
|
| 81 |
+
export default CatalogoMonturaCard;
|
src/components/DatosCliente.jsx
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
|
| 3 |
+
const DatosCliente = ({
|
| 4 |
+
cliente,
|
| 5 |
+
setNotaAdicional,
|
| 6 |
+
notaAdicional,
|
| 7 |
+
}) => {
|
| 8 |
+
return (
|
| 9 |
+
<div className="w-full">
|
| 10 |
+
<p className=" font-semibold text-4xl mb-8">
|
| 11 |
+
{cliente["nombres_y_apellidos"]}
|
| 12 |
+
</p>
|
| 13 |
+
<div className="flex flex-row">
|
| 14 |
+
<p className="w-1/2 mb-2">Edad: {cliente["edad"]}</p>
|
| 15 |
+
<p className="w-1/2 mb-2">Teléfono: {cliente["telefono"]}</p>
|
| 16 |
+
</div>
|
| 17 |
+
<p className="mb-2"> Dirección: {cliente["direccion"]}</p>
|
| 18 |
+
<label htmlFor="notaAdicional">Nota adicional: {""}</label>
|
| 19 |
+
<textarea
|
| 20 |
+
className="mt-2 border w-full py-2 px-3 rounded-md"
|
| 21 |
+
id="notaAdicional"
|
| 22 |
+
type="text"
|
| 23 |
+
placeholder="Detalle de lunas"
|
| 24 |
+
onChange={(e) => setNotaAdicional(e.target.value)}
|
| 25 |
+
value={notaAdicional}
|
| 26 |
+
></textarea>
|
| 27 |
+
</div>
|
| 28 |
+
);
|
| 29 |
+
};
|
| 30 |
+
|
| 31 |
+
export default DatosCliente;
|
src/components/DetalleClienteModalPrescripcion.jsx
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
|
| 3 |
+
const DetalleClienteModalPrescripcion = ({ cliente, notaAdicional }) => {
|
| 4 |
+
return (
|
| 5 |
+
(cliente && Object.keys(cliente).length !== 0) > 0 && (
|
| 6 |
+
<div className="w-full h-full mr-5 flex flex-row justify-center">
|
| 7 |
+
<div className="flex flex-col w-full">
|
| 8 |
+
<p className=" mb-2">Edad: {cliente["edad"]}</p>
|
| 9 |
+
<p className=" mb-2">Teléfono: {cliente["telefono"]}</p>
|
| 10 |
+
</div>
|
| 11 |
+
<div className="flex flex-col w-full">
|
| 12 |
+
<p className=" mb-2"> Dirección: {cliente["direccion"]}</p>
|
| 13 |
+
<p className=" mb-2"> Nota adicional: {notaAdicional}</p>
|
| 14 |
+
</div>
|
| 15 |
+
</div>
|
| 16 |
+
)
|
| 17 |
+
);
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
export default DetalleClienteModalPrescripcion;
|
src/components/DetalleTablaMedidas.jsx
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
|
| 3 |
+
const DetalleTablaMedidas = ({ medidas }) => {
|
| 4 |
+
return (
|
| 5 |
+
(medidas && medidas.length > 0) && (
|
| 6 |
+
<div className=" flex flex-col gap-5 w-[462.3px] items-center justify-center px-5 mt-5">
|
| 7 |
+
<div className=" flex flex-col items-center justify-center">
|
| 8 |
+
<h3 className="font-semibold text-gray-500 mb-2 uppercase ">Lejos</h3>
|
| 9 |
+
<div className="w-full flex items-end mb-8">
|
| 10 |
+
<div className="">
|
| 11 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 12 |
+
OD
|
| 13 |
+
</p>
|
| 14 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 15 |
+
OI
|
| 16 |
+
</p>
|
| 17 |
+
</div>
|
| 18 |
+
<table className="rounded-lg text-center border-2 table-fixed w-full border-separate lg:border-collapse h-[6.5rem]">
|
| 19 |
+
<thead className="border-2">
|
| 20 |
+
<tr>
|
| 21 |
+
<th className="border">Esfera</th>
|
| 22 |
+
<th className="border">Cilindro</th>
|
| 23 |
+
<th className="border">Eje</th>
|
| 24 |
+
<th className="border">A/Y</th>
|
| 25 |
+
</tr>
|
| 26 |
+
</thead>
|
| 27 |
+
<tbody>
|
| 28 |
+
<tr>
|
| 29 |
+
<td className="border">{medidas[0]["Esfera_OD_lejos"]}</td>
|
| 30 |
+
<td className="border">{medidas[0]["Cilindro_OD_lejos"]}</td>
|
| 31 |
+
<td className="border">{medidas[0]["Eje_OD_lejos"]}</td>
|
| 32 |
+
<td className="border">
|
| 33 |
+
{medidas[0]["Agudeza_visual_OD_lejos"]}
|
| 34 |
+
</td>
|
| 35 |
+
</tr>
|
| 36 |
+
<tr>
|
| 37 |
+
<td className="border">{medidas[0]["Esfera_OI_lejos"]}</td>
|
| 38 |
+
<td className="border">{medidas[0]["Cilindro_OI_lejos"]}</td>
|
| 39 |
+
<td className="border">{medidas[0]["Eje_OI_lejos"]}</td>
|
| 40 |
+
<td className="border">
|
| 41 |
+
{medidas[0]["Agudeza_visual_OI_lejos"]}
|
| 42 |
+
</td>
|
| 43 |
+
</tr>
|
| 44 |
+
</tbody>
|
| 45 |
+
</table>
|
| 46 |
+
</div>
|
| 47 |
+
</div>
|
| 48 |
+
<div className=" flex flex-col items-center justify-center">
|
| 49 |
+
<h3 className="font-semibold text-gray-500 mb-2 uppercase ">Cerca</h3>
|
| 50 |
+
<div className="w-full flex items-end mb-8">
|
| 51 |
+
<div className="">
|
| 52 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 53 |
+
OD
|
| 54 |
+
</p>
|
| 55 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 56 |
+
OI
|
| 57 |
+
</p>
|
| 58 |
+
</div>
|
| 59 |
+
<table className="w-full rounded-lg bg-white text-center border-2 table-fixed border-separate lg:border-collapse h-[6.5rem]">
|
| 60 |
+
<thead className="border-2">
|
| 61 |
+
<tr>
|
| 62 |
+
<th className="border">Esfera</th>
|
| 63 |
+
<th className="border">Cilindro</th>
|
| 64 |
+
<th className="border">Eje</th>
|
| 65 |
+
<th className="border">A/Y</th>
|
| 66 |
+
</tr>
|
| 67 |
+
</thead>
|
| 68 |
+
<tbody>
|
| 69 |
+
<tr>
|
| 70 |
+
<td className="border">{medidas[0]["Esfera_OD_cerca"]}</td>
|
| 71 |
+
<td className="border">{medidas[0]["Cilindro_OD_cerca"]}</td>
|
| 72 |
+
<td className="border">{medidas[0]["Eje_OD_cerca"]}</td>
|
| 73 |
+
<td className="border">
|
| 74 |
+
{medidas[0]["Agudeza_visual_OD_cerca"]}
|
| 75 |
+
</td>
|
| 76 |
+
</tr>
|
| 77 |
+
<tr>
|
| 78 |
+
<td className="border">{medidas[0]["Esfera_OI_cerca"]}</td>
|
| 79 |
+
<td className="border">{medidas[0]["Cilindro_OI_cerca"]}</td>
|
| 80 |
+
<td className="border">{medidas[0]["Eje_OI_cerca"]}</td>
|
| 81 |
+
<td className="border">
|
| 82 |
+
{medidas[0]["Agudeza_visual_OI_cerca"]}
|
| 83 |
+
</td>
|
| 84 |
+
</tr>
|
| 85 |
+
</tbody>
|
| 86 |
+
</table>
|
| 87 |
+
</div>
|
| 88 |
+
</div>
|
| 89 |
+
</div>
|
| 90 |
+
)
|
| 91 |
+
);
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
export default DetalleTablaMedidas;
|
src/components/DropdownClientesItem.jsx
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
|
| 3 |
+
const DropdownClientesItem = ({ cli, setBtnBuscarClick, setCliente, setClienteBusqueda, setNotaAdicional }) => {
|
| 4 |
+
return (
|
| 5 |
+
<li
|
| 6 |
+
key={cli["id_cliente"]}
|
| 7 |
+
onClick={() => {
|
| 8 |
+
setBtnBuscarClick(false);
|
| 9 |
+
setClienteBusqueda("");
|
| 10 |
+
setCliente(cli);
|
| 11 |
+
setNotaAdicional("");
|
| 12 |
+
}}
|
| 13 |
+
className="cursor-pointer hover:font-semibold hover:bg-slate-50 p-2 "
|
| 14 |
+
>
|
| 15 |
+
<p>{cli["nombres_y_apellidos"]}</p>
|
| 16 |
+
<p className="text-sm text-slate-400">{cli["edad"]}</p>
|
| 17 |
+
<p className="text-sm text-slate-400">{cli["telefono"]}</p>
|
| 18 |
+
<p className="text-sm text-slate-400">{cli["direccion"]}</p>
|
| 19 |
+
</li>
|
| 20 |
+
);
|
| 21 |
+
};
|
| 22 |
+
|
| 23 |
+
export default DropdownClientesItem;
|
src/components/ErrorMessage.jsx
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
const ErrorMessage = ({ mensaje }) => {
|
| 3 |
+
return (
|
| 4 |
+
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative my-2 mr-5" role="alert ">
|
| 5 |
+
<strong className="font-bold">Error: </strong>
|
| 6 |
+
<span className="block sm:inline">{mensaje}</span>
|
| 7 |
+
</div>
|
| 8 |
+
);
|
| 9 |
+
};
|
| 10 |
+
|
| 11 |
+
export default ErrorMessage;
|
src/components/Modal.jsx
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
import { registrarPost } from "../lib/conexionApi";
|
| 3 |
+
|
| 4 |
+
const Modal = ({
|
| 5 |
+
openModal,
|
| 6 |
+
setOpenModal,
|
| 7 |
+
nombresYApellidos,
|
| 8 |
+
setNombresYApellidos,
|
| 9 |
+
edad,
|
| 10 |
+
setEdad,
|
| 11 |
+
telefono,
|
| 12 |
+
setTelefono,
|
| 13 |
+
direccion,
|
| 14 |
+
setDireccion,
|
| 15 |
+
setError,
|
| 16 |
+
setClienteBusqueda
|
| 17 |
+
}) => {
|
| 18 |
+
return (
|
| 19 |
+
<div className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex justify-center items-center">
|
| 20 |
+
<div className="bg-white p-5 w-1/3 shadow-md rounded-lg">
|
| 21 |
+
<form>
|
| 22 |
+
<h3 className="text-center text-3xl text-bold mb-8">
|
| 23 |
+
Agregar nuevo cliente
|
| 24 |
+
</h3>
|
| 25 |
+
<div className="">
|
| 26 |
+
<label htmlFor="nombresYApellidos" className="block">
|
| 27 |
+
Nombres y apellidos
|
| 28 |
+
</label>
|
| 29 |
+
<input
|
| 30 |
+
type="text"
|
| 31 |
+
id="nombresYApellidos"
|
| 32 |
+
className="block w-full border p-2 rounded-md"
|
| 33 |
+
placeholder="Ej. Juan Perez"
|
| 34 |
+
onChange={(e) => setNombresYApellidos(e.target.value)}
|
| 35 |
+
value={nombresYApellidos}
|
| 36 |
+
/>
|
| 37 |
+
</div>
|
| 38 |
+
<div className="flex flex-row gap-3 my-3">
|
| 39 |
+
<div className="w-1/2">
|
| 40 |
+
<label htmlFor="edad" className="block">
|
| 41 |
+
Edad
|
| 42 |
+
</label>
|
| 43 |
+
<input
|
| 44 |
+
type="number"
|
| 45 |
+
id="edad"
|
| 46 |
+
className="block w-full border p-2 rounded-md"
|
| 47 |
+
placeholder="Ej. 40"
|
| 48 |
+
onChange={(e) => setEdad(e.target.value)}
|
| 49 |
+
value={edad}
|
| 50 |
+
/>
|
| 51 |
+
</div>
|
| 52 |
+
<div className="w-1/2">
|
| 53 |
+
<label htmlFor="telefono" className="">
|
| 54 |
+
Telefono
|
| 55 |
+
</label>
|
| 56 |
+
<input
|
| 57 |
+
type="text"
|
| 58 |
+
id="telefono"
|
| 59 |
+
className="block w-full border p-2 rounded-md"
|
| 60 |
+
placeholder="Ej. 999888777"
|
| 61 |
+
onChange={(e) => setTelefono(e.target.value)}
|
| 62 |
+
value={telefono}
|
| 63 |
+
/>
|
| 64 |
+
</div>
|
| 65 |
+
</div>
|
| 66 |
+
<div>
|
| 67 |
+
<label htmlFor="direccion" className="">
|
| 68 |
+
Direccion
|
| 69 |
+
</label>
|
| 70 |
+
<input
|
| 71 |
+
type="text"
|
| 72 |
+
id="direccion"
|
| 73 |
+
className="block w-full border p-2 rounded-md"
|
| 74 |
+
placeholder="Ej. Calle 123"
|
| 75 |
+
onChange={(e) => setDireccion(e.target.value)}
|
| 76 |
+
value={direccion}
|
| 77 |
+
/>
|
| 78 |
+
</div>
|
| 79 |
+
<div>
|
| 80 |
+
<div>
|
| 81 |
+
<button
|
| 82 |
+
type="submit"
|
| 83 |
+
className="cursor-pointer py-2 w-full bg-slate-700 hover:bg-slate-800 text-white font-semibold text-center rounded-md mt-5"
|
| 84 |
+
onClick={(e) => {
|
| 85 |
+
e.preventDefault();
|
| 86 |
+
const nuevoCliente = {
|
| 87 |
+
nombres_y_apellidos: nombresYApellidos,
|
| 88 |
+
edad: edad,
|
| 89 |
+
telefono: telefono,
|
| 90 |
+
direccion: direccion,
|
| 91 |
+
};
|
| 92 |
+
registrarPost("clientes", nuevoCliente);
|
| 93 |
+
setOpenModal(false);
|
| 94 |
+
setNombresYApellidos("");
|
| 95 |
+
setEdad("");
|
| 96 |
+
setTelefono("");
|
| 97 |
+
setDireccion("");
|
| 98 |
+
setError(false);
|
| 99 |
+
setClienteBusqueda("");
|
| 100 |
+
}}
|
| 101 |
+
>
|
| 102 |
+
Agregar cliente
|
| 103 |
+
</button>
|
| 104 |
+
</div>
|
| 105 |
+
<div>
|
| 106 |
+
<button
|
| 107 |
+
className="cursor-pointer py-2 w-full bg-slate-300 hover:bg-slate-400 text-gray-700 font-semibold text-center rounded-md mt-2"
|
| 108 |
+
onClick={(e) => {
|
| 109 |
+
e.preventDefault();
|
| 110 |
+
setOpenModal(false);
|
| 111 |
+
setNombresYApellidos("");
|
| 112 |
+
setEdad("");
|
| 113 |
+
setTelefono("");
|
| 114 |
+
setDireccion("");
|
| 115 |
+
setClienteBusqueda("");
|
| 116 |
+
}}
|
| 117 |
+
>
|
| 118 |
+
Cancelar
|
| 119 |
+
</button>
|
| 120 |
+
</div>
|
| 121 |
+
</div>
|
| 122 |
+
</form>
|
| 123 |
+
</div>
|
| 124 |
+
</div>
|
| 125 |
+
);
|
| 126 |
+
};
|
| 127 |
+
|
| 128 |
+
export default Modal;
|
src/components/ModalBoleta.jsx
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useEffect, useState } from "react";
|
| 2 |
+
import { obtenerEspecifico, obtenerGet, procesarBoleta, registrarPost } from "../lib/conexionApi";
|
| 3 |
+
import { Navigate } from "react-router";
|
| 4 |
+
|
| 5 |
+
const ModalBoleta = ({
|
| 6 |
+
fecha,
|
| 7 |
+
setModalBoleta,
|
| 8 |
+
precioTotal,
|
| 9 |
+
carrito,
|
| 10 |
+
prescripcion,
|
| 11 |
+
adelanto,
|
| 12 |
+
precioLunas,
|
| 13 |
+
setPrescripcion,
|
| 14 |
+
setPrecioTotal,
|
| 15 |
+
setCarrito
|
| 16 |
+
}) => {
|
| 17 |
+
|
| 18 |
+
const [clienteBoleta, setClienteBoleta] = useState({})
|
| 19 |
+
const [errorClienteBoleta, setErrorClienteBoleta] = useState(false)
|
| 20 |
+
const [boleta, setBoleta] = useState({})
|
| 21 |
+
const [errorBoleta, setErrorBoleta] = useState(false)
|
| 22 |
+
|
| 23 |
+
const [boletaEmitida, setBoletaEmitida] = useState(false)
|
| 24 |
+
|
| 25 |
+
useEffect(() => {
|
| 26 |
+
obtenerEspecifico("clientes/prescripcion", { "id_prescripcion": prescripcion[0]["id_prescripcion"] }, setClienteBoleta, setErrorClienteBoleta)
|
| 27 |
+
}, [])
|
| 28 |
+
|
| 29 |
+
return (
|
| 30 |
+
<div className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex justify-center items-center">
|
| 31 |
+
<div className="bg-white p-10 shadow-md rounded-lg w-[50rem]">
|
| 32 |
+
<div className=" flex flex-col w-full h-full ">
|
| 33 |
+
<div className="flex flex-col w-full h-full p-5 px-10 mb-5 border-2 pt-5 rounded-lg">
|
| 34 |
+
<p className="text-4xl font-bold mb-2">Arte Visual</p>
|
| 35 |
+
<div className="flex">
|
| 36 |
+
<div className="w-2/3">
|
| 37 |
+
<p>Av. Los Héroes 632 S. J. M</p>
|
| 38 |
+
<div className="flex gap-1 mb-5">
|
| 39 |
+
<svg
|
| 40 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 41 |
+
className="icon icon-tabler icon-tabler-brand-whatsapp"
|
| 42 |
+
width="25"
|
| 43 |
+
height="25"
|
| 44 |
+
viewBox="0 0 24 24"
|
| 45 |
+
strokeWidth="1"
|
| 46 |
+
stroke="#000000"
|
| 47 |
+
fill="none"
|
| 48 |
+
strokeLinecap="round"
|
| 49 |
+
strokeLinejoin="round"
|
| 50 |
+
>
|
| 51 |
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
| 52 |
+
<path d="M3 21l1.65 -3.8a9 9 0 1 1 3.4 2.9l-5.05 .9" />
|
| 53 |
+
<path d="M9 10a.5 .5 0 0 0 1 0v-1a.5 .5 0 0 0 -1 0v1a5 5 0 0 0 5 5h1a.5 .5 0 0 0 0 -1h-1a.5 .5 0 0 0 0 1" />
|
| 54 |
+
</svg>
|
| 55 |
+
<p>902 501 054/968 600 415</p>
|
| 56 |
+
</div>
|
| 57 |
+
<p>Señor(a): {clienteBoleta["nombres_y_apellidos"]}</p>
|
| 58 |
+
<p>Dirección: {clienteBoleta["direccion"]}</p>
|
| 59 |
+
<p>Teléfono: {clienteBoleta["telefono"]}</p>
|
| 60 |
+
</div>
|
| 61 |
+
<div className="w-1/3 text-right">
|
| 62 |
+
<p className="uppercase">NOTA DE PEDIDO</p>
|
| 63 |
+
<p>00000{prescripcion[0]["id_prescripcion"]}</p>
|
| 64 |
+
<p>Fecha: {fecha}</p>
|
| 65 |
+
</div>
|
| 66 |
+
</div>
|
| 67 |
+
<p className="mt-8">Tabla de productos</p>
|
| 68 |
+
<div className="flex justify-center items-center w-full my-5">
|
| 69 |
+
<table className="rounded-lg bg-white text-center border-2 table-fixed w-full border-separate lg:border-collapse">
|
| 70 |
+
<thead className="border-2">
|
| 71 |
+
<tr>
|
| 72 |
+
<th className="border w-[7rem] font-semibold">Cantidad</th>
|
| 73 |
+
<th className="border font-semibold">Descripción</th>
|
| 74 |
+
<th className="border w-[8rem] font-semibold">Precio Unit.</th>
|
| 75 |
+
<th className="border w-[8rem] font-semibold">Importe</th>
|
| 76 |
+
</tr>
|
| 77 |
+
</thead>
|
| 78 |
+
<tbody>
|
| 79 |
+
{carrito.map(item => {
|
| 80 |
+
return (
|
| 81 |
+
<tr key={item["monturaInventario"]["codigo"]}>
|
| 82 |
+
<td className="border">{item["cantidad"]}</td>
|
| 83 |
+
<td className="border">{item["montura"]["nombre_montura"]}</td>
|
| 84 |
+
<td className="border">S/.{item["monturaInventario"]["precio_unit"]}</td>
|
| 85 |
+
<td className="border">S/.{item["monturaInventario"]["precio_unit"]*item["cantidad"]}</td>
|
| 86 |
+
</tr>
|
| 87 |
+
)
|
| 88 |
+
})}
|
| 89 |
+
<tr>
|
| 90 |
+
<td className="border">{1}</td>
|
| 91 |
+
<td className="border">detalle de lunas: {prescripcion[0]["detalle_lunas"]}</td>
|
| 92 |
+
<td className="border">S/.{parseFloat(precioLunas)}</td>
|
| 93 |
+
<td className="border">S/.{1*parseFloat(precioLunas)}</td>
|
| 94 |
+
</tr>
|
| 95 |
+
</tbody>
|
| 96 |
+
</table>
|
| 97 |
+
</div>
|
| 98 |
+
<div className="flex justify-between">
|
| 99 |
+
<p>Adelanto: S/.{adelanto}</p>
|
| 100 |
+
<p>Saldo: S/.{precioTotal-adelanto}</p>
|
| 101 |
+
<p>Total: S/.{precioTotal}</p>
|
| 102 |
+
</div>
|
| 103 |
+
</div>
|
| 104 |
+
<h3 className="text-center text-2xl text-bold mb-8">
|
| 105 |
+
¿Emitir boleta?
|
| 106 |
+
</h3>
|
| 107 |
+
<div className="flex gap-5">
|
| 108 |
+
<button
|
| 109 |
+
className="cursor-pointer py-2 w-1/2 bg-slate-300 hover:bg-slate-400 text-gray-700 font-semibold text-center rounded-md mt-2"
|
| 110 |
+
onClick={(e) => {
|
| 111 |
+
setModalBoleta(false)
|
| 112 |
+
}}
|
| 113 |
+
>
|
| 114 |
+
No
|
| 115 |
+
</button>
|
| 116 |
+
|
| 117 |
+
<button
|
| 118 |
+
type="submit"
|
| 119 |
+
className="w-1/2 mt-2 cursor-pointer py-2 bg-slate-700 hover:bg-slate-800 text-white font-semibold text-center rounded-md "
|
| 120 |
+
onClick={async (e) => {
|
| 121 |
+
const finalizarEmisionBoleta = async () => {
|
| 122 |
+
await procesarBoleta(precioTotal, carrito, adelanto, prescripcion[0]["id_prescripcion"], prescripcion[0]["detalle_lunas"], precioLunas );
|
| 123 |
+
// reiniciar precioTotal carrito, prescripcion,
|
| 124 |
+
await setPrecioTotal(0)
|
| 125 |
+
await setCarrito([])
|
| 126 |
+
await setPrescripcion([])
|
| 127 |
+
|
| 128 |
+
}
|
| 129 |
+
finalizarEmisionBoleta()
|
| 130 |
+
setBoletaEmitida(true)
|
| 131 |
+
}}
|
| 132 |
+
>
|
| 133 |
+
Sí
|
| 134 |
+
</button>
|
| 135 |
+
</div>
|
| 136 |
+
</div>
|
| 137 |
+
</div>
|
| 138 |
+
{boletaEmitida && (
|
| 139 |
+
<Navigate to="/" replace={true}/>
|
| 140 |
+
)}
|
| 141 |
+
</div>
|
| 142 |
+
);
|
| 143 |
+
};
|
| 144 |
+
|
| 145 |
+
export default ModalBoleta;
|
src/components/ModalPrescripcion.jsx
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
import DetalleTablaMedidas from "./DetalleTablaMedidas";
|
| 3 |
+
import DetalleClienteModalPrescripcion from "./DetalleClienteModalPrescripcion";
|
| 4 |
+
import { registrarPost } from "../lib/conexionApi";
|
| 5 |
+
|
| 6 |
+
const ModalPrescripcion = ({
|
| 7 |
+
setOpenModalPrescripcion,
|
| 8 |
+
setPrescripcionLista,
|
| 9 |
+
cliente,
|
| 10 |
+
medidas,
|
| 11 |
+
fechaFormateada,
|
| 12 |
+
notaAdicional,
|
| 13 |
+
setActualizacionMedidas,
|
| 14 |
+
setAsignacionNuevasMedidas,
|
| 15 |
+
setPrescripcionRegistrada
|
| 16 |
+
}) => {
|
| 17 |
+
return (
|
| 18 |
+
<div className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex justify-center items-center">
|
| 19 |
+
<div className="bg-white p-10 shadow-md rounded-lg">
|
| 20 |
+
<form className=" flex flex-col w-full h-full ">
|
| 21 |
+
<div className="flex flex-col w-full h-full p-5 px-10 mb-5 border-2 pt-5 rounded-lg ">
|
| 22 |
+
<div className="flex flex-row justify-between text-gray-500">
|
| 23 |
+
<p className="italic text-left w-ful mb-5">Prescripción</p>
|
| 24 |
+
<p className="text-right w-ful mb-5">{fechaFormateada}</p>
|
| 25 |
+
</div>
|
| 26 |
+
<p className="font-semibold text-2xl mb-8 text-center">
|
| 27 |
+
{cliente["nombres_y_apellidos"]}
|
| 28 |
+
</p>
|
| 29 |
+
<div className="flex flex-col">
|
| 30 |
+
<div className="">
|
| 31 |
+
<DetalleClienteModalPrescripcion
|
| 32 |
+
cliente={cliente}
|
| 33 |
+
notaAdicional={notaAdicional}
|
| 34 |
+
/>
|
| 35 |
+
</div>
|
| 36 |
+
<div>
|
| 37 |
+
<DetalleTablaMedidas medidas={medidas} />
|
| 38 |
+
</div>
|
| 39 |
+
</div>
|
| 40 |
+
</div>
|
| 41 |
+
<h3 className="text-center text-2xl text-bold mb-8">
|
| 42 |
+
¿Estás seguro que deseas continuar?
|
| 43 |
+
</h3>
|
| 44 |
+
<div className="flex gap-5">
|
| 45 |
+
<button
|
| 46 |
+
className="cursor-pointer py-2 w-1/2 bg-slate-300 hover:bg-slate-400 text-gray-700 font-semibold text-center rounded-md mt-2"
|
| 47 |
+
onClick={(e) => {
|
| 48 |
+
e.preventDefault();
|
| 49 |
+
console.log("No");
|
| 50 |
+
setOpenModalPrescripcion(false);
|
| 51 |
+
setActualizacionMedidas(false)
|
| 52 |
+
setAsignacionNuevasMedidas(false)
|
| 53 |
+
setPrescripcionLista(false);
|
| 54 |
+
}}
|
| 55 |
+
>
|
| 56 |
+
No
|
| 57 |
+
</button>
|
| 58 |
+
|
| 59 |
+
<button
|
| 60 |
+
type="submit"
|
| 61 |
+
className="w-1/2 mt-2 cursor-pointer py-2 bg-slate-700 hover:bg-slate-800 text-white font-semibold text-center rounded-md "
|
| 62 |
+
onClick={(e) => {
|
| 63 |
+
e.preventDefault();
|
| 64 |
+
const nuevaPrescripcion = {
|
| 65 |
+
"id_medidas": medidas[0]["id_medidas"],
|
| 66 |
+
"detalle_lunas": notaAdicional,
|
| 67 |
+
"fecha": fechaFormateada,
|
| 68 |
+
};
|
| 69 |
+
|
| 70 |
+
registrarPost('prescripciones', nuevaPrescripcion)
|
| 71 |
+
setPrescripcionRegistrada(true)
|
| 72 |
+
}}
|
| 73 |
+
>
|
| 74 |
+
Sí
|
| 75 |
+
</button>
|
| 76 |
+
</div>
|
| 77 |
+
</form>
|
| 78 |
+
</div>
|
| 79 |
+
</div>
|
| 80 |
+
);
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
export default ModalPrescripcion;
|
src/components/ModalVerCarrito.jsx
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
import { formatearStringUrlImagen } from "../lib/funciones";
|
| 3 |
+
|
| 4 |
+
const ModalVerCarrito = ({
|
| 5 |
+
montura = {
|
| 6 |
+
"id_montura": 10,
|
| 7 |
+
"nombre_montura": "Nombre monturaaaaaaaaaaaaaaaaaaa",
|
| 8 |
+
"imagen":
|
| 9 |
+
'<img src="https://i.ibb.co/jHWcz8B/EBJ8-NK3-Ko81-301-C5-Frontal.png" alt="EBJ8-NK3-Ko81-301-C5-Frontal" border="0">',
|
| 10 |
+
"marca": "Marca montura",
|
| 11 |
+
"color": "Color montura",
|
| 12 |
+
"material": "Material Montura",
|
| 13 |
+
},
|
| 14 |
+
monturaInventario = {
|
| 15 |
+
"id_montura_inventario": 10,
|
| 16 |
+
"id_montura": 8,
|
| 17 |
+
"precio_unit": 90,
|
| 18 |
+
"stock": 20,
|
| 19 |
+
"codigo": "montura8",
|
| 20 |
+
},
|
| 21 |
+
setModalVerCarrito,
|
| 22 |
+
carrito,
|
| 23 |
+
setMontura,
|
| 24 |
+
setMonturaInventario,
|
| 25 |
+
setIrAlCarrito
|
| 26 |
+
}) => {
|
| 27 |
+
const { src, alt, border } = formatearStringUrlImagen(montura["imagen"]);
|
| 28 |
+
|
| 29 |
+
return (
|
| 30 |
+
<div className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex justify-center items-center">
|
| 31 |
+
<div className="bg-white px-10 py-5 w-[790.5px] shadow-md rounded-lg ">
|
| 32 |
+
<div className=" flex items-center justify-between border-b-2 border-black pb-2">
|
| 33 |
+
<p className="uppercase">Recién añadido a tu carrito de compra</p>
|
| 34 |
+
<svg
|
| 35 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 36 |
+
className="icon icon-tabler icon-tabler-x w-10 h-10 rounded-full cursor-pointer p-1"
|
| 37 |
+
width="25"
|
| 38 |
+
height="25"
|
| 39 |
+
viewBox="0 0 24 24"
|
| 40 |
+
strokeWidth="2"
|
| 41 |
+
stroke="#000000"
|
| 42 |
+
fill="none"
|
| 43 |
+
strokeLinecap="round"
|
| 44 |
+
strokeLinejoin="round"
|
| 45 |
+
onClick={() => {
|
| 46 |
+
setMonturaInventario({})
|
| 47 |
+
setMontura({})
|
| 48 |
+
setModalVerCarrito(false)
|
| 49 |
+
}}
|
| 50 |
+
>
|
| 51 |
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
| 52 |
+
<path d="M18 6l-12 12" />
|
| 53 |
+
<path d="M6 6l12 12" />
|
| 54 |
+
</svg>
|
| 55 |
+
</div>
|
| 56 |
+
<div className="flex w-full my-10 ">
|
| 57 |
+
<div className="w-1/2">
|
| 58 |
+
<img src={src} alt={alt} border={border} />
|
| 59 |
+
</div>
|
| 60 |
+
<div className="w-1/2">
|
| 61 |
+
<div className="flex flex-col gap-2">
|
| 62 |
+
<p className="w-full text-xl truncate uppercase">
|
| 63 |
+
{montura["nombre_montura"]}
|
| 64 |
+
</p>
|
| 65 |
+
<p className="text-xl uppercase">{montura["marca"]}</p>
|
| 66 |
+
<p className="mt-3">
|
| 67 |
+
Color: <span className="uppercase">{montura["color"]}</span>
|
| 68 |
+
</p>
|
| 69 |
+
<p className="">
|
| 70 |
+
Material:{" "}
|
| 71 |
+
<span className="uppercase">{montura["material"]}</span>
|
| 72 |
+
</p>
|
| 73 |
+
</div>
|
| 74 |
+
</div>
|
| 75 |
+
</div>
|
| 76 |
+
<button className="w-full text-xl py-4 uppercase border-2 cursor-pointer border-black hover:bg-gray-300" onClick={() => setIrAlCarrito(true)} >
|
| 77 |
+
Ver Carrito ({carrito.length})
|
| 78 |
+
</button>
|
| 79 |
+
</div>
|
| 80 |
+
</div>
|
| 81 |
+
);
|
| 82 |
+
};
|
| 83 |
+
|
| 84 |
+
export default ModalVerCarrito;
|
src/components/TablaMedidas.jsx
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react'
|
| 2 |
+
|
| 3 |
+
const TablaMedidas = ({
|
| 4 |
+
esferaODlejos, setEsferaODLejos,
|
| 5 |
+
cilindroODlejos, setCilindroODlejos,
|
| 6 |
+
ejeODlejos, setEjeODlejos,
|
| 7 |
+
agudezavisualODlejos, setAgudezavisualODlejos,
|
| 8 |
+
esferaOIlejos, setEsferaOIlejos,
|
| 9 |
+
cilindroOIlejos, setCilindroOIlejos,
|
| 10 |
+
ejeOIlejos, setEjeOIlejos,
|
| 11 |
+
agudezavisualOIlejos, setAgudezavisualOIlejos,
|
| 12 |
+
esferaODcerca, setEsferaODcerca,
|
| 13 |
+
cilindroODcerca, setCilindroODcerca,
|
| 14 |
+
ejeODcerca, setEjeODcerca,
|
| 15 |
+
agudezavisualODcerca, setAgudezavisualODcerca,
|
| 16 |
+
esferaOIcerca, setEsferaOIcerca,
|
| 17 |
+
cilindroOIcerca, setCilindroOIcerca,
|
| 18 |
+
ejeOIcerca, setEjeOIcerca,
|
| 19 |
+
agudezavisualOIcerca, setAgudezavisualOIcerca
|
| 20 |
+
}) => {
|
| 21 |
+
return (
|
| 22 |
+
<div className=" flex flex-col items-center justify-center mt-5 px-5">
|
| 23 |
+
<h3 className="font-semibold text-gray-500 mb-2 uppercase ">
|
| 24 |
+
Lejos
|
| 25 |
+
</h3>
|
| 26 |
+
<div className="w-full flex items-end mb-8">
|
| 27 |
+
<div className="">
|
| 28 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 29 |
+
OD
|
| 30 |
+
</p>
|
| 31 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 32 |
+
OI
|
| 33 |
+
</p>
|
| 34 |
+
</div>
|
| 35 |
+
<table className="rounded-lg bg-white text-center border-2 table-fixed border-separate lg:border-collapse h-[6.5rem]">
|
| 36 |
+
<thead className="border-2">
|
| 37 |
+
<tr>
|
| 38 |
+
<th className="border">Esfera</th>
|
| 39 |
+
<th className="border">Cilindro</th>
|
| 40 |
+
<th className="border">Eje</th>
|
| 41 |
+
<th className="border">A/Y</th>
|
| 42 |
+
</tr>
|
| 43 |
+
</thead>
|
| 44 |
+
<tbody>
|
| 45 |
+
<tr>
|
| 46 |
+
<td className="border">
|
| 47 |
+
<input
|
| 48 |
+
type="text"
|
| 49 |
+
className="text-center w-full h-full"
|
| 50 |
+
onChange={(e) =>
|
| 51 |
+
setEsferaODLejos(e.target.value)
|
| 52 |
+
}
|
| 53 |
+
value={esferaODlejos}
|
| 54 |
+
/>
|
| 55 |
+
</td>
|
| 56 |
+
<td className="border">
|
| 57 |
+
<input
|
| 58 |
+
type="text"
|
| 59 |
+
className="text-center w-full h-full"
|
| 60 |
+
onChange={(e) =>
|
| 61 |
+
setCilindroODlejos(e.target.value)
|
| 62 |
+
}
|
| 63 |
+
value={cilindroODlejos}
|
| 64 |
+
/>
|
| 65 |
+
</td>
|
| 66 |
+
<td className="border">
|
| 67 |
+
<input
|
| 68 |
+
type="text"
|
| 69 |
+
className="text-center w-full h-full"
|
| 70 |
+
onChange={(e) =>
|
| 71 |
+
setEjeODlejos(e.target.value)
|
| 72 |
+
}
|
| 73 |
+
value={ejeODlejos}
|
| 74 |
+
/>
|
| 75 |
+
</td>
|
| 76 |
+
<td className="border">
|
| 77 |
+
<input
|
| 78 |
+
type="text"
|
| 79 |
+
className="text-center w-full h-full"
|
| 80 |
+
onChange={(e) =>
|
| 81 |
+
setAgudezavisualODlejos(e.target.value)
|
| 82 |
+
}
|
| 83 |
+
value={agudezavisualODlejos}
|
| 84 |
+
/>
|
| 85 |
+
</td>
|
| 86 |
+
</tr>
|
| 87 |
+
<tr>
|
| 88 |
+
<td className="border">
|
| 89 |
+
<input
|
| 90 |
+
type="text"
|
| 91 |
+
className="text-center w-full h-full"
|
| 92 |
+
onChange={(e) =>
|
| 93 |
+
setEsferaOIlejos(e.target.value)
|
| 94 |
+
}
|
| 95 |
+
value={esferaOIlejos}
|
| 96 |
+
/>
|
| 97 |
+
</td>
|
| 98 |
+
<td className="border">
|
| 99 |
+
<input
|
| 100 |
+
type="text"
|
| 101 |
+
className="text-center w-full h-full"
|
| 102 |
+
onChange={(e) =>
|
| 103 |
+
setCilindroOIlejos(e.target.value)
|
| 104 |
+
}
|
| 105 |
+
value={cilindroOIlejos}
|
| 106 |
+
/>
|
| 107 |
+
</td>
|
| 108 |
+
<td className="border">
|
| 109 |
+
<input
|
| 110 |
+
type="text"
|
| 111 |
+
className="text-center w-full h-full"
|
| 112 |
+
onChange={(e) =>
|
| 113 |
+
setEjeOIlejos(e.target.value)
|
| 114 |
+
}
|
| 115 |
+
value={ejeOIlejos}
|
| 116 |
+
/>
|
| 117 |
+
</td>
|
| 118 |
+
<td className="border">
|
| 119 |
+
<input
|
| 120 |
+
type="text"
|
| 121 |
+
className="text-center w-full h-full"
|
| 122 |
+
onChange={(e) =>
|
| 123 |
+
setAgudezavisualOIlejos(e.target.value)
|
| 124 |
+
}
|
| 125 |
+
value={agudezavisualOIlejos}
|
| 126 |
+
/>
|
| 127 |
+
</td>
|
| 128 |
+
</tr>
|
| 129 |
+
</tbody>
|
| 130 |
+
</table>
|
| 131 |
+
</div>
|
| 132 |
+
<div className=" flex flex-col items-center justify-center mt-5">
|
| 133 |
+
<h3 className="font-semibold text-gray-500 mb-2 uppercase ">
|
| 134 |
+
Cerca
|
| 135 |
+
</h3>
|
| 136 |
+
<div className="w-full flex items-end mb-8">
|
| 137 |
+
<div className="">
|
| 138 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 139 |
+
OD
|
| 140 |
+
</p>
|
| 141 |
+
<p className="h-[34.81px] pr-2 font-semibold text-gray-500 text-center">
|
| 142 |
+
OI
|
| 143 |
+
</p>
|
| 144 |
+
</div>
|
| 145 |
+
<table className="rounded-lg bg-white text-center border-2 table-fixed border-separate lg:border-collapse h-[6.5rem]">
|
| 146 |
+
<thead className="border-2">
|
| 147 |
+
<tr>
|
| 148 |
+
<th className="border">Esfera</th>
|
| 149 |
+
<th className="border">Cilindro</th>
|
| 150 |
+
<th className="border">Eje</th>
|
| 151 |
+
<th className="border">A/Y</th>
|
| 152 |
+
</tr>
|
| 153 |
+
</thead>
|
| 154 |
+
<tbody>
|
| 155 |
+
<tr>
|
| 156 |
+
<td className="border">
|
| 157 |
+
<input
|
| 158 |
+
type="text"
|
| 159 |
+
className="text-center w-full h-full"
|
| 160 |
+
onChange={(e) =>
|
| 161 |
+
setEsferaODcerca(e.target.value)
|
| 162 |
+
}
|
| 163 |
+
value={esferaODcerca}
|
| 164 |
+
/>
|
| 165 |
+
</td>
|
| 166 |
+
<td className="border">
|
| 167 |
+
<input
|
| 168 |
+
type="text"
|
| 169 |
+
className="text-center w-full h-full"
|
| 170 |
+
onChange={(e) =>
|
| 171 |
+
setCilindroODcerca(e.target.value)
|
| 172 |
+
}
|
| 173 |
+
value={cilindroODcerca}
|
| 174 |
+
/>
|
| 175 |
+
</td>
|
| 176 |
+
<td className="border">
|
| 177 |
+
<input
|
| 178 |
+
type="text"
|
| 179 |
+
className="text-center w-full h-full"
|
| 180 |
+
onChange={(e) =>
|
| 181 |
+
setEjeODcerca(e.target.value)
|
| 182 |
+
}
|
| 183 |
+
value={ejeODcerca}
|
| 184 |
+
/>
|
| 185 |
+
</td>
|
| 186 |
+
<td className="border">
|
| 187 |
+
<input
|
| 188 |
+
type="text"
|
| 189 |
+
className="text-center w-full h-full"
|
| 190 |
+
onChange={(e) =>
|
| 191 |
+
setAgudezavisualODcerca(e.target.value)
|
| 192 |
+
}
|
| 193 |
+
value={agudezavisualODcerca}
|
| 194 |
+
/>
|
| 195 |
+
</td>
|
| 196 |
+
</tr>
|
| 197 |
+
<tr>
|
| 198 |
+
<td className="border">
|
| 199 |
+
<input
|
| 200 |
+
type="text"
|
| 201 |
+
className="text-center w-full h-full"
|
| 202 |
+
onChange={(e) =>
|
| 203 |
+
setEsferaOIcerca(e.target.value)
|
| 204 |
+
}
|
| 205 |
+
value={esferaOIcerca}
|
| 206 |
+
/>
|
| 207 |
+
</td>
|
| 208 |
+
<td className="border">
|
| 209 |
+
<input
|
| 210 |
+
type="text"
|
| 211 |
+
className="text-center w-full h-full"
|
| 212 |
+
onChange={(e) =>
|
| 213 |
+
setCilindroOIcerca(e.target.value)
|
| 214 |
+
}
|
| 215 |
+
value={cilindroOIcerca}
|
| 216 |
+
/>
|
| 217 |
+
</td>
|
| 218 |
+
<td className="border">
|
| 219 |
+
<input
|
| 220 |
+
type="text"
|
| 221 |
+
className="text-center w-full h-full"
|
| 222 |
+
onChange={(e) =>
|
| 223 |
+
setEjeOIcerca(e.target.value)
|
| 224 |
+
}
|
| 225 |
+
value={ejeOIcerca}
|
| 226 |
+
/>
|
| 227 |
+
</td>
|
| 228 |
+
<td className="border">
|
| 229 |
+
<input
|
| 230 |
+
type="text"
|
| 231 |
+
className="text-center w-full h-full"
|
| 232 |
+
onChange={(e) =>
|
| 233 |
+
setAgudezavisualOIcerca(e.target.value)
|
| 234 |
+
}
|
| 235 |
+
value={agudezavisualOIcerca}
|
| 236 |
+
/>
|
| 237 |
+
</td>
|
| 238 |
+
</tr>
|
| 239 |
+
</tbody>
|
| 240 |
+
</table>
|
| 241 |
+
</div>
|
| 242 |
+
</div>
|
| 243 |
+
</div>
|
| 244 |
+
)
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
export default TablaMedidas
|
src/index.css
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@tailwind base;
|
| 2 |
+
@tailwind components;
|
| 3 |
+
@tailwind utilities;
|
| 4 |
+
|
| 5 |
+
#nav-ul a.active li{
|
| 6 |
+
background-color: rgb(255 255 255);
|
| 7 |
+
color: black;
|
| 8 |
+
font-weight: 600;
|
| 9 |
+
}
|
src/lib/conexionApi.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const url = import.meta.env.VITE_API_URL
|
| 2 |
+
|
| 3 |
+
export const cargarApi = async () => {
|
| 4 |
+
const response = await fetch(url)
|
| 5 |
+
if (response.ok) {
|
| 6 |
+
const data = await response.json()
|
| 7 |
+
console.log(data);
|
| 8 |
+
}
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
export const obtenerGet = async (endpoint, funcionSet, funcionSetError) => {
|
| 12 |
+
const response = await fetch(`${url}/${endpoint}`)
|
| 13 |
+
const data = await response.json()
|
| 14 |
+
if (data.error || data.length === 0 || Object.keys(data).length === 0) {
|
| 15 |
+
funcionSetError(true)
|
| 16 |
+
}
|
| 17 |
+
funcionSet(data)
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
export const registrarPost = async (endpoint, data) => {
|
| 21 |
+
const response = await fetch(`${url}/${endpoint}`, {
|
| 22 |
+
method: 'POST',
|
| 23 |
+
body: JSON.stringify(data),
|
| 24 |
+
headers: {
|
| 25 |
+
'Content-type': 'application/json'
|
| 26 |
+
}
|
| 27 |
+
})
|
| 28 |
+
const res = await response.json()
|
| 29 |
+
return res
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
export const obtenerEspecifico = async (endpoint, dato, funcionSet, funcionSetError) => {
|
| 33 |
+
const response = await fetch(`${url}/${endpoint}`, {
|
| 34 |
+
method: 'POST',
|
| 35 |
+
headers: {
|
| 36 |
+
'Content-type': 'application/json'
|
| 37 |
+
},
|
| 38 |
+
body: JSON.stringify(dato),
|
| 39 |
+
})
|
| 40 |
+
const data = await response.json()
|
| 41 |
+
funcionSet(data)
|
| 42 |
+
if (data.error || data.length === 0) {
|
| 43 |
+
funcionSetError(true)
|
| 44 |
+
}
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
export const actualizarPut = async (endpoint, data) => {
|
| 48 |
+
const response = await fetch(`${url}/${endpoint}`, {
|
| 49 |
+
method: 'PUT',
|
| 50 |
+
body: JSON.stringify(data),
|
| 51 |
+
headers: {
|
| 52 |
+
'Content-type': 'application/json'
|
| 53 |
+
}
|
| 54 |
+
})
|
| 55 |
+
const res = await response.json()
|
| 56 |
+
return res
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
export const getEspecifico = async (endpoint, dato) => {
|
| 60 |
+
const response = await fetch(`${url}/${endpoint}`)
|
| 61 |
+
const data = await response.json()
|
| 62 |
+
return data
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
export const emitirPdfPrescripcion = (idPrescripcion) => {
|
| 66 |
+
const urlPdf = `${url}/prescripcion/pdf/${idPrescripcion}`
|
| 67 |
+
return urlPdf
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
export const procesarBoleta = async (precioTotal, carrito, adelanto, idprescripcion, descripcion, precioLunas) => {
|
| 71 |
+
const responseRegistrarBoleta = await fetch(`${url}/boletas`, {
|
| 72 |
+
method: 'POST',
|
| 73 |
+
body: JSON.stringify({
|
| 74 |
+
"precio_total": precioTotal,
|
| 75 |
+
"estado_recojo": "pendiente"
|
| 76 |
+
}),
|
| 77 |
+
headers: {
|
| 78 |
+
'Content-type': 'application/json'
|
| 79 |
+
}
|
| 80 |
+
})
|
| 81 |
+
const resRegistrarBoleta = await responseRegistrarBoleta.json()
|
| 82 |
+
console.log(resRegistrarBoleta)
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
const boleta = await fetch(`${url}/boleta/ultima`)
|
| 86 |
+
const responseBoleta = await boleta.json()
|
| 87 |
+
console.log(responseBoleta)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
carrito.forEach(async item => {
|
| 91 |
+
console.log(item);
|
| 92 |
+
const responseMonturasPedidos = await fetch(`${url}/monturas_pedidos`, {
|
| 93 |
+
method: 'POST',
|
| 94 |
+
body: JSON.stringify({
|
| 95 |
+
"id_montura_inventario": item["monturaInventario"]["id_montura_inventario"],
|
| 96 |
+
"cantidad": item["cantidad"],
|
| 97 |
+
"precio": item["monturaInventario"]["precio_unit"]*item["cantidad"],
|
| 98 |
+
"id_boleta": responseBoleta["id_boleta"]
|
| 99 |
+
}),
|
| 100 |
+
headers: {
|
| 101 |
+
'Content-type': 'application/json'
|
| 102 |
+
}
|
| 103 |
+
})
|
| 104 |
+
const resMonturasPedidos = await responseMonturasPedidos.json()
|
| 105 |
+
console.log(resMonturasPedidos)
|
| 106 |
+
})
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
const lunasPedido = await fetch(`${url}/lunas_pedido`, {
|
| 111 |
+
method: 'POST',
|
| 112 |
+
body: JSON.stringify({
|
| 113 |
+
"id_prescripcion": idprescripcion,
|
| 114 |
+
"precio": parseFloat(precioLunas),
|
| 115 |
+
"id_boleta": responseBoleta["id_boleta"] ,
|
| 116 |
+
"descripcion": descripcion,
|
| 117 |
+
"cantidad": 1
|
| 118 |
+
}),
|
| 119 |
+
headers: {
|
| 120 |
+
'Content-type': 'application/json'
|
| 121 |
+
}
|
| 122 |
+
})
|
| 123 |
+
const resLunasPedido = await lunasPedido.json()
|
| 124 |
+
console.log(resLunasPedido);
|
| 125 |
+
|
| 126 |
+
const responsePDF = await fetch(`${url}/boleta/descargarPDF/${responseBoleta["id_boleta"]}/${adelanto}`)
|
| 127 |
+
|
| 128 |
+
window.open(responsePDF.url, "_blank");
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
export const prescripcionPdff = async (idPrescripcion) => {
|
| 132 |
+
const responsePDF = await fetch(`${url}/prescripcion/pdf/${idPrescripcion}`)
|
| 133 |
+
window.open(responsePDF.url, "_blank");
|
| 134 |
+
}
|
src/lib/funciones.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { obtenerGet, registrarPost } from "./conexionApi";
|
| 2 |
+
|
| 3 |
+
export function formatearStringUrlImagen(stringImagen='<img src="https://i.ibb.co/TTmWTjV/df-BBqw-TYjvfrontal-tom-silver-optimania.png" alt="df-BBqw-TYjvfrontal-tom-silver-optimania" border="0">') {
|
| 4 |
+
// Crear un elemento temporal para parsear el string HTML
|
| 5 |
+
const tempElement = document.createElement('div');
|
| 6 |
+
tempElement.innerHTML = stringImagen;
|
| 7 |
+
|
| 8 |
+
// Obtener los atributos necesarios del elemento
|
| 9 |
+
const src = tempElement.querySelector('img').getAttribute('src');
|
| 10 |
+
const alt = tempElement.querySelector('img').getAttribute('alt');
|
| 11 |
+
const border = tempElement.querySelector('img').getAttribute('border');
|
| 12 |
+
|
| 13 |
+
// Crear un objeto con los valores obtenidos
|
| 14 |
+
const imagenObj = {
|
| 15 |
+
src: src,
|
| 16 |
+
alt: alt,
|
| 17 |
+
border: border
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
return imagenObj;
|
| 21 |
+
}
|
| 22 |
+
|
src/main.jsx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react'
|
| 2 |
+
import ReactDOM from "react-dom/client";
|
| 3 |
+
import App from "./App.jsx";
|
| 4 |
+
import "./index.css";
|
| 5 |
+
import { BrowserRouter } from "react-router-dom";
|
| 6 |
+
|
| 7 |
+
ReactDOM.createRoot(document.getElementById("root")).render(
|
| 8 |
+
<React.StrictMode>
|
| 9 |
+
<BrowserRouter>
|
| 10 |
+
<App />
|
| 11 |
+
</BrowserRouter>
|
| 12 |
+
</React.StrictMode>
|
| 13 |
+
);
|
tailwind.config.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/** @type {import('tailwindcss').Config} */
|
| 2 |
+
export default {
|
| 3 |
+
content: ["index.html", "./src/**/*.jsx"],
|
| 4 |
+
theme: {
|
| 5 |
+
extend: {},
|
| 6 |
+
},
|
| 7 |
+
plugins: []
|
| 8 |
+
}
|
| 9 |
+
|
vite.config.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { defineConfig } from 'vite'
|
| 2 |
+
import react from '@vitejs/plugin-react'
|
| 3 |
+
|
| 4 |
+
// https://vitejs.dev/config/
|
| 5 |
+
export default defineConfig({
|
| 6 |
+
plugins: [react()],
|
| 7 |
+
})
|