@digilogiclabs/create-saas-app 1.14.0 → 1.17.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/README.md +134 -29
- package/bin/index.js +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/prompts/project-setup.d.ts.map +1 -1
- package/dist/cli/prompts/project-setup.js +45 -12
- package/dist/cli/prompts/project-setup.js.map +1 -1
- package/dist/generators/template-generator.d.ts.map +1 -1
- package/dist/generators/template-generator.js +27 -4
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/mobile/ui-auth-payments/template/.env.example +20 -0
- package/dist/templates/mobile/ui-auth-payments/template/README.md +218 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/_layout.tsx +153 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/analytics.tsx +668 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/billing.tsx +743 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/index.tsx +676 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/orders.tsx +402 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/profile.tsx +580 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/_layout.tsx +125 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/auth/login.tsx +246 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/auth/signup.tsx +362 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/onboarding/index.tsx +193 -0
- package/dist/templates/mobile/ui-auth-payments/template/app/tour/index.tsx +272 -0
- package/dist/templates/mobile/ui-auth-payments/template/app.json +93 -0
- package/dist/templates/mobile/ui-auth-payments/template/babel.config.js +23 -0
- package/dist/templates/mobile/ui-auth-payments/template/eas.json +45 -0
- package/dist/templates/mobile/ui-auth-payments/template/expo-env.d.ts +3 -0
- package/dist/templates/mobile/ui-auth-payments/template/jest-setup.ts +74 -0
- package/dist/templates/mobile/ui-auth-payments/template/metro.config.js +11 -0
- package/dist/templates/mobile/ui-auth-payments/template/package.json +106 -0
- package/dist/templates/mobile/ui-auth-payments/template/tsconfig.json +31 -0
- package/dist/templates/web/base/template/src/app/dashboard/page.tsx +62 -20
- package/dist/templates/web/ui-auth/template/package.json +1 -1
- package/dist/templates/web/ui-auth-payments/template/package.json +1 -1
- package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +69 -17
- package/dist/templates/web/ui-auth-payments-ai/template/package.json +1 -1
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +218 -7
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +62 -9
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +364 -0
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +532 -0
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +70 -51
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +76 -60
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +1 -1
- package/dist/templates/web/ui-auth-payments-audio/template/package.json +1 -1
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +71 -17
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +1 -1
- package/dist/templates/web/ui-auth-payments-video/template/package.json +1 -1
- package/package.json +1 -1
- package/src/templates/mobile/ui-auth-payments/template/.env.example +20 -0
- package/src/templates/mobile/ui-auth-payments/template/README.md +218 -0
- package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/_layout.tsx +153 -0
- package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/analytics.tsx +668 -0
- package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/billing.tsx +743 -0
- package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/index.tsx +676 -0
- package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/orders.tsx +402 -0
- package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/profile.tsx +580 -0
- package/src/templates/mobile/ui-auth-payments/template/app/_layout.tsx +125 -0
- package/src/templates/mobile/ui-auth-payments/template/app/auth/login.tsx +246 -0
- package/src/templates/mobile/ui-auth-payments/template/app/auth/signup.tsx +362 -0
- package/src/templates/mobile/ui-auth-payments/template/app/onboarding/index.tsx +193 -0
- package/src/templates/mobile/ui-auth-payments/template/app/tour/index.tsx +272 -0
- package/src/templates/mobile/ui-auth-payments/template/app.json +93 -0
- package/src/templates/mobile/ui-auth-payments/template/babel.config.js +23 -0
- package/src/templates/mobile/ui-auth-payments/template/eas.json +45 -0
- package/src/templates/mobile/ui-auth-payments/template/expo-env.d.ts +3 -0
- package/src/templates/mobile/ui-auth-payments/template/jest-setup.ts +74 -0
- package/src/templates/mobile/ui-auth-payments/template/metro.config.js +11 -0
- package/src/templates/mobile/ui-auth-payments/template/package.json +106 -0
- package/src/templates/mobile/ui-auth-payments/template/tsconfig.json +31 -0
- package/src/templates/web/base/template/src/app/dashboard/page.tsx +62 -20
- package/src/templates/web/ui-auth/template/package.json +1 -1
- package/src/templates/web/ui-auth-payments/template/package.json +1 -1
- package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +69 -17
- package/src/templates/web/ui-auth-payments-ai/template/package.json +1 -1
- package/src/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +218 -7
- package/src/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +62 -9
- package/src/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +364 -0
- package/src/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +532 -0
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +70 -51
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +76 -60
- package/src/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +1 -1
- package/src/templates/web/ui-auth-payments-audio/template/package.json +1 -1
- package/src/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +71 -17
- package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +1 -1
- package/src/templates/web/ui-auth-payments-video/template/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { getDefaultConfig } = require('expo/metro-config');
|
|
2
|
+
|
|
3
|
+
/** @type {import('expo/metro-config').MetroConfig} */
|
|
4
|
+
const config = getDefaultConfig(__dirname);
|
|
5
|
+
|
|
6
|
+
// Add SVG support
|
|
7
|
+
config.transformer.babelTransformerPath = require.resolve('react-native-svg-transformer');
|
|
8
|
+
config.resolver.assetExts = config.resolver.assetExts.filter((ext) => ext !== 'svg');
|
|
9
|
+
config.resolver.sourceExts = [...config.resolver.sourceExts, 'svg'];
|
|
10
|
+
|
|
11
|
+
module.exports = config;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "{{description}} - Mobile App with UI, Auth, and Payments",
|
|
5
|
+
"main": "node_modules/expo/AppEntry.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "expo start",
|
|
8
|
+
"dev": "expo start --dev-client",
|
|
9
|
+
"android": "expo start --android",
|
|
10
|
+
"ios": "expo start --ios",
|
|
11
|
+
"web": "expo start --web",
|
|
12
|
+
"build": "eas build",
|
|
13
|
+
"build:android": "eas build --platform android",
|
|
14
|
+
"build:ios": "eas build --platform ios",
|
|
15
|
+
"preview": "eas build --profile preview",
|
|
16
|
+
"submit": "eas submit",
|
|
17
|
+
"test": "jest",
|
|
18
|
+
"lint": "expo lint",
|
|
19
|
+
"type-check": "tsc --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"expo": "~50.0.0",
|
|
23
|
+
"react": "18.2.0",
|
|
24
|
+
"react-native": "0.73.4",
|
|
25
|
+
|
|
26
|
+
"@expo/vector-icons": "^14.0.0",
|
|
27
|
+
"@expo/config-plugins": "~7.8.0",
|
|
28
|
+
|
|
29
|
+
"@react-navigation/native": "^6.1.9",
|
|
30
|
+
"@react-navigation/stack": "^6.3.20",
|
|
31
|
+
"@react-navigation/bottom-tabs": "^6.5.11",
|
|
32
|
+
"@react-navigation/drawer": "^6.6.6",
|
|
33
|
+
"react-native-screens": "~3.29.0",
|
|
34
|
+
"react-native-safe-area-context": "4.8.2",
|
|
35
|
+
"react-native-gesture-handler": "~2.14.0",
|
|
36
|
+
"react-native-reanimated": "~3.6.2",
|
|
37
|
+
|
|
38
|
+
"@digilogiclabs/saas-factory-ui": "^0.22.0",
|
|
39
|
+
"@digilogiclabs/saas-factory-auth": "^1.0.1",
|
|
40
|
+
"@digilogiclabs/saas-factory-payments": "^1.1.0",
|
|
41
|
+
|
|
42
|
+
"@supabase/supabase-js": "^2.39.0",
|
|
43
|
+
"@react-native-async-storage/async-storage": "1.21.0",
|
|
44
|
+
|
|
45
|
+
"@stripe/stripe-react-native": "0.37.2",
|
|
46
|
+
|
|
47
|
+
"expo-router": "~3.4.0",
|
|
48
|
+
"expo-font": "~11.10.0",
|
|
49
|
+
"expo-linking": "~6.2.2",
|
|
50
|
+
"expo-constants": "~15.4.0",
|
|
51
|
+
"expo-status-bar": "~1.11.1",
|
|
52
|
+
"expo-splash-screen": "~0.26.4",
|
|
53
|
+
"expo-system-ui": "~2.9.3",
|
|
54
|
+
"expo-web-browser": "~12.8.2",
|
|
55
|
+
"expo-haptics": "~12.8.1",
|
|
56
|
+
"expo-device": "~5.9.3",
|
|
57
|
+
"expo-location": "~16.5.3",
|
|
58
|
+
"expo-image-picker": "~14.7.1",
|
|
59
|
+
"expo-camera": "~14.1.3",
|
|
60
|
+
"expo-barcode-scanner": "~12.9.3",
|
|
61
|
+
"expo-notifications": "~0.27.6",
|
|
62
|
+
"expo-secure-store": "~12.8.1",
|
|
63
|
+
"expo-file-system": "~16.0.6",
|
|
64
|
+
"expo-updates": "~0.24.11",
|
|
65
|
+
"expo-linear-gradient": "~12.7.2",
|
|
66
|
+
"expo-blur": "~12.9.2",
|
|
67
|
+
|
|
68
|
+
"@react-native-community/netinfo": "11.2.1",
|
|
69
|
+
"react-native-mmkv": "^2.12.2",
|
|
70
|
+
"react-native-svg": "14.1.0",
|
|
71
|
+
"react-native-url-polyfill": "^2.0.0",
|
|
72
|
+
|
|
73
|
+
"zustand": "^4.4.7",
|
|
74
|
+
"react-hook-form": "^7.48.2",
|
|
75
|
+
"@hookform/resolvers": "^3.3.2",
|
|
76
|
+
"zod": "^3.22.4",
|
|
77
|
+
"date-fns": "^3.0.6",
|
|
78
|
+
"react-native-heroicons": "^4.0.0"
|
|
79
|
+
},
|
|
80
|
+
"devDependencies": {
|
|
81
|
+
"@babel/core": "^7.23.6",
|
|
82
|
+
"@types/react": "~18.2.45",
|
|
83
|
+
"@types/react-native": "~0.73.0",
|
|
84
|
+
"typescript": "~5.3.3",
|
|
85
|
+
"jest": "^29.7.0",
|
|
86
|
+
"@testing-library/react-native": "^12.4.2",
|
|
87
|
+
"@testing-library/jest-native": "^5.4.3",
|
|
88
|
+
"babel-plugin-module-resolver": "^5.0.0",
|
|
89
|
+
"eslint": "^8.57.0",
|
|
90
|
+
"eslint-config-expo": "^7.0.0",
|
|
91
|
+
"prettier": "^3.1.1"
|
|
92
|
+
},
|
|
93
|
+
"jest": {
|
|
94
|
+
"preset": "jest-expo",
|
|
95
|
+
"setupFilesAfterEnv": ["<rootDir>/jest-setup.ts"],
|
|
96
|
+
"transformIgnorePatterns": [
|
|
97
|
+
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"private": true,
|
|
101
|
+
"expo": {
|
|
102
|
+
"install": {
|
|
103
|
+
"exclude": ["react-native-safe-area-context"]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "expo/tsconfig.base",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"strict": true,
|
|
5
|
+
"baseUrl": "./",
|
|
6
|
+
"paths": {
|
|
7
|
+
"@/*": ["./*"],
|
|
8
|
+
"@/components/*": ["./components/*"],
|
|
9
|
+
"@/hooks/*": ["./hooks/*"],
|
|
10
|
+
"@/utils/*": ["./utils/*"],
|
|
11
|
+
"@/types/*": ["./types/*"],
|
|
12
|
+
"@/constants/*": ["./constants/*"]
|
|
13
|
+
},
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"allowSyntheticDefaultImports": true,
|
|
16
|
+
"esModuleInterop": true,
|
|
17
|
+
"moduleResolution": "node",
|
|
18
|
+
"resolveJsonModule": true,
|
|
19
|
+
"noEmit": true,
|
|
20
|
+
"jsx": "react-jsx"
|
|
21
|
+
},
|
|
22
|
+
"include": [
|
|
23
|
+
"**/*.ts",
|
|
24
|
+
"**/*.tsx",
|
|
25
|
+
".expo/types/**/*.ts",
|
|
26
|
+
"expo-env.d.ts"
|
|
27
|
+
],
|
|
28
|
+
"exclude": [
|
|
29
|
+
"node_modules"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
NetworkAwareContent,
|
|
16
16
|
OfflineWrapper,
|
|
17
17
|
useNetworkInfo,
|
|
18
|
-
useOfflineState
|
|
18
|
+
useOfflineState,
|
|
19
|
+
DashboardLayout,
|
|
20
|
+
CommandPalette,
|
|
21
|
+
Tour
|
|
19
22
|
} from '@digilogiclabs/saas-factory-ui';
|
|
20
23
|
import {
|
|
21
24
|
BarChart3,
|
|
@@ -27,7 +30,10 @@ import {
|
|
|
27
30
|
Star,
|
|
28
31
|
Trash2,
|
|
29
32
|
Wifi,
|
|
30
|
-
WifiOff
|
|
33
|
+
WifiOff,
|
|
34
|
+
Home,
|
|
35
|
+
FileText,
|
|
36
|
+
Activity
|
|
31
37
|
} from 'lucide-react';
|
|
32
38
|
|
|
33
39
|
// Mock data for demonstration
|
|
@@ -43,6 +49,32 @@ const mockActivityData = Array.from({ length: 50 }, (_, i) => ({
|
|
|
43
49
|
export default function DashboardPage() {
|
|
44
50
|
const { user } = useAuth();
|
|
45
51
|
|
|
52
|
+
const sidebarNavigation = [
|
|
53
|
+
{ name: 'Dashboard', href: '/dashboard', icon: Home, current: true },
|
|
54
|
+
{ name: 'Analytics', href: '/dashboard/analytics', icon: BarChart3 },
|
|
55
|
+
{ name: 'Reports', href: '/dashboard/reports', icon: FileText },
|
|
56
|
+
{ name: 'Activity', href: '/dashboard/activity', icon: Activity },
|
|
57
|
+
{ name: 'Settings', href: '/settings', icon: Settings }
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
const tourSteps = [
|
|
61
|
+
{
|
|
62
|
+
target: '[data-tour="overview"]',
|
|
63
|
+
title: 'Mobile-First Dashboard',
|
|
64
|
+
content: 'This dashboard is optimized for mobile devices with offline support and responsive design.'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
target: '[data-tour="stats"]',
|
|
68
|
+
title: 'Network-Aware Stats',
|
|
69
|
+
content: 'Statistics automatically adapt based on your network connection speed.'
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
target: '[data-tour="activity"]',
|
|
73
|
+
title: 'Interactive Activity Feed',
|
|
74
|
+
content: 'Swipe left or right on activity items to archive, star, or delete them.'
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
|
|
46
78
|
const lazyImageConfig = {
|
|
47
79
|
mobileOptimization: {
|
|
48
80
|
quality: 80,
|
|
@@ -116,23 +148,30 @@ export default function DashboardPage() {
|
|
|
116
148
|
|
|
117
149
|
|
|
118
150
|
return (
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
<DashboardLayout
|
|
152
|
+
navigation={sidebarNavigation}
|
|
153
|
+
headerActions={[
|
|
154
|
+
<CommandPalette key="command-palette" />,
|
|
155
|
+
<Tour key="tour" steps={tourSteps} />
|
|
156
|
+
]}
|
|
157
|
+
>
|
|
158
|
+
<PageTransition type="slide" direction="horizontal" duration={300}>
|
|
159
|
+
<OfflineWrapper
|
|
160
|
+
cacheStrategy="stale-while-revalidate"
|
|
161
|
+
showOfflineIndicator={true}
|
|
162
|
+
backgroundSync={true}
|
|
131
163
|
>
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
164
|
+
<PullToRefresh
|
|
165
|
+
onRefresh={handleRefresh}
|
|
166
|
+
threshold={80}
|
|
167
|
+
loadingIndicator="spinner"
|
|
168
|
+
hapticOnTrigger={true}
|
|
169
|
+
networkAware={true}
|
|
170
|
+
>
|
|
171
|
+
<div className="min-h-screen bg-gray-50">
|
|
172
|
+
<MobileContainer className="py-6">
|
|
173
|
+
{/* Header */}
|
|
174
|
+
<div className="mb-6" data-tour="overview">
|
|
136
175
|
<div className="flex items-center justify-between">
|
|
137
176
|
<div>
|
|
138
177
|
<h1 className="text-2xl font-bold text-gray-900">
|
|
@@ -164,7 +203,8 @@ export default function DashboardPage() {
|
|
|
164
203
|
</div>
|
|
165
204
|
|
|
166
205
|
{/* Stats Grid */}
|
|
167
|
-
<
|
|
206
|
+
<div data-tour="stats">
|
|
207
|
+
<NetworkAwareContent
|
|
168
208
|
showOnSlow={
|
|
169
209
|
<ResponsiveGrid columns={gridConfig.columns_2_2} gap="sm" className="mb-6">
|
|
170
210
|
{stats.slice(0, 2).map((stat, index) => (
|
|
@@ -202,9 +242,10 @@ export default function DashboardPage() {
|
|
|
202
242
|
))}
|
|
203
243
|
</ResponsiveGrid>
|
|
204
244
|
</NetworkAwareContent>
|
|
245
|
+
</div>
|
|
205
246
|
|
|
206
247
|
{/* Activity Feed */}
|
|
207
|
-
<Card className="mb-6">
|
|
248
|
+
<Card className="mb-6" data-tour="activity">
|
|
208
249
|
<CardHeader>
|
|
209
250
|
<CardTitle className="flex items-center gap-2">
|
|
210
251
|
<BarChart3 className="h-5 w-5" />
|
|
@@ -320,5 +361,6 @@ export default function DashboardPage() {
|
|
|
320
361
|
</PullToRefresh>
|
|
321
362
|
</OfflineWrapper>
|
|
322
363
|
</PageTransition>
|
|
364
|
+
</DashboardLayout>
|
|
323
365
|
);
|
|
324
366
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"next": "^15.0.0",
|
|
18
18
|
"react": "^19.0.0",
|
|
19
19
|
"react-dom": "^19.0.0",
|
|
20
|
-
"@digilogiclabs/saas-factory-ui": "^0.
|
|
20
|
+
"@digilogiclabs/saas-factory-ui": "^0.21.0",
|
|
21
21
|
"@digilogiclabs/saas-factory-auth": "^1.0.1",
|
|
22
22
|
"tailwindcss": "^3.3.0",
|
|
23
23
|
"autoprefixer": "^10.4.16",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"next": "^15.0.0",
|
|
18
18
|
"react": "^19.0.0",
|
|
19
19
|
"react-dom": "^19.0.0",
|
|
20
|
-
"@digilogiclabs/saas-factory-ui": "^0.
|
|
20
|
+
"@digilogiclabs/saas-factory-ui": "^0.21.0",
|
|
21
21
|
"@digilogiclabs/saas-factory-auth": "^1.0.1",
|
|
22
22
|
"@digilogiclabs/saas-factory-payments": "^1.1.0",
|
|
23
23
|
"stripe": "^14.0.0",
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { Suspense } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
DashboardLayout,
|
|
6
|
+
CommandPalette,
|
|
7
|
+
Tour
|
|
8
|
+
} from '@digilogiclabs/saas-factory-ui'
|
|
9
|
+
import {
|
|
10
|
+
User,
|
|
11
|
+
Settings,
|
|
12
|
+
CreditCard,
|
|
13
|
+
Activity,
|
|
14
|
+
Home,
|
|
15
|
+
BarChart,
|
|
16
|
+
FileText,
|
|
17
|
+
ShoppingCart
|
|
18
|
+
} from 'lucide-react'
|
|
4
19
|
import { requireAuth } from '@/lib/auth-server'
|
|
5
20
|
import Link from 'next/link'
|
|
6
21
|
|
|
@@ -90,26 +105,62 @@ export default async function DashboardPage() {
|
|
|
90
105
|
// Server-side authentication requirement
|
|
91
106
|
const user = await requireAuth()
|
|
92
107
|
|
|
108
|
+
const sidebarNavigation = [
|
|
109
|
+
{ name: 'Overview', href: '/dashboard', icon: Home, current: true },
|
|
110
|
+
{ name: 'Orders', href: '/dashboard/orders', icon: ShoppingCart },
|
|
111
|
+
{ name: 'Analytics', href: '/dashboard/analytics', icon: BarChart },
|
|
112
|
+
{ name: 'Reports', href: '/dashboard/reports', icon: FileText },
|
|
113
|
+
{ name: 'Settings', href: '/settings', icon: Settings },
|
|
114
|
+
{ name: 'Billing', href: '/billing', icon: CreditCard }
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
const tourSteps = [
|
|
118
|
+
{
|
|
119
|
+
target: '[data-tour="overview"]',
|
|
120
|
+
title: 'Dashboard Overview',
|
|
121
|
+
content: 'Get a comprehensive view of your business metrics and activity.'
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
target: '[data-tour="stats"]',
|
|
125
|
+
title: 'Key Statistics',
|
|
126
|
+
content: 'Monitor your most important business metrics at a glance.'
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
target: '[data-tour="actions"]',
|
|
130
|
+
title: 'Quick Actions',
|
|
131
|
+
content: 'Access your most frequently used features and settings.'
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
|
|
93
135
|
return (
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
136
|
+
<DashboardLayout
|
|
137
|
+
navigation={sidebarNavigation}
|
|
138
|
+
headerActions={[
|
|
139
|
+
<CommandPalette key="command-palette" />,
|
|
140
|
+
<Tour key="tour" steps={tourSteps} />
|
|
141
|
+
]}
|
|
142
|
+
>
|
|
143
|
+
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
|
144
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
145
|
+
{/* Header */}
|
|
146
|
+
<div className="mb-8" data-tour="overview">
|
|
147
|
+
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">
|
|
148
|
+
Welcome back, {user.name || user.email}!
|
|
149
|
+
</h1>
|
|
150
|
+
<p className="text-gray-600 dark:text-gray-300 mt-2">
|
|
151
|
+
Here's what's happening with your account today.
|
|
152
|
+
</p>
|
|
153
|
+
</div>
|
|
105
154
|
|
|
106
155
|
{/* Stats - Streaming with Suspense */}
|
|
107
|
-
<
|
|
108
|
-
<
|
|
109
|
-
|
|
156
|
+
<div data-tour="stats">
|
|
157
|
+
<Suspense fallback={<UserStatsSkeleton />}>
|
|
158
|
+
<UserStats userId={user.id} />
|
|
159
|
+
</Suspense>
|
|
160
|
+
</div>
|
|
110
161
|
|
|
111
162
|
{/* Quick Actions */}
|
|
112
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
|
163
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8" data-tour="actions">
|
|
113
164
|
<Card className="p-6">
|
|
114
165
|
<div className="flex items-center mb-4">
|
|
115
166
|
<User className="h-6 w-6 text-blue-600 dark:text-blue-400 mr-3" />
|
|
@@ -179,5 +230,6 @@ export default async function DashboardPage() {
|
|
|
179
230
|
</Card>
|
|
180
231
|
</div>
|
|
181
232
|
</div>
|
|
233
|
+
</DashboardLayout>
|
|
182
234
|
)
|
|
183
235
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"next": "^15.0.0",
|
|
18
18
|
"react": "^19.0.0",
|
|
19
19
|
"react-dom": "^19.0.0",
|
|
20
|
-
"@digilogiclabs/saas-factory-ui": "^0.
|
|
20
|
+
"@digilogiclabs/saas-factory-ui": "^0.21.0",
|
|
21
21
|
"@digilogiclabs/saas-factory-auth": "^1.0.1",
|
|
22
22
|
"@digilogiclabs/saas-factory-payments": "^1.1.0",
|
|
23
23
|
"@digilogiclabs/saas-factory-ai": "^3.1.1",
|
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React from 'react';
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
4
|
import { usePayments, formatCurrency, formatDate } from '@digilogiclabs/saas-factory-payments';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
Card,
|
|
8
|
+
SingleStepForm,
|
|
9
|
+
FormField,
|
|
10
|
+
FormSection,
|
|
11
|
+
FormProvider,
|
|
12
|
+
Modal
|
|
13
|
+
} from '@digilogiclabs/saas-factory-ui';
|
|
6
14
|
|
|
7
15
|
export default function BillingPage() {
|
|
8
16
|
const { loading } = usePayments();
|
|
17
|
+
const [showPaymentMethodModal, setShowPaymentMethodModal] = useState(false);
|
|
18
|
+
const [showPlanChangeModal, setShowPlanChangeModal] = useState(false);
|
|
19
|
+
const [editingPaymentMethod, setEditingPaymentMethod] = useState<string | null>(null);
|
|
9
20
|
|
|
10
21
|
const handleSubscriptionChange = () => {
|
|
11
|
-
|
|
12
|
-
// Handle subscription changes (upgrade, downgrade, cancel, resume)
|
|
22
|
+
setShowPlanChangeModal(true);
|
|
13
23
|
};
|
|
14
24
|
|
|
15
|
-
const handlePaymentMethodUpdate = () => {
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
const handlePaymentMethodUpdate = (methodId?: string) => {
|
|
26
|
+
setEditingPaymentMethod(methodId || null);
|
|
27
|
+
setShowPaymentMethodModal(true);
|
|
18
28
|
};
|
|
19
29
|
|
|
20
30
|
const handleInvoiceDownload = (invoiceId: string) => {
|
|
@@ -22,6 +32,19 @@ export default function BillingPage() {
|
|
|
22
32
|
// Handle invoice download
|
|
23
33
|
};
|
|
24
34
|
|
|
35
|
+
const handlePaymentMethodSubmit = async (formData: FormData) => {
|
|
36
|
+
console.log('Payment method data:', Object.fromEntries(formData));
|
|
37
|
+
// Handle payment method creation/update
|
|
38
|
+
setShowPaymentMethodModal(false);
|
|
39
|
+
setEditingPaymentMethod(null);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handlePlanChangeSubmit = async (formData: FormData) => {
|
|
43
|
+
console.log('Plan change data:', Object.fromEntries(formData));
|
|
44
|
+
// Handle plan change
|
|
45
|
+
setShowPlanChangeModal(false);
|
|
46
|
+
};
|
|
47
|
+
|
|
25
48
|
// Mock current subscription data - in real app this would come from your backend
|
|
26
49
|
const currentSubscription = {
|
|
27
50
|
plan: 'Pro Plan',
|
|
@@ -204,6 +227,194 @@ export default function BillingPage() {
|
|
|
204
227
|
</table>
|
|
205
228
|
</div>
|
|
206
229
|
</Card>
|
|
230
|
+
|
|
231
|
+
{/* Payment Method Modal */}
|
|
232
|
+
<Modal
|
|
233
|
+
isOpen={showPaymentMethodModal}
|
|
234
|
+
onClose={() => {
|
|
235
|
+
setShowPaymentMethodModal(false);
|
|
236
|
+
setEditingPaymentMethod(null);
|
|
237
|
+
}}
|
|
238
|
+
title={editingPaymentMethod ? "Edit Payment Method" : "Add Payment Method"}
|
|
239
|
+
size="lg"
|
|
240
|
+
>
|
|
241
|
+
<FormProvider>
|
|
242
|
+
<SingleStepForm
|
|
243
|
+
onSubmit={handlePaymentMethodSubmit}
|
|
244
|
+
submitButton={{
|
|
245
|
+
text: editingPaymentMethod ? "Update Payment Method" : "Add Payment Method",
|
|
246
|
+
disabled: loading
|
|
247
|
+
}}
|
|
248
|
+
realTimeValidation={true}
|
|
249
|
+
className="space-y-4"
|
|
250
|
+
>
|
|
251
|
+
<FormSection title="Card Information">
|
|
252
|
+
<FormField
|
|
253
|
+
name="cardNumber"
|
|
254
|
+
type="creditCard"
|
|
255
|
+
label="Card Number"
|
|
256
|
+
placeholder="1234 5678 9012 3456"
|
|
257
|
+
validation={['required', 'creditCard']}
|
|
258
|
+
disabled={loading}
|
|
259
|
+
/>
|
|
260
|
+
|
|
261
|
+
<div className="grid grid-cols-2 gap-4">
|
|
262
|
+
<FormField
|
|
263
|
+
name="expiryDate"
|
|
264
|
+
type="text"
|
|
265
|
+
label="Expiry Date"
|
|
266
|
+
placeholder="MM/YY"
|
|
267
|
+
validation={['required', 'expiryDate']}
|
|
268
|
+
disabled={loading}
|
|
269
|
+
/>
|
|
270
|
+
<FormField
|
|
271
|
+
name="cvc"
|
|
272
|
+
type="text"
|
|
273
|
+
label="CVC"
|
|
274
|
+
placeholder="123"
|
|
275
|
+
validation={['required', 'cvc']}
|
|
276
|
+
disabled={loading}
|
|
277
|
+
/>
|
|
278
|
+
</div>
|
|
279
|
+
</FormSection>
|
|
280
|
+
|
|
281
|
+
<FormSection title="Billing Information">
|
|
282
|
+
<FormField
|
|
283
|
+
name="cardholderName"
|
|
284
|
+
type="text"
|
|
285
|
+
label="Cardholder Name"
|
|
286
|
+
placeholder="Full name as it appears on card"
|
|
287
|
+
validation={['required']}
|
|
288
|
+
disabled={loading}
|
|
289
|
+
/>
|
|
290
|
+
|
|
291
|
+
<FormField
|
|
292
|
+
name="billingAddress"
|
|
293
|
+
type="address"
|
|
294
|
+
label="Billing Address"
|
|
295
|
+
validation={['required']}
|
|
296
|
+
disabled={loading}
|
|
297
|
+
fields={{
|
|
298
|
+
line1: { placeholder: "Street address" },
|
|
299
|
+
city: { placeholder: "City" },
|
|
300
|
+
state: { placeholder: "State/Province" },
|
|
301
|
+
postalCode: { placeholder: "ZIP/Postal code" },
|
|
302
|
+
country: { placeholder: "Country" }
|
|
303
|
+
}}
|
|
304
|
+
/>
|
|
305
|
+
|
|
306
|
+
<FormField
|
|
307
|
+
name="makeDefault"
|
|
308
|
+
type="checkbox"
|
|
309
|
+
label="Make this my default payment method"
|
|
310
|
+
disabled={loading}
|
|
311
|
+
/>
|
|
312
|
+
</FormSection>
|
|
313
|
+
</SingleStepForm>
|
|
314
|
+
</FormProvider>
|
|
315
|
+
</Modal>
|
|
316
|
+
|
|
317
|
+
{/* Plan Change Modal */}
|
|
318
|
+
<Modal
|
|
319
|
+
isOpen={showPlanChangeModal}
|
|
320
|
+
onClose={() => setShowPlanChangeModal(false)}
|
|
321
|
+
title="Change Subscription Plan"
|
|
322
|
+
size="xl"
|
|
323
|
+
>
|
|
324
|
+
<FormProvider>
|
|
325
|
+
<SingleStepForm
|
|
326
|
+
onSubmit={handlePlanChangeSubmit}
|
|
327
|
+
submitButton={{
|
|
328
|
+
text: "Change Plan",
|
|
329
|
+
disabled: loading
|
|
330
|
+
}}
|
|
331
|
+
realTimeValidation={true}
|
|
332
|
+
className="space-y-6"
|
|
333
|
+
>
|
|
334
|
+
<FormSection title="Select New Plan">
|
|
335
|
+
<FormField
|
|
336
|
+
name="newPlan"
|
|
337
|
+
type="radio"
|
|
338
|
+
label="Choose Your Plan"
|
|
339
|
+
options={[
|
|
340
|
+
{
|
|
341
|
+
value: 'basic',
|
|
342
|
+
label: 'Basic Plan',
|
|
343
|
+
description: 'Perfect for individuals getting started',
|
|
344
|
+
price: '$9/month',
|
|
345
|
+
features: [
|
|
346
|
+
'1,000 AI requests/month',
|
|
347
|
+
'Basic AI models',
|
|
348
|
+
'Email support',
|
|
349
|
+
'5GB storage'
|
|
350
|
+
]
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
value: 'pro',
|
|
354
|
+
label: 'Pro Plan',
|
|
355
|
+
description: 'Best for growing teams and businesses',
|
|
356
|
+
price: '$29/month',
|
|
357
|
+
features: [
|
|
358
|
+
'10,000 AI requests/month',
|
|
359
|
+
'Advanced AI models',
|
|
360
|
+
'Priority support',
|
|
361
|
+
'50GB storage',
|
|
362
|
+
'Team collaboration'
|
|
363
|
+
],
|
|
364
|
+
recommended: true
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
value: 'enterprise',
|
|
368
|
+
label: 'Enterprise Plan',
|
|
369
|
+
description: 'For large organizations',
|
|
370
|
+
price: 'Custom pricing',
|
|
371
|
+
features: [
|
|
372
|
+
'Unlimited AI requests',
|
|
373
|
+
'All AI models',
|
|
374
|
+
'Dedicated support',
|
|
375
|
+
'Unlimited storage',
|
|
376
|
+
'Advanced security'
|
|
377
|
+
]
|
|
378
|
+
}
|
|
379
|
+
]}
|
|
380
|
+
validation={['required']}
|
|
381
|
+
defaultValue="pro"
|
|
382
|
+
/>
|
|
383
|
+
</FormSection>
|
|
384
|
+
|
|
385
|
+
<FormSection title="Billing Options">
|
|
386
|
+
<FormField
|
|
387
|
+
name="billingInterval"
|
|
388
|
+
type="radio"
|
|
389
|
+
label="Billing Frequency"
|
|
390
|
+
options={[
|
|
391
|
+
{ value: 'monthly', label: 'Monthly billing' },
|
|
392
|
+
{ value: 'yearly', label: 'Yearly billing (save 20%)' }
|
|
393
|
+
]}
|
|
394
|
+
defaultValue="monthly"
|
|
395
|
+
validation={['required']}
|
|
396
|
+
/>
|
|
397
|
+
|
|
398
|
+
<FormField
|
|
399
|
+
name="prorationPolicy"
|
|
400
|
+
type="checkbox"
|
|
401
|
+
label="I understand that charges will be prorated for the current billing period"
|
|
402
|
+
validation={['required']}
|
|
403
|
+
/>
|
|
404
|
+
</FormSection>
|
|
405
|
+
|
|
406
|
+
<div className="bg-blue-50 dark:bg-blue-900/20 p-4 rounded-lg">
|
|
407
|
+
<h4 className="font-medium text-blue-900 dark:text-blue-100 mb-2">Plan Change Summary</h4>
|
|
408
|
+
<div className="text-sm text-blue-800 dark:text-blue-200 space-y-1">
|
|
409
|
+
<div>Current plan: Pro Plan ($29/month)</div>
|
|
410
|
+
<div>New plan: Will be calculated based on selection</div>
|
|
411
|
+
<div>Effective date: Immediate</div>
|
|
412
|
+
<div>Next billing date: {formatDate(new Date(Date.now() + 15 * 24 * 60 * 60 * 1000))}</div>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
</SingleStepForm>
|
|
416
|
+
</FormProvider>
|
|
417
|
+
</Modal>
|
|
207
418
|
</div>
|
|
208
419
|
</div>
|
|
209
420
|
);
|