anima-ds-nucleus 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anima-ds-nucleus.css +1 -1
- package/dist/anima-ds.cjs.js +152 -34
- package/dist/anima-ds.esm.js +10124 -7528
- package/package.json +10 -2
- package/src/assets/nucleus-logo.svg +3 -0
- package/src/components/Atoms/LogoHexa/LogoHexa.jsx +34 -0
- package/src/components/Atoms/LogoHexa/LogoHexa.stories.jsx +36 -0
- package/src/components/Atoms/Typography/Typography.jsx +53 -18
- package/src/components/Atoms/Typography/Typography.stories.jsx +40 -4
- package/src/components/DataDisplay/Card/Card.jsx +117 -24
- package/src/components/DataDisplay/Card/Card.stories.jsx +119 -35
- package/src/components/DataDisplay/Card/CardError.jsx +142 -0
- package/src/components/DataDisplay/Card/CardSkeleton.jsx +96 -0
- package/src/components/DataDisplay/Card/CardTituloCorto.jsx +61 -0
- package/src/components/DataDisplay/Card/CardTituloCortoMasEstado.jsx +79 -0
- package/src/components/DataDisplay/Card/CardTituloLargo.jsx +61 -0
- package/src/components/DataDisplay/Card/CardTituloLargoMasEstado.jsx +77 -0
- package/src/components/DataDisplay/Card/CardVacia.jsx +111 -0
- package/src/components/Layout/Header/HeaderConBuscador.jsx +136 -0
- package/src/components/Layout/Header/HeaderConBuscador.stories.jsx +86 -0
- package/src/components/Layout/Header/HeaderCore.jsx +347 -0
- package/src/components/Layout/Header/HeaderCore.stories.jsx +59 -0
- package/src/components/Layout/Header/HeaderGeneral.jsx +92 -0
- package/src/components/Layout/Header/HeaderGeneral.stories.jsx +64 -0
- package/src/components/Layout/Header/HeaderPoint.jsx +120 -0
- package/src/components/Layout/Header/HeaderPoint.stories.jsx +110 -0
- package/src/components/Layout/NavPoint/NavPoint.jsx +64 -0
- package/src/components/Layout/NavPoint/NavPoint.stories.jsx +52 -0
- package/src/components/Layout/Sidebar/SidebarCore.jsx +779 -0
- package/src/components/Layout/Sidebar/SidebarCore.stories.jsx +167 -0
- package/src/components/Layout/Sidebar/SidebarPoint.jsx +645 -0
- package/src/components/Layout/Sidebar/SidebarPoint.stories.jsx +183 -0
- package/src/index.js +15 -2
- package/src/style.css +37 -0
- package/src/components/Layout/Header/Header.jsx +0 -50
- package/src/components/Layout/Header/Header.stories.jsx +0 -36
- package/src/components/Layout/Sidebar/Sidebar.jsx +0 -57
- package/src/components/Layout/Sidebar/Sidebar.stories.jsx +0 -51
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Icon } from '../../Atoms/Icon/Icon';
|
|
3
|
+
import { Typography } from '../../Atoms/Typography/Typography';
|
|
4
|
+
import { LogoHexa } from '../../Atoms/LogoHexa/LogoHexa';
|
|
5
|
+
|
|
6
|
+
// Mock data con 2 títulos y 2 secciones
|
|
7
|
+
const MOCK_SECTIONS = [
|
|
8
|
+
{
|
|
9
|
+
title: 'PERSONAS',
|
|
10
|
+
items: [
|
|
11
|
+
{ id: 'empleados', label: 'Empleados', icon: 'UserGroupIcon' },
|
|
12
|
+
{ id: 'organizacion', label: 'Organización', icon: 'BuildingOfficeIcon' },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
title: 'TALENTO',
|
|
17
|
+
items: [
|
|
18
|
+
{ id: 'reclutamiento', label: 'Reclutamiento', icon: 'UserPlusIcon' },
|
|
19
|
+
{ id: 'desarrollo', label: 'Desarrollo', icon: 'AcademicCapIcon' },
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export const SidebarPoint = ({
|
|
25
|
+
sections = MOCK_SECTIONS,
|
|
26
|
+
activeItem,
|
|
27
|
+
onItemClick,
|
|
28
|
+
defaultCollapsed = false,
|
|
29
|
+
companyName = 'HEXA Point',
|
|
30
|
+
companyLogo,
|
|
31
|
+
onCompanyClick,
|
|
32
|
+
itemBadges = {}, // Objeto con { itemId: number } para los badges
|
|
33
|
+
footerText, // Texto del footer: puede ser string "v1.0 | Powered by Nucleus" o objeto { version: "v1.0", poweredBy: "Powered by", brand: "Nucleus" }
|
|
34
|
+
footerCollapsedContent, // Contenido a mostrar en el footer cuando está colapsado (puede ser string, ReactNode, o objeto con icon y text)
|
|
35
|
+
Client = false, // Propiedad booleana para mostrar el logo de la empresa en la parte superior
|
|
36
|
+
className = '',
|
|
37
|
+
...props
|
|
38
|
+
}) => {
|
|
39
|
+
const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
|
|
40
|
+
|
|
41
|
+
const toggleCollapse = () => {
|
|
42
|
+
setIsCollapsed(!isCollapsed);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<aside
|
|
47
|
+
className={`bg-white border-r border-gray-200 transition-all duration-300 ease-in-out h-full ${
|
|
48
|
+
isCollapsed ? 'w-20' : 'w-64'
|
|
49
|
+
} ${className}`}
|
|
50
|
+
{...props}
|
|
51
|
+
>
|
|
52
|
+
<nav className="h-full flex flex-col" style={{ overflow: 'hidden' }}>
|
|
53
|
+
{/* Barra superior con HEXA Point */}
|
|
54
|
+
{!isCollapsed && (
|
|
55
|
+
<div className="p-4 border-b border-gray-200 flex-shrink-0">
|
|
56
|
+
<button
|
|
57
|
+
onClick={onCompanyClick}
|
|
58
|
+
className="w-full bg-white rounded-lg px-3 py-2.5
|
|
59
|
+
flex items-center justify-between hover:bg-gray-50 transition-colors"
|
|
60
|
+
>
|
|
61
|
+
<div className="flex items-center space-x-3">
|
|
62
|
+
{/* Logo hexagonal */}
|
|
63
|
+
{companyLogo ? (
|
|
64
|
+
<img
|
|
65
|
+
src={companyLogo}
|
|
66
|
+
alt={companyName}
|
|
67
|
+
className="w-8 h-8 rounded"
|
|
68
|
+
/>
|
|
69
|
+
) : (
|
|
70
|
+
<LogoHexa width={36} height={40} />
|
|
71
|
+
)}
|
|
72
|
+
{/* Nombre de la empresa */}
|
|
73
|
+
<Typography
|
|
74
|
+
variant="body-md"
|
|
75
|
+
className="color-gray-900 font-medium"
|
|
76
|
+
>
|
|
77
|
+
{companyName}
|
|
78
|
+
</Typography>
|
|
79
|
+
</div>
|
|
80
|
+
</button>
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
{/* Botón de colapsar/expandir - Solo visible cuando está expandido */}
|
|
85
|
+
{!isCollapsed && (
|
|
86
|
+
<div className="px-4 pt-2 pb-2 flex justify-end flex-shrink-0">
|
|
87
|
+
<button
|
|
88
|
+
onClick={toggleCollapse}
|
|
89
|
+
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
|
|
90
|
+
aria-label="Colapsar sidebar"
|
|
91
|
+
style={{ marginRight: '10px' }}
|
|
92
|
+
>
|
|
93
|
+
<Icon
|
|
94
|
+
name="ChevronDoubleLeftIcon"
|
|
95
|
+
variant="24-outline"
|
|
96
|
+
size={20}
|
|
97
|
+
className="color-teal"
|
|
98
|
+
/>
|
|
99
|
+
</button>
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
{/* Header con logo de empresa cuando Client es true - entre botón colapsar y botón Inicio */}
|
|
104
|
+
{Client && companyLogo && !isCollapsed && (
|
|
105
|
+
<div className="flex-shrink-0 border-b border-gray-200" style={{ borderStyle: 'dashed' }}>
|
|
106
|
+
<div className="px-4 py-6 flex flex-col items-center justify-center">
|
|
107
|
+
<img
|
|
108
|
+
src={companyLogo}
|
|
109
|
+
alt={companyName || 'Company Logo'}
|
|
110
|
+
className="max-w-[200px] max-h-[80px] object-contain"
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
)}
|
|
115
|
+
|
|
116
|
+
{/* Logo cuando está colapsado */}
|
|
117
|
+
{isCollapsed && (
|
|
118
|
+
<div className="p-4 border-b border-gray-200 flex justify-center flex-shrink-0">
|
|
119
|
+
{companyLogo ? (
|
|
120
|
+
<img
|
|
121
|
+
src={companyLogo}
|
|
122
|
+
alt={companyName}
|
|
123
|
+
className="w-8 h-8 rounded"
|
|
124
|
+
/>
|
|
125
|
+
) : (
|
|
126
|
+
<LogoHexa width={36} height={40} />
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
)}
|
|
130
|
+
|
|
131
|
+
{/* Botón para expandir - Solo visible cuando está colapsado */}
|
|
132
|
+
{isCollapsed && (
|
|
133
|
+
<div className="px-4 pt-2 pb-2 flex justify-center flex-shrink-0">
|
|
134
|
+
<button
|
|
135
|
+
onClick={toggleCollapse}
|
|
136
|
+
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
|
|
137
|
+
aria-label="Expandir sidebar"
|
|
138
|
+
>
|
|
139
|
+
<Icon
|
|
140
|
+
name="ChevronDoubleRightIcon"
|
|
141
|
+
variant="24-outline"
|
|
142
|
+
size={20}
|
|
143
|
+
className="color-teal"
|
|
144
|
+
/>
|
|
145
|
+
</button>
|
|
146
|
+
</div>
|
|
147
|
+
)}
|
|
148
|
+
|
|
149
|
+
{/* Contenido del sidebar - Wrapper para controlar el espacio */}
|
|
150
|
+
<div className="flex-1 min-h-0 flex flex-col overflow-hidden">
|
|
151
|
+
<div className={`flex-1 overflow-y-auto ${isCollapsed ? 'py-2' : 'py-4'}`} style={{ overflowX: 'hidden' }}>
|
|
152
|
+
{/* Item "Inicio" destacado */}
|
|
153
|
+
<div className="px-4 mb-4">
|
|
154
|
+
<button
|
|
155
|
+
onClick={() => onItemClick && onItemClick('inicio')}
|
|
156
|
+
className={`w-full flex items-center cursor-pointer ${
|
|
157
|
+
isCollapsed ? 'justify-center px-2' : 'px-4 justify-between'
|
|
158
|
+
} py-2.5 rounded-lg transition-all duration-200 ${
|
|
159
|
+
activeItem === 'inicio'
|
|
160
|
+
? ''
|
|
161
|
+
: 'color-gray-700 hover:bg-gray-100'
|
|
162
|
+
}`}
|
|
163
|
+
style={
|
|
164
|
+
activeItem === 'inicio'
|
|
165
|
+
? { backgroundColor: '#2D5C63' }
|
|
166
|
+
: {}
|
|
167
|
+
}
|
|
168
|
+
>
|
|
169
|
+
<Icon
|
|
170
|
+
name="HomeIcon"
|
|
171
|
+
variant="24-outline"
|
|
172
|
+
size={20}
|
|
173
|
+
className={`${isCollapsed ? '' : 'mr-3'} ${
|
|
174
|
+
activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
|
|
175
|
+
}`}
|
|
176
|
+
/>
|
|
177
|
+
{!isCollapsed && (
|
|
178
|
+
<Typography
|
|
179
|
+
variant="body-md"
|
|
180
|
+
className={`font-medium ${
|
|
181
|
+
activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
|
|
182
|
+
}`}
|
|
183
|
+
>
|
|
184
|
+
Inicio
|
|
185
|
+
</Typography>
|
|
186
|
+
)}
|
|
187
|
+
{!isCollapsed && itemBadges['inicio'] !== undefined && itemBadges['inicio'] > 0 && (
|
|
188
|
+
<span
|
|
189
|
+
className="px-2 py-0.5 min-w-[20px] h-5
|
|
190
|
+
text-white rounded-full flex items-center justify-center
|
|
191
|
+
text-body-sm font-medium"
|
|
192
|
+
style={{
|
|
193
|
+
backgroundColor: '#6D3856',
|
|
194
|
+
borderRadius: '12px'
|
|
195
|
+
}}
|
|
196
|
+
>
|
|
197
|
+
{itemBadges['inicio'] > 9 ? '9+' : itemBadges['inicio']}
|
|
198
|
+
</span>
|
|
199
|
+
)}
|
|
200
|
+
</button>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
{/* Secciones */}
|
|
204
|
+
{sections.map((section, sectionIndex) => (
|
|
205
|
+
<div key={sectionIndex} className="mb-6">
|
|
206
|
+
{/* Línea separadora cuando está colapsado - antes de cada sección */}
|
|
207
|
+
{isCollapsed && (
|
|
208
|
+
<div className="px-4 mb-4">
|
|
209
|
+
<div className="border-t" style={{ borderColor: '#2D5C63' }}></div>
|
|
210
|
+
</div>
|
|
211
|
+
)}
|
|
212
|
+
|
|
213
|
+
{/* Título de la sección - solo visible cuando NO está colapsado */}
|
|
214
|
+
{!isCollapsed && (
|
|
215
|
+
<div className="px-4 mb-2">
|
|
216
|
+
<Typography
|
|
217
|
+
variant="body-sm"
|
|
218
|
+
className="color-gray-500 uppercase font-medium tracking-wider"
|
|
219
|
+
>
|
|
220
|
+
{section.title}
|
|
221
|
+
</Typography>
|
|
222
|
+
</div>
|
|
223
|
+
)}
|
|
224
|
+
|
|
225
|
+
{/* Items de la sección */}
|
|
226
|
+
<div className="space-y-1">
|
|
227
|
+
{section.items.map((item) => (
|
|
228
|
+
<div key={item.id} className="px-4">
|
|
229
|
+
<button
|
|
230
|
+
onClick={() => onItemClick && onItemClick(item.id)}
|
|
231
|
+
className={`w-full flex items-center cursor-pointer ${
|
|
232
|
+
isCollapsed ? 'justify-center px-2' : 'px-4 justify-between'
|
|
233
|
+
} py-2.5 rounded-lg transition-all duration-200 ${
|
|
234
|
+
activeItem === item.id
|
|
235
|
+
? ''
|
|
236
|
+
: 'color-gray-700 hover:bg-gray-100'
|
|
237
|
+
}`}
|
|
238
|
+
style={
|
|
239
|
+
activeItem === item.id
|
|
240
|
+
? { backgroundColor: '#2D5C63' }
|
|
241
|
+
: {}
|
|
242
|
+
}
|
|
243
|
+
title={isCollapsed ? item.label : ''}
|
|
244
|
+
>
|
|
245
|
+
<div className="flex items-center">
|
|
246
|
+
<Icon
|
|
247
|
+
name={item.icon}
|
|
248
|
+
variant="24-outline"
|
|
249
|
+
size={20}
|
|
250
|
+
className={`${isCollapsed ? '' : 'mr-3'} ${
|
|
251
|
+
activeItem === item.id ? 'color-white' : 'color-gray-700'
|
|
252
|
+
}`}
|
|
253
|
+
/>
|
|
254
|
+
{!isCollapsed && (
|
|
255
|
+
<Typography
|
|
256
|
+
variant="body-md"
|
|
257
|
+
className={`font-medium ${
|
|
258
|
+
activeItem === item.id ? 'color-white' : 'color-gray-700'
|
|
259
|
+
}`}
|
|
260
|
+
>
|
|
261
|
+
{item.label}
|
|
262
|
+
</Typography>
|
|
263
|
+
)}
|
|
264
|
+
</div>
|
|
265
|
+
{!isCollapsed && ((itemBadges[item.id] !== undefined && itemBadges[item.id] > 0) || (item.id === 'empleados' && 2)) && (
|
|
266
|
+
<span
|
|
267
|
+
className="px-2 py-0.5 min-w-[20px] h-5
|
|
268
|
+
text-white rounded-full flex items-center justify-center
|
|
269
|
+
text-body-sm font-medium"
|
|
270
|
+
style={{
|
|
271
|
+
backgroundColor: '#6D3856',
|
|
272
|
+
borderRadius: '12px'
|
|
273
|
+
}}
|
|
274
|
+
>
|
|
275
|
+
{item.id === 'empleados' ? 2 : (itemBadges[item.id] > 9 ? '9+' : itemBadges[item.id])}
|
|
276
|
+
</span>
|
|
277
|
+
)}
|
|
278
|
+
</button>
|
|
279
|
+
</div>
|
|
280
|
+
))}
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
))}
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
|
|
287
|
+
{/* Footer con texto configurable - cuando está expandido */}
|
|
288
|
+
{footerText && !isCollapsed && (
|
|
289
|
+
<div className="px-4 pb-4 flex-shrink-0">
|
|
290
|
+
<div
|
|
291
|
+
className="bg-white border rounded-lg px-3 py-2 flex items-center justify-center"
|
|
292
|
+
style={{
|
|
293
|
+
borderColor: '#2D5C63',
|
|
294
|
+
borderRadius: '8px'
|
|
295
|
+
}}
|
|
296
|
+
>
|
|
297
|
+
{typeof footerText === 'string' ? (
|
|
298
|
+
<Typography
|
|
299
|
+
variant="body-sm"
|
|
300
|
+
style={{ color: '#2D5C63' }}
|
|
301
|
+
className="text-center"
|
|
302
|
+
>
|
|
303
|
+
{(() => {
|
|
304
|
+
const parts = footerText.split('|');
|
|
305
|
+
if (parts.length === 2) {
|
|
306
|
+
const leftPart = parts[0].trim();
|
|
307
|
+
const rightPart = parts[1].trim();
|
|
308
|
+
// Si contiene "Powered by", separar y poner la marca en bold
|
|
309
|
+
if (rightPart.includes('Powered by')) {
|
|
310
|
+
const poweredByMatch = rightPart.match(/Powered by (.+)/);
|
|
311
|
+
if (poweredByMatch) {
|
|
312
|
+
return (
|
|
313
|
+
<>
|
|
314
|
+
{leftPart} | Powered by <span className="font-bold">{poweredByMatch[1]}</span>
|
|
315
|
+
</>
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return `${leftPart} | ${rightPart}`;
|
|
320
|
+
}
|
|
321
|
+
return footerText;
|
|
322
|
+
})()}
|
|
323
|
+
</Typography>
|
|
324
|
+
) : (
|
|
325
|
+
<Typography
|
|
326
|
+
variant="body-sm"
|
|
327
|
+
style={{ color: '#2D5C63' }}
|
|
328
|
+
className="text-center"
|
|
329
|
+
>
|
|
330
|
+
{footerText.version && `${footerText.version}`}
|
|
331
|
+
{footerText.version && (footerText.poweredBy || footerText.brand) && ' | '}
|
|
332
|
+
{footerText.poweredBy && `${footerText.poweredBy} `}
|
|
333
|
+
{footerText.brand && <span className="font-bold">{footerText.brand}</span>}
|
|
334
|
+
</Typography>
|
|
335
|
+
)}
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
)}
|
|
339
|
+
|
|
340
|
+
{/* Footer cuando está colapsado */}
|
|
341
|
+
{footerCollapsedContent && isCollapsed && (
|
|
342
|
+
<div className="px-1 pt-2 pb-2 flex justify-center flex-shrink-0" style={{ zIndex: 10 }}>
|
|
343
|
+
<div
|
|
344
|
+
className="bg-white border rounded px-1 py-0.5 flex items-center justify-center"
|
|
345
|
+
style={{
|
|
346
|
+
borderColor: '#2D5C63',
|
|
347
|
+
borderRadius: '4px',
|
|
348
|
+
width: 'calc(100% - 8px)',
|
|
349
|
+
minHeight: '20px'
|
|
350
|
+
}}
|
|
351
|
+
>
|
|
352
|
+
{typeof footerCollapsedContent === 'string' ? (
|
|
353
|
+
<span
|
|
354
|
+
style={{
|
|
355
|
+
color: '#2D5C63',
|
|
356
|
+
fontSize: '9px',
|
|
357
|
+
lineHeight: '1.2',
|
|
358
|
+
fontWeight: '600',
|
|
359
|
+
textAlign: 'center',
|
|
360
|
+
whiteSpace: 'nowrap',
|
|
361
|
+
overflow: 'hidden',
|
|
362
|
+
textOverflow: 'ellipsis',
|
|
363
|
+
maxWidth: '100%'
|
|
364
|
+
}}
|
|
365
|
+
>
|
|
366
|
+
{footerCollapsedContent}
|
|
367
|
+
</span>
|
|
368
|
+
) : typeof footerCollapsedContent === 'object' && footerCollapsedContent.icon ? (
|
|
369
|
+
<div className="flex items-center justify-center">
|
|
370
|
+
{footerCollapsedContent.icon && (
|
|
371
|
+
<Icon
|
|
372
|
+
name={footerCollapsedContent.icon}
|
|
373
|
+
variant="24-outline"
|
|
374
|
+
size={14}
|
|
375
|
+
style={{ color: '#2D5C63' }}
|
|
376
|
+
/>
|
|
377
|
+
)}
|
|
378
|
+
{footerCollapsedContent.text && (
|
|
379
|
+
<span
|
|
380
|
+
style={{
|
|
381
|
+
color: '#2D5C63',
|
|
382
|
+
fontSize: '10px',
|
|
383
|
+
marginLeft: footerCollapsedContent.icon ? '4px' : '0'
|
|
384
|
+
}}
|
|
385
|
+
>
|
|
386
|
+
{footerCollapsedContent.text}
|
|
387
|
+
</span>
|
|
388
|
+
)}
|
|
389
|
+
</div>
|
|
390
|
+
) : (
|
|
391
|
+
footerCollapsedContent
|
|
392
|
+
)}
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
)}
|
|
396
|
+
</nav>
|
|
397
|
+
</aside>
|
|
398
|
+
);
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// Componente SidebarPoint Mobile
|
|
402
|
+
const SidebarPointMobile = ({
|
|
403
|
+
sections = MOCK_SECTIONS,
|
|
404
|
+
activeItem,
|
|
405
|
+
onItemClick,
|
|
406
|
+
companyName = 'HEXA Point',
|
|
407
|
+
companyLogo,
|
|
408
|
+
onCompanyClick,
|
|
409
|
+
itemBadges = {},
|
|
410
|
+
className = '',
|
|
411
|
+
...props
|
|
412
|
+
}) => {
|
|
413
|
+
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
|
414
|
+
|
|
415
|
+
const toggleMobileMenu = () => {
|
|
416
|
+
setIsMobileMenuOpen(!isMobileMenuOpen);
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
// Formatear fecha de hoy
|
|
420
|
+
const formattedDate = new Date().toLocaleDateString('es-AR', {
|
|
421
|
+
weekday: 'long',
|
|
422
|
+
year: 'numeric',
|
|
423
|
+
month: 'long',
|
|
424
|
+
day: 'numeric',
|
|
425
|
+
});
|
|
426
|
+
const capitalizedDate = formattedDate.charAt(0).toUpperCase() + formattedDate.slice(1);
|
|
427
|
+
|
|
428
|
+
return (
|
|
429
|
+
<>
|
|
430
|
+
<style>{`
|
|
431
|
+
.sidebar-point-mobile {
|
|
432
|
+
width: 100%;
|
|
433
|
+
transform: ${isMobileMenuOpen ? 'translateX(0)' : 'translateX(-100%)'};
|
|
434
|
+
position: fixed;
|
|
435
|
+
left: 0;
|
|
436
|
+
top: 0;
|
|
437
|
+
height: 100vh;
|
|
438
|
+
z-index: 50;
|
|
439
|
+
transition: transform 0.3s ease-in-out;
|
|
440
|
+
}
|
|
441
|
+
`}</style>
|
|
442
|
+
{/* Botón hamburguesa - solo visible cuando el menú está cerrado */}
|
|
443
|
+
{!isMobileMenuOpen && (
|
|
444
|
+
<button
|
|
445
|
+
onClick={toggleMobileMenu}
|
|
446
|
+
className="fixed top-4 left-4 z-50 p-2 bg-white border border-gray-200 rounded-lg shadow-md
|
|
447
|
+
hover:bg-gray-50 transition-colors"
|
|
448
|
+
aria-label="Toggle menu"
|
|
449
|
+
>
|
|
450
|
+
<Icon
|
|
451
|
+
name="Bars3Icon"
|
|
452
|
+
variant="24-outline"
|
|
453
|
+
size={24}
|
|
454
|
+
className="color-gray-700"
|
|
455
|
+
/>
|
|
456
|
+
</button>
|
|
457
|
+
)}
|
|
458
|
+
{/* Overlay para cerrar el menú */}
|
|
459
|
+
{isMobileMenuOpen && (
|
|
460
|
+
<div
|
|
461
|
+
className="fixed inset-0 bg-black bg-opacity-50 z-40"
|
|
462
|
+
onClick={toggleMobileMenu}
|
|
463
|
+
/>
|
|
464
|
+
)}
|
|
465
|
+
<aside
|
|
466
|
+
className={`bg-gray-100 border-r border-gray-200 sidebar-point-mobile ${className}`}
|
|
467
|
+
{...props}
|
|
468
|
+
>
|
|
469
|
+
<nav className="h-full flex flex-col">
|
|
470
|
+
{/* Header verde con "Point" y botón X */}
|
|
471
|
+
<div className="bg-brand px-4 py-4 flex items-center justify-between" style={{ backgroundColor: '#56B676' }}>
|
|
472
|
+
<Typography
|
|
473
|
+
variant="h5"
|
|
474
|
+
className="color-white font-bold"
|
|
475
|
+
>
|
|
476
|
+
Point
|
|
477
|
+
</Typography>
|
|
478
|
+
<button
|
|
479
|
+
onClick={toggleMobileMenu}
|
|
480
|
+
className="p-1 hover:bg-opacity-80 rounded transition-colors"
|
|
481
|
+
aria-label="Cerrar menú"
|
|
482
|
+
>
|
|
483
|
+
<Icon
|
|
484
|
+
name="XMarkIcon"
|
|
485
|
+
variant="24-outline"
|
|
486
|
+
size={24}
|
|
487
|
+
className="color-white"
|
|
488
|
+
/>
|
|
489
|
+
</button>
|
|
490
|
+
</div>
|
|
491
|
+
{/* Sección gris con fecha */}
|
|
492
|
+
<div className="bg-gray-100 px-4 py-3 border-b border-gray-200">
|
|
493
|
+
<Typography
|
|
494
|
+
variant="body-md"
|
|
495
|
+
className="color-gray-700"
|
|
496
|
+
>
|
|
497
|
+
{capitalizedDate}
|
|
498
|
+
</Typography>
|
|
499
|
+
</div>
|
|
500
|
+
{/* Logo de empresa (si se proporciona) */}
|
|
501
|
+
{companyLogo && (
|
|
502
|
+
<div className="bg-gray-100 px-4 py-6 flex justify-center border-b border-gray-200">
|
|
503
|
+
<img
|
|
504
|
+
src={companyLogo}
|
|
505
|
+
alt={companyName || 'Company Logo'}
|
|
506
|
+
className="max-w-[120px] max-h-[120px] object-contain"
|
|
507
|
+
/>
|
|
508
|
+
</div>
|
|
509
|
+
)}
|
|
510
|
+
{/* Contenido del sidebar mobile */}
|
|
511
|
+
<div className="flex-1 overflow-y-auto py-4">
|
|
512
|
+
{/* Item "Inicio" destacado */}
|
|
513
|
+
<div className="px-4 mb-4">
|
|
514
|
+
<button
|
|
515
|
+
onClick={() => {
|
|
516
|
+
onItemClick && onItemClick('inicio');
|
|
517
|
+
toggleMobileMenu();
|
|
518
|
+
}}
|
|
519
|
+
className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
|
|
520
|
+
activeItem === 'inicio'
|
|
521
|
+
? ''
|
|
522
|
+
: 'color-gray-700 hover:bg-gray-100'
|
|
523
|
+
}`}
|
|
524
|
+
style={
|
|
525
|
+
activeItem === 'inicio'
|
|
526
|
+
? { backgroundColor: '#2D5C63' }
|
|
527
|
+
: {}
|
|
528
|
+
}
|
|
529
|
+
>
|
|
530
|
+
<div className="flex items-center">
|
|
531
|
+
<Icon
|
|
532
|
+
name="HomeIcon"
|
|
533
|
+
variant="24-outline"
|
|
534
|
+
size={20}
|
|
535
|
+
className={`mr-3 ${
|
|
536
|
+
activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
|
|
537
|
+
}`}
|
|
538
|
+
/>
|
|
539
|
+
<Typography
|
|
540
|
+
variant="body-md"
|
|
541
|
+
className={`font-medium ${
|
|
542
|
+
activeItem === 'inicio' ? 'color-white' : 'color-gray-700'
|
|
543
|
+
}`}
|
|
544
|
+
>
|
|
545
|
+
Inicio
|
|
546
|
+
</Typography>
|
|
547
|
+
</div>
|
|
548
|
+
{itemBadges['inicio'] !== undefined && itemBadges['inicio'] > 0 && (
|
|
549
|
+
<span
|
|
550
|
+
className="px-2 py-0.5 min-w-[20px] h-5
|
|
551
|
+
text-white rounded-full flex items-center justify-center
|
|
552
|
+
text-body-sm font-medium"
|
|
553
|
+
style={{
|
|
554
|
+
backgroundColor: '#6D3856',
|
|
555
|
+
borderRadius: '12px'
|
|
556
|
+
}}
|
|
557
|
+
>
|
|
558
|
+
{itemBadges['inicio'] > 9 ? '9+' : itemBadges['inicio']}
|
|
559
|
+
</span>
|
|
560
|
+
)}
|
|
561
|
+
</button>
|
|
562
|
+
</div>
|
|
563
|
+
|
|
564
|
+
{/* Secciones */}
|
|
565
|
+
{sections.map((section, sectionIndex) => (
|
|
566
|
+
<div key={sectionIndex} className="mb-6">
|
|
567
|
+
{/* Título de la sección */}
|
|
568
|
+
<div className="px-4 mb-2">
|
|
569
|
+
<Typography
|
|
570
|
+
variant="body-sm"
|
|
571
|
+
className="color-gray-500 uppercase font-medium tracking-wider"
|
|
572
|
+
>
|
|
573
|
+
{section.title}
|
|
574
|
+
</Typography>
|
|
575
|
+
</div>
|
|
576
|
+
|
|
577
|
+
{/* Items de la sección */}
|
|
578
|
+
<div className="space-y-1">
|
|
579
|
+
{section.items.map((item) => (
|
|
580
|
+
<div key={item.id} className="px-4">
|
|
581
|
+
<button
|
|
582
|
+
onClick={() => {
|
|
583
|
+
onItemClick && onItemClick(item.id);
|
|
584
|
+
toggleMobileMenu();
|
|
585
|
+
}}
|
|
586
|
+
className={`w-full flex items-center cursor-pointer px-4 justify-between py-2.5 rounded-lg transition-all duration-200 ${
|
|
587
|
+
activeItem === item.id
|
|
588
|
+
? ''
|
|
589
|
+
: 'color-gray-700 hover:bg-gray-100'
|
|
590
|
+
}`}
|
|
591
|
+
style={
|
|
592
|
+
activeItem === item.id
|
|
593
|
+
? { backgroundColor: '#2D5C63' }
|
|
594
|
+
: {}
|
|
595
|
+
}
|
|
596
|
+
>
|
|
597
|
+
<div className="flex items-center">
|
|
598
|
+
<Icon
|
|
599
|
+
name={item.icon}
|
|
600
|
+
variant="24-outline"
|
|
601
|
+
size={20}
|
|
602
|
+
className={`mr-3 ${
|
|
603
|
+
activeItem === item.id ? 'color-white' : 'color-gray-700'
|
|
604
|
+
}`}
|
|
605
|
+
/>
|
|
606
|
+
<Typography
|
|
607
|
+
variant="body-md"
|
|
608
|
+
className={`font-medium ${
|
|
609
|
+
activeItem === item.id ? 'color-white' : 'color-gray-700'
|
|
610
|
+
}`}
|
|
611
|
+
>
|
|
612
|
+
{item.label}
|
|
613
|
+
</Typography>
|
|
614
|
+
</div>
|
|
615
|
+
{((itemBadges[item.id] !== undefined && itemBadges[item.id] > 0) || (item.id === 'empleados' && 2)) && (
|
|
616
|
+
<span
|
|
617
|
+
className="px-2 py-0.5 min-w-[20px] h-5
|
|
618
|
+
text-white rounded-full flex items-center justify-center
|
|
619
|
+
text-body-sm font-medium"
|
|
620
|
+
style={{
|
|
621
|
+
backgroundColor: '#6D3856',
|
|
622
|
+
borderRadius: '12px'
|
|
623
|
+
}}
|
|
624
|
+
>
|
|
625
|
+
{item.id === 'empleados' ? 2 : (itemBadges[item.id] > 9 ? '9+' : itemBadges[item.id])}
|
|
626
|
+
</span>
|
|
627
|
+
)}
|
|
628
|
+
</button>
|
|
629
|
+
</div>
|
|
630
|
+
))}
|
|
631
|
+
</div>
|
|
632
|
+
</div>
|
|
633
|
+
))}
|
|
634
|
+
</div>
|
|
635
|
+
</nav>
|
|
636
|
+
</aside>
|
|
637
|
+
</>
|
|
638
|
+
);
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
// Exportar ambos componentes
|
|
642
|
+
export { SidebarPointMobile };
|
|
643
|
+
export default SidebarPoint;
|
|
644
|
+
|
|
645
|
+
|