Added IVATypes
This commit is contained in:
parent
c81a1ea588
commit
52918e3393
Binary file not shown.
|
|
@ -14,6 +14,8 @@ public class ProductServiceDTO {
|
||||||
@NotNull
|
@NotNull
|
||||||
private Integer ivaTypeId;
|
private Integer ivaTypeId;
|
||||||
|
|
||||||
|
private IVATypeDTO ivaType;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
|
@ -28,11 +30,13 @@ public class ProductServiceDTO {
|
||||||
@NotNull
|
@NotNull
|
||||||
private StatusValues status;
|
private StatusValues status;
|
||||||
|
|
||||||
public ProductServiceDTO() {}
|
public ProductServiceDTO() {
|
||||||
|
}
|
||||||
|
|
||||||
public ProductServiceDTO(ProductService entity) {
|
public ProductServiceDTO(ProductService entity) {
|
||||||
this.id = entity.getId();
|
this.id = entity.getId();
|
||||||
this.ivaTypeId = entity.getIvaType() != null ? entity.getIvaType().getId() : null;
|
this.ivaTypeId = entity.getIvaType() != null ? entity.getIvaType().getId() : null;
|
||||||
|
this.ivaType = entity.getIvaType() != null ? new IVATypeDTO(entity.getIvaType()) : null;
|
||||||
this.name = entity.getName();
|
this.name = entity.getName();
|
||||||
this.description = entity.getDescription();
|
this.description = entity.getDescription();
|
||||||
this.price = entity.getPrice();
|
this.price = entity.getPrice();
|
||||||
|
|
@ -66,9 +70,7 @@ public class ProductServiceDTO {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getters y setters
|
||||||
// Getters y setters...
|
|
||||||
|
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
return id;
|
return id;
|
||||||
|
|
@ -86,6 +88,14 @@ public class ProductServiceDTO {
|
||||||
this.ivaTypeId = ivaTypeId;
|
this.ivaTypeId = ivaTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IVATypeDTO getIvaType() {
|
||||||
|
return ivaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIvaType(IVATypeDTO ivaType) {
|
||||||
|
this.ivaType = ivaType;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,10 +131,23 @@ public class InvoiceService extends AbstractService<Invoice, Integer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateInvoiceTotal(Invoice invoice) {
|
public void updateInvoiceTotal(Invoice invoice) {
|
||||||
BigDecimal total = invoice.getInvoiceLines().stream()
|
BigDecimal total = BigDecimal.ZERO;
|
||||||
.map(InvoiceLine::getSubtotal)
|
|
||||||
.filter(Objects::nonNull)
|
for (InvoiceLine line : invoice.getInvoiceLines()) {
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
if (line.getUnitPrice() != null && line.getQuantity() != null) {
|
||||||
|
BigDecimal quantity = BigDecimal.valueOf(line.getQuantity());
|
||||||
|
BigDecimal base = line.getUnitPrice().multiply(quantity);
|
||||||
|
|
||||||
|
BigDecimal ivaMultiplier = BigDecimal.ONE;
|
||||||
|
if (line.getProductService() != null && line.getProductService().getIvaType() != null) {
|
||||||
|
BigDecimal iva = line.getProductService().getIvaType().getPercentage();
|
||||||
|
ivaMultiplier = ivaMultiplier.add(iva.divide(BigDecimal.valueOf(100)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal lineTotal = base.multiply(ivaMultiplier);
|
||||||
|
total = total.add(lineTotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
invoice.setTotal(total);
|
invoice.setTotal(total);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import api from "../../api/axiosConfig";
|
||||||
|
|
||||||
|
const IVATypeManager = () => {
|
||||||
|
const [ivaTypes, setIvaTypes] = useState([]);
|
||||||
|
const [newIva, setNewIva] = useState({ percentage: "", description: "" });
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
const fetchIvaTypes = async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.get("/iva-types/getAll");
|
||||||
|
setIvaTypes(res.data);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
setError("Error al obtener los tipos de IVA.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchIvaTypes();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setNewIva((prev) => ({ ...prev, [name]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddIva = async () => {
|
||||||
|
setError("");
|
||||||
|
if (!newIva.percentage || isNaN(newIva.percentage)) {
|
||||||
|
setError("Introduce un porcentaje válido.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
percentage: parseFloat(newIva.percentage),
|
||||||
|
description: newIva.description
|
||||||
|
};
|
||||||
|
|
||||||
|
await api.post("/iva-types/create", payload);
|
||||||
|
setNewIva({ percentage: "", description: "" });
|
||||||
|
fetchIvaTypes();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
setError("No se pudo crear el tipo de IVA.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = async (id) => {
|
||||||
|
if (!window.confirm("¿Seguro que deseas eliminar este tipo de IVA?")) return;
|
||||||
|
try {
|
||||||
|
await api.delete(`/iva-types/deleteById/${id}`);
|
||||||
|
fetchIvaTypes();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
setError("No se pudo eliminar el tipo de IVA.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="content-area">
|
||||||
|
<h2>Gestión de Tipos de IVA</h2>
|
||||||
|
|
||||||
|
{error && <p style={{ color: "red" }}>{error}</p>}
|
||||||
|
|
||||||
|
<div className="form-section">
|
||||||
|
<label>Porcentaje:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="percentage"
|
||||||
|
value={newIva.percentage}
|
||||||
|
onChange={handleChange}
|
||||||
|
step="0.01"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<label>Descripción:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="description"
|
||||||
|
value={newIva.description}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button className="btn btn-primary" onClick={handleAddIva}>
|
||||||
|
+ Añadir IVA
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table className="table" style={{ marginTop: "2rem" }}>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Porcentaje</th>
|
||||||
|
<th>Descripción</th>
|
||||||
|
<th>Acciones</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{ivaTypes.map((iva) => (
|
||||||
|
<tr key={iva.id}>
|
||||||
|
<td>{iva.id}</td>
|
||||||
|
<td>{iva.percentage}%</td>
|
||||||
|
<td>{iva.description}</td>
|
||||||
|
<td>
|
||||||
|
<button className="btn btn-danger btn-sm" onClick={() => handleDelete(iva.id)}>
|
||||||
|
🗑️ Eliminar
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default IVATypeManager;
|
||||||
|
|
@ -10,7 +10,7 @@ const InvoiceForm = () => {
|
||||||
const [lines, setLines] = useState([]);
|
const [lines, setLines] = useState([]);
|
||||||
const [products, setProducts] = useState([]);
|
const [products, setProducts] = useState([]);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [createdInvoiceId, setCreatedInvoiceId] = useState(null);
|
const [createdInvoice, setCreatedInvoice] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.get("/students/getAll").then((res) => setStudents(res.data));
|
api.get("/students/getAll").then((res) => setStudents(res.data));
|
||||||
|
|
@ -31,19 +31,31 @@ const InvoiceForm = () => {
|
||||||
setLines(lines.filter((_, i) => i !== index));
|
setLines(lines.filter((_, i) => i !== index));
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateTotal = () => {
|
const calculateSubtotal = () => {
|
||||||
return lines.reduce((acc, line) => {
|
return lines.reduce((acc, line) => {
|
||||||
const product = products.find(
|
const product = products.find((p) => p.id === parseInt(line.productServiceId));
|
||||||
(p) => p.id === parseInt(line.productServiceId)
|
|
||||||
);
|
|
||||||
if (!product) return acc;
|
if (!product) return acc;
|
||||||
return acc + product.price * line.quantity;
|
return acc + product.price * (parseInt(line.quantity) || 1);
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const calculateIVA = () => {
|
||||||
|
return lines.reduce((acc, line) => {
|
||||||
|
const product = products.find((p) => p.id === parseInt(line.productServiceId));
|
||||||
|
if (!product || !product.ivaType) return acc;
|
||||||
|
const quantity = parseInt(line.quantity) || 1;
|
||||||
|
const iva = product.ivaType.percentage || 0;
|
||||||
|
return acc + (product.price * quantity * (iva / 100));
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateTotal = () => {
|
||||||
|
return calculateSubtotal() + calculateIVA();
|
||||||
|
};
|
||||||
|
|
||||||
const createInvoice = async () => {
|
const createInvoice = async () => {
|
||||||
setError("");
|
setError("");
|
||||||
setCreatedInvoiceId(null);
|
setCreatedInvoice(null);
|
||||||
|
|
||||||
if (!userId || lines.length === 0) {
|
if (!userId || lines.length === 0) {
|
||||||
setError("Selecciona un estudiante y al menos un producto.");
|
setError("Selecciona un estudiante y al menos un producto.");
|
||||||
|
|
@ -52,9 +64,7 @@ const InvoiceForm = () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const preparedLines = lines.map((line) => {
|
const preparedLines = lines.map((line) => {
|
||||||
const product = products.find(
|
const product = products.find((p) => p.id === parseInt(line.productServiceId));
|
||||||
(p) => p.id === parseInt(line.productServiceId)
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
productServiceId: parseInt(line.productServiceId),
|
productServiceId: parseInt(line.productServiceId),
|
||||||
quantity: parseInt(line.quantity),
|
quantity: parseInt(line.quantity),
|
||||||
|
|
@ -71,9 +81,7 @@ const InvoiceForm = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await api.post("/invoices/createInvoiceWithLines", payload);
|
const res = await api.post("/invoices/createInvoiceWithLines", payload);
|
||||||
const invoiceId = res.data.id;
|
setCreatedInvoice(res.data);
|
||||||
|
|
||||||
setCreatedInvoiceId(invoiceId);
|
|
||||||
alert("✅ Factura creada correctamente.");
|
alert("✅ Factura creada correctamente.");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
@ -83,14 +91,14 @@ const InvoiceForm = () => {
|
||||||
|
|
||||||
const downloadPdf = async () => {
|
const downloadPdf = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await api.get(`/invoices/generatePDFById/${createdInvoiceId}`, {
|
const response = await api.get(`/invoices/generatePDFById/${createdInvoice.id}`, {
|
||||||
responseType: "blob", // para recibir el PDF correctamente
|
responseType: "blob",
|
||||||
});
|
});
|
||||||
|
|
||||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.setAttribute("download", `factura_${createdInvoiceId}.pdf`);
|
link.setAttribute("download", `factura_${createdInvoice.id}.pdf`);
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -141,9 +149,11 @@ const InvoiceForm = () => {
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<h4 style={{ marginTop: "1rem" }}>
|
<div style={{ marginTop: "1rem" }}>
|
||||||
Total: <strong>{calculateTotal().toFixed(2)} €</strong>
|
<h4>Subtotal: <strong>{calculateSubtotal().toFixed(2)} €</strong></h4>
|
||||||
</h4>
|
<h4>IVA: <strong>{calculateIVA().toFixed(2)} €</strong></h4>
|
||||||
|
<h4>Total estimado con IVA: <strong>{calculateTotal().toFixed(2)} €</strong></h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ErrorMessage message={error} />
|
<ErrorMessage message={error} />
|
||||||
|
|
||||||
|
|
@ -160,9 +170,10 @@ const InvoiceForm = () => {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{createdInvoiceId && (
|
{createdInvoice && (
|
||||||
<div style={{ marginTop: "2rem" }}>
|
<div style={{ marginTop: "2rem" }}>
|
||||||
<h4>Factura creada: #{createdInvoiceId}</h4>
|
<h4>Factura creada: #{createdInvoice.id}</h4>
|
||||||
|
<h4>Total con IVA: <strong>{createdInvoice.total.toFixed(2)} €</strong></h4>
|
||||||
<button className="btn btn-primary" onClick={downloadPdf}>
|
<button className="btn btn-primary" onClick={downloadPdf}>
|
||||||
📄 Descargar PDF
|
📄 Descargar PDF
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
// src/components/forms/InvoiceLineItem.jsx
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const InvoiceLineItem = ({ index, line, products, onUpdate, onRemove }) => {
|
const InvoiceLineItem = ({ index, line, products, onUpdate, onRemove }) => {
|
||||||
|
|
@ -8,6 +6,10 @@ const InvoiceLineItem = ({ index, line, products, onUpdate, onRemove }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedProduct = products.find(p => p.id === parseInt(line.productServiceId));
|
const selectedProduct = products.find(p => p.id === parseInt(line.productServiceId));
|
||||||
|
const quantity = parseInt(line.quantity) || 1;
|
||||||
|
const price = selectedProduct?.price || 0;
|
||||||
|
const ivaPercentage = selectedProduct?.ivaType?.percentage || 0;
|
||||||
|
const totalConIVA = price * quantity * (1 + ivaPercentage / 100);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="content-area" style={{ marginBottom: "1rem", display: "flex", flexDirection: "column", gap: "0.5rem" }}>
|
<div className="content-area" style={{ marginBottom: "1rem", display: "flex", flexDirection: "column", gap: "0.5rem" }}>
|
||||||
|
|
@ -36,9 +38,14 @@ const InvoiceLineItem = ({ index, line, products, onUpdate, onRemove }) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{selectedProduct && (
|
{selectedProduct && (
|
||||||
<div style={{ fontSize: '0.9rem', color: '#666' }}>
|
<>
|
||||||
<strong>{selectedProduct.name}</strong>: {selectedProduct.description}
|
<div style={{ fontSize: '0.9rem', color: '#666' }}>
|
||||||
</div>
|
<strong>{selectedProduct.name}</strong>: {selectedProduct.description}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: '0.9rem', color: '#333' }}>
|
||||||
|
<strong>Total con IVA:</strong> {totalConIVA.toFixed(2)} €
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<button className="btn btn-danger" onClick={() => onRemove(index)}>Eliminar producto</button>
|
<button className="btn btn-danger" onClick={() => onRemove(index)}>Eliminar producto</button>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
||||||
import { Routes, Route } from 'react-router-dom';
|
import { Routes, Route } from 'react-router-dom';
|
||||||
import Topbar from './Topbar';
|
import Topbar from './Topbar';
|
||||||
import Sidebar from './Sidebar';
|
import Sidebar from './Sidebar';
|
||||||
import ContentArea from './ContentArea';
|
|
||||||
import AdminDashboard from '../../pages/admin/AdminDashboard';
|
import AdminDashboard from '../../pages/admin/AdminDashboard';
|
||||||
import TeacherDashboard from '../../pages/teacher/TeacherDashboard';
|
import TeacherDashboard from '../../pages/teacher/TeacherDashboard';
|
||||||
import StudentDashboard from '../../pages/student/StudentDashboard';
|
import StudentDashboard from '../../pages/student/StudentDashboard';
|
||||||
|
|
@ -11,7 +10,7 @@ import UserList from '../../components/lists/UserList';
|
||||||
import NotificationCreateForm from '../../components/forms/NotificationCreateForm';
|
import NotificationCreateForm from '../../components/forms/NotificationCreateForm';
|
||||||
import StudentHistoryCreateForm from '../../components/forms/StudentHistoryCreateForm';
|
import StudentHistoryCreateForm from '../../components/forms/StudentHistoryCreateForm';
|
||||||
import StudentHistoryList from '../../components/lists/StudentHistoryList';
|
import StudentHistoryList from '../../components/lists/StudentHistoryList';
|
||||||
import ProfilePage from '../../pages/ProfilePage'
|
import ProfilePage from '../../pages/ProfilePage';
|
||||||
import NotificationList from '../../components/lists/NotificationList';
|
import NotificationList from '../../components/lists/NotificationList';
|
||||||
import TrainingGroupForm from '../forms/TrainingGroupFrom';
|
import TrainingGroupForm from '../forms/TrainingGroupFrom';
|
||||||
import TrainingGroupList from '../lists/TrainingGroupList';
|
import TrainingGroupList from '../lists/TrainingGroupList';
|
||||||
|
|
@ -28,9 +27,9 @@ import PaymentForm from '../forms/PaymentForm';
|
||||||
import PaymentList from '../lists/PaymentList';
|
import PaymentList from '../lists/PaymentList';
|
||||||
import ProductForm from '../forms/ProductForm';
|
import ProductForm from '../forms/ProductForm';
|
||||||
import ProductList from '../lists/ProductList';
|
import ProductList from '../lists/ProductList';
|
||||||
|
import IVATypeManager from '../forms/IVATypeManager';
|
||||||
import '../styles/MainLayout.css';
|
import '../styles/MainLayout.css';
|
||||||
|
|
||||||
|
|
||||||
const MainLayout = () => {
|
const MainLayout = () => {
|
||||||
return (
|
return (
|
||||||
<div className="main-layout">
|
<div className="main-layout">
|
||||||
|
|
@ -40,27 +39,20 @@ const MainLayout = () => {
|
||||||
|
|
||||||
<div className="content-area">
|
<div className="content-area">
|
||||||
<Routes>
|
<Routes>
|
||||||
{/* Dashboards principales */}
|
{/* Dashboards */}
|
||||||
<Route path="/admin/dashboard" element={<AdminDashboard />} />
|
<Route path="/admin/dashboard" element={<AdminDashboard />} />
|
||||||
<Route path="/teacher/dashboard" element={<TeacherDashboard />} />
|
<Route path="/teacher/dashboard" element={<TeacherDashboard />} />
|
||||||
<Route path="/student/dashboard" element={<StudentDashboard />} />
|
<Route path="/student/dashboard" element={<StudentDashboard />} />
|
||||||
|
|
||||||
{/* User Management - rutas específicas */}
|
{/* User Management */}
|
||||||
<Route path="/admin/user-management/users/create" element={<UserCreateForm />} />
|
<Route path="/admin/user-management/users/create" element={<UserCreateForm />} />
|
||||||
<Route path="/admin/user-management/users/list" element={<UserList />} />
|
<Route path="/admin/user-management/users/list" element={<UserList />} />
|
||||||
<Route path="/admin/user-management/notifications/create" element={<NotificationCreateForm />} />
|
<Route path="/admin/user-management/notifications/create" element={<NotificationCreateForm />} />
|
||||||
<Route path="/admin/user-management/notifications/list" element={<NotificationList />} />
|
<Route path="/admin/user-management/notifications/list" element={<NotificationList />} />
|
||||||
|
|
||||||
{/* Student History */}
|
|
||||||
<Route path="/admin/user-management/student-history/create" element={<StudentHistoryCreateForm />} />
|
<Route path="/admin/user-management/student-history/create" element={<StudentHistoryCreateForm />} />
|
||||||
<Route path="/admin/user-management/student-history/list" element={<StudentHistoryList />} />
|
<Route path="/admin/user-management/student-history/list" element={<StudentHistoryList />} />
|
||||||
|
|
||||||
{/* ContentArea general para secciones sin componentes específicos */}
|
{/* Class Management */}
|
||||||
<Route path="/admin/user-management/*" element={<ContentArea />} />
|
|
||||||
<Route path="/admin/class-management/*" element={<ContentArea />} />
|
|
||||||
<Route path="/admin/finance/*" element={<ContentArea />} />
|
|
||||||
|
|
||||||
{/*Class Management - rutas específicas*/}
|
|
||||||
<Route path="/admin/class-management/training-groups/create" element={<TrainingGroupForm />} />
|
<Route path="/admin/class-management/training-groups/create" element={<TrainingGroupForm />} />
|
||||||
<Route path="/admin/class-management/training-groups/list" element={<TrainingGroupList />} />
|
<Route path="/admin/class-management/training-groups/list" element={<TrainingGroupList />} />
|
||||||
<Route path="/admin/class-management/training-groups/manage-students" element={<TrainingGroupStudentManager />} />
|
<Route path="/admin/class-management/training-groups/manage-students" element={<TrainingGroupStudentManager />} />
|
||||||
|
|
@ -71,19 +63,17 @@ const MainLayout = () => {
|
||||||
<Route path="/admin/class-management/memberships/create" element={<MembershipForm />} />
|
<Route path="/admin/class-management/memberships/create" element={<MembershipForm />} />
|
||||||
<Route path="/admin/class-management/memberships/list" element={<MembershipList />} />
|
<Route path="/admin/class-management/memberships/list" element={<MembershipList />} />
|
||||||
|
|
||||||
|
{/* Finance */}
|
||||||
<Route path="/admin/finance/invoices/create" element={<InvoiceForm />} />
|
<Route path="/admin/finance/invoices/create" element={<InvoiceForm />} />
|
||||||
<Route path="/admin/finance/invoices/list" element={<InvoiceList />} />
|
<Route path="/admin/finance/invoices/list" element={<InvoiceList />} />
|
||||||
<Route path="/admin/finance/payments/create" element={<PaymentForm />} />
|
<Route path="/admin/finance/payments/create" element={<PaymentForm />} />
|
||||||
<Route path="/admin/finance/payments/list" element={<PaymentList />} />
|
<Route path="/admin/finance/payments/list" element={<PaymentList />} />
|
||||||
<Route path="/admin/finance/products/create" element={<ProductForm />} />
|
<Route path="/admin/finance/products/create" element={<ProductForm />} />
|
||||||
<Route path="/admin/finance/products/list" element={<ProductList />} />
|
<Route path="/admin/finance/products/list" element={<ProductList />} />
|
||||||
|
<Route path="/admin/finance/ivatypes/create" element={<IVATypeManager />} />
|
||||||
|
|
||||||
|
{/* Perfil */}
|
||||||
|
|
||||||
|
|
||||||
{/* Profile Page*/}
|
|
||||||
<Route path="/profile" element={<ProfilePage />} />
|
<Route path="/profile" element={<ProfilePage />} />
|
||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
width: 320px;
|
width: 320px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
color: #2d3436;
|
color: #2d3436;
|
||||||
padding: 0; /* importante para evitar que el padding afecte la altura */
|
padding: 0;
|
||||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.05);
|
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.05);
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -44,4 +44,5 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue