Skip to content

Commit bc6e379

Browse files
authored
Merge pull request #50 from chechojgb/buttonsLovers
add: modal detalles del cliente
2 parents 058b418 + badd6de commit bc6e379

File tree

6 files changed

+262
-9
lines changed

6 files changed

+262
-9
lines changed

app/Http/Controllers/BLClientesController.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,15 @@ public function store(Request $request)
6262
],
6363
]);
6464
}
65+
66+
public function show($id)
67+
{
68+
$clientesDetails = BLCliente::with([
69+
'pedidos.items.empaque.producto',
70+
])
71+
->findOrFail($id);
72+
return response()->json([
73+
'clientesDetails' => $clientesDetails
74+
]);
75+
}
6576
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React, { useEffect, useState } from 'react';
2+
3+
const BigModalWrapper = ({ children, closeModal }) => {
4+
const [show, setShow] = useState(false);
5+
6+
useEffect(() => {
7+
setShow(true);
8+
9+
const handleKeyDown = (e) => {
10+
if (e.key === 'Escape') {
11+
handleClose();
12+
}
13+
};
14+
15+
document.addEventListener('keydown', handleKeyDown);
16+
return () => document.removeEventListener('keydown', handleKeyDown);
17+
}, []);
18+
19+
const handleClose = () => {
20+
setShow(false);
21+
setTimeout(closeModal, 300);
22+
};
23+
24+
return (
25+
<div
26+
className="fixed inset-0 z-50 flex justify-center items-center bg-opacity-40 backdrop-blur-sm p-2 sm:p-4"
27+
onClick={handleClose}
28+
>
29+
<div
30+
onClick={(e) => e.stopPropagation()}
31+
className={`transform transition-all duration-300 ease-out
32+
${show ? 'opacity-100 scale-100' : 'opacity-0 scale-95'}
33+
bg-white dark:bg-black border rounded-xl shadow-xl
34+
w-full sm:max-w-6xl max-h-[95vh] overflow-y-auto`}
35+
>
36+
<div className="p-4 sm:p-6">
37+
{children}
38+
</div>
39+
</div>
40+
</div>
41+
);
42+
};
43+
44+
export default BigModalWrapper;
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import { useState } from 'react';
2+
import {
3+
Badge,
4+
Button,
5+
Card,
6+
Table,
7+
TableBody,
8+
TableCell,
9+
TableHead,
10+
TableHeadCell,
11+
TableRow,
12+
Progress
13+
} from 'flowbite-react';
14+
import {
15+
HiOutlineUser,
16+
HiOutlineMail,
17+
HiOutlinePhone,
18+
HiOutlineLocationMarker,
19+
HiOutlineCalendar,
20+
HiOutlineShoppingBag,
21+
HiOutlineCurrencyDollar,
22+
HiOutlineClock,
23+
HiOutlineStar
24+
} from 'react-icons/hi';
25+
26+
const CustomerDetailsContainer = ({clienteDetails}) => {
27+
console.log('detalles del cliente:',clienteDetails);
28+
29+
const [customer] = useState({
30+
id: 'CUST-78945',
31+
name: 'María González',
32+
email: 'maria.gonzalez@example.com',
33+
phone: '+34 612 345 678',
34+
address: 'Calle Principal 123, Madrid, España',
35+
joinDate: '15/03/2021',
36+
status: 'active',
37+
totalOrders: 24,
38+
totalSpent: 3425.5,
39+
avgOrderValue: 142.73,
40+
lastOrder: '12/05/2023',
41+
favoriteCategory: 'Electrónica',
42+
satisfaction: 4.5
43+
});
44+
45+
const [orders] = useState([
46+
{ id: 'ORD-98765', date: '12/05/2023', amount: 189.99, status: 'Entregado', items: 3 },
47+
{ id: 'ORD-98764', date: '05/05/2023', amount: 245.5, status: 'Entregado', items: 5 },
48+
{ id: 'ORD-98763', date: '28/04/2023', amount: 89.99, status: 'Cancelado', items: 2 },
49+
{ id: 'ORD-98762', date: '15/04/2023', amount: 320.75, status: 'Entregado', items: 4 },
50+
{ id: 'ORD-98761', date: '02/04/2023', amount: 156.3, status: 'Entregado', items: 3 }
51+
]);
52+
53+
54+
55+
return (
56+
<div className="container mx-auto px-4 py-6 space-y-6">
57+
{/* Encabezado */}
58+
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4">
59+
<h1 className="text-3xl font-extrabold bg-gradient-to-r from-blue-500 to-purple-600 bg-clip-text text-transparent">
60+
Detalles del Cliente
61+
</h1>
62+
</div>
63+
64+
{/* Información y estadísticas */}
65+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
66+
{/* Info cliente */}
67+
<Card className="bg-white dark:bg-gray-950 shadow-lg border border-gray-200 dark:border-gray-700 rounded-2xl p-6">
68+
<div className="flex flex-col items-center pb-6 text-center">
69+
<div className="mb-3 h-24 w-24 rounded-full bg-gradient-to-br from-blue-100 to-blue-300 dark:from-blue-800 dark:to-blue-600 flex items-center justify-center text-4xl text-blue-600 dark:text-blue-200 shadow-md">
70+
<HiOutlineUser />
71+
</div>
72+
<h5 className="mb-1 text-xl font-bold text-gray-900 dark:text-white">{clienteDetails?.nombre}</h5>
73+
<Badge color={customer.status === 'active' ? 'success' : 'failure'} className="mb-3 px-3 py-1 rounded-full">
74+
{customer.status === 'active' ? 'Activo' : 'Inactivo'}
75+
</Badge>
76+
77+
</div>
78+
79+
<div className="space-y-3 text-sm sm:text-base divide-y divide-gray-200 dark:divide-gray-700">
80+
<InfoRow icon={<HiOutlineMail />} text={clienteDetails.email} />
81+
<InfoRow icon={<HiOutlinePhone />} text={clienteDetails?.telefono} />
82+
<InfoRow icon={<HiOutlineLocationMarker />} text={clienteDetails?.direccion} />
83+
<InfoRow icon={<HiOutlineCalendar />} text={`Cliente desde: ${clienteDetails.created_at}`} />
84+
</div>
85+
</Card>
86+
87+
{/* Estadísticas */}
88+
<Card className="lg:col-span-2 bg-white dark:bg-gray-950 shadow-lg border border-gray-200 dark:border-gray-700 rounded-2xl p-6">
89+
<h5 className="text-xl font-bold mb-6 text-gray-900 dark:text-white">Estadísticas del Cliente</h5>
90+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
91+
<StatCard icon={<HiOutlineShoppingBag />} label="Pedidos totales" value={customer.totalOrders} color="text-blue-500" />
92+
<StatCard icon={<HiOutlineCurrencyDollar />} label="Total gastado" value={`$${customer.totalSpent.toFixed(2)}`} color="text-green-500" />
93+
<StatCard icon={<HiOutlineClock />} label="Último pedido" value={customer.lastOrder} color="text-purple-500" />
94+
</div>
95+
96+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
97+
<StatCard icon={<HiOutlineCurrencyDollar />} label="Valor promedio por pedido" value={`$${customer.avgOrderValue.toFixed(2)}`} color="text-yellow-500" />
98+
<div className="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg shadow-sm">
99+
<div className="flex items-center mb-2">
100+
<HiOutlineStar className="mr-2 h-5 w-5 text-orange-500" />
101+
<span className="text-gray-600 dark:text-gray-300">Satisfacción</span>
102+
</div>
103+
<div className="flex items-center">
104+
<Progress progress={customer.satisfaction * 20} color="yellow" className="mr-2 flex-1" />
105+
<span className="text-gray-800 dark:text-white font-bold">{customer.satisfaction}/5</span>
106+
</div>
107+
</div>
108+
</div>
109+
</Card>
110+
</div>
111+
112+
{/* Historial pedidos */}
113+
<Card className="bg-white dark:bg-gray-950 shadow-lg border border-gray-200 dark:border-gray-700 rounded-2xl p-6">
114+
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 gap-2">
115+
<h5 className="text-xl font-bold text-gray-900 dark:text-white">Pedidos Recientes</h5>
116+
<Button color="light" size="sm">Ver todos ({customer.totalOrders})</Button>
117+
</div>
118+
119+
<div className="overflow-x-auto">
120+
<Table hoverable={true}>
121+
<TableHead>
122+
<TableRow>
123+
<TableHeadCell>ID Pedido</TableHeadCell>
124+
<TableHeadCell>Fecha</TableHeadCell>
125+
<TableHeadCell>Artículos</TableHeadCell>
126+
<TableHeadCell>Total</TableHeadCell>
127+
<TableHeadCell>Estado</TableHeadCell>
128+
<TableHeadCell><span className="sr-only">Acciones</span></TableHeadCell>
129+
</TableRow>
130+
</TableHead>
131+
<TableBody className="divide-y divide-gray-200 dark:divide-gray-700">
132+
{orders.map((order) => (
133+
<TableRow key={order.id} className="transition hover:bg-gray-50 dark:hover:bg-gray-800">
134+
<TableCell className="font-medium text-blue-600 dark:text-blue-400 hover:underline cursor-pointer">{order.id}</TableCell>
135+
<TableCell>{order.date}</TableCell>
136+
<TableCell>{order.items}</TableCell>
137+
<TableCell>${order.amount.toFixed(2)}</TableCell>
138+
<TableCell>
139+
<Badge color={order.status === 'Entregado' ? 'success' : order.status === 'Cancelado' ? 'failure' : 'warning'} className="px-2 py-1 rounded-full">
140+
{order.status}
141+
</Badge>
142+
</TableCell>
143+
<TableCell>
144+
<Button size="xs" gradientduotone="cyanToBlue">Detalles</Button>
145+
</TableCell>
146+
</TableRow>
147+
))}
148+
</TableBody>
149+
</Table>
150+
</div>
151+
</Card>
152+
</div>
153+
);
154+
};
155+
156+
const StatCard = ({ icon, label, value, color }) => (
157+
<div className="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition">
158+
<div className="flex items-center mb-2">
159+
<span className={`mr-2 h-5 w-5 ${color}`}>{icon}</span>
160+
<span className="text-gray-600 dark:text-gray-300">{label}</span>
161+
</div>
162+
<p className="text-2xl font-bold text-gray-900 dark:text-white">{value}</p>
163+
</div>
164+
);
165+
166+
const InfoRow = ({ icon, text }) => (
167+
<div className="flex items-center py-2">
168+
<span className="mr-2 h-5 w-5 text-gray-500">{icon}</span>
169+
<span className="text-gray-600 dark:text-gray-300 break-all">{text}</span>
170+
</div>
171+
);
172+
173+
export default CustomerDetailsContainer;

