ar-saas 0.3.1 → 0.3.2

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.
Files changed (114) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +338 -314
  3. package/dist/cli.js +19 -0
  4. package/dist/generator.js +166 -55
  5. package/package.json +52 -50
  6. package/templates/backend/.env.example +67 -67
  7. package/templates/backend/.prettierrc +4 -4
  8. package/templates/backend/README.md +249 -168
  9. package/templates/backend/eslint.config.mjs +35 -35
  10. package/templates/backend/nest-cli.json +8 -8
  11. package/templates/backend/package-lock.json +10979 -10979
  12. package/templates/backend/package.json +88 -88
  13. package/templates/backend/src/app.controller.spec.ts +24 -24
  14. package/templates/backend/src/app.controller.ts +15 -15
  15. package/templates/backend/src/app.module.ts +40 -40
  16. package/templates/backend/src/app.service.ts +11 -11
  17. package/templates/backend/src/common/base/base.repository.ts +221 -221
  18. package/templates/backend/src/common/base/base.schema.ts +24 -24
  19. package/templates/backend/src/common/decorators/cookie.decorator.ts +9 -9
  20. package/templates/backend/src/common/decorators/current-user.decorator.ts +20 -20
  21. package/templates/backend/src/common/decorators/workspace-id.decorator.ts +14 -14
  22. package/templates/backend/src/common/filters/global-exception.filter.ts +61 -61
  23. package/templates/backend/src/common/guards/jwt-auth.guard.ts +5 -5
  24. package/templates/backend/src/common/interceptors/workspace-tenant.interceptor.ts +45 -45
  25. package/templates/backend/src/main.ts +51 -51
  26. package/templates/backend/src/modules/auth/auth.controller.ts +158 -158
  27. package/templates/backend/src/modules/auth/auth.module.ts +20 -20
  28. package/templates/backend/src/modules/auth/auth.service.ts +257 -257
  29. package/templates/backend/src/modules/auth/dto/forgot-password.dto.ts +9 -9
  30. package/templates/backend/src/modules/auth/dto/login.dto.ts +14 -14
  31. package/templates/backend/src/modules/auth/dto/refresh-token.dto.ts +12 -12
  32. package/templates/backend/src/modules/auth/dto/register.dto.ts +26 -26
  33. package/templates/backend/src/modules/auth/dto/reset-password.dto.ts +16 -16
  34. package/templates/backend/src/modules/auth/dto/verify-email.dto.ts +9 -9
  35. package/templates/backend/src/modules/auth/strategies/jwt.strategy.ts +43 -43
  36. package/templates/backend/src/modules/mail/mail.module.ts +9 -9
  37. package/templates/backend/src/modules/mail/mail.service.ts +141 -141
  38. package/templates/backend/src/modules/users/schemas/user.schema.ts +54 -54
  39. package/templates/backend/src/modules/users/users.module.ts +14 -14
  40. package/templates/backend/src/modules/users/users.repository.ts +51 -51
  41. package/templates/backend/src/modules/users/users.service.ts +104 -104
  42. package/templates/backend/src/modules/workspaces/schemas/workspace.schema.ts +26 -26
  43. package/templates/backend/src/modules/workspaces/workspaces.module.ts +16 -16
  44. package/templates/backend/src/modules/workspaces/workspaces.repository.ts +34 -34
  45. package/templates/backend/src/modules/workspaces/workspaces.service.ts +42 -42
  46. package/templates/backend/test/app.e2e-spec.ts +25 -25
  47. package/templates/backend/test/jest-e2e.json +9 -9
  48. package/templates/backend/tsconfig.build.json +4 -4
  49. package/templates/backend/tsconfig.json +26 -26
  50. package/templates/frontend/.env.local.example +1 -1
  51. package/templates/frontend/README.md +152 -0
  52. package/templates/frontend/components.json +20 -20
  53. package/templates/frontend/eslint.config.mjs +14 -14
  54. package/templates/frontend/next.config.ts +5 -5
  55. package/templates/frontend/package-lock.json +6722 -6722
  56. package/templates/frontend/package.json +48 -48
  57. package/templates/frontend/pnpm-lock.yaml +5012 -5012
  58. package/templates/frontend/pnpm-workspace.yaml +3 -3
  59. package/templates/frontend/postcss.config.mjs +7 -7
  60. package/templates/frontend/src/app/(auth)/forgot-password/page.tsx +84 -84
  61. package/templates/frontend/src/app/(auth)/layout.tsx +28 -28
  62. package/templates/frontend/src/app/(auth)/login/page.tsx +111 -111
  63. package/templates/frontend/src/app/(auth)/register/page.tsx +161 -161
  64. package/templates/frontend/src/app/(auth)/reset-password/page.tsx +120 -120
  65. package/templates/frontend/src/app/(auth)/verify-email/page.tsx +78 -78
  66. package/templates/frontend/src/app/(dashboard)/billing/page.tsx +111 -111
  67. package/templates/frontend/src/app/(dashboard)/dashboard/page.tsx +105 -105
  68. package/templates/frontend/src/app/(dashboard)/layout.tsx +38 -38
  69. package/templates/frontend/src/app/(dashboard)/profile/page.tsx +226 -226
  70. package/templates/frontend/src/app/(dashboard)/settings/page.tsx +156 -156
  71. package/templates/frontend/src/app/(dashboard)/team/page.tsx +178 -178
  72. package/templates/frontend/src/app/(legal)/privacy/page.tsx +127 -127
  73. package/templates/frontend/src/app/(legal)/terms/page.tsx +118 -118
  74. package/templates/frontend/src/app/globals.css +81 -81
  75. package/templates/frontend/src/app/layout.tsx +26 -26
  76. package/templates/frontend/src/app/page.tsx +5 -45
  77. package/templates/frontend/src/app/setup/page.tsx +371 -275
  78. package/templates/frontend/src/components/dashboard/header.tsx +89 -89
  79. package/templates/frontend/src/components/dashboard/sidebar.tsx +71 -71
  80. package/templates/frontend/src/components/dashboard/stat-card.tsx +34 -34
  81. package/templates/frontend/src/components/landing/faq.tsx +39 -39
  82. package/templates/frontend/src/components/landing/features.tsx +54 -54
  83. package/templates/frontend/src/components/landing/footer.tsx +76 -76
  84. package/templates/frontend/src/components/landing/hero.tsx +72 -72
  85. package/templates/frontend/src/components/landing/navbar.tsx +78 -78
  86. package/templates/frontend/src/components/landing/pricing.tsx +90 -90
  87. package/templates/frontend/src/components/ui/accordion.tsx +52 -52
  88. package/templates/frontend/src/components/ui/avatar.tsx +46 -46
  89. package/templates/frontend/src/components/ui/badge.tsx +30 -30
  90. package/templates/frontend/src/components/ui/button.tsx +52 -52
  91. package/templates/frontend/src/components/ui/card.tsx +50 -50
  92. package/templates/frontend/src/components/ui/checkbox.tsx +27 -27
  93. package/templates/frontend/src/components/ui/dialog.tsx +100 -100
  94. package/templates/frontend/src/components/ui/dropdown-menu.tsx +173 -173
  95. package/templates/frontend/src/components/ui/form.tsx +158 -158
  96. package/templates/frontend/src/components/ui/input.tsx +21 -21
  97. package/templates/frontend/src/components/ui/label.tsx +22 -22
  98. package/templates/frontend/src/components/ui/separator.tsx +25 -25
  99. package/templates/frontend/src/components/ui/skeleton.tsx +7 -7
  100. package/templates/frontend/src/components/ui/switch.tsx +28 -28
  101. package/templates/frontend/src/components/ui/tabs.tsx +54 -54
  102. package/templates/frontend/src/components/ui/textarea.tsx +20 -20
  103. package/templates/frontend/src/components/ui/toast.tsx +109 -109
  104. package/templates/frontend/src/components/ui/toaster.tsx +30 -30
  105. package/templates/frontend/src/config/site.ts +197 -197
  106. package/templates/frontend/src/hooks/use-toast.ts +116 -116
  107. package/templates/frontend/src/lib/api/auth.ts +39 -39
  108. package/templates/frontend/src/lib/api/client.ts +66 -66
  109. package/templates/frontend/src/lib/hooks/use-auth.ts +1 -1
  110. package/templates/frontend/src/lib/utils.ts +6 -6
  111. package/templates/frontend/src/providers/auth-provider.tsx +60 -60
  112. package/templates/frontend/src/types/api.ts +12 -12
  113. package/templates/frontend/src/types/auth.ts +27 -27
  114. package/templates/frontend/tsconfig.json +23 -23
