@create-lft-app/nextjs 1.0.0 → 2.0.1
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/package.json +7 -2
- package/template/package.json +1 -1
- package/template/public/logolft.svg +12 -0
- package/template/src/app/dashboard/page.tsx +93 -84
- package/template/src/app/layout.tsx +9 -13
- package/template/src/components/layout/midday-sidebar.tsx +22 -252
- package/template/src/modules/auth/actions/auth-actions.ts +4 -4
- package/template/src/test/test.js +0 -0
- package/template/tsconfig.json +19 -5
- package/template/src/app/auth/login/page.tsx +0 -153
- package/template/src/components/layout/admin-midday-sidebar.tsx +0 -247
- package/template/src/components/layout/admin-sidebar.tsx +0 -146
- package/template/src/components/layout/header.tsx +0 -71
- package/template/src/components/layout/nav-user.tsx +0 -108
- package/template/src/components/layout/page-header.tsx +0 -95
- package/template/src/components/layout/sidebar.tsx +0 -194
- package/template/src/components/layout/suspension-banner.tsx +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@create-lft-app/nextjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Next.js template para proyectos LFT con Midday Design System",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
|
11
|
-
"template"
|
|
11
|
+
"template",
|
|
12
|
+
"!template/node_modules",
|
|
13
|
+
"!template/.next",
|
|
14
|
+
"!template/package-lock.json",
|
|
15
|
+
"!template/next-env.d.ts",
|
|
16
|
+
"!template/.env*"
|
|
12
17
|
],
|
|
13
18
|
"scripts": {
|
|
14
19
|
"build": "tsc",
|
package/template/package.json
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600">
|
|
3
|
+
<defs>
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #fff;
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
9
|
+
</defs>
|
|
10
|
+
<path class="cls-1" d="M1357.03,701.25c31.01,5.88,33.1,52.52,27.83,76.47-22.02,100.1-115.04,46.89-183.73,49.56-10.3.4-43.49,5.78-50.12-1.42-3.21-3.48-2.63-13.05-6.62-14.26l-41.66,2.43c-34.11-3.39-67.14-12.54-99.12-24.42-3.54-1.31-13.64-6.57-16.05-6.81-3.98-.39-9.48,18.31-10.5,21.91-2.13,7.53-9.74,44.52-6.25,49.46,28.53,9.37,58.36,16.51,84.61,31.54,37.82,21.65,50.9,52.08,52.99,94.93,4.63,94.94-46.9,183.67-43.23,278.51.83,1.31,2.16,1.84,3.47,2.48,42.36,20.6,101.39,27.22,147.14,40.48,19.22,5.57,47.76,13.45,52.3,35.87-.82,3.35-14.71.86-17.76.58,1.38,4.7,7.77,8.18,4.82,13.76-7.61,1.64-13.81-2.77-20.7-4.83.47,5.61.13,11.72-6.52,12.84-13.32,2.25-33.11-9.47-46.9-12.55-24.86-5.56-52.66-5.96-78-9.36-23.86-3.2-84.21-12.25-102.38-25.68-26.78-19.8-7.33-73.2-3.62-101.89,3.83-29.62,3.09-61.5-2.16-90.87-1.74-9.72-10.28-47.05-17.2-52.29-7.82-5.92-31.28-8.13-41.21-11.54l-1.58.71c-37.59,66.83-95.48,120.07-123.33,192.88l.89,2.01,57.74,47.51c30.52,20.18,68.99,29.77,93.2,58.68,4.4,5.26,18.1,24.41,13.03,30.84-4.06,5.15-17.23-3.77-21.93-5.55-1.46,1.6,8.78,23.05-15.88,7.94.78,4.15-1.93,9.73-6.44,9.82-3.49.08-19.68-10.85-24.32-13.32-47.18-25.07-96.81-45.6-141.89-74.52-13.74-8.81-33.8-21.96-43.74-34.68-21.89-28.02,13.48-38.57,27.59-57.74,27.72-37.66,48.37-93.86,54.48-140.1.28-2.11,1.87-8.69.35-9.66-17.03-.05-32.2-4.93-47.96-10.62-3.01-1.09-6.97-4.4-9.94-3.59-12.58,12.25-25.25,24.46-37.47,37.06-68.16,70.26-120.06,129.98-220.14,156.1-97.98,25.57-214.24-15.58-256.51-111.22-13.98-31.62-35.69-110-27.18-142.69,1.09-4.2,4.12-11.04,9.37-9.74,22.01,42.53,42.67,89.23,74.59,125.42,33.9,38.44,85.05,66.63,137.78,54.44,83.93-19.39,133.44-147.97,156.74-221.48,19.62-61.86,25.84-120.74,57.35-178.92,38.23-70.59,119.82-178.6,181.17-229.81,30.16-25.17,65.38-42.19,92.36-71.43,21.15-22.92,36.82-49.98,54.76-75.29,16.75-23.64,34.7-48.2,58.38-65.22.36-1.67-.44-2.01-1.62-2.82-4.61-3.19-17.46-6.1-23.57-9.19-20.96-10.61-25.97-29.85-34.12-50.26-5.28-13.23-11.51-28.59-15.41-42.17-1.26-4.38-4.74-14.55-1.82-18.23,4.4-5.54,25.15.7,31.39,2.56,16.65,4.96,33.94,12.61,48.63,21.84,3.4-.23,4.11-29.64,7.94-33.73,2.18-2.32,5.81-1.38,8.4-.48,21.79,7.57,73.56,68.69,76.36,91.42.86,6.99-.86,16.05,3.54,22.27,7.53,10.61,37.47,13.53,49.71,18.79,12.77,5.49,11.9,15.47,16.88,26.8,14.52,33.07,46.21,37.72,71.41,58.63,14.53,12.05,18.39,23.96,5.14,39.33-3.96,4.6-20.7,17.67-26.18,18.99-2.52.61-8.02-.12-9.94,1.47-3.67,3.05-3.87,13.24-11.73,14.57-22.41,3.8-51.48-23.48-73.66-26.49-20.94-2.84-42.45,6.16-63.65,1.84-5.18,11.86-11.9,23.1-15.5,35.63-10.79,37.53-5.56,77.64,4.4,114.71,3.76,2.63,35.59-5.35,40.77-7.99,6.91-3.52,3.9-9.76,9.21-13.63,4.22-3.08,30.06-13.27,35.41-14.23,4.58-.82,8.94.25,13.28-1.36,9.56-15.59,5.17-38.42,23.46-48.26,10.06-5.41,12.91-2.27,22.36-2.37,17.46-.18,28.49-22.48,51.59-23.95,59.64-3.79,67.17,83.41,45.01,122.44-18.42,32.44-58.07,21.19-88.54,25.63-17.09,2.49-11.36,4.9-20.48,14.27-5.87,6.03-32.12,18.82-40.43,20.12-8.98,1.4-21.02,1.07-23.11-9.69l-69.8,38.88-1.66,2.8c25.76,1.17,49.1,15.8,73.95,21.89,4.17-.37,4.54-12.26,11.14-13.73,8.67-1.93,23.3,2.26,32.51,2.81,3.98.24,15.23.58,18.47-.48,5.15-1.68,4.56-11.56,9.48-14.34,7.53-4.26,17.54,3.37,20.27,2.36,5.92-5.09,9.2-13.77,14.84-18.87,15.62-14.15,68.98-22.72,87.61-14.1,12.34,5.71,5.1,14.32,1.76,23.56,4.63.6,11.05-.82,15.39,0ZM1043.9,236.57c6.28,3.58,6.81-7.86,13.39-3.93,3.24,1.93,9.58,10.3,12.17,13.64,13.68,17.55,24.14,37.98,37.49,55.82,8.99,6.24,9.05-7.2,8.12-13.07-3.09-19.53-42.66-66.29-58.32-79.67-1.29-1.1-8.88-7.5-9.94-6.44l-2.91,33.66ZM1113.32,340.91c21.88-.3,40.72,13.84,60.77,19.13,2.47.65,14.01,3.55,14.67.19l-14.93-26.73c-8-2.44-16.14-3.9-24.05-6.73-10.65-3.81-23.1-12.14-34.09-13.56-6.12-.79-13.03.29-19.23-1.61-16.36-20.19-28.18-41.86-47.65-59.56-23.34-21.22-53.11-39.01-85.39-40.19-2.45,2.42,18.7,58.42,21.67,65.19,6.69,15.27,11.13,23.31,26.62,30.96,20,9.87,46.27,11.26,59.92,30.9-13.28-1.3-17.14-12.26-32.03-9.68-17.59,3.05-53.75,56.58-64.68,72.32-18.38,26.47-34.54,55.63-57.12,78.88-28.95,29.8-67.44,49.27-99.79,74.93-22.02,17.47-40.39,38.3-58.07,60.06-47.6,58.57-99.44,126.64-126.12,197.5-40.8,108.36-61.02,288.18-169.43,350.75-111.72,64.48-207.41-55.8-246.32-147.4-.97-2.28-2.08-5.92-4.13-7.27,3.68,66.85,19.35,133.62,70.94,179.71,70.03,62.56,170.75,47.7,245.03.78,68.68-43.38,91.03-118.94,116.58-191.73-7.43-24.27-14.5-50.59-13.16-76.11,16.22,25.65,30.71,54.25,51.16,76.9,20.73,22.97,79.89,59.26,110.67,62.05,1.75.16,8.22.39,9.22-.19,14.83-28.25,32.58-58.41,62.74-72.25,1.24,1.37-6.48,19.41-7.76,22.51-13.13,31.66-28.71,62.39-42.04,93.96-16.58,39.27-38.87,113.41-72.79,139.65-5.66,4.38-16.02,6.69-14.99,15.9,1.49,13.33,21.37,26.95,31.85,33.76,48.45,31.47,106.67,54.11,153.72,87.51,3.1,2.2,11.99,11.57,14.95,10.7,6.29-1.85-7.96-16.46-5.35-20.8,3.69-3.65,17.12,14,21.83,14.89-.63-8.46-9.91-14.3-8.92-22.83l27.78,14.89c.73-.79-1.9-3.98-2.57-4.87-23.56-31.4-46.78-33.1-78.5-50.55-25.78-14.18-61.51-42.58-82.73-63.2-3.63-3.53-4.87-3.77-3.19-9.17,4.39-14.09,25.7-44.9,34.55-58.76,45.91-71.91,138.05-178.92,131.44-267.61-1.93-25.9-14.28-46.55-30.25-66.04-14.49-17.68-56.58-62.36-77.17-68.76-21.39-6.02-43.54-.96-65.1.98-1.1.1-3.37,1.18-3.17-.69,39.67-15.35,86.09-17.17,119.13-46.16,9.7-8.51,36.26-38.55,37.74-50.62,3.48-28.54-19.78-83.05-9.46-105.75.53-1.16,1.03-2.73,2.47-2.98-.56,13.06.59,26.01,3.45,38.75,6.32,28.2,23.41,58.72,23.98,87.65.44,22.54-9.93,43.87,13.61,58.41,26.29,16.25,102.71,37.32,133.23,35.61,6.11-.34,25.07-2.97,28.32-8.41s-1.47-22.03-2.04-28.87c-.44-5.27,1.47-21.83-2.04-24.77-23.28-7.25-54.04-23.69-78.8-20.3-5.85.8-10.94,6.2-17.46,4.87-.04-8.21,10.83-10.9,15.85-15.67,1.19-10.48,2.92-20.99,4-31.48,2.19-21.18,5.67-51.7,2.69-72.17-3.67-25.23-17.76-58.34-12.32-83.38,1.77-8.13,6.61-16.83,7.54-25.22,3.17-28.52-8.96-61.78-12.66-90.37-1.1-8.47-5.07-34.87.9-40.51s3.68,9.69,3.93,12.85c2.08,26.14,8.6,67.02,41.2,69.98,19.99,1.82,39.69-6.4,60.28-2.71,22.23,3.99,41.69,21.18,61.3,26.06,1.69.42,3.23.71,4.97.49l-.98-8.45-78.43-38.2c17,.95,37.13,2.44,53.38,7.65,16.46,5.28,31.66,17.73,48.36,23.03,2.47.01,17.69-10.65,18.24-12.54,2.35-8.08-14.44-12.26-11.34-17.2,4.13-6.59,16.95,5.2,19.91,8.96,3.37-16.52-22.13-30.15-34.58-36.9-10.35-5.62-25.26-9.71-32.85-18.78-2.26-2.7-5.35-9.85-7.58-11.28-2.43-1.57-17.42-4.06-20.27-3.51-7.01,1.35-7.85,11.95-21.4,8.45-11.27-2.91-10.11-12.78-10.01-22.25-9.12-3.84-19.83-7.05-27.68-13ZM1265.96,507.93c-10.98,1.49-24.14,10.21-32.5,17.12,0,4.48,27.16,1.17,31.29,1.45,29.14,2,34.05,24.15,37.19,49.18l-4.99,33.7c6.6,12.91,13.49-5.72,15.66-12.11,11.63-34.29.33-95.71-46.64-89.33ZM1289.02,575.17c-4.61-11.77-14.98-29.53-26.48-35.56-8.78-4.6-35.73-7.4-46.49-8.11-10.74-.7-17.97-2-23.5,8.25-7.13,13.23-8.76,43.16.33,55.62,1.77,2.42,4.25,4.68,6.85,1.98.34-10.91-3.04-22.69-1.91-33.47,1.93-18.43,13.27-7.56,23.74-4.14,21.95,7.18,44.98,10.4,67.46,15.42ZM1167.69,583.39c-7.24.78-34.22,10.3-36.32,17.31-1.94,6.46,9.76,24.57,14.67,29.55,12.94-3.32,36.43-25.96,35.83-39.68-.35-8.07-8.1-7.84-14.18-7.18ZM1070.93,684.08c4.14,5.12,17.48-2.87,22.21-5.5,7.65-4.24,15.95-10.43,22.64-16.08,4.97-4.2,15.96-12.6,16.06-19.14.11-6.91-7.9-30.1-14.56-32.93-4.82-2.05-17.27,2.49-22.58,4.18-7.26,2.31-22.88,6.46-23.96,14.75-1.75,13.44-2.27,36.11-1.13,49.58.16,1.84.09,3.59,1.33,5.13ZM1294.99,707.22c7.38.6,34.98-11.38,35.63-18.55.29-3.19-10.73-5.89-13.42-6.16-16.1-1.62-54.96,9.83-65.74,22.36-14.17,16.47,14.73,21.47,26.12,22.23,19.57,1.31,42.21-3.86,60.12,5.4,6.53,3.38,15.34,10.53,16.62,18.13,2.36,13.95-.31,41.63-4.94,55.13-1.06,3.08-7.57,11.48-1.06,13.43,10.17,3.06,19.02-18.37,21.42-25.84,6.17-19.23,10.85-73.17-14.16-80.71-15.24-4.6-35,2.74-50.14,1.49-4.08-.34-11.09-1.82-10.43-6.92ZM1221.25,718.27c-8.47,2.3,5.32,17.08,9.65,18.8,7.36,2.92,12.2-5.56,7.52-11.52-2.09-2.66-13.97-8.15-17.18-7.28ZM1210.48,736.13c-2.06-3.17-38.69-3.77-44.07-3.13-17.54,2.07-7.93,34.12,6.95,40.75,28.52,12.69,39.35-13.78,37.12-37.62ZM1252.29,1328.64c1.85-1.57-9.93-7.92-10.89-8.45-25.56-14.15-54.45-16.18-82.43-22.8-32.57-7.7-64.7-17.18-97.29-24.81-7.77-3.03-7.18-21.72-6.92-28.8,2-53.92,21.32-117.42,31.28-171.23,11.26-60.8,22.37-127.31-30.82-171.73-8.14-6.8-17.37-13.04-27.26-16.9-1.07,1.15,7.68,14.16,8.7,16.6,10.64,25.39,8.35,84.93,5.04,112.81-3.3,27.85-11.4,55.17-16.42,82.85-5.7,31.42-9.32,63.19-14.52,94.68-4.77,28.93-16.19,65.94-13.63,94.65.56,6.26,3.45,10.7,7.97,14.86,29.01,26.71,118.94,27.99,158.08,34.51,19.29,3.21,37.63,11.77,56.8,15.55l1.38-2.2c-.18-3.09-8.99-16.41-4.23-17.53l23.26,8.87-10.91-15.87c7.91.38,14.5,6.49,22.82,4.95Z"/>
|
|
11
|
+
<path class="cls-1" d="M1081.41,325.87c-4.01,6.44-36.94-9.19-42.9-11.92-6.17-2.82-27.61-12.57-31.46-16.19-6.05-5.7-14.87-40.74-15.71-49.8-1.57-16.76,4.82-12.01,15.97-7.04,23.53,10.48,46.41,37.04,61.15,57.97,3.04,4.32,15.8,22.4,12.95,26.98Z"/>
|
|
12
|
+
</svg>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Header } from "@/components/layout/header"
|
|
2
1
|
import { Widget, WidgetGrid } from "@/components/dashboard/widget"
|
|
3
2
|
import {
|
|
4
3
|
Users,
|
|
@@ -11,92 +10,102 @@ import {
|
|
|
11
10
|
CheckCircle,
|
|
12
11
|
} from "lucide-react"
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<div>
|
|
21
|
-
<h2 className="text-2xl font-bold tracking-tight">
|
|
22
|
-
Bienvenido de vuelta
|
|
23
|
-
</h2>
|
|
24
|
-
<p className="text-muted-foreground">
|
|
25
|
-
Aquí está el resumen de tu actividad
|
|
26
|
-
</p>
|
|
27
|
-
</div>
|
|
13
|
+
function getGreeting(): string {
|
|
14
|
+
const hour = new Date().getHours()
|
|
15
|
+
if (hour >= 5 && hour < 12) return "Buenos días"
|
|
16
|
+
if (hour >= 12 && hour < 19) return "Buenas tardes"
|
|
17
|
+
return "Buenas noches"
|
|
18
|
+
}
|
|
28
19
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
title="Usuarios Activos"
|
|
32
|
-
icon={<Users className="h-4 w-4" />}
|
|
33
|
-
value="1,234"
|
|
34
|
-
subValue="usuarios registrados"
|
|
35
|
-
trend={{ value: 12.5, positive: true }}
|
|
36
|
-
href="/admin/users"
|
|
37
|
-
/>
|
|
38
|
-
<Widget
|
|
39
|
-
title="Ingresos"
|
|
40
|
-
icon={<DollarSign className="h-4 w-4" />}
|
|
41
|
-
value="$45,231"
|
|
42
|
-
subValue="este mes"
|
|
43
|
-
trend={{ value: 8.2, positive: true }}
|
|
44
|
-
variant="success"
|
|
45
|
-
/>
|
|
46
|
-
<Widget
|
|
47
|
-
title="Organizaciones"
|
|
48
|
-
icon={<Building2 className="h-4 w-4" />}
|
|
49
|
-
value="89"
|
|
50
|
-
subValue="organizaciones activas"
|
|
51
|
-
trend={{ value: 3.1, positive: true }}
|
|
52
|
-
href="/admin/organizations"
|
|
53
|
-
/>
|
|
54
|
-
<Widget
|
|
55
|
-
title="Actividad"
|
|
56
|
-
icon={<Activity className="h-4 w-4" />}
|
|
57
|
-
value="2,345"
|
|
58
|
-
subValue="eventos hoy"
|
|
59
|
-
trend={{ value: 5.4, positive: true }}
|
|
60
|
-
/>
|
|
61
|
-
</WidgetGrid>
|
|
20
|
+
export default function DashboardPage() {
|
|
21
|
+
const greeting = getGreeting()
|
|
62
22
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
<Widget
|
|
73
|
-
title="Alertas"
|
|
74
|
-
icon={<AlertCircle className="h-4 w-4" />}
|
|
75
|
-
value="5"
|
|
76
|
-
subValue="alertas activas"
|
|
77
|
-
variant="danger"
|
|
78
|
-
/>
|
|
79
|
-
</WidgetGrid>
|
|
23
|
+
return (
|
|
24
|
+
<div className="flex flex-col h-screen">
|
|
25
|
+
{/* Header */}
|
|
26
|
+
<header className="h-[70px] flex items-center border-b border-border px-6">
|
|
27
|
+
<div>
|
|
28
|
+
<h1 className="text-lg font-medium">Dashboard</h1>
|
|
29
|
+
<p className="text-xs text-[#878787]">Resumen de actividad</p>
|
|
30
|
+
</div>
|
|
31
|
+
</header>
|
|
80
32
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
value="+24%"
|
|
93
|
-
subValue="vs mes anterior"
|
|
94
|
-
trend={{ value: 24, positive: true }}
|
|
95
|
-
/>
|
|
96
|
-
</WidgetGrid>
|
|
97
|
-
</div>
|
|
33
|
+
{/* Content */}
|
|
34
|
+
<div className="flex-1 overflow-auto p-6">
|
|
35
|
+
{/* Greeting */}
|
|
36
|
+
<div className="mb-8">
|
|
37
|
+
<h2 className="text-[28px] font-medium leading-tight">
|
|
38
|
+
{greeting}{" "}
|
|
39
|
+
<span className="text-[#606060]">Usuario,</span>
|
|
40
|
+
</h2>
|
|
41
|
+
<p className="text-[#878787] text-sm mt-1">
|
|
42
|
+
aquí está el resumen de tu actividad.
|
|
43
|
+
</p>
|
|
98
44
|
</div>
|
|
99
|
-
|
|
100
|
-
|
|
45
|
+
|
|
46
|
+
{/* Widgets Grid */}
|
|
47
|
+
<WidgetGrid>
|
|
48
|
+
<Widget
|
|
49
|
+
title="Usuarios Activos"
|
|
50
|
+
icon={<Users className="h-4 w-4" />}
|
|
51
|
+
value="1,234"
|
|
52
|
+
subValue="usuarios registrados"
|
|
53
|
+
trend={{ value: 12.5, positive: true }}
|
|
54
|
+
href="/admin/users"
|
|
55
|
+
/>
|
|
56
|
+
<Widget
|
|
57
|
+
title="Ingresos"
|
|
58
|
+
icon={<DollarSign className="h-4 w-4" />}
|
|
59
|
+
value="$45,231"
|
|
60
|
+
subValue="este mes"
|
|
61
|
+
trend={{ value: 8.2, positive: true }}
|
|
62
|
+
variant="success"
|
|
63
|
+
/>
|
|
64
|
+
<Widget
|
|
65
|
+
title="Organizaciones"
|
|
66
|
+
icon={<Building2 className="h-4 w-4" />}
|
|
67
|
+
value="89"
|
|
68
|
+
subValue="organizaciones activas"
|
|
69
|
+
trend={{ value: 3.1, positive: true }}
|
|
70
|
+
href="/admin/organizations"
|
|
71
|
+
/>
|
|
72
|
+
<Widget
|
|
73
|
+
title="Actividad"
|
|
74
|
+
icon={<Activity className="h-4 w-4" />}
|
|
75
|
+
value="2,345"
|
|
76
|
+
subValue="eventos hoy"
|
|
77
|
+
trend={{ value: 5.4, positive: true }}
|
|
78
|
+
/>
|
|
79
|
+
<Widget
|
|
80
|
+
title="Documentos Pendientes"
|
|
81
|
+
icon={<FileText className="h-4 w-4" />}
|
|
82
|
+
value="23"
|
|
83
|
+
subValue="requieren revisión"
|
|
84
|
+
variant="warning"
|
|
85
|
+
/>
|
|
86
|
+
<Widget
|
|
87
|
+
title="Alertas"
|
|
88
|
+
icon={<AlertCircle className="h-4 w-4" />}
|
|
89
|
+
value="5"
|
|
90
|
+
subValue="alertas activas"
|
|
91
|
+
variant="danger"
|
|
92
|
+
/>
|
|
93
|
+
<Widget
|
|
94
|
+
title="Tareas Completadas"
|
|
95
|
+
icon={<CheckCircle className="h-4 w-4" />}
|
|
96
|
+
value="156"
|
|
97
|
+
subValue="esta semana"
|
|
98
|
+
variant="success"
|
|
99
|
+
/>
|
|
100
|
+
<Widget
|
|
101
|
+
title="Crecimiento"
|
|
102
|
+
icon={<TrendingUp className="h-4 w-4" />}
|
|
103
|
+
value="+24%"
|
|
104
|
+
subValue="vs mes anterior"
|
|
105
|
+
trend={{ value: 24, positive: true }}
|
|
106
|
+
/>
|
|
107
|
+
</WidgetGrid>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
101
110
|
)
|
|
102
111
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Metadata } from "next"
|
|
2
2
|
import { Inter } from "next/font/google"
|
|
3
3
|
import "./globals.css"
|
|
4
|
-
import { SidebarProvider
|
|
5
|
-
import {
|
|
4
|
+
import { SidebarProvider } from "@/components/layout/sidebar-context"
|
|
5
|
+
import { Sidebar } from "@/components/layout/midday-sidebar"
|
|
6
|
+
import { MainContent } from "@/components/layout/main-content"
|
|
6
7
|
import { Toaster } from "@/components/ui/sonner"
|
|
7
8
|
|
|
8
9
|
const inter = Inter({ subsets: ["latin"] })
|
|
@@ -17,21 +18,16 @@ export default function RootLayout({
|
|
|
17
18
|
}: {
|
|
18
19
|
children: React.ReactNode
|
|
19
20
|
}) {
|
|
20
|
-
// Usuario de ejemplo - en producción esto vendría de Supabase Auth
|
|
21
|
-
const user = {
|
|
22
|
-
email: "admin@ejemplo.com",
|
|
23
|
-
full_name: "Admin Usuario",
|
|
24
|
-
role: "Super Admin",
|
|
25
|
-
}
|
|
26
|
-
|
|
27
21
|
return (
|
|
28
22
|
<html lang="es" className="dark" suppressHydrationWarning>
|
|
29
23
|
<body className={`${inter.className} font-sans antialiased`}>
|
|
30
24
|
<SidebarProvider>
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
<div className="min-h-screen bg-background flex">
|
|
26
|
+
<Sidebar />
|
|
27
|
+
<MainContent>
|
|
28
|
+
{children}
|
|
29
|
+
</MainContent>
|
|
30
|
+
</div>
|
|
35
31
|
</SidebarProvider>
|
|
36
32
|
<Toaster />
|
|
37
33
|
</body>
|
|
@@ -2,28 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import Link from 'next/link'
|
|
4
4
|
import { usePathname } from 'next/navigation'
|
|
5
|
-
import {
|
|
5
|
+
import { useRef, useCallback } from 'react'
|
|
6
6
|
import { cn } from '@/lib/utils'
|
|
7
7
|
import { Icons } from '@/components/ui/icons'
|
|
8
8
|
import { useSidebar } from './sidebar-context'
|
|
9
|
-
import {
|
|
10
|
-
DropdownMenu,
|
|
11
|
-
DropdownMenuContent,
|
|
12
|
-
DropdownMenuItem,
|
|
13
|
-
DropdownMenuSeparator,
|
|
14
|
-
DropdownMenuTrigger,
|
|
15
|
-
} from '@/components/ui/dropdown-menu'
|
|
16
|
-
import { Avatar, AvatarFallback } from '@/components/ui/avatar'
|
|
17
|
-
import { logoutAction } from '@/modules/auth/actions/auth-actions'
|
|
18
9
|
|
|
19
10
|
interface NavItem {
|
|
20
11
|
path: string
|
|
21
12
|
name: string
|
|
22
13
|
icon: keyof typeof Icons
|
|
23
|
-
children?: { path: string; name: string }[]
|
|
24
14
|
}
|
|
25
15
|
|
|
26
|
-
const
|
|
16
|
+
const navItems: NavItem[] = [
|
|
27
17
|
{
|
|
28
18
|
path: '/dashboard',
|
|
29
19
|
name: 'Dashboard',
|
|
@@ -34,104 +24,34 @@ const mainNavItems: NavItem[] = [
|
|
|
34
24
|
name: 'Clientes',
|
|
35
25
|
icon: 'Users',
|
|
36
26
|
},
|
|
37
|
-
{
|
|
38
|
-
path: '/onboarding',
|
|
39
|
-
name: 'Onboarding',
|
|
40
|
-
icon: 'UserPlus',
|
|
41
|
-
},
|
|
42
27
|
{
|
|
43
28
|
path: '/documents',
|
|
44
29
|
name: 'Documentos',
|
|
45
30
|
icon: 'Documents',
|
|
46
31
|
},
|
|
47
|
-
{
|
|
48
|
-
path: '/alerts',
|
|
49
|
-
name: 'Alertas',
|
|
50
|
-
icon: 'Alert',
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
path: '/operations',
|
|
54
|
-
name: 'Operaciones',
|
|
55
|
-
icon: 'Operations',
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
path: '/calendar',
|
|
59
|
-
name: 'Calendario',
|
|
60
|
-
icon: 'Calendar',
|
|
61
|
-
},
|
|
62
|
-
]
|
|
63
|
-
|
|
64
|
-
const getConfigNavItems = (isSuperAdmin: boolean): NavItem[] => [
|
|
65
32
|
{
|
|
66
33
|
path: '/settings',
|
|
67
34
|
name: 'Configuración',
|
|
68
35
|
icon: 'Settings',
|
|
69
|
-
children: [
|
|
70
|
-
{ path: '/settings', name: 'General' },
|
|
71
|
-
{ path: '/settings/organization', name: 'Organización' },
|
|
72
|
-
{ path: '/settings/documents', name: 'Documentos' },
|
|
73
|
-
{ path: '/settings/onboarding', name: 'Onboarding' },
|
|
74
|
-
{ path: '/settings/integrations', name: 'Integraciones' },
|
|
75
|
-
...(isSuperAdmin ? [{ path: '/admin', name: 'Super Admin' }] : []),
|
|
76
|
-
],
|
|
77
36
|
},
|
|
78
37
|
]
|
|
79
38
|
|
|
80
|
-
interface MiddaySidebarProps {
|
|
81
|
-
user: {
|
|
82
|
-
email: string
|
|
83
|
-
full_name: string | null
|
|
84
|
-
role: string
|
|
85
|
-
organization?: {
|
|
86
|
-
name: string
|
|
87
|
-
} | null
|
|
88
|
-
} | null
|
|
89
|
-
}
|
|
90
|
-
|
|
91
39
|
function MenuItem({
|
|
92
40
|
item,
|
|
93
41
|
isExpanded,
|
|
94
42
|
pathname,
|
|
95
|
-
onNavigate,
|
|
96
43
|
}: {
|
|
97
44
|
item: NavItem
|
|
98
45
|
isExpanded: boolean
|
|
99
46
|
pathname: string
|
|
100
|
-
onNavigate?: () => void
|
|
101
47
|
}) {
|
|
102
|
-
const [isSubmenuOpen, setIsSubmenuOpen] = useState(false)
|
|
103
|
-
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
104
48
|
const IconComponent = Icons[item.icon]
|
|
105
|
-
|
|
106
|
-
const isExactMatch = pathname === item.path
|
|
107
|
-
const isChildMatch = item.children?.some(child => pathname === child.path)
|
|
108
|
-
const isActive = isExactMatch || isChildMatch
|
|
109
|
-
const hasChildren = item.children && item.children.length > 0
|
|
110
|
-
|
|
111
|
-
const handleMouseEnter = useCallback(() => {
|
|
112
|
-
if (timeoutRef.current) {
|
|
113
|
-
clearTimeout(timeoutRef.current)
|
|
114
|
-
}
|
|
115
|
-
if (hasChildren) {
|
|
116
|
-
setIsSubmenuOpen(true)
|
|
117
|
-
}
|
|
118
|
-
}, [hasChildren])
|
|
119
|
-
|
|
120
|
-
const handleMouseLeave = useCallback(() => {
|
|
121
|
-
timeoutRef.current = setTimeout(() => {
|
|
122
|
-
setIsSubmenuOpen(false)
|
|
123
|
-
}, 150)
|
|
124
|
-
}, [])
|
|
49
|
+
const isActive = pathname === item.path || pathname.startsWith(item.path + '/')
|
|
125
50
|
|
|
126
51
|
return (
|
|
127
|
-
<li
|
|
128
|
-
className="relative"
|
|
129
|
-
onMouseEnter={handleMouseEnter}
|
|
130
|
-
onMouseLeave={handleMouseLeave}
|
|
131
|
-
>
|
|
52
|
+
<li className="relative">
|
|
132
53
|
<Link
|
|
133
|
-
href={
|
|
134
|
-
onClick={onNavigate}
|
|
54
|
+
href={item.path}
|
|
135
55
|
className={cn(
|
|
136
56
|
'h-[40px] flex items-center gap-3',
|
|
137
57
|
'mx-[10px] px-[10px]',
|
|
@@ -145,165 +65,36 @@ function MenuItem({
|
|
|
145
65
|
)}
|
|
146
66
|
>
|
|
147
67
|
<div className="w-5 h-5 flex items-center justify-center flex-shrink-0">
|
|
148
|
-
<IconComponent
|
|
149
|
-
size={20}
|
|
68
|
+
<IconComponent
|
|
69
|
+
size={20}
|
|
150
70
|
className={cn(
|
|
151
71
|
'transition-colors',
|
|
152
72
|
isActive ? 'text-foreground' : 'text-[#878787]'
|
|
153
|
-
)}
|
|
73
|
+
)}
|
|
154
74
|
/>
|
|
155
75
|
</div>
|
|
156
76
|
{isExpanded && (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
isActive ? 'font-medium text-foreground' : 'text-[#878787]'
|
|
163
|
-
)}
|
|
164
|
-
>
|
|
165
|
-
{item.name}
|
|
166
|
-
</span>
|
|
167
|
-
{hasChildren && (
|
|
168
|
-
<Icons.ChevronRight
|
|
169
|
-
size={14}
|
|
170
|
-
className={cn(
|
|
171
|
-
'ml-auto text-[#878787]',
|
|
172
|
-
'transition-transform duration-200',
|
|
173
|
-
isSubmenuOpen && 'rotate-90'
|
|
174
|
-
)}
|
|
175
|
-
/>
|
|
77
|
+
<span
|
|
78
|
+
className={cn(
|
|
79
|
+
'text-sm whitespace-nowrap',
|
|
80
|
+
'transition-all duration-150',
|
|
81
|
+
isActive ? 'font-medium text-foreground' : 'text-[#878787]'
|
|
176
82
|
)}
|
|
177
|
-
|
|
83
|
+
>
|
|
84
|
+
{item.name}
|
|
85
|
+
</span>
|
|
178
86
|
)}
|
|
179
87
|
</Link>
|
|
180
|
-
|
|
181
|
-
{/* Submenu - Midday style with staggered animation */}
|
|
182
|
-
{hasChildren && isExpanded && isSubmenuOpen && (
|
|
183
|
-
<ul className="mt-1 space-y-0.5">
|
|
184
|
-
{item.children?.map((child, index) => {
|
|
185
|
-
const isChildActive = pathname === child.path
|
|
186
|
-
return (
|
|
187
|
-
<li
|
|
188
|
-
key={child.path}
|
|
189
|
-
className="animate-in fade-in-0 slide-in-from-left-1"
|
|
190
|
-
style={{
|
|
191
|
-
animationDuration: '150ms',
|
|
192
|
-
animationDelay: `${40 + index * 20}ms`,
|
|
193
|
-
animationFillMode: 'backwards'
|
|
194
|
-
}}
|
|
195
|
-
>
|
|
196
|
-
<div className="ml-[35px] border-l border-[#e6e6e6] dark:border-[#2c2c2c]">
|
|
197
|
-
<Link
|
|
198
|
-
href={child.path}
|
|
199
|
-
onClick={onNavigate}
|
|
200
|
-
className={cn(
|
|
201
|
-
'block py-1.5 pl-3 pr-4',
|
|
202
|
-
'text-xs',
|
|
203
|
-
'transition-colors duration-150',
|
|
204
|
-
isChildActive
|
|
205
|
-
? 'text-foreground font-medium'
|
|
206
|
-
: 'text-[#888] hover:text-foreground'
|
|
207
|
-
)}
|
|
208
|
-
>
|
|
209
|
-
{child.name}
|
|
210
|
-
</Link>
|
|
211
|
-
</div>
|
|
212
|
-
</li>
|
|
213
|
-
)
|
|
214
|
-
})}
|
|
215
|
-
</ul>
|
|
216
|
-
)}
|
|
217
88
|
</li>
|
|
218
89
|
)
|
|
219
90
|
}
|
|
220
91
|
|
|
221
|
-
function
|
|
222
|
-
user,
|
|
223
|
-
isExpanded,
|
|
224
|
-
}: {
|
|
225
|
-
user: MiddaySidebarProps['user']
|
|
226
|
-
isExpanded: boolean
|
|
227
|
-
}) {
|
|
228
|
-
const initials = user?.full_name
|
|
229
|
-
? user.full_name
|
|
230
|
-
.split(' ')
|
|
231
|
-
.map((n) => n[0])
|
|
232
|
-
.join('')
|
|
233
|
-
.toUpperCase()
|
|
234
|
-
.slice(0, 2)
|
|
235
|
-
: user?.email?.slice(0, 2).toUpperCase() || 'U'
|
|
236
|
-
|
|
237
|
-
return (
|
|
238
|
-
<DropdownMenu>
|
|
239
|
-
<DropdownMenuTrigger asChild>
|
|
240
|
-
<button
|
|
241
|
-
className={cn(
|
|
242
|
-
'flex items-center gap-3',
|
|
243
|
-
'w-[calc(100%-20px)] mx-[10px] px-[10px] py-2',
|
|
244
|
-
'rounded-md',
|
|
245
|
-
'hover:bg-[#f7f7f7] dark:hover:bg-[#1a1a1a]',
|
|
246
|
-
'transition-colors duration-150',
|
|
247
|
-
'focus:outline-none focus-visible:ring-1 focus-visible:ring-ring'
|
|
248
|
-
)}
|
|
249
|
-
>
|
|
250
|
-
<Avatar className="h-8 w-8 flex-shrink-0">
|
|
251
|
-
<AvatarFallback className="bg-primary text-primary-foreground text-xs font-medium">
|
|
252
|
-
{initials}
|
|
253
|
-
</AvatarFallback>
|
|
254
|
-
</Avatar>
|
|
255
|
-
{isExpanded && (
|
|
256
|
-
<div className="flex-1 text-left overflow-hidden min-w-0">
|
|
257
|
-
<p className="text-sm font-medium truncate leading-tight">
|
|
258
|
-
{user?.full_name || 'Usuario'}
|
|
259
|
-
</p>
|
|
260
|
-
<p className="text-xs text-[#878787] truncate leading-tight">
|
|
261
|
-
{user?.email}
|
|
262
|
-
</p>
|
|
263
|
-
</div>
|
|
264
|
-
)}
|
|
265
|
-
</button>
|
|
266
|
-
</DropdownMenuTrigger>
|
|
267
|
-
<DropdownMenuContent
|
|
268
|
-
align="start"
|
|
269
|
-
side="top"
|
|
270
|
-
sideOffset={8}
|
|
271
|
-
className="w-56"
|
|
272
|
-
>
|
|
273
|
-
<div className="px-2 py-1.5">
|
|
274
|
-
<p className="text-sm font-medium">{user?.full_name || 'Usuario'}</p>
|
|
275
|
-
<p className="text-xs text-[#878787]">{user?.email}</p>
|
|
276
|
-
</div>
|
|
277
|
-
<DropdownMenuSeparator />
|
|
278
|
-
<DropdownMenuItem asChild>
|
|
279
|
-
<Link href="/settings" className="cursor-pointer">
|
|
280
|
-
<Icons.Settings size={16} className="mr-2 text-[#878787]" />
|
|
281
|
-
<span>Configuración</span>
|
|
282
|
-
</Link>
|
|
283
|
-
</DropdownMenuItem>
|
|
284
|
-
<DropdownMenuSeparator />
|
|
285
|
-
<DropdownMenuItem
|
|
286
|
-
className="text-destructive focus:text-destructive cursor-pointer"
|
|
287
|
-
onClick={() => logoutAction()}
|
|
288
|
-
>
|
|
289
|
-
<Icons.LogOut size={16} className="mr-2" />
|
|
290
|
-
<span>Cerrar sesión</span>
|
|
291
|
-
</DropdownMenuItem>
|
|
292
|
-
</DropdownMenuContent>
|
|
293
|
-
</DropdownMenu>
|
|
294
|
-
)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
export function MiddaySidebar({ user }: MiddaySidebarProps) {
|
|
92
|
+
export function Sidebar() {
|
|
298
93
|
const { isExpanded, setIsExpanded } = useSidebar()
|
|
299
94
|
const pathname = usePathname()
|
|
300
95
|
const sidebarRef = useRef<HTMLDivElement>(null)
|
|
301
96
|
const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
302
97
|
|
|
303
|
-
const isAdmin = user?.role && ['admin', 'super_admin'].includes(user.role)
|
|
304
|
-
const isSuperAdmin = user?.role === 'super_admin'
|
|
305
|
-
const configNavItems = getConfigNavItems(isSuperAdmin)
|
|
306
|
-
|
|
307
98
|
const handleMouseEnter = useCallback(() => {
|
|
308
99
|
if (hoverTimeoutRef.current) {
|
|
309
100
|
clearTimeout(hoverTimeoutRef.current)
|
|
@@ -329,8 +120,8 @@ export function MiddaySidebar({ user }: MiddaySidebarProps) {
|
|
|
329
120
|
onMouseEnter={handleMouseEnter}
|
|
330
121
|
onMouseLeave={handleMouseLeave}
|
|
331
122
|
>
|
|
332
|
-
{/* Header / Logo
|
|
333
|
-
<div
|
|
123
|
+
{/* Header / Logo */}
|
|
124
|
+
<div
|
|
334
125
|
className={cn(
|
|
335
126
|
"absolute top-0 left-0 h-[70px] flex items-center justify-center bg-background border-b border-border transition-all duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]",
|
|
336
127
|
isExpanded ? "w-full" : "w-[69px]"
|
|
@@ -342,10 +133,10 @@ export function MiddaySidebar({ user }: MiddaySidebarProps) {
|
|
|
342
133
|
</Link>
|
|
343
134
|
</div>
|
|
344
135
|
|
|
345
|
-
{/* Navigation
|
|
346
|
-
<nav className="flex-1 pt-[70px] pb-4 overflow-y-auto scrollbar-hide
|
|
136
|
+
{/* Navigation */}
|
|
137
|
+
<nav className="flex-1 pt-[70px] pb-4 overflow-y-auto scrollbar-hide">
|
|
347
138
|
<ul className="space-y-1">
|
|
348
|
-
{
|
|
139
|
+
{navItems.map((item) => (
|
|
349
140
|
<MenuItem
|
|
350
141
|
key={item.path}
|
|
351
142
|
item={item}
|
|
@@ -354,28 +145,7 @@ export function MiddaySidebar({ user }: MiddaySidebarProps) {
|
|
|
354
145
|
/>
|
|
355
146
|
))}
|
|
356
147
|
</ul>
|
|
357
|
-
|
|
358
|
-
{/* Admin section with separator */}
|
|
359
|
-
{isAdmin && (
|
|
360
|
-
<div className="mt-6 pt-4 mx-[10px] border-t border-border">
|
|
361
|
-
<ul className="space-y-1">
|
|
362
|
-
{configNavItems.map((item) => (
|
|
363
|
-
<MenuItem
|
|
364
|
-
key={item.path}
|
|
365
|
-
item={item}
|
|
366
|
-
isExpanded={isExpanded}
|
|
367
|
-
pathname={pathname}
|
|
368
|
-
/>
|
|
369
|
-
))}
|
|
370
|
-
</ul>
|
|
371
|
-
</div>
|
|
372
|
-
)}
|
|
373
148
|
</nav>
|
|
374
|
-
|
|
375
|
-
{/* User section - Midday style */}
|
|
376
|
-
<div className="border-t border-border py-3">
|
|
377
|
-
<UserDropdown user={user} isExpanded={isExpanded} />
|
|
378
|
-
</div>
|
|
379
149
|
</aside>
|
|
380
150
|
)
|
|
381
151
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use server'
|
|
2
2
|
|
|
3
|
-
import { createClient } from '@/lib/supabase/server'
|
|
4
3
|
import { redirect } from 'next/navigation'
|
|
5
4
|
|
|
6
5
|
export async function logout() {
|
|
7
|
-
|
|
8
|
-
await
|
|
9
|
-
|
|
6
|
+
// TODO: Implementar con Supabase
|
|
7
|
+
// const supabase = await createClient()
|
|
8
|
+
// await supabase.auth.signOut()
|
|
9
|
+
redirect('/login')
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export const logoutAction = logout
|
|
File without changes
|