resources/js/components/app-sidebar.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,11 @@ export function AppSidebar() {
125125

126126
const [sshSessions, setSshSessions] = useState([]);
127127

128-
useEffect(() => {
129-
axios.get('/terminal/index')
130-
.then((res) => setSshSessions(res.data))
131-
.catch((err) => console.error('Error loading SSH sessions', err));
132-
}, []);
128+
// useEffect(() => {
129+
// axios.get('/terminal/index')
130+
// .then((res) => setSshSessions(res.data))
131+
// .catch((err) => console.error('Error loading SSH sessions', err));
132+
// }, []);
133133

134134
const visibleNavItems = staticNavItems.filter(item => {
135135
// 1. Verificar áreas requeridas

resources/js/pages/BLClientes.jsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ import { ModalAddClientesBL } from '@/components/BL/modalesBL';
7373
import { router } from '@inertiajs/react';
7474
import { Toast } from "flowbite-react";
7575
import { HiCheck, HiX } from "react-icons/hi";
76+
import CustomerDetailsContainer from '@/components/BL/DetailsCustomerModal';
77+
import BigModalWrapper from '@/components/BL/BigmodalWrapper';
78+
import axios from "axios";
7679

7780
const breadcrumbs = [
7881
{ title: "Clientes", href: "/clientesBL" }
@@ -85,7 +88,9 @@ export default function Clientes({clientes}) {
8588
const proyecto = props?.auth?.user?.proyecto || 'AZZU';
8689
const theme = themeByProject[proyecto];
8790
const [modalOpen, setModalOpen] = useState(false);
91+
const [modalOpenClient, setModalOpenClient] = useState(false);
8892
console.log('clientes', clientes);
93+
const [clienteDetails, setClienteDetails] = useState(null);
8994
const [toast, setToast] = useState({
9095
show: false,
9196
success: false,
@@ -159,7 +164,21 @@ export default function Clientes({clientes}) {
159164
};
160165
const closeModal = () => {
161166
setModalOpen(false);
167+
setModalOpenClient(false)
168+
setClienteDetails(null);
162169
};
170+
const openModalClient = async (id)=> {
171+
try {
172+
const response = await axios.get(`BLClientesShow/${id}`);
173+
setClienteDetails(response.data.clientesDetails);
174+
setModalOpenClient(true);
175+
} catch (error) {
176+
console.error("Error al cargar el cliente", error);
177+
}
178+
}
179+
180+
181+
163182

164183
return (
165184
<AppLayout breadcrumbs={breadcrumbs}>
@@ -201,7 +220,7 @@ export default function Clientes({clientes}) {
201220
)}
202221
</td> */}
203222
<td className="px-6 py-4">
204-
<button className="text-blue-600 hover:underline mr-2">Ver</button>
223+
<button className="text-blue-600 hover:underline mr-2" onClick={() => openModalClient(cliente.id)} >Ver</button>
205224
<button className="text-yellow-600 hover:underline mr-2">Editar</button>
206225
<button className="text-red-600 hover:underline">Eliminar</button>
207226
</td>
@@ -211,9 +230,15 @@ export default function Clientes({clientes}) {
211230
</table>
212231
</div>
213232
{modalOpen && (
214-
<AgentModalWrapper closeModal={closeModal}>
233+
<AgentModalWrapper closeModal={closeModal}>
215234
<ModalAddClientesBL onClose={closeModal} onSave={handleGuardarCliente}/>
216-
</AgentModalWrapper>
235+
</AgentModalWrapper>
236+
)}
237+
{modalOpenClient && (
238+
<BigModalWrapper closeModal={closeModal}>
239+
<CustomerDetailsContainer closeModal={closeModal} clienteDetails={clienteDetails}/>
240+
{/* <ModalAddClientesBL onClose={closeModal} onSave={handleGuardarCliente}/> */}
241+
</BigModalWrapper>
217242
)}
218243
{toast.show && (
219244
<div className="fixed bottom-6 right-6 z-51">

routes/web.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178
Route::post('clientes', [BLClientesController::class, 'store'])->name('clientesBL.store');
179179
Route::post('pedidos', [BLPedidosController::class, 'store'])->name('pedidosBL.store');
180180
Route::get('BLPedidosShow/{id}', [BLPedidosController::class, 'show'])->name('pedidosBL.show');
181-
181+
Route::get('BLClientesShow/{id}', [BLClientesController::class, 'show'])->name('ClientesBL.show');
182182
});
183183
});
184184

0 commit comments

Comments
 (0)