@create-lft-app/nextjs 1.0.0
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/bin/cli.d.ts +2 -0
- package/bin/cli.js +42 -0
- package/package.json +42 -0
- package/template/eslint.config.mjs +16 -0
- package/template/gitignore +36 -0
- package/template/next.config.ts +7 -0
- package/template/package.json +61 -0
- package/template/postcss.config.mjs +7 -0
- package/template/src/app/auth/login/page.tsx +153 -0
- package/template/src/app/dashboard/page.tsx +102 -0
- package/template/src/app/globals.css +249 -0
- package/template/src/app/layout.tsx +40 -0
- package/template/src/app/page.tsx +5 -0
- package/template/src/components/dashboard/widget.tsx +113 -0
- package/template/src/components/layout/admin-midday-sidebar.tsx +247 -0
- package/template/src/components/layout/admin-sidebar.tsx +146 -0
- package/template/src/components/layout/header.tsx +71 -0
- package/template/src/components/layout/main-content.tsx +28 -0
- package/template/src/components/layout/midday-sidebar.tsx +381 -0
- package/template/src/components/layout/nav-user.tsx +108 -0
- package/template/src/components/layout/page-header.tsx +95 -0
- package/template/src/components/layout/sidebar-context.tsx +33 -0
- package/template/src/components/layout/sidebar.tsx +194 -0
- package/template/src/components/layout/suspension-banner.tsx +21 -0
- package/template/src/components/ui/accordion.tsx +58 -0
- package/template/src/components/ui/alert-dialog.tsx +165 -0
- package/template/src/components/ui/alert.tsx +66 -0
- package/template/src/components/ui/avatar.tsx +55 -0
- package/template/src/components/ui/badge.tsx +50 -0
- package/template/src/components/ui/button.tsx +89 -0
- package/template/src/components/ui/calendar.tsx +220 -0
- package/template/src/components/ui/card.tsx +89 -0
- package/template/src/components/ui/checkbox.tsx +38 -0
- package/template/src/components/ui/collapsible.tsx +33 -0
- package/template/src/components/ui/command.tsx +196 -0
- package/template/src/components/ui/dialog.tsx +153 -0
- package/template/src/components/ui/dropdown-menu.tsx +280 -0
- package/template/src/components/ui/form.tsx +171 -0
- package/template/src/components/ui/icons.tsx +167 -0
- package/template/src/components/ui/input.tsx +28 -0
- package/template/src/components/ui/label.tsx +25 -0
- package/template/src/components/ui/popover.tsx +59 -0
- package/template/src/components/ui/progress.tsx +32 -0
- package/template/src/components/ui/radio-group.tsx +45 -0
- package/template/src/components/ui/scroll-area.tsx +63 -0
- package/template/src/components/ui/select.tsx +208 -0
- package/template/src/components/ui/separator.tsx +28 -0
- package/template/src/components/ui/sheet.tsx +146 -0
- package/template/src/components/ui/sidebar.tsx +726 -0
- package/template/src/components/ui/skeleton.tsx +15 -0
- package/template/src/components/ui/slider.tsx +58 -0
- package/template/src/components/ui/sonner.tsx +47 -0
- package/template/src/components/ui/spinner.tsx +27 -0
- package/template/src/components/ui/submit-button.tsx +47 -0
- package/template/src/components/ui/switch.tsx +31 -0
- package/template/src/components/ui/table.tsx +120 -0
- package/template/src/components/ui/tabs.tsx +75 -0
- package/template/src/components/ui/textarea.tsx +26 -0
- package/template/src/components/ui/tooltip.tsx +70 -0
- package/template/src/hooks/use-mobile.ts +21 -0
- package/template/src/lib/supabase/client.ts +8 -0
- package/template/src/lib/supabase/server.ts +36 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/modules/auth/actions/auth-actions.ts +12 -0
- package/template/tsconfig.json +27 -0
package/bin/cli.d.ts
ADDED
package/bin/cli.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
program
|
|
9
|
+
.name('create-lft-nextjs')
|
|
10
|
+
.description('Crea un proyecto Next.js con el template LFT')
|
|
11
|
+
.version('1.0.0')
|
|
12
|
+
.argument('<project-name>', 'Nombre del proyecto')
|
|
13
|
+
.option('--cwd <path>', 'Directorio donde crear el proyecto', process.cwd())
|
|
14
|
+
.action(async (projectName, options) => {
|
|
15
|
+
const templateDir = path.join(__dirname, '..', 'template');
|
|
16
|
+
const targetDir = path.join(options.cwd, projectName);
|
|
17
|
+
// Verificar si el directorio ya existe
|
|
18
|
+
if (fs.existsSync(targetDir)) {
|
|
19
|
+
console.log(`El directorio ${projectName} ya existe`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
// Copiar template
|
|
24
|
+
await fs.copy(templateDir, targetDir);
|
|
25
|
+
// Actualizar package.json con el nombre del proyecto
|
|
26
|
+
const pkgPath = path.join(targetDir, 'package.json');
|
|
27
|
+
const pkg = await fs.readJson(pkgPath);
|
|
28
|
+
pkg.name = projectName;
|
|
29
|
+
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
30
|
+
// Renombrar gitignore
|
|
31
|
+
const gitignorePath = path.join(targetDir, 'gitignore');
|
|
32
|
+
if (fs.existsSync(gitignorePath)) {
|
|
33
|
+
await fs.rename(gitignorePath, path.join(targetDir, '.gitignore'));
|
|
34
|
+
}
|
|
35
|
+
console.log(`Proyecto ${projectName} creado exitosamente`);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error('Error al crear el proyecto:', error);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@create-lft-app/nextjs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Next.js template para proyectos LFT con Midday Design System",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-lft-nextjs": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"template"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"nextjs",
|
|
19
|
+
"template",
|
|
20
|
+
"lft",
|
|
21
|
+
"midday",
|
|
22
|
+
"dashboard"
|
|
23
|
+
],
|
|
24
|
+
"author": "LFT",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/Test-Boiler/create-lft-nextjs"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/fs-extra": "^11.0.0",
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"commander": "^12.0.0",
|
|
40
|
+
"fs-extra": "^11.0.0"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { dirname } from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import { FlatCompat } from "@eslint/eslintrc";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const compat = new FlatCompat({
|
|
9
|
+
baseDirectory: __dirname,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const eslintConfig = [
|
|
13
|
+
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export default eslintConfig;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
/node_modules
|
|
3
|
+
/.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
.yarn/install-state.gz
|
|
6
|
+
|
|
7
|
+
# Testing
|
|
8
|
+
/coverage
|
|
9
|
+
|
|
10
|
+
# Next.js
|
|
11
|
+
/.next/
|
|
12
|
+
/out/
|
|
13
|
+
|
|
14
|
+
# Production
|
|
15
|
+
/build
|
|
16
|
+
|
|
17
|
+
# Misc
|
|
18
|
+
.DS_Store
|
|
19
|
+
*.pem
|
|
20
|
+
|
|
21
|
+
# Debug
|
|
22
|
+
npm-debug.log*
|
|
23
|
+
yarn-debug.log*
|
|
24
|
+
yarn-error.log*
|
|
25
|
+
.pnpm-debug.log*
|
|
26
|
+
|
|
27
|
+
# Local env files
|
|
28
|
+
.env*.local
|
|
29
|
+
.env
|
|
30
|
+
|
|
31
|
+
# Vercel
|
|
32
|
+
.vercel
|
|
33
|
+
|
|
34
|
+
# TypeScript
|
|
35
|
+
*.tsbuildinfo
|
|
36
|
+
next-env.d.ts
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lft-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev --turbopack",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"next": "^16.0.0",
|
|
13
|
+
"react": "^19.0.0",
|
|
14
|
+
"react-dom": "^19.0.0",
|
|
15
|
+
"@radix-ui/react-accordion": "^1.2.0",
|
|
16
|
+
"@radix-ui/react-alert-dialog": "^1.1.0",
|
|
17
|
+
"@radix-ui/react-avatar": "^1.1.0",
|
|
18
|
+
"@radix-ui/react-checkbox": "^1.1.0",
|
|
19
|
+
"@radix-ui/react-collapsible": "^1.1.0",
|
|
20
|
+
"@radix-ui/react-dialog": "^1.1.0",
|
|
21
|
+
"@radix-ui/react-dropdown-menu": "^2.1.0",
|
|
22
|
+
"@radix-ui/react-label": "^2.1.0",
|
|
23
|
+
"@radix-ui/react-popover": "^1.1.0",
|
|
24
|
+
"@radix-ui/react-progress": "^1.1.0",
|
|
25
|
+
"@radix-ui/react-radio-group": "^1.2.0",
|
|
26
|
+
"@radix-ui/react-scroll-area": "^1.1.0",
|
|
27
|
+
"@radix-ui/react-select": "^2.1.0",
|
|
28
|
+
"@radix-ui/react-separator": "^1.1.0",
|
|
29
|
+
"@radix-ui/react-slider": "^1.2.0",
|
|
30
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
31
|
+
"@radix-ui/react-switch": "^1.1.0",
|
|
32
|
+
"@radix-ui/react-tabs": "^1.1.0",
|
|
33
|
+
"@radix-ui/react-tooltip": "^1.1.0",
|
|
34
|
+
"class-variance-authority": "^0.7.0",
|
|
35
|
+
"clsx": "^2.1.0",
|
|
36
|
+
"tailwind-merge": "^2.5.0",
|
|
37
|
+
"lucide-react": "^0.400.0",
|
|
38
|
+
"react-hook-form": "^7.50.0",
|
|
39
|
+
"@hookform/resolvers": "^3.9.0",
|
|
40
|
+
"cmdk": "^1.0.0",
|
|
41
|
+
"react-day-picker": "^9.0.0",
|
|
42
|
+
"date-fns": "^4.0.0",
|
|
43
|
+
"sonner": "^1.5.0",
|
|
44
|
+
"next-themes": "^0.4.0",
|
|
45
|
+
"tw-animate-css": "^1.2.0",
|
|
46
|
+
"zod": "^3.23.0",
|
|
47
|
+
"@supabase/supabase-js": "^2.45.0",
|
|
48
|
+
"@supabase/ssr": "^0.5.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^22.0.0",
|
|
52
|
+
"@types/react": "^19.0.0",
|
|
53
|
+
"@types/react-dom": "^19.0.0",
|
|
54
|
+
"typescript": "^5.7.0",
|
|
55
|
+
"eslint": "^9.0.0",
|
|
56
|
+
"eslint-config-next": "^16.0.0",
|
|
57
|
+
"tailwindcss": "^4.0.0",
|
|
58
|
+
"@tailwindcss/postcss": "^4.0.0",
|
|
59
|
+
"tailwindcss-animate": "^1.0.0"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useState } from "react"
|
|
4
|
+
import { useRouter } from "next/navigation"
|
|
5
|
+
import Link from "next/link"
|
|
6
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@/components/ui/card"
|
|
7
|
+
import { Input } from "@/components/ui/input"
|
|
8
|
+
import { Button } from "@/components/ui/button"
|
|
9
|
+
import { Label } from "@/components/ui/label"
|
|
10
|
+
import { Separator } from "@/components/ui/separator"
|
|
11
|
+
import { Spinner } from "@/components/ui/spinner"
|
|
12
|
+
|
|
13
|
+
export default function LoginPage() {
|
|
14
|
+
const router = useRouter()
|
|
15
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
16
|
+
const [error, setError] = useState<string | null>(null)
|
|
17
|
+
|
|
18
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
19
|
+
e.preventDefault()
|
|
20
|
+
setIsLoading(true)
|
|
21
|
+
setError(null)
|
|
22
|
+
|
|
23
|
+
const formData = new FormData(e.currentTarget)
|
|
24
|
+
const email = formData.get("email") as string
|
|
25
|
+
const password = formData.get("password") as string
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// TODO: Implementar autenticación con Supabase
|
|
29
|
+
// const { error } = await supabase.auth.signInWithPassword({ email, password })
|
|
30
|
+
|
|
31
|
+
// Simulación de login exitoso
|
|
32
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
33
|
+
|
|
34
|
+
router.push("/dashboard")
|
|
35
|
+
} catch (err) {
|
|
36
|
+
setError("Error al iniciar sesión. Verifica tus credenciales.")
|
|
37
|
+
} finally {
|
|
38
|
+
setIsLoading(false)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="min-h-screen flex items-center justify-center bg-background p-4">
|
|
44
|
+
<Card className="w-full max-w-md">
|
|
45
|
+
<CardHeader className="space-y-1 text-center">
|
|
46
|
+
<CardTitle className="text-2xl font-bold">Iniciar Sesión</CardTitle>
|
|
47
|
+
<CardDescription>
|
|
48
|
+
Ingresa tus credenciales para acceder al panel
|
|
49
|
+
</CardDescription>
|
|
50
|
+
</CardHeader>
|
|
51
|
+
<CardContent>
|
|
52
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
53
|
+
{error && (
|
|
54
|
+
<div className="p-3 text-sm text-destructive bg-destructive/10 border border-destructive/20 rounded-md">
|
|
55
|
+
{error}
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
|
|
59
|
+
<div className="space-y-2">
|
|
60
|
+
<Label htmlFor="email">Email</Label>
|
|
61
|
+
<Input
|
|
62
|
+
id="email"
|
|
63
|
+
name="email"
|
|
64
|
+
type="email"
|
|
65
|
+
placeholder="tu@email.com"
|
|
66
|
+
required
|
|
67
|
+
disabled={isLoading}
|
|
68
|
+
autoComplete="email"
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div className="space-y-2">
|
|
73
|
+
<div className="flex items-center justify-between">
|
|
74
|
+
<Label htmlFor="password">Contraseña</Label>
|
|
75
|
+
<Link
|
|
76
|
+
href="/auth/forgot-password"
|
|
77
|
+
className="text-sm text-primary hover:underline"
|
|
78
|
+
>
|
|
79
|
+
¿Olvidaste tu contraseña?
|
|
80
|
+
</Link>
|
|
81
|
+
</div>
|
|
82
|
+
<Input
|
|
83
|
+
id="password"
|
|
84
|
+
name="password"
|
|
85
|
+
type="password"
|
|
86
|
+
placeholder="••••••••"
|
|
87
|
+
required
|
|
88
|
+
disabled={isLoading}
|
|
89
|
+
autoComplete="current-password"
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<Button type="submit" className="w-full" disabled={isLoading}>
|
|
94
|
+
{isLoading ? (
|
|
95
|
+
<>
|
|
96
|
+
<Spinner className="mr-2 h-4 w-4" />
|
|
97
|
+
Iniciando sesión...
|
|
98
|
+
</>
|
|
99
|
+
) : (
|
|
100
|
+
"Iniciar Sesión"
|
|
101
|
+
)}
|
|
102
|
+
</Button>
|
|
103
|
+
</form>
|
|
104
|
+
|
|
105
|
+
<div className="relative my-6">
|
|
106
|
+
<Separator />
|
|
107
|
+
<span className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-background px-2 text-xs text-muted-foreground">
|
|
108
|
+
O continuar con
|
|
109
|
+
</span>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div className="grid grid-cols-2 gap-4">
|
|
113
|
+
<Button variant="outline" disabled={isLoading}>
|
|
114
|
+
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24">
|
|
115
|
+
<path
|
|
116
|
+
fill="currentColor"
|
|
117
|
+
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
|
118
|
+
/>
|
|
119
|
+
<path
|
|
120
|
+
fill="currentColor"
|
|
121
|
+
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
|
|
122
|
+
/>
|
|
123
|
+
<path
|
|
124
|
+
fill="currentColor"
|
|
125
|
+
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
|
|
126
|
+
/>
|
|
127
|
+
<path
|
|
128
|
+
fill="currentColor"
|
|
129
|
+
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
|
130
|
+
/>
|
|
131
|
+
</svg>
|
|
132
|
+
Google
|
|
133
|
+
</Button>
|
|
134
|
+
<Button variant="outline" disabled={isLoading}>
|
|
135
|
+
<svg className="mr-2 h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
|
136
|
+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
|
137
|
+
</svg>
|
|
138
|
+
GitHub
|
|
139
|
+
</Button>
|
|
140
|
+
</div>
|
|
141
|
+
</CardContent>
|
|
142
|
+
<CardFooter className="flex justify-center">
|
|
143
|
+
<p className="text-sm text-muted-foreground">
|
|
144
|
+
¿No tienes una cuenta?{" "}
|
|
145
|
+
<Link href="/auth/register" className="text-primary hover:underline">
|
|
146
|
+
Regístrate
|
|
147
|
+
</Link>
|
|
148
|
+
</p>
|
|
149
|
+
</CardFooter>
|
|
150
|
+
</Card>
|
|
151
|
+
</div>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Header } from "@/components/layout/header"
|
|
2
|
+
import { Widget, WidgetGrid } from "@/components/dashboard/widget"
|
|
3
|
+
import {
|
|
4
|
+
Users,
|
|
5
|
+
DollarSign,
|
|
6
|
+
Activity,
|
|
7
|
+
TrendingUp,
|
|
8
|
+
Building2,
|
|
9
|
+
FileText,
|
|
10
|
+
AlertCircle,
|
|
11
|
+
CheckCircle,
|
|
12
|
+
} from "lucide-react"
|
|
13
|
+
|
|
14
|
+
export default function DashboardPage() {
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
<Header title="Dashboard" />
|
|
18
|
+
<main className="flex-1 p-6">
|
|
19
|
+
<div className="space-y-6">
|
|
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>
|
|
28
|
+
|
|
29
|
+
<WidgetGrid>
|
|
30
|
+
<Widget
|
|
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>
|
|
62
|
+
|
|
63
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
64
|
+
<WidgetGrid>
|
|
65
|
+
<Widget
|
|
66
|
+
title="Documentos Pendientes"
|
|
67
|
+
icon={<FileText className="h-4 w-4" />}
|
|
68
|
+
value="23"
|
|
69
|
+
subValue="requieren revisión"
|
|
70
|
+
variant="warning"
|
|
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>
|
|
80
|
+
|
|
81
|
+
<WidgetGrid>
|
|
82
|
+
<Widget
|
|
83
|
+
title="Tareas Completadas"
|
|
84
|
+
icon={<CheckCircle className="h-4 w-4" />}
|
|
85
|
+
value="156"
|
|
86
|
+
subValue="esta semana"
|
|
87
|
+
variant="success"
|
|
88
|
+
/>
|
|
89
|
+
<Widget
|
|
90
|
+
title="Crecimiento"
|
|
91
|
+
icon={<TrendingUp className="h-4 w-4" />}
|
|
92
|
+
value="+24%"
|
|
93
|
+
subValue="vs mes anterior"
|
|
94
|
+
trend={{ value: 24, positive: true }}
|
|
95
|
+
/>
|
|
96
|
+
</WidgetGrid>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</main>
|
|
100
|
+
</>
|
|
101
|
+
)
|
|
102
|
+
}
|