create-varity-app 2.0.0-beta.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +85 -0
  3. package/dist/create.js +141 -0
  4. package/dist/index.js +45 -0
  5. package/dist/utils.js +29 -0
  6. package/package.json +61 -0
  7. package/template/.env.example +17 -0
  8. package/template/KNOWN_ISSUES.md +69 -0
  9. package/template/LICENSE +21 -0
  10. package/template/README.md +241 -0
  11. package/template/gitignore +42 -0
  12. package/template/next-env.d.ts +6 -0
  13. package/template/next.config.js +21 -0
  14. package/template/package.json +39 -0
  15. package/template/postcss.config.js +6 -0
  16. package/template/public/logo.svg +4 -0
  17. package/template/public/robots.txt +4 -0
  18. package/template/public/sitemap.xml +4 -0
  19. package/template/src/app/dashboard/layout.tsx +298 -0
  20. package/template/src/app/dashboard/page.tsx +209 -0
  21. package/template/src/app/dashboard/projects/page.tsx +638 -0
  22. package/template/src/app/dashboard/settings/page.tsx +749 -0
  23. package/template/src/app/dashboard/tasks/page.tsx +301 -0
  24. package/template/src/app/dashboard/team/page.tsx +295 -0
  25. package/template/src/app/globals.css +177 -0
  26. package/template/src/app/icon.svg +4 -0
  27. package/template/src/app/layout.tsx +33 -0
  28. package/template/src/app/login/page.tsx +98 -0
  29. package/template/src/app/not-found.tsx +20 -0
  30. package/template/src/app/page.tsx +23 -0
  31. package/template/src/components/dashboard/DashboardStats.tsx +137 -0
  32. package/template/src/components/dashboard/RecentActivity.tsx +63 -0
  33. package/template/src/components/landing/CTA.tsx +42 -0
  34. package/template/src/components/landing/Features.tsx +116 -0
  35. package/template/src/components/landing/Hero.tsx +146 -0
  36. package/template/src/components/landing/HowItWorks.tsx +80 -0
  37. package/template/src/components/landing/Pricing.tsx +124 -0
  38. package/template/src/components/landing/Testimonials.tsx +78 -0
  39. package/template/src/components/providers.tsx +11 -0
  40. package/template/src/components/shared/Footer.tsx +71 -0
  41. package/template/src/components/shared/Navbar.tsx +87 -0
  42. package/template/src/lib/constants.ts +35 -0
  43. package/template/src/lib/database.ts +7 -0
  44. package/template/src/lib/hooks.ts +331 -0
  45. package/template/src/lib/utils.ts +68 -0
  46. package/template/src/lib/varity.ts +1 -0
  47. package/template/src/services/dashboardService.ts +589 -0
  48. package/template/src/types/index.ts +52 -0
  49. package/template/tailwind.config.js +27 -0
  50. package/template/tsconfig.json +23 -0
  51. package/template/varity.config.json +14 -0
