@digilogiclabs/create-saas-app 1.4.0 → 1.5.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/CHANGELOG.md +42 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.js +45 -3
- package/dist/index.js.map +1 -1
- package/dist/templates/web/base/template/package.json +20 -10
- package/dist/templates/web/base/template/src/app/error.tsx +97 -0
- package/dist/templates/web/base/template/src/app/layout.tsx +8 -2
- package/dist/templates/web/base/template/src/app/loading.tsx +34 -0
- package/dist/templates/web/base/template/src/components/__tests__/example.test.tsx +49 -0
- package/dist/templates/web/base/template/src/components/providers/app-providers.tsx +6 -2
- package/dist/templates/web/base/template/src/components/providers/theme-provider.tsx +94 -0
- package/dist/templates/web/base/template/src/components/shared/footer.tsx +36 -0
- package/dist/templates/web/base/template/src/components/shared/header.tsx +2 -0
- package/dist/templates/web/base/template/src/components/ui/theme-toggle.tsx +34 -0
- package/dist/templates/web/base/template/src/lib/auth-server.ts +177 -0
- package/dist/templates/web/base/template/src/lib/env.ts +46 -0
- package/dist/templates/web/base/template/src/lib/utils.ts +133 -0
- package/dist/templates/web/base/template/src/test/setup.ts +79 -0
- package/dist/templates/web/base/template/vitest.config.ts +17 -0
- package/dist/templates/web/ui-auth/template/package.json +14 -4
- package/dist/templates/web/ui-auth/template/src/app/error.tsx +67 -0
- package/dist/templates/web/ui-auth/template/src/app/layout.tsx +6 -2
- package/dist/templates/web/ui-auth/template/src/app/loading.tsx +20 -0
- package/dist/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +49 -0
- package/dist/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +6 -2
- package/dist/templates/web/ui-auth/template/src/components/providers/theme-provider.tsx +94 -0
- package/dist/templates/web/ui-auth/template/src/components/shared/footer.tsx +36 -0
- package/dist/templates/web/ui-auth/template/src/components/shared/header.tsx +2 -0
- package/dist/templates/web/ui-auth/template/src/components/ui/theme-toggle.tsx +34 -0
- package/dist/templates/web/ui-auth/template/src/lib/env.ts +49 -0
- package/dist/templates/web/ui-auth/template/src/lib/utils.ts +133 -0
- package/dist/templates/web/ui-auth/template/src/test/setup.ts +79 -0
- package/dist/templates/web/ui-auth/template/vitest.config.ts +17 -0
- package/dist/templates/web/ui-auth-payments/template/middleware.ts +68 -0
- package/dist/templates/web/ui-auth-payments/template/package.json +14 -4
- package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/layout.tsx +22 -0
- package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +183 -0
- package/dist/templates/web/ui-auth-payments/template/src/app/error.tsx +67 -0
- package/dist/templates/web/ui-auth-payments/template/src/app/layout.tsx +6 -2
- package/dist/templates/web/ui-auth-payments/template/src/app/loading.tsx +20 -0
- package/dist/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +38 -0
- package/dist/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +50 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +49 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +52 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +144 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +68 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +185 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +6 -2
- package/dist/templates/web/ui-auth-payments/template/src/components/providers/theme-provider.tsx +94 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/shared/footer.tsx +36 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +2 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/ui/theme-toggle.tsx +34 -0
- package/dist/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +246 -0
- package/dist/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +340 -0
- package/dist/templates/web/ui-auth-payments/template/src/lib/auth-server.ts +177 -0
- package/dist/templates/web/ui-auth-payments/template/src/lib/env.ts +49 -0
- package/dist/templates/web/ui-auth-payments/template/src/lib/utils.ts +133 -0
- package/dist/templates/web/ui-auth-payments/template/src/test/setup.ts +79 -0
- package/dist/templates/web/ui-auth-payments/template/vitest.config.ts +17 -0
- package/dist/templates/web/ui-auth-payments-audio/template/package.json +14 -4
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/error.tsx +67 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +8 -2
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/loading.tsx +20 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +49 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +6 -2
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/providers/theme-provider.tsx +94 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/footer.tsx +36 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +2 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/ui/theme-toggle.tsx +34 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/lib/env.ts +49 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/lib/utils.ts +133 -0
- package/dist/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +79 -0
- package/dist/templates/web/ui-auth-payments-audio/template/vitest.config.ts +17 -0
- package/dist/templates/web/ui-auth-payments-video/template/package.json +14 -4
- package/dist/templates/web/ui-auth-payments-video/template/src/app/error.tsx +67 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +6 -2
- package/dist/templates/web/ui-auth-payments-video/template/src/app/loading.tsx +20 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +49 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +6 -2
- package/dist/templates/web/ui-auth-payments-video/template/src/components/providers/theme-provider.tsx +94 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/components/shared/footer.tsx +36 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +2 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/components/ui/theme-toggle.tsx +34 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/lib/env.ts +49 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/lib/utils.ts +133 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/test/setup.ts +79 -0
- package/dist/templates/web/ui-auth-payments-video/template/vitest.config.ts +17 -0
- package/dist/templates/web/ui-only/template/package.json +14 -4
- package/dist/templates/web/ui-only/template/src/app/error.tsx +67 -0
- package/dist/templates/web/ui-only/template/src/app/layout.tsx +6 -2
- package/dist/templates/web/ui-only/template/src/app/loading.tsx +20 -0
- package/dist/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +49 -0
- package/dist/templates/web/ui-only/template/src/components/providers/app-providers.tsx +6 -2
- package/dist/templates/web/ui-only/template/src/components/providers/theme-provider.tsx +94 -0
- package/dist/templates/web/ui-only/template/src/components/shared/footer.tsx +36 -0
- package/dist/templates/web/ui-only/template/src/components/shared/header.tsx +2 -0
- package/dist/templates/web/ui-only/template/src/components/ui/theme-toggle.tsx +34 -0
- package/dist/templates/web/ui-only/template/src/lib/env.ts +49 -0
- package/dist/templates/web/ui-only/template/src/lib/utils.ts +133 -0
- package/dist/templates/web/ui-only/template/src/test/setup.ts +79 -0
- package/dist/templates/web/ui-only/template/vitest.config.ts +17 -0
- package/package.json +1 -1
- package/src/templates/web/base/template/package.json +20 -10
- package/src/templates/web/base/template/src/app/error.tsx +97 -0
- package/src/templates/web/base/template/src/app/layout.tsx +8 -2
- package/src/templates/web/base/template/src/app/loading.tsx +34 -0
- package/src/templates/web/base/template/src/components/__tests__/example.test.tsx +49 -0
- package/src/templates/web/base/template/src/components/providers/app-providers.tsx +6 -2
- package/src/templates/web/base/template/src/components/providers/theme-provider.tsx +94 -0
- package/src/templates/web/base/template/src/components/shared/footer.tsx +36 -0
- package/src/templates/web/base/template/src/components/shared/header.tsx +2 -0
- package/src/templates/web/base/template/src/components/ui/theme-toggle.tsx +34 -0
- package/src/templates/web/base/template/src/lib/auth-server.ts +177 -0
- package/src/templates/web/base/template/src/lib/env.ts +46 -0
- package/src/templates/web/base/template/src/lib/utils.ts +133 -0
- package/src/templates/web/base/template/src/test/setup.ts +79 -0
- package/src/templates/web/base/template/vitest.config.ts +17 -0
- package/src/templates/web/ui-auth/template/package.json +14 -4
- package/src/templates/web/ui-auth/template/src/app/error.tsx +67 -0
- package/src/templates/web/ui-auth/template/src/app/layout.tsx +6 -2
- package/src/templates/web/ui-auth/template/src/app/loading.tsx +20 -0
- package/src/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +49 -0
- package/src/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +6 -2
- package/src/templates/web/ui-auth/template/src/components/providers/theme-provider.tsx +94 -0
- package/src/templates/web/ui-auth/template/src/components/shared/footer.tsx +36 -0
- package/src/templates/web/ui-auth/template/src/components/shared/header.tsx +2 -0
- package/src/templates/web/ui-auth/template/src/components/ui/theme-toggle.tsx +34 -0
- package/src/templates/web/ui-auth/template/src/lib/env.ts +49 -0
- package/src/templates/web/ui-auth/template/src/lib/utils.ts +133 -0
- package/src/templates/web/ui-auth/template/src/test/setup.ts +79 -0
- package/src/templates/web/ui-auth/template/vitest.config.ts +17 -0
- package/src/templates/web/ui-auth-payments/template/middleware.ts +68 -0
- package/src/templates/web/ui-auth-payments/template/package.json +14 -4
- package/src/templates/web/ui-auth-payments/template/src/app/dashboard/layout.tsx +22 -0
- package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +183 -0
- package/src/templates/web/ui-auth-payments/template/src/app/error.tsx +67 -0
- package/src/templates/web/ui-auth-payments/template/src/app/layout.tsx +6 -2
- package/src/templates/web/ui-auth-payments/template/src/app/loading.tsx +20 -0
- package/src/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +38 -0
- package/src/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +50 -0
- package/src/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +49 -0
- package/src/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +52 -0
- package/src/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +144 -0
- package/src/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +68 -0
- package/src/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +185 -0
- package/src/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +6 -2
- package/src/templates/web/ui-auth-payments/template/src/components/providers/theme-provider.tsx +94 -0
- package/src/templates/web/ui-auth-payments/template/src/components/shared/footer.tsx +36 -0
- package/src/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +2 -0
- package/src/templates/web/ui-auth-payments/template/src/components/ui/theme-toggle.tsx +34 -0
- package/src/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +246 -0
- package/src/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +340 -0
- package/src/templates/web/ui-auth-payments/template/src/lib/auth-server.ts +177 -0
- package/src/templates/web/ui-auth-payments/template/src/lib/env.ts +49 -0
- package/src/templates/web/ui-auth-payments/template/src/lib/utils.ts +133 -0
- package/src/templates/web/ui-auth-payments/template/src/test/setup.ts +79 -0
- package/src/templates/web/ui-auth-payments/template/vitest.config.ts +17 -0
- package/src/templates/web/ui-auth-payments-audio/template/package.json +14 -4
- package/src/templates/web/ui-auth-payments-audio/template/src/app/error.tsx +67 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +8 -2
- package/src/templates/web/ui-auth-payments-audio/template/src/app/loading.tsx +20 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +49 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +6 -2
- package/src/templates/web/ui-auth-payments-audio/template/src/components/providers/theme-provider.tsx +94 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/footer.tsx +36 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +2 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/components/ui/theme-toggle.tsx +34 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/lib/env.ts +49 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/lib/utils.ts +133 -0
- package/src/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +79 -0
- package/src/templates/web/ui-auth-payments-audio/template/vitest.config.ts +17 -0
- package/src/templates/web/ui-auth-payments-video/template/package.json +14 -4
- package/src/templates/web/ui-auth-payments-video/template/src/app/error.tsx +67 -0
- package/src/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +6 -2
- package/src/templates/web/ui-auth-payments-video/template/src/app/loading.tsx +20 -0
- package/src/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +49 -0
- package/src/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +6 -2
- package/src/templates/web/ui-auth-payments-video/template/src/components/providers/theme-provider.tsx +94 -0
- package/src/templates/web/ui-auth-payments-video/template/src/components/shared/footer.tsx +36 -0
- package/src/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +2 -0
- package/src/templates/web/ui-auth-payments-video/template/src/components/ui/theme-toggle.tsx +34 -0
- package/src/templates/web/ui-auth-payments-video/template/src/lib/env.ts +49 -0
- package/src/templates/web/ui-auth-payments-video/template/src/lib/utils.ts +133 -0
- package/src/templates/web/ui-auth-payments-video/template/src/test/setup.ts +79 -0
- package/src/templates/web/ui-auth-payments-video/template/vitest.config.ts +17 -0
- package/src/templates/web/ui-only/template/package.json +14 -4
- package/src/templates/web/ui-only/template/src/app/error.tsx +67 -0
- package/src/templates/web/ui-only/template/src/app/layout.tsx +6 -2
- package/src/templates/web/ui-only/template/src/app/loading.tsx +20 -0
- package/src/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +49 -0
- package/src/templates/web/ui-only/template/src/components/providers/app-providers.tsx +6 -2
- package/src/templates/web/ui-only/template/src/components/providers/theme-provider.tsx +94 -0
- package/src/templates/web/ui-only/template/src/components/shared/footer.tsx +36 -0
- package/src/templates/web/ui-only/template/src/components/shared/header.tsx +2 -0
- package/src/templates/web/ui-only/template/src/components/ui/theme-toggle.tsx +34 -0
- package/src/templates/web/ui-only/template/src/lib/env.ts +49 -0
- package/src/templates/web/ui-only/template/src/lib/utils.ts +133 -0
- package/src/templates/web/ui-only/template/src/test/setup.ts +79 -0
- package/src/templates/web/ui-only/template/vitest.config.ts +17 -0
package/dist/templates/web/ui-auth-payments/template/src/components/providers/theme-provider.tsx
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, useEffect } from 'react'
|
|
4
|
+
|
|
5
|
+
interface ThemeContextType {
|
|
6
|
+
themeColor: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
|
|
10
|
+
|
|
11
|
+
interface AppThemeProviderProps {
|
|
12
|
+
children: React.ReactNode
|
|
13
|
+
themeColor: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const THEME_COLORS = {
|
|
17
|
+
blue: {
|
|
18
|
+
primary: '221.2 83.2% 53.3%',
|
|
19
|
+
primaryForeground: '210 40% 98%',
|
|
20
|
+
secondary: '210 40% 96%',
|
|
21
|
+
accent: '210 40% 96%',
|
|
22
|
+
ring: '221.2 83.2% 53.3%',
|
|
23
|
+
},
|
|
24
|
+
green: {
|
|
25
|
+
primary: '142.1 76.2% 36.3%',
|
|
26
|
+
primaryForeground: '355.7 100% 97.3%',
|
|
27
|
+
secondary: '138.5 76.2% 96.7%',
|
|
28
|
+
accent: '138.5 76.2% 96.7%',
|
|
29
|
+
ring: '142.1 76.2% 36.3%',
|
|
30
|
+
},
|
|
31
|
+
purple: {
|
|
32
|
+
primary: '262.1 83.3% 57.8%',
|
|
33
|
+
primaryForeground: '210 40% 98%',
|
|
34
|
+
secondary: '270 3.18% 96.5%',
|
|
35
|
+
accent: '270 3.18% 96.5%',
|
|
36
|
+
ring: '262.1 83.3% 57.8%',
|
|
37
|
+
},
|
|
38
|
+
orange: {
|
|
39
|
+
primary: '24.6 95% 53.1%',
|
|
40
|
+
primaryForeground: '60 9.1% 97.8%',
|
|
41
|
+
secondary: '60 4.8% 95.9%',
|
|
42
|
+
accent: '60 4.8% 95.9%',
|
|
43
|
+
ring: '24.6 95% 53.1%',
|
|
44
|
+
},
|
|
45
|
+
red: {
|
|
46
|
+
primary: '0 72.2% 50.6%',
|
|
47
|
+
primaryForeground: '0 85.7% 97.3%',
|
|
48
|
+
secondary: '0 0% 96.3%',
|
|
49
|
+
accent: '0 0% 96.3%',
|
|
50
|
+
ring: '0 72.2% 50.6%',
|
|
51
|
+
},
|
|
52
|
+
slate: {
|
|
53
|
+
primary: '215 27.9% 16.9%',
|
|
54
|
+
primaryForeground: '0 0% 98%',
|
|
55
|
+
secondary: '210 40% 96%',
|
|
56
|
+
accent: '210 40% 96%',
|
|
57
|
+
ring: '215 27.9% 16.9%',
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function AppThemeProvider({ children, themeColor }: AppThemeProviderProps) {
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const colorScheme = THEME_COLORS[themeColor as keyof typeof THEME_COLORS] || THEME_COLORS.blue
|
|
64
|
+
|
|
65
|
+
// Apply theme colors to CSS custom properties
|
|
66
|
+
const root = document.documentElement
|
|
67
|
+
root.style.setProperty('--primary', colorScheme.primary)
|
|
68
|
+
root.style.setProperty('--primary-foreground', colorScheme.primaryForeground)
|
|
69
|
+
root.style.setProperty('--secondary', colorScheme.secondary)
|
|
70
|
+
root.style.setProperty('--accent', colorScheme.accent)
|
|
71
|
+
root.style.setProperty('--ring', colorScheme.ring)
|
|
72
|
+
|
|
73
|
+
// Store theme color preference
|
|
74
|
+
localStorage.setItem('{{packageName}}-theme-color', themeColor)
|
|
75
|
+
}, [themeColor])
|
|
76
|
+
|
|
77
|
+
const contextValue: ThemeContextType = {
|
|
78
|
+
themeColor,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<ThemeContext.Provider value={contextValue}>
|
|
83
|
+
{children}
|
|
84
|
+
</ThemeContext.Provider>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function useAppTheme() {
|
|
89
|
+
const context = useContext(ThemeContext)
|
|
90
|
+
if (context === undefined) {
|
|
91
|
+
throw new Error('useAppTheme must be used within a AppThemeProvider')
|
|
92
|
+
}
|
|
93
|
+
return context
|
|
94
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React from 'react'
|
|
4
|
+
|
|
5
|
+
interface FooterProps {
|
|
6
|
+
className?: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Footer({ className = '' }: FooterProps) {
|
|
10
|
+
return (
|
|
11
|
+
<footer className={`border-t bg-background py-4 ${className}`}>
|
|
12
|
+
<div className="container mx-auto px-4">
|
|
13
|
+
<div className="flex flex-col sm:flex-row justify-between items-center gap-4 text-sm text-muted-foreground">
|
|
14
|
+
<div className="flex items-center gap-2">
|
|
15
|
+
<span>© {new Date().getFullYear()} {{titleCaseName}}</span>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div className="flex items-center gap-2 text-xs">
|
|
19
|
+
<span>Generated with</span>
|
|
20
|
+
<a
|
|
21
|
+
href="https://docs.digilogiclabs.com"
|
|
22
|
+
target="_blank"
|
|
23
|
+
rel="noopener noreferrer"
|
|
24
|
+
className="hover:text-foreground transition-colors"
|
|
25
|
+
>
|
|
26
|
+
Digi Logic Labs
|
|
27
|
+
</a>
|
|
28
|
+
<span className="text-muted-foreground/60">
|
|
29
|
+
• UI v{{uiVersion}} • Auth v{{authVersion}} • Payments v{{paymentsVersion}} • {{generatedDate}}
|
|
30
|
+
</span>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</footer>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -4,6 +4,7 @@ import React from 'react';
|
|
|
4
4
|
import Link from 'next/link';
|
|
5
5
|
import { LogOut, CreditCard } from 'lucide-react';
|
|
6
6
|
import { useAuth } from '@digilogiclabs/saas-factory-auth';
|
|
7
|
+
import { ThemeToggle } from '../ui/theme-toggle';
|
|
7
8
|
|
|
8
9
|
export function Header() {
|
|
9
10
|
const { user, signOut } = useAuth();
|
|
@@ -23,6 +24,7 @@ export function Header() {
|
|
|
23
24
|
{{titleCaseName}}
|
|
24
25
|
</Link>
|
|
25
26
|
<nav className="flex items-center gap-4">
|
|
27
|
+
<ThemeToggle />
|
|
26
28
|
{user ? (
|
|
27
29
|
<>
|
|
28
30
|
<Link href="/dashboard" className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Moon, Sun } from "lucide-react"
|
|
5
|
+
import { useTheme } from "next-themes"
|
|
6
|
+
|
|
7
|
+
import { Button } from "@digilogiclabs/saas-factory-ui"
|
|
8
|
+
|
|
9
|
+
export function ThemeToggle() {
|
|
10
|
+
const { theme, setTheme } = useTheme()
|
|
11
|
+
|
|
12
|
+
const toggleTheme = () => {
|
|
13
|
+
if (theme === 'light') {
|
|
14
|
+
setTheme('dark')
|
|
15
|
+
} else if (theme === 'dark') {
|
|
16
|
+
setTheme('system')
|
|
17
|
+
} else {
|
|
18
|
+
setTheme('light')
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Button
|
|
24
|
+
variant="outline"
|
|
25
|
+
size="icon"
|
|
26
|
+
onClick={toggleTheme}
|
|
27
|
+
className="h-9 w-9"
|
|
28
|
+
>
|
|
29
|
+
<Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
|
30
|
+
<Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
|
31
|
+
<span className="sr-only">Toggle theme</span>
|
|
32
|
+
</Button>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
'use server'
|
|
2
|
+
|
|
3
|
+
import { redirect } from 'next/navigation'
|
|
4
|
+
import { cookies } from 'next/headers'
|
|
5
|
+
import { z } from 'zod'
|
|
6
|
+
|
|
7
|
+
// Schema for form validation
|
|
8
|
+
const signInSchema = z.object({
|
|
9
|
+
email: z.string().email('Invalid email address'),
|
|
10
|
+
password: z.string().min(6, 'Password must be at least 6 characters'),
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const signUpSchema = z.object({
|
|
14
|
+
email: z.string().email('Invalid email address'),
|
|
15
|
+
password: z.string().min(6, 'Password must be at least 6 characters'),
|
|
16
|
+
confirmPassword: z.string(),
|
|
17
|
+
name: z.string().min(2, 'Name must be at least 2 characters').optional(),
|
|
18
|
+
}).refine((data) => data.password === data.confirmPassword, {
|
|
19
|
+
message: "Passwords don't match",
|
|
20
|
+
path: ["confirmPassword"],
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
// Response types
|
|
24
|
+
type ActionResult = {
|
|
25
|
+
success: boolean
|
|
26
|
+
error?: string
|
|
27
|
+
fieldErrors?: Record<string, string[]>
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Server action for signing in
|
|
32
|
+
* This works alongside the client-side @digilogiclabs/saas-factory-auth
|
|
33
|
+
*/
|
|
34
|
+
export async function signInAction(prevState: any, formData: FormData): Promise<ActionResult> {
|
|
35
|
+
try {
|
|
36
|
+
const rawData = {
|
|
37
|
+
email: formData.get('email') as string,
|
|
38
|
+
password: formData.get('password') as string,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Validate form data
|
|
42
|
+
const validationResult = signInSchema.safeParse(rawData)
|
|
43
|
+
|
|
44
|
+
if (!validationResult.success) {
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
error: 'Please check your input',
|
|
48
|
+
fieldErrors: validationResult.error.formErrors.fieldErrors,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { email, password } = validationResult.data
|
|
53
|
+
|
|
54
|
+
// Note: The actual authentication is handled by the client-side library
|
|
55
|
+
// This server action is mainly for form validation and server-side processing
|
|
56
|
+
// You might want to add additional server-side logic here like:
|
|
57
|
+
// - Rate limiting
|
|
58
|
+
// - Logging
|
|
59
|
+
// - Analytics
|
|
60
|
+
|
|
61
|
+
// For now, we'll return success and let the client handle the actual auth
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('Sign in error:', error)
|
|
67
|
+
return {
|
|
68
|
+
success: false,
|
|
69
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Server action for signing up
|
|
76
|
+
*/
|
|
77
|
+
export async function signUpAction(prevState: any, formData: FormData): Promise<ActionResult> {
|
|
78
|
+
try {
|
|
79
|
+
const rawData = {
|
|
80
|
+
email: formData.get('email') as string,
|
|
81
|
+
password: formData.get('password') as string,
|
|
82
|
+
confirmPassword: formData.get('confirmPassword') as string,
|
|
83
|
+
name: formData.get('name') as string,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Validate form data
|
|
87
|
+
const validationResult = signUpSchema.safeParse(rawData)
|
|
88
|
+
|
|
89
|
+
if (!validationResult.success) {
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
error: 'Please check your input',
|
|
93
|
+
fieldErrors: validationResult.error.formErrors.fieldErrors,
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { email, password, name } = validationResult.data
|
|
98
|
+
|
|
99
|
+
// Additional server-side processing can go here
|
|
100
|
+
// - User existence check
|
|
101
|
+
// - Welcome email preparation
|
|
102
|
+
// - User analytics setup
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
success: true,
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error('Sign up error:', error)
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Server action for signing out
|
|
118
|
+
*/
|
|
119
|
+
export async function signOutAction(): Promise<void> {
|
|
120
|
+
try {
|
|
121
|
+
const cookieStore = await cookies()
|
|
122
|
+
|
|
123
|
+
// Clear auth cookies (adjust cookie names based on the auth library)
|
|
124
|
+
cookieStore.delete('saas-factory-auth-token')
|
|
125
|
+
cookieStore.delete('saas-factory-auth-user')
|
|
126
|
+
|
|
127
|
+
// Additional cleanup can go here
|
|
128
|
+
// - Clear session data
|
|
129
|
+
// - Log sign out event
|
|
130
|
+
// - Clear cache
|
|
131
|
+
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('Sign out error:', error)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
redirect('/')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Server action for OAuth redirect handling
|
|
141
|
+
*/
|
|
142
|
+
export async function handleOAuthCallback(provider: string, code: string): Promise<ActionResult> {
|
|
143
|
+
try {
|
|
144
|
+
// This would handle OAuth callback processing
|
|
145
|
+
// For now, we'll delegate to the client-side library
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error('OAuth callback error:', error)
|
|
152
|
+
return {
|
|
153
|
+
success: false,
|
|
154
|
+
error: 'Authentication failed. Please try again.',
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Server action for password reset request
|
|
161
|
+
*/
|
|
162
|
+
export async function requestPasswordReset(prevState: any, formData: FormData): Promise<ActionResult> {
|
|
163
|
+
try {
|
|
164
|
+
const email = formData.get('email') as string
|
|
165
|
+
|
|
166
|
+
if (!email) {
|
|
167
|
+
return {
|
|
168
|
+
success: false,
|
|
169
|
+
error: 'Email is required',
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const emailSchema = z.string().email()
|
|
174
|
+
const validationResult = emailSchema.safeParse(email)
|
|
175
|
+
|
|
176
|
+
if (!validationResult.success) {
|
|
177
|
+
return {
|
|
178
|
+
success: false,
|
|
179
|
+
error: 'Please enter a valid email address',
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Password reset logic would go here
|
|
184
|
+
// - Generate reset token
|
|
185
|
+
// - Send reset email
|
|
186
|
+
// - Log reset request
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
success: true,
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('Password reset error:', error)
|
|
193
|
+
return {
|
|
194
|
+
success: false,
|
|
195
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Server action for updating user profile
|
|
202
|
+
*/
|
|
203
|
+
export async function updateProfileAction(prevState: any, formData: FormData): Promise<ActionResult> {
|
|
204
|
+
try {
|
|
205
|
+
// This would require authentication check
|
|
206
|
+
const cookieStore = await cookies()
|
|
207
|
+
const authToken = cookieStore.get('saas-factory-auth-token')?.value
|
|
208
|
+
|
|
209
|
+
if (!authToken) {
|
|
210
|
+
redirect('/login')
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const name = formData.get('name') as string
|
|
214
|
+
const email = formData.get('email') as string
|
|
215
|
+
|
|
216
|
+
const updateSchema = z.object({
|
|
217
|
+
name: z.string().min(2, 'Name must be at least 2 characters').optional(),
|
|
218
|
+
email: z.string().email('Invalid email address').optional(),
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const validationResult = updateSchema.safeParse({ name, email })
|
|
222
|
+
|
|
223
|
+
if (!validationResult.success) {
|
|
224
|
+
return {
|
|
225
|
+
success: false,
|
|
226
|
+
error: 'Please check your input',
|
|
227
|
+
fieldErrors: validationResult.error.formErrors.fieldErrors,
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Profile update logic would go here
|
|
232
|
+
// - Update user in database
|
|
233
|
+
// - Update auth cookies
|
|
234
|
+
// - Send confirmation email if email changed
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
success: true,
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.error('Profile update error:', error)
|
|
241
|
+
return {
|
|
242
|
+
success: false,
|
|
243
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|