@@ -1,156 +1,156 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
5
- import { Switch } from '@/components/ui/switch'
6
- import { Separator } from '@/components/ui/separator'
7
- import { Button } from '@/components/ui/button'
8
- import { Label } from '@/components/ui/label'
9
- import { Badge } from '@/components/ui/badge'
10
-
11
- interface NotificationSettings {
12
- emailMarketing: boolean
13
- emailProduct: boolean
14
- emailSecurity: boolean
15
- pushAll: boolean
16
- }
17
-
18
- interface WorkspaceSettings {
19
- publicProfile: boolean
20
- allowInvites: boolean
21
- }
22
-
23
- export default function SettingsPage() {
24
- const [notifications, setNotifications] = useState<NotificationSettings>({
25
- emailMarketing: false,
26
- emailProduct: true,
27
- emailSecurity: true,
28
- pushAll: false,
29
- })
30
-
31
- const [workspace, setWorkspace] = useState<WorkspaceSettings>({
32
- publicProfile: false,
33
- allowInvites: true,
34
- })
35
-
36
- const [saved, setSaved] = useState(false)
37
-
38
- function toggleNotification(key: keyof NotificationSettings) {
39
- setNotifications((prev) => ({ ...prev, [key]: !prev[key] }))
40
- }
41
-
42
- function toggleWorkspace(key: keyof WorkspaceSettings) {
43
- setWorkspace((prev) => ({ ...prev, [key]: !prev[key] }))
44
- }
45
-
46
- function handleSave() {
47
- // TODO: llamar a PATCH /users/me/settings con notifications y workspace
48
- console.log('Guardar ajustes:', { notifications, workspace })
49
- setSaved(true)
50
- setTimeout(() => setSaved(false), 2000)
51
- }
52
-
53
- return (
54
- <div className="max-w-2xl space-y-6">
55
- {/* Notificaciones */}
56
- <Card>
57
- <CardHeader>
58
- <CardTitle>Notificaciones por email</CardTitle>
59
- <CardDescription>Elegí qué correos querés recibir de nuestra parte.</CardDescription>
60
- </CardHeader>
61
- <CardContent className="space-y-4">
62
- {[
63
- {
64
- key: 'emailSecurity' as const,
65
- label: 'Seguridad',
66
- description: 'Alertas de inicio de sesión y cambios de contraseña.',
67
- badge: 'Recomendado',
68
- },
69
- {
70
- key: 'emailProduct' as const,
71
- label: 'Actualizaciones del producto',
72
- description: 'Nuevas funcionalidades, mejoras y fixes importantes.',
73
- badge: null,
74
- },
75
- {
76
- key: 'emailMarketing' as const,
77
- label: 'Marketing y promociones',
78
- description: 'Ofertas, descuentos y contenido educativo.',
79
- badge: null,
80
- },
81
- ].map(({ key, label, description, badge }) => (
82
- <div key={key} className="flex items-start justify-between gap-4">
83
- <div className="space-y-0.5">
84
- <div className="flex items-center gap-2">
85
- <Label className="text-sm font-medium">{label}</Label>
86
- {badge && <Badge variant="secondary" className="text-xs">{badge}</Badge>}
87
- </div>
88
- <p className="text-xs text-muted-foreground">{description}</p>
89
- </div>
90
- <Switch
91
- checked={notifications[key]}
92
- onCheckedChange={() => toggleNotification(key)}
93
- />
94
- </div>
95
- ))}
96
- </CardContent>
97
- </Card>
98
-
99
- {/* Workspace */}
100
- <Card>
101
- <CardHeader>
102
- <CardTitle>Workspace</CardTitle>
103
- <CardDescription>Configuración de tu espacio de trabajo.</CardDescription>
104
- </CardHeader>
105
- <CardContent className="space-y-4">
106
- <div className="flex items-start justify-between gap-4">
107
- <div className="space-y-0.5">
108
- <Label className="text-sm font-medium">Perfil público</Label>
109
- <p className="text-xs text-muted-foreground">
110
- Permite que otros usuarios encuentren tu perfil.
111
- </p>
112
- </div>
113
- <Switch
114
- checked={workspace.publicProfile}
115
- onCheckedChange={() => toggleWorkspace('publicProfile')}
116
- />
117
- </div>
118
-
119
- <Separator />
120
-
121
- <div className="flex items-start justify-between gap-4">
122
- <div className="space-y-0.5">
123
- <Label className="text-sm font-medium">Invitaciones de equipo</Label>
124
- <p className="text-xs text-muted-foreground">
125
- Permite que otros te inviten a sus workspaces.
126
- </p>
127
- </div>
128
- <Switch
129
- checked={workspace.allowInvites}
130
- onCheckedChange={() => toggleWorkspace('allowInvites')}
131
- />
132
- </div>
133
- </CardContent>
134
- </Card>
135
-
136
- {/* Danger zone */}
137
- <Card className="border-destructive/40">
138
- <CardHeader>
139
- <CardTitle className="text-destructive">Zona peligrosa</CardTitle>
140
- <CardDescription>Acciones irreversibles sobre tu cuenta.</CardDescription>
141
- </CardHeader>
142
- <CardContent className="space-y-3">
143
- <div className="flex items-center justify-between">
144
- <div>
145
- <p className="text-sm font-medium">Exportar mis datos</p>
146
- <p className="text-xs text-muted-foreground">Descargá toda tu información en formato JSON.</p>
147
- </div>
148
- <Button variant="outline" size="sm" disabled>Exportar</Button>
149
- </div>
150
- </CardContent>
151
- </Card>
152
-
153
- <Button onClick={handleSave}>{saved ? 'Guardado' : 'Guardar ajustes'}</Button>
154
- </div>
155
- )
156
- }
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
5
+ import { Switch } from '@/components/ui/switch'
6
+ import { Separator } from '@/components/ui/separator'
7
+ import { Button } from '@/components/ui/button'
8
+ import { Label } from '@/components/ui/label'
9
+ import { Badge } from '@/components/ui/badge'
10
+
11
+ interface NotificationSettings {
12
+ emailMarketing: boolean
13
+ emailProduct: boolean
14
+ emailSecurity: boolean
15
+ pushAll: boolean
16
+ }
17
+
18
+ interface WorkspaceSettings {
19
+ publicProfile: boolean
20
+ allowInvites: boolean
21
+ }
22
+
23
+ export default function SettingsPage() {
24
+ const [notifications, setNotifications] = useState<NotificationSettings>({
25
+ emailMarketing: false,
26
+ emailProduct: true,
27
+ emailSecurity: true,
28
+ pushAll: false,
29
+ })
30
+
31
+ const [workspace, setWorkspace] = useState<WorkspaceSettings>({
32
+ publicProfile: false,
33
+ allowInvites: true,
34
+ })
35
+
36
+ const [saved, setSaved] = useState(false)
37
+
38
+ function toggleNotification(key: keyof NotificationSettings) {
39
+ setNotifications((prev) => ({ ...prev, [key]: !prev[key] }))
40
+ }
41
+
42
+ function toggleWorkspace(key: keyof WorkspaceSettings) {
43
+ setWorkspace((prev) => ({ ...prev, [key]: !prev[key] }))
44
+ }
45
+
46
+ function handleSave() {
47
+ // TODO: llamar a PATCH /users/me/settings con notifications y workspace
48
+ console.log('Guardar ajustes:', { notifications, workspace })
49
+ setSaved(true)
50
+ setTimeout(() => setSaved(false), 2000)
51
+ }
52
+
53
+ return (
54
+ <div className="max-w-2xl space-y-6">
55
+ {/* Notificaciones */}
56
+ <Card>
57
+ <CardHeader>
58
+ <CardTitle>Notificaciones por email</CardTitle>
59
+ <CardDescription>Elegí qué correos querés recibir de nuestra parte.</CardDescription>
60
+ </CardHeader>
61
+ <CardContent className="space-y-4">
62
+ {[
63
+ {
64
+ key: 'emailSecurity' as const,
65
+ label: 'Seguridad',
66
+ description: 'Alertas de inicio de sesión y cambios de contraseña.',
67
+ badge: 'Recomendado',
68
+ },
69
+ {
70
+ key: 'emailProduct' as const,
71
+ label: 'Actualizaciones del producto',
72
+ description: 'Nuevas funcionalidades, mejoras y fixes importantes.',
73
+ badge: null,
74
+ },
75
+ {
76
+ key: 'emailMarketing' as const,
77
+ label: 'Marketing y promociones',
78
+ description: 'Ofertas, descuentos y contenido educativo.',
79
+ badge: null,
80
+ },
81
+ ].map(({ key, label, description, badge }) => (
82
+ <div key={key} className="flex items-start justify-between gap-4">
83
+ <div className="space-y-0.5">
84
+ <div className="flex items-center gap-2">
85
+ <Label className="text-sm font-medium">{label}</Label>
86
+ {badge && <Badge variant="secondary" className="text-xs">{badge}</Badge>}
87
+ </div>
88
+ <p className="text-xs text-muted-foreground">{description}</p>
89
+ </div>
90
+ <Switch
91
+ checked={notifications[key]}
92
+ onCheckedChange={() => toggleNotification(key)}
93
+ />
94
+ </div>
95
+ ))}
96
+ </CardContent>
97
+ </Card>
98
+
99
+ {/* Workspace */}
100
+ <Card>
101
+ <CardHeader>
102
+ <CardTitle>Workspace</CardTitle>
103
+ <CardDescription>Configuración de tu espacio de trabajo.</CardDescription>
104
+ </CardHeader>
105
+ <CardContent className="space-y-4">
106
+ <div className="flex items-start justify-between gap-4">
107
+ <div className="space-y-0.5">
108
+ <Label className="text-sm font-medium">Perfil público</Label>
109
+ <p className="text-xs text-muted-foreground">
110
+ Permite que otros usuarios encuentren tu perfil.
111
+ </p>
112
+ </div>
113
+ <Switch
114
+ checked={workspace.publicProfile}
115
+ onCheckedChange={() => toggleWorkspace('publicProfile')}
116
+ />
117
+ </div>
118
+
119
+ <Separator />
120
+
121
+ <div className="flex items-start justify-between gap-4">
122
+ <div className="space-y-0.5">
123
+ <Label className="text-sm font-medium">Invitaciones de equipo</Label>
124
+ <p className="text-xs text-muted-foreground">
125
+ Permite que otros te inviten a sus workspaces.
126
+ </p>
127
+ </div>
128
+ <Switch
129
+ checked={workspace.allowInvites}
130
+ onCheckedChange={() => toggleWorkspace('allowInvites')}
131
+ />
132
+ </div>
133
+ </CardContent>
134
+ </Card>
135
+
136
+ {/* Danger zone */}
137
+ <Card className="border-destructive/40">
138
+ <CardHeader>
139
+ <CardTitle className="text-destructive">Zona peligrosa</CardTitle>
140
+ <CardDescription>Acciones irreversibles sobre tu cuenta.</CardDescription>
141
+ </CardHeader>
142
+ <CardContent className="space-y-3">
143
+ <div className="flex items-center justify-between">
144
+ <div>
145
+ <p className="text-sm font-medium">Exportar mis datos</p>
146
+ <p className="text-xs text-muted-foreground">Descargá toda tu información en formato JSON.</p>
147
+ </div>
148
+ <Button variant="outline" size="sm" disabled>Exportar</Button>
149
+ </div>
150
+ </CardContent>
151
+ </Card>
152
+
153
+ <Button onClick={handleSave}>{saved ? 'Guardado' : 'Guardar ajustes'}</Button>
154
+ </div>
155
+ )
156
+ }