create-varity-app 2.0.0-beta.16 → 2.0.0-beta.17
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 +1 -1
- package/template/.turbo/turbo-build.log +9 -0
- package/template/KNOWN_ISSUES.md +1 -1
- package/template/next.config.js +3 -9
- package/template/package.json +2 -1
- package/template/src/app/dashboard/layout.tsx +12 -8
- package/template/src/app/dashboard/page.tsx +7 -5
- package/template/src/app/dashboard/projects/page.tsx +4 -4
- package/template/src/app/dashboard/tasks/page.tsx +4 -4
- package/template/src/app/dashboard/team/page.tsx +4 -4
- package/template/src/app/layout.tsx +7 -10
- package/template/src/app/login/page.tsx +8 -9
- package/template/src/app/not-found.tsx +2 -0
- package/template/src/app/page.tsx +2 -1
- package/template/src/components/dashboard/RecentActivity.tsx +2 -1
- package/template/src/components/landing/Pricing.tsx +9 -10
- package/template/src/components/shared/Navbar.tsx +2 -0
- package/template/src/lib/constants.ts +1 -1
- package/template/src/lib/hooks.ts +4 -16
- package/template/varity.config.json +1 -1
package/package.json
CHANGED
|
@@ -2,5 +2,14 @@
|
|
|
2
2
|
> my-saas-app@0.1.0 build /home/macoding/varity-workspace/varity-sdk-private/templates/saas-starter
|
|
3
3
|
> next build
|
|
4
4
|
|
|
5
|
+
⚠ Warning: Next.js inferred your workspace root, but it may not be correct.
|
|
6
|
+
We detected multiple lockfiles and selected the directory of /home/macoding/varity-workspace/package-lock.json as the root directory.
|
|
7
|
+
To silence this warning, set `outputFileTracingRoot` in your Next.js config, or consider removing one of the lockfiles if it's not needed.
|
|
8
|
+
See https://nextjs.org/docs/app/api-reference/config/next-config-js/output#caveats for more information.
|
|
9
|
+
Detected additional lockfiles:
|
|
10
|
+
* /home/macoding/varity-workspace/varity-sdk-private/pnpm-lock.yaml
|
|
11
|
+
|
|
5
12
|
▲ Next.js 15.5.11
|
|
6
13
|
|
|
14
|
+
Creating an optimized production build ...
|
|
15
|
+
⚠ Mismatching @next/swc version, detected: 15.5.7 while Next.js is on 15.5.11. Please ensure these match
|
package/template/KNOWN_ISSUES.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
| Settings | Working | 4 tabs with backend persistence via DB Proxy |
|
|
18
18
|
| Command Palette | Working | Cmd+K / Ctrl+K |
|
|
19
19
|
| Color Themes | Working | 4 presets (Blue, Purple, Green, Orange) |
|
|
20
|
-
| Static Export | Working | `output: 'export'` for
|
|
20
|
+
| Static Export | Working | `output: 'export'` for static hosting (global CDN) |
|
|
21
21
|
| Mobile Nav | Working | Responsive sidebar with hamburger menu |
|
|
22
22
|
|
|
23
23
|
## Known Issues
|
package/template/next.config.js
CHANGED
|
@@ -5,15 +5,9 @@ const nextConfig = {
|
|
|
5
5
|
trailingSlash: true,
|
|
6
6
|
productionBrowserSourceMaps: false,
|
|
7
7
|
webpack: (config, { isServer, dev }) => {
|
|
8
|
-
// Suppress
|
|
9
|
-
config.resolve.
|
|
10
|
-
|
|
11
|
-
'@react-native-async-storage/async-storage': false,
|
|
12
|
-
};
|
|
13
|
-
// Force production devtool to avoid 35MB eval-source-map chunks
|
|
14
|
-
if (!dev && !isServer) {
|
|
15
|
-
config.devtool = false;
|
|
16
|
-
}
|
|
8
|
+
// Suppress unused optional peer dependencies from UI Kit internals
|
|
9
|
+
['@react-native-async-storage/async-storage', '@solana/kit', '@solana/sysvars', '@solana-program/token-2022', 'x402', '@coinbase/wallet-sdk', '@walletconnect/ethereum-provider'].forEach(pkg => { config.resolve.alias[pkg] = false; });
|
|
10
|
+
if (!dev && !isServer) config.devtool = false;
|
|
17
11
|
return config;
|
|
18
12
|
},
|
|
19
13
|
};
|
package/template/package.json
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"test:e2e:ui": "playwright test --ui",
|
|
14
14
|
"test:e2e:headed": "playwright test --headed",
|
|
15
15
|
"test:e2e:debug": "playwright test --debug",
|
|
16
|
-
"prepare": "husky install"
|
|
16
|
+
"prepare": "husky install",
|
|
17
|
+
"deploy": "varitykit app deploy"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"@varity-labs/sdk": "workspace:^",
|
|
@@ -7,7 +7,11 @@ import { useProjects, useTasks, useTeam } from '@/lib/hooks';
|
|
|
7
7
|
import { CommandPalette } from '@varity-labs/ui-kit';
|
|
8
8
|
import { Menu, X } from 'lucide-react';
|
|
9
9
|
|
|
10
|
-
//
|
|
10
|
+
// Defensively import Privy/UI-Kit components at runtime (not statically) so the
|
|
11
|
+
// dashboard renders gracefully even if @varity-labs/ui-kit hasn't been installed
|
|
12
|
+
// yet (e.g. during local scaffolding before `npm install` completes).
|
|
13
|
+
// This is intentional — it is NOT a sign that something is broken.
|
|
14
|
+
// See KNOWN_ISSUES.md for details on this pattern.
|
|
11
15
|
let DashboardLayout: any = null;
|
|
12
16
|
let PrivyProtectedRoute: any = null;
|
|
13
17
|
let PrivyStackComponent: any = null;
|
|
@@ -19,7 +23,9 @@ try {
|
|
|
19
23
|
PrivyProtectedRoute = uiKit.PrivyProtectedRoute;
|
|
20
24
|
PrivyStackComponent = uiKit.PrivyStack;
|
|
21
25
|
usePrivyHook = uiKit.usePrivy;
|
|
22
|
-
} catch {
|
|
26
|
+
} catch {
|
|
27
|
+
// ui-kit not installed or not yet available — DashboardShell fallback renders below
|
|
28
|
+
}
|
|
23
29
|
|
|
24
30
|
function RedirectToLogin() {
|
|
25
31
|
const router = useRouter();
|
|
@@ -113,8 +119,8 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
113
119
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
|
|
114
120
|
const privy = usePrivyHook ? usePrivyHook() : { user: null, logout: async () => {} };
|
|
115
121
|
const { user, logout } = privy;
|
|
116
|
-
const router = useRouter();
|
|
117
122
|
const pathname = usePathname();
|
|
123
|
+
const router = useRouter();
|
|
118
124
|
const isMobile = useIsMobile();
|
|
119
125
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
120
126
|
const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
|
|
@@ -154,7 +160,7 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
154
160
|
|
|
155
161
|
const handleLogout = async () => {
|
|
156
162
|
await logout();
|
|
157
|
-
|
|
163
|
+
router.push('/');
|
|
158
164
|
};
|
|
159
165
|
|
|
160
166
|
// Fallback layout when DashboardLayout from ui-kit isn't available
|
|
@@ -255,9 +261,8 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
255
261
|
showSidebar={!isMobile}
|
|
256
262
|
user={{
|
|
257
263
|
name: userName,
|
|
258
|
-
|
|
264
|
+
email: userEmail,
|
|
259
265
|
}}
|
|
260
|
-
onNavigate={(path: string) => router.push(path)}
|
|
261
266
|
onLogout={handleLogout}
|
|
262
267
|
onNavigateToProfile={() => router.push('/dashboard/settings')}
|
|
263
268
|
onNavigateToSettings={() => router.push('/dashboard/settings')}
|
|
@@ -287,9 +292,8 @@ export default function DashboardRootLayout({
|
|
|
287
292
|
return (
|
|
288
293
|
<PrivyStackComponent
|
|
289
294
|
appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}
|
|
290
|
-
thirdwebClientId={process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID}
|
|
291
295
|
loginMethods={['email', 'google']}
|
|
292
|
-
appearance={{ theme: 'light', accentColor: '#2563EB' }}
|
|
296
|
+
appearance={{ theme: 'light', accentColor: '#2563EB', logo: '/logo.svg' }}
|
|
293
297
|
>
|
|
294
298
|
<PrivyProtectedRoute fallback={<RedirectToLogin />}>
|
|
295
299
|
<DashboardShell>{children}</DashboardShell>
|
|
@@ -9,6 +9,7 @@ import { FolderKanban, ListTodo, Users, ArrowRight } from 'lucide-react';
|
|
|
9
9
|
|
|
10
10
|
function QuickActions() {
|
|
11
11
|
const router = useRouter();
|
|
12
|
+
|
|
12
13
|
const actions = [
|
|
13
14
|
{
|
|
14
15
|
label: 'New Project',
|
|
@@ -137,6 +138,7 @@ function GettingStarted({
|
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
export default function DashboardPage() {
|
|
141
|
+
const router = useRouter();
|
|
140
142
|
const { name } = useCurrentUser();
|
|
141
143
|
const { data: projects, loading: projectsLoading, error: projectsError, refresh: refreshProjects } = useProjects();
|
|
142
144
|
const { data: tasks, loading: tasksLoading, error: tasksError, refresh: refreshTasks } = useTasks();
|
|
@@ -161,14 +163,14 @@ export default function DashboardPage() {
|
|
|
161
163
|
</p>
|
|
162
164
|
</div>
|
|
163
165
|
|
|
164
|
-
{error &&
|
|
165
|
-
<div className="flex items-center justify-between rounded-lg border border-
|
|
166
|
-
<p className="text-sm text-
|
|
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>
|
|
167
169
|
<button
|
|
168
170
|
onClick={() => { refreshProjects(); refreshTasks(); refreshTeam(); }}
|
|
169
|
-
className="text-sm font-medium text-
|
|
171
|
+
className="text-sm font-medium text-red-700 hover:text-red-800 underline"
|
|
170
172
|
>
|
|
171
|
-
|
|
173
|
+
Retry
|
|
172
174
|
</button>
|
|
173
175
|
</div>
|
|
174
176
|
)}
|
|
@@ -606,10 +606,10 @@ export default function ProjectsPage() {
|
|
|
606
606
|
</div>
|
|
607
607
|
</Dialog>
|
|
608
608
|
|
|
609
|
-
{error &&
|
|
610
|
-
<div className="flex items-center justify-between rounded-lg border border-
|
|
611
|
-
<p className="text-sm text-
|
|
612
|
-
<button onClick={refresh} className="text-sm font-medium text-
|
|
609
|
+
{error && (
|
|
610
|
+
<div className="flex items-center justify-between rounded-lg border border-red-200 bg-red-50 px-4 py-3">
|
|
611
|
+
<p className="text-sm text-red-700">Failed to load projects. Please check your connection and try again.</p>
|
|
612
|
+
<button onClick={refresh} className="text-sm font-medium text-red-700 hover:text-red-800 underline">Retry</button>
|
|
613
613
|
</div>
|
|
614
614
|
)}
|
|
615
615
|
|
|
@@ -258,10 +258,10 @@ export default function TasksPage() {
|
|
|
258
258
|
)}
|
|
259
259
|
</div>
|
|
260
260
|
|
|
261
|
-
{error &&
|
|
262
|
-
<div className="flex items-center justify-between rounded-lg border border-
|
|
263
|
-
<p className="text-sm text-
|
|
264
|
-
<button onClick={refresh} className="text-sm font-medium text-
|
|
261
|
+
{error && (
|
|
262
|
+
<div className="flex items-center justify-between rounded-lg border border-red-200 bg-red-50 px-4 py-3">
|
|
263
|
+
<p className="text-sm text-red-700">Failed to load tasks. Please check your connection and try again.</p>
|
|
264
|
+
<button onClick={refresh} className="text-sm font-medium text-red-700 hover:text-red-800 underline">Retry</button>
|
|
265
265
|
</div>
|
|
266
266
|
)}
|
|
267
267
|
|
|
@@ -246,10 +246,10 @@ export default function TeamPage() {
|
|
|
246
246
|
loading={removeSubmitting}
|
|
247
247
|
/>
|
|
248
248
|
|
|
249
|
-
{error &&
|
|
250
|
-
<div className="flex items-center justify-between rounded-lg border border-
|
|
251
|
-
<p className="text-sm text-
|
|
252
|
-
<button onClick={refresh} className="text-sm font-medium text-
|
|
249
|
+
{error && (
|
|
250
|
+
<div className="flex items-center justify-between rounded-lg border border-red-200 bg-red-50 px-4 py-3">
|
|
251
|
+
<p className="text-sm text-red-700">Failed to load team data. Please check your connection and try again.</p>
|
|
252
|
+
<button onClick={refresh} className="text-sm font-medium text-red-700 hover:text-red-800 underline">Retry</button>
|
|
253
253
|
</div>
|
|
254
254
|
)}
|
|
255
255
|
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import type { Metadata } from 'next';
|
|
2
2
|
import { Providers } from '@/components/providers';
|
|
3
|
-
import { APP_NAME } from '@/lib/constants';
|
|
4
3
|
import './globals.css';
|
|
5
4
|
|
|
6
|
-
const description = 'Built with Varity — auth, database, and deployment included.';
|
|
7
|
-
|
|
8
5
|
export const metadata: Metadata = {
|
|
9
|
-
title:
|
|
10
|
-
description,
|
|
11
|
-
metadataBase: new URL('https://
|
|
6
|
+
title: 'TaskFlow - Project Management',
|
|
7
|
+
description: 'Manage projects, track tasks, and collaborate with your team.',
|
|
8
|
+
metadataBase: new URL('https://example.com'),
|
|
12
9
|
openGraph: {
|
|
13
|
-
title:
|
|
14
|
-
description,
|
|
10
|
+
title: 'TaskFlow - Project Management',
|
|
11
|
+
description: 'Manage projects, track tasks, and collaborate with your team.',
|
|
15
12
|
type: 'website',
|
|
16
13
|
},
|
|
17
14
|
twitter: {
|
|
18
15
|
card: 'summary',
|
|
19
|
-
title:
|
|
20
|
-
description,
|
|
16
|
+
title: 'TaskFlow - Project Management',
|
|
17
|
+
description: 'Manage projects, track tasks, and collaborate with your team.',
|
|
21
18
|
},
|
|
22
19
|
};
|
|
23
20
|
|
|
@@ -15,12 +15,6 @@ try {
|
|
|
15
15
|
usePrivyHook = uiKit.usePrivy;
|
|
16
16
|
} catch {}
|
|
17
17
|
|
|
18
|
-
function loginButtonLabel(privy: { ready: boolean; authenticated: boolean }): string {
|
|
19
|
-
if (!privy.ready) return 'Loading...';
|
|
20
|
-
if (privy.authenticated) return 'Already Signed In';
|
|
21
|
-
return 'Sign In with Email or Social';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
18
|
function LoginContent() {
|
|
25
19
|
const router = useRouter();
|
|
26
20
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
|
|
@@ -61,7 +55,11 @@ function LoginContent() {
|
|
|
61
55
|
disabled={!privy.ready || privy.authenticated}
|
|
62
56
|
className="w-full px-6 py-3 bg-primary-600 hover:bg-primary-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors shadow-sm"
|
|
63
57
|
>
|
|
64
|
-
{
|
|
58
|
+
{!privy.ready
|
|
59
|
+
? 'Loading...'
|
|
60
|
+
: privy.authenticated
|
|
61
|
+
? 'Already Signed In'
|
|
62
|
+
: 'Sign In with Email or Social'}
|
|
65
63
|
</button>
|
|
66
64
|
) : (
|
|
67
65
|
<div className="text-center space-y-4">
|
|
@@ -81,18 +79,19 @@ function LoginContent() {
|
|
|
81
79
|
}
|
|
82
80
|
|
|
83
81
|
export default function LoginPage() {
|
|
82
|
+
// Always wrap in PrivyStack - it uses dev credentials automatically when no appId is provided
|
|
84
83
|
if (PrivyStackComponent) {
|
|
85
84
|
return (
|
|
86
85
|
<PrivyStackComponent
|
|
87
86
|
appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}
|
|
88
|
-
thirdwebClientId={process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID}
|
|
89
87
|
loginMethods={['email', 'google']}
|
|
90
|
-
appearance={{ theme: 'light', accentColor: '#2563EB' }}
|
|
88
|
+
appearance={{ theme: 'light', accentColor: '#2563EB', logo: '/logo.svg' }}
|
|
91
89
|
>
|
|
92
90
|
<LoginContent />
|
|
93
91
|
</PrivyStackComponent>
|
|
94
92
|
);
|
|
95
93
|
}
|
|
96
94
|
|
|
95
|
+
// Fallback if ui-kit package isn't installed
|
|
97
96
|
return <LoginContent />;
|
|
98
97
|
}
|
|
@@ -2,6 +2,7 @@ import { Navbar } from '@/components/shared/Navbar';
|
|
|
2
2
|
import { Hero } from '@/components/landing/Hero';
|
|
3
3
|
import { Features } from '@/components/landing/Features';
|
|
4
4
|
import { HowItWorks } from '@/components/landing/HowItWorks';
|
|
5
|
+
import { Testimonials } from '@/components/landing/Testimonials';
|
|
5
6
|
import { Pricing } from '@/components/landing/Pricing';
|
|
6
7
|
import { CTA } from '@/components/landing/CTA';
|
|
7
8
|
import { Footer } from '@/components/shared/Footer';
|
|
@@ -13,7 +14,7 @@ export default function HomePage() {
|
|
|
13
14
|
<Hero />
|
|
14
15
|
<Features />
|
|
15
16
|
<HowItWorks />
|
|
16
|
-
|
|
17
|
+
<Testimonials />
|
|
17
18
|
<Pricing />
|
|
18
19
|
<CTA />
|
|
19
20
|
<Footer />
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import Link from 'next/link';
|
|
4
|
-
import { DataTable
|
|
4
|
+
import { DataTable } from '@varity-labs/ui-kit';
|
|
5
|
+
import { TaskStatusBadge, PriorityBadge } from '@varity-labs/ui-kit';
|
|
5
6
|
import { formatRelativeDate } from '@/lib/utils';
|
|
6
7
|
import { ArrowRight } from 'lucide-react';
|
|
7
8
|
import type { Task } from '@/types';
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Link from 'next/link';
|
|
2
1
|
import { Check } from 'lucide-react';
|
|
3
2
|
|
|
4
3
|
const plans = [
|
|
@@ -53,12 +52,6 @@ const plans = [
|
|
|
53
52
|
},
|
|
54
53
|
];
|
|
55
54
|
|
|
56
|
-
function buttonStyle(plan: (typeof plans)[number]): string {
|
|
57
|
-
if (plan.popular) return 'bg-primary-600 text-white hover:bg-primary-700';
|
|
58
|
-
if (plan.price === 0) return 'bg-gray-100 text-gray-900 hover:bg-gray-200';
|
|
59
|
-
return 'bg-gray-900 text-white hover:bg-gray-800';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
55
|
export function Pricing() {
|
|
63
56
|
return (
|
|
64
57
|
<section id="pricing" className="py-24 bg-white">
|
|
@@ -109,12 +102,18 @@ export function Pricing() {
|
|
|
109
102
|
</ul>
|
|
110
103
|
|
|
111
104
|
<div className="mt-8">
|
|
112
|
-
<
|
|
105
|
+
<a
|
|
113
106
|
href="/login"
|
|
114
|
-
className={`block w-full rounded-lg py-3 text-center font-medium transition-colors ${
|
|
107
|
+
className={`block w-full rounded-lg py-3 text-center font-medium transition-colors ${
|
|
108
|
+
plan.popular
|
|
109
|
+
? 'bg-primary-600 text-white hover:bg-primary-700'
|
|
110
|
+
: plan.price === 0
|
|
111
|
+
? 'bg-gray-100 text-gray-900 hover:bg-gray-200'
|
|
112
|
+
: 'bg-gray-900 text-white hover:bg-gray-800'
|
|
113
|
+
}`}
|
|
115
114
|
>
|
|
116
115
|
{plan.cta}
|
|
117
|
-
</
|
|
116
|
+
</a>
|
|
118
117
|
</div>
|
|
119
118
|
</div>
|
|
120
119
|
))}
|
|
@@ -46,6 +46,7 @@ export function Navbar() {
|
|
|
46
46
|
>
|
|
47
47
|
Get Started
|
|
48
48
|
</Link>
|
|
49
|
+
{/* Mobile menu toggle */}
|
|
49
50
|
<button
|
|
50
51
|
onClick={() => setMobileOpen(!mobileOpen)}
|
|
51
52
|
className="rounded-lg p-2 text-gray-600 hover:bg-gray-100 sm:hidden"
|
|
@@ -57,6 +58,7 @@ export function Navbar() {
|
|
|
57
58
|
</div>
|
|
58
59
|
</div>
|
|
59
60
|
|
|
61
|
+
{/* Mobile dropdown */}
|
|
60
62
|
{mobileOpen && (
|
|
61
63
|
<div className="border-t border-gray-100 bg-white px-4 pb-4 pt-2 sm:hidden">
|
|
62
64
|
<div className="space-y-1">
|
|
@@ -10,18 +10,6 @@ try {
|
|
|
10
10
|
usePrivyHook = uiKit.usePrivy;
|
|
11
11
|
} catch {}
|
|
12
12
|
|
|
13
|
-
async function fetchWithRetry<T>(fn: () => Promise<T>, retries = 3, delay = 1500): Promise<T> {
|
|
14
|
-
for (let i = 0; i < retries; i++) {
|
|
15
|
-
try {
|
|
16
|
-
return await fn();
|
|
17
|
-
} catch (err) {
|
|
18
|
-
if (i === retries - 1) throw err;
|
|
19
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
throw new Error('Unexpected');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
13
|
export function useCurrentUser() {
|
|
26
14
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
|
|
27
15
|
const privy = usePrivyHook ? usePrivyHook() : { user: null, authenticated: false, logout: async () => {} };
|
|
@@ -66,7 +54,7 @@ export function useProjects(): UseCollectionReturn<Project> {
|
|
|
66
54
|
try {
|
|
67
55
|
setLoading(true);
|
|
68
56
|
setError(null);
|
|
69
|
-
const result = await
|
|
57
|
+
const result = await projects().get();
|
|
70
58
|
setData(result as Project[]);
|
|
71
59
|
} catch (err) {
|
|
72
60
|
setError(err instanceof Error ? err.message : 'Failed to load projects');
|
|
@@ -138,7 +126,7 @@ export function useTasks(projectId?: string): UseCollectionReturn<Task> {
|
|
|
138
126
|
try {
|
|
139
127
|
setLoading(true);
|
|
140
128
|
setError(null);
|
|
141
|
-
const result = await
|
|
129
|
+
const result = await tasks().get();
|
|
142
130
|
setAllTasks(result as Task[]);
|
|
143
131
|
} catch (err) {
|
|
144
132
|
setError(err instanceof Error ? err.message : 'Failed to load tasks');
|
|
@@ -214,7 +202,7 @@ export function useTeam(): UseCollectionReturn<TeamMember> {
|
|
|
214
202
|
try {
|
|
215
203
|
setLoading(true);
|
|
216
204
|
setError(null);
|
|
217
|
-
const result = await
|
|
205
|
+
const result = await teamMembers().get();
|
|
218
206
|
setData(result as TeamMember[]);
|
|
219
207
|
} catch (err) {
|
|
220
208
|
setError(err instanceof Error ? err.message : 'Failed to load team');
|
|
@@ -301,7 +289,7 @@ export function useUserSettings() {
|
|
|
301
289
|
try {
|
|
302
290
|
setLoading(true);
|
|
303
291
|
setError(null);
|
|
304
|
-
const all = await
|
|
292
|
+
const all = await userSettings().get();
|
|
305
293
|
const mine = (all as UserSettings[]).find((s) => s.user_id === userId);
|
|
306
294
|
if (mine) {
|
|
307
295
|
setSettings(mine);
|