@@ -0,0 +1,209 @@
1
+ 'use client';
2
+
3
+ import { useRouter } from 'next/navigation';
4
+ import { useProjects, useTasks, useTeam, useCurrentUser } from '@/lib/hooks';
5
+ import { DashboardStats } from '@/components/dashboard/DashboardStats';
6
+ import { RecentActivity } from '@/components/dashboard/RecentActivity';
7
+ import { APP_NAME } from '@/lib/constants';
8
+ import { FolderKanban, ListTodo, Users, ArrowRight } from 'lucide-react';
9
+
10
+ function QuickActions() {
11
+ const router = useRouter();
12
+
13
+ const actions = [
14
+ {
15
+ label: 'New Project',
16
+ description: 'Organize your work',
17
+ icon: 'folderKanban',
18
+ path: '/dashboard/projects',
19
+ color: 'bg-blue-50 text-blue-600',
20
+ },
21
+ {
22
+ label: 'View Tasks',
23
+ description: 'Track your progress',
24
+ icon: 'listTodo',
25
+ path: '/dashboard/tasks',
26
+ color: 'bg-amber-50 text-amber-600',
27
+ },
28
+ {
29
+ label: 'Invite Team',
30
+ description: 'Collaborate together',
31
+ icon: 'users',
32
+ path: '/dashboard/team',
33
+ color: 'bg-green-50 text-green-600',
34
+ },
35
+ ];
36
+
37
+ const getIcon = (name: string) => {
38
+ const className = "h-5 w-5";
39
+ switch (name) {
40
+ case 'folderKanban': return <FolderKanban className={className} />;
41
+ case 'listTodo': return <ListTodo className={className} />;
42
+ case 'users': return <Users className={className} />;
43
+ default: return null;
44
+ }
45
+ };
46
+
47
+ return (
48
+ <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
49
+ {actions.map((action) => (
50
+ <button
51
+ key={action.path}
52
+ onClick={() => router.push(action.path)}
53
+ className="flex items-center gap-3 rounded-xl border border-gray-200 bg-white p-4 text-left shadow-sm hover:shadow-md hover:border-gray-300 transition-all"
54
+ >
55
+ <div className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-lg ${action.color}`}>
56
+ {getIcon(action.icon)}
57
+ </div>
58
+ <div>
59
+ <p className="text-sm font-medium text-gray-900">{action.label}</p>
60
+ <p className="text-xs text-gray-500">{action.description}</p>
61
+ </div>
62
+ </button>
63
+ ))}
64
+ </div>
65
+ );
66
+ }
67
+
68
+ function GettingStarted({
69
+ hasProjects,
70
+ hasTasks,
71
+ hasTeam,
72
+ }: {
73
+ hasProjects: boolean;
74
+ hasTasks: boolean;
75
+ hasTeam: boolean;
76
+ }) {
77
+ const router = useRouter();
78
+ const completedCount = [hasProjects, hasTasks, hasTeam].filter(Boolean).length;
79
+
80
+ if (completedCount === 3) return null;
81
+
82
+ const steps = [
83
+ {
84
+ label: 'Create your first project',
85
+ done: hasProjects,
86
+ path: '/dashboard/projects',
87
+ },
88
+ {
89
+ label: 'Add a task to your project',
90
+ done: hasTasks,
91
+ path: '/dashboard/projects',
92
+ },
93
+ {
94
+ label: 'Invite a team member',
95
+ done: hasTeam,
96
+ path: '/dashboard/team',
97
+ },
98
+ ];
99
+
100
+ return (
101
+ <div className="rounded-xl border border-primary-200 bg-primary-50 p-5">
102
+ <div className="flex items-center justify-between mb-3">
103
+ <h3 className="text-sm font-semibold text-primary-900">Getting Started</h3>
104
+ <span className="text-xs font-medium text-primary-600">{completedCount}/3 complete</span>
105
+ </div>
106
+ <div className="h-1.5 rounded-full bg-primary-100 mb-4">
107
+ <div
108
+ className="h-1.5 rounded-full bg-primary-600 transition-all"
109
+ style={{ width: `${(completedCount / 3) * 100}%` }}
110
+ />
111
+ </div>
112
+ <div className="space-y-2">
113
+ {steps.map((step) => (
114
+ <button
115
+ key={step.label}
116
+ onClick={() => !step.done && router.push(step.path)}
117
+ disabled={step.done}
118
+ className={`flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors ${
119
+ step.done
120
+ ? 'text-primary-400'
121
+ : 'text-primary-800 hover:bg-primary-100'
122
+ }`}
123
+ >
124
+ <span className={`flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-xs font-bold ${
125
+ step.done
126
+ ? 'bg-primary-600 text-white'
127
+ : 'border-2 border-primary-300'
128
+ }`}>
129
+ {step.done ? '✓' : ''}
130
+ </span>
131
+ <span className={step.done ? 'line-through' : ''}>{step.label}</span>
132
+ {!step.done && <ArrowRight className="ml-auto h-4 w-4 opacity-50" />}
133
+ </button>
134
+ ))}
135
+ </div>
136
+ </div>
137
+ );
138
+ }
139
+
140
+ export default function DashboardPage() {
141
+ const router = useRouter();
142
+ const { name } = useCurrentUser();
143
+ const { data: projects, loading: projectsLoading, error: projectsError, refresh: refreshProjects } = useProjects();
144
+ const { data: tasks, loading: tasksLoading, error: tasksError, refresh: refreshTasks } = useTasks();
145
+ const { data: team, loading: teamLoading, error: teamError, refresh: refreshTeam } = useTeam();
146
+ const loading = projectsLoading || tasksLoading || teamLoading;
147
+ const error = projectsError || tasksError || teamError;
148
+ const hasProjects = projects.length > 0;
149
+ const hasTasks = tasks.length > 0;
150
+ const hasTeam = team.length > 0;
151
+ const hasData = hasProjects || hasTasks;
152
+
153
+ return (
154
+ <div className="space-y-6">
155
+ <div>
156
+ <h1 className="text-2xl font-bold text-gray-900">
157
+ {hasData ? 'Dashboard' : `Welcome, ${name || 'there'}`}
158
+ </h1>
159
+ <p className="mt-1 text-sm text-gray-600">
160
+ {hasData
161
+ ? 'Overview of your projects and tasks.'
162
+ : `Get started with ${APP_NAME} by creating your first project.`}
163
+ </p>
164
+ </div>
165
+
166
+ {error && (
167
+ <div className="flex items-center justify-between rounded-lg border border-red-200 bg-red-50 px-4 py-3">
168
+ <p className="text-sm text-red-700">Failed to load data. Please check your connection and try again.</p>
169
+ <button
170
+ onClick={() => { refreshProjects(); refreshTasks(); refreshTeam(); }}
171
+ className="text-sm font-medium text-red-700 hover:text-red-800 underline"
172
+ >
173
+ Retry
174
+ </button>
175
+ </div>
176
+ )}
177
+
178
+ <DashboardStats
179
+ projects={projects}
180
+ tasks={tasks}
181
+ team={team}
182
+ loading={loading}
183
+ />
184
+
185
+ {!loading && !hasData ? (
186
+ <div className="space-y-6">
187
+ <GettingStarted
188
+ hasProjects={hasProjects}
189
+ hasTasks={hasTasks}
190
+ hasTeam={hasTeam}
191
+ />
192
+ <QuickActions />
193
+ </div>
194
+ ) : (
195
+ <>
196
+ {!loading && (!hasProjects || !hasTasks || !hasTeam) && (
197
+ <GettingStarted
198
+ hasProjects={hasProjects}
199
+ hasTasks={hasTasks}
200
+ hasTeam={hasTeam}
201
+ />
202
+ )}
203
+ <QuickActions />
204
+ <RecentActivity tasks={tasks} loading={tasksLoading} />
205
+ </>
206
+ )}
207
+ </div>
208
+ );
209
+ }