@digilogiclabs/create-saas-app 2.8.0 → 2.9.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/dist/.tsbuildinfo +1 -1
- package/dist/generators/template-generator.js +8 -8
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/shared/quality/web/src/__tests__/accessibility.test.tsx +3 -3
- package/dist/templates/web/ai-platform/template/src/app/page.tsx +207 -207
- package/dist/templates/web/base/template/package.json +1 -3
- package/dist/templates/web/base/template/src/app/auth/callback/route.ts +32 -18
- package/dist/templates/web/base/template/src/app/dashboard/page.tsx +6 -43
- package/dist/templates/web/base/template/src/app/globals.css +158 -157
- package/dist/templates/web/base/template/src/app/page.tsx +2 -2
- package/dist/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +800 -800
- package/dist/templates/web/ui-auth/template/src/app/globals.css +96 -95
- package/dist/templates/web/ui-auth/template/src/app/login/page.tsx +109 -109
- package/dist/templates/web/ui-auth/template/src/app/page.tsx +4 -3
- package/dist/templates/web/ui-auth/template/src/app/signup/page.tsx +128 -128
- package/dist/templates/web/ui-auth-ai/template/src/app/globals.css +35 -40
- package/dist/templates/web/ui-auth-ai/template/src/app/layout.tsx +1 -0
- package/dist/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +3 -3
- package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +10 -49
- package/dist/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +800 -800
- package/dist/templates/web/ui-auth-payments/template/src/app/globals.css +212 -211
- package/dist/templates/web/ui-auth-payments/template/src/app/login/page.tsx +109 -109
- package/dist/templates/web/ui-auth-payments/template/src/app/page.tsx +350 -350
- package/dist/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +506 -506
- package/dist/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +128 -128
- package/dist/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +143 -143
- package/dist/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +184 -184
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +143 -233
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +10 -50
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +800 -800
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/globals.css +97 -96
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +325 -364
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +1 -1
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +389 -532
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +644 -644
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +119 -163
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +158 -201
- package/dist/templates/web/ui-auth-payments-ai-rag/template/package.json +1 -2
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +10 -51
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/globals.css +97 -96
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +402 -403
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +143 -143
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +184 -184
- package/dist/templates/web/ui-auth-payments-video/template/src/app/globals.css +229 -228
- package/dist/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +1 -1
- package/dist/templates/web/ui-auth-payments-video/template/src/app/page.tsx +4 -7
- package/dist/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +1 -1
- package/dist/templates/web/ui-only/template/src/app/globals.css +43 -42
- package/package.json +1 -1
- package/src/templates/shared/quality/web/src/__tests__/accessibility.test.tsx +3 -3
- package/src/templates/web/ai-platform/template/src/app/page.tsx +207 -207
- package/src/templates/web/base/template/package.json +1 -3
- package/src/templates/web/base/template/src/app/auth/callback/route.ts +32 -18
- package/src/templates/web/base/template/src/app/dashboard/page.tsx +6 -43
- package/src/templates/web/base/template/src/app/globals.css +158 -157
- package/src/templates/web/base/template/src/app/page.tsx +2 -2
- package/src/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +800 -800
- package/src/templates/web/ui-auth/template/src/app/globals.css +96 -95
- package/src/templates/web/ui-auth/template/src/app/login/page.tsx +109 -109
- package/src/templates/web/ui-auth/template/src/app/page.tsx +4 -3
- package/src/templates/web/ui-auth/template/src/app/signup/page.tsx +128 -128
- package/src/templates/web/ui-auth-ai/template/src/app/globals.css +35 -40
- package/src/templates/web/ui-auth-ai/template/src/app/layout.tsx +1 -0
- package/src/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +3 -3
- package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +10 -49
- package/src/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +800 -800
- package/src/templates/web/ui-auth-payments/template/src/app/globals.css +212 -211
- package/src/templates/web/ui-auth-payments/template/src/app/login/page.tsx +109 -109
- package/src/templates/web/ui-auth-payments/template/src/app/page.tsx +350 -350
- package/src/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +506 -506
- package/src/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +128 -128
- package/src/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +143 -143
- package/src/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +184 -184
- package/src/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +143 -233
- package/src/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +10 -50
- package/src/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +800 -800
- package/src/templates/web/ui-auth-payments-ai/template/src/app/globals.css +97 -96
- package/src/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +325 -364
- package/src/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +1 -1
- package/src/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +389 -532
- package/src/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +644 -644
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +119 -163
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +158 -201
- package/src/templates/web/ui-auth-payments-ai-rag/template/package.json +1 -2
- package/src/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +10 -51
- package/src/templates/web/ui-auth-payments-audio/template/src/app/globals.css +97 -96
- package/src/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +402 -403
- package/src/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +143 -143
- package/src/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +184 -184
- package/src/templates/web/ui-auth-payments-video/template/src/app/globals.css +229 -228
- package/src/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +1 -1
- package/src/templates/web/ui-auth-payments-video/template/src/app/page.tsx +4 -7
- package/src/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +1 -1
- package/src/templates/web/ui-only/template/src/app/globals.css +43 -42
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
4
|
import { usePayments } from '@digilogiclabs/app-sdk';
|
|
5
5
|
import { formatCurrency, formatDate } from '@/lib/utils';
|
|
6
|
-
import {
|
|
7
|
-
Button,
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
8
|
Card,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
FormSection,
|
|
12
|
-
FormProvider,
|
|
9
|
+
Input,
|
|
10
|
+
Label,
|
|
13
11
|
Modal
|
|
14
12
|
} from '@digilogiclabs/saas-factory-ui';
|
|
15
13
|
|
|
@@ -18,6 +16,7 @@ export default function BillingPage() {
|
|
|
18
16
|
const [showPaymentMethodModal, setShowPaymentMethodModal] = useState(false);
|
|
19
17
|
const [showPlanChangeModal, setShowPlanChangeModal] = useState(false);
|
|
20
18
|
const [editingPaymentMethod, setEditingPaymentMethod] = useState<string | null>(null);
|
|
19
|
+
const [selectedPlan, setSelectedPlan] = useState('pro');
|
|
21
20
|
|
|
22
21
|
const handleSubscriptionChange = () => {
|
|
23
22
|
setShowPlanChangeModal(true);
|
|
@@ -30,23 +29,24 @@ export default function BillingPage() {
|
|
|
30
29
|
|
|
31
30
|
const handleInvoiceDownload = (invoiceId: string) => {
|
|
32
31
|
console.log('Download invoice:', invoiceId);
|
|
33
|
-
// Handle invoice download
|
|
34
32
|
};
|
|
35
33
|
|
|
36
|
-
const handlePaymentMethodSubmit = async (
|
|
34
|
+
const handlePaymentMethodSubmit = async (e: React.FormEvent) => {
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
const formData = new FormData(e.target as HTMLFormElement);
|
|
37
37
|
console.log('Payment method data:', Object.fromEntries(formData));
|
|
38
|
-
// Handle payment method creation/update
|
|
39
38
|
setShowPaymentMethodModal(false);
|
|
40
39
|
setEditingPaymentMethod(null);
|
|
41
40
|
};
|
|
42
41
|
|
|
43
|
-
const handlePlanChangeSubmit = async (
|
|
42
|
+
const handlePlanChangeSubmit = async (e: React.FormEvent) => {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
const formData = new FormData(e.target as HTMLFormElement);
|
|
44
45
|
console.log('Plan change data:', Object.fromEntries(formData));
|
|
45
|
-
// Handle plan change
|
|
46
46
|
setShowPlanChangeModal(false);
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
// Mock
|
|
49
|
+
// Mock data
|
|
50
50
|
const currentSubscription = {
|
|
51
51
|
plan: 'Pro Plan',
|
|
52
52
|
price: 1999,
|
|
@@ -55,64 +55,31 @@ export default function BillingPage() {
|
|
|
55
55
|
nextBilling: new Date(Date.now() + 15 * 24 * 60 * 60 * 1000)
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
// Mock payment methods - in real app this would come from your backend
|
|
59
58
|
const paymentMethods = [
|
|
60
|
-
{
|
|
61
|
-
|
|
62
|
-
type: 'card',
|
|
63
|
-
last4: '4242',
|
|
64
|
-
brand: 'visa',
|
|
65
|
-
expiryMonth: 12,
|
|
66
|
-
expiryYear: 2025,
|
|
67
|
-
isDefault: true
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: 'pm_456',
|
|
71
|
-
type: 'card',
|
|
72
|
-
last4: '0005',
|
|
73
|
-
brand: 'mastercard',
|
|
74
|
-
expiryMonth: 8,
|
|
75
|
-
expiryYear: 2026,
|
|
76
|
-
isDefault: false
|
|
77
|
-
}
|
|
59
|
+
{ id: 'pm_123', type: 'card', last4: '4242', brand: 'visa', expiryMonth: 12, expiryYear: 2025, isDefault: true },
|
|
60
|
+
{ id: 'pm_456', type: 'card', last4: '0005', brand: 'mastercard', expiryMonth: 8, expiryYear: 2026, isDefault: false }
|
|
78
61
|
];
|
|
79
62
|
|
|
80
|
-
// Mock billing history - in real app this would come from your backend
|
|
81
63
|
const invoices = [
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
id: 'inv_456',
|
|
92
|
-
amount: 1999,
|
|
93
|
-
currency: 'usd',
|
|
94
|
-
status: 'paid',
|
|
95
|
-
date: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000),
|
|
96
|
-
description: 'Pro Plan - Monthly'
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
id: 'inv_789',
|
|
100
|
-
amount: 999,
|
|
101
|
-
currency: 'usd',
|
|
102
|
-
status: 'paid',
|
|
103
|
-
date: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000),
|
|
104
|
-
description: 'Basic Plan - Monthly'
|
|
105
|
-
}
|
|
64
|
+
{ id: 'inv_123', amount: 1999, currency: 'usd', status: 'paid', date: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), description: 'Pro Plan - Monthly' },
|
|
65
|
+
{ id: 'inv_456', amount: 1999, currency: 'usd', status: 'paid', date: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000), description: 'Pro Plan - Monthly' },
|
|
66
|
+
{ id: 'inv_789', amount: 999, currency: 'usd', status: 'paid', date: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000), description: 'Basic Plan - Monthly' }
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
const plans = [
|
|
70
|
+
{ value: 'basic', label: 'Basic Plan', price: '$9/month', description: 'Perfect for individuals getting started', features: ['1,000 AI requests/month', 'Basic AI models', 'Email support', '5GB storage'] },
|
|
71
|
+
{ value: 'pro', label: 'Pro Plan', price: '$29/month', description: 'Best for growing teams and businesses', features: ['10,000 AI requests/month', 'Advanced AI models', 'Priority support', '50GB storage', 'Team collaboration'], recommended: true },
|
|
72
|
+
{ value: 'enterprise', label: 'Enterprise Plan', price: 'Custom pricing', description: 'For large organizations', features: ['Unlimited AI requests', 'All AI models', 'Dedicated support', 'Unlimited storage', 'Advanced security'] }
|
|
106
73
|
];
|
|
107
74
|
|
|
108
75
|
return (
|
|
109
76
|
<div className="min-h-screen bg-gray-100 py-8">
|
|
110
77
|
<div className="max-w-7xl mx-auto px-4">
|
|
111
78
|
<div className="mb-8">
|
|
112
|
-
<h1 className="text-4xl font-bold text-gray-900 mb-2">Billing & Subscription</h1>
|
|
79
|
+
<h1 className="text-4xl font-bold text-gray-900 mb-2">Billing & Subscription</h1>
|
|
113
80
|
<p className="text-xl text-gray-600">Manage your subscription and billing information</p>
|
|
114
81
|
</div>
|
|
115
|
-
|
|
82
|
+
|
|
116
83
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
|
|
117
84
|
{/* Current Subscription */}
|
|
118
85
|
<Card className="p-6">
|
|
@@ -135,7 +102,7 @@ export default function BillingPage() {
|
|
|
135
102
|
<p className="text-sm text-gray-600">Next billing date</p>
|
|
136
103
|
<p>{formatDate(currentSubscription.nextBilling)}</p>
|
|
137
104
|
</div>
|
|
138
|
-
<Button
|
|
105
|
+
<Button
|
|
139
106
|
onClick={handleSubscriptionChange}
|
|
140
107
|
disabled={loading}
|
|
141
108
|
variant="outline"
|
|
@@ -154,11 +121,11 @@ export default function BillingPage() {
|
|
|
154
121
|
<div key={method.id} className="flex items-center justify-between p-3 border rounded-lg">
|
|
155
122
|
<div className="flex items-center">
|
|
156
123
|
<div className="w-8 h-8 bg-blue-100 rounded flex items-center justify-center mr-3">
|
|
157
|
-
|
|
124
|
+
<span role="img" aria-label="credit card">💳</span>
|
|
158
125
|
</div>
|
|
159
126
|
<div>
|
|
160
127
|
<p className="font-medium">
|
|
161
|
-
{method.brand.toUpperCase()}
|
|
128
|
+
{method.brand.toUpperCase()} •••• {method.last4}
|
|
162
129
|
</p>
|
|
163
130
|
<p className="text-sm text-gray-600">
|
|
164
131
|
Expires {method.expiryMonth}/{method.expiryYear}
|
|
@@ -166,8 +133,8 @@ export default function BillingPage() {
|
|
|
166
133
|
</p>
|
|
167
134
|
</div>
|
|
168
135
|
</div>
|
|
169
|
-
<Button
|
|
170
|
-
onClick={handlePaymentMethodUpdate}
|
|
136
|
+
<Button
|
|
137
|
+
onClick={() => handlePaymentMethodUpdate(method.id)}
|
|
171
138
|
disabled={loading}
|
|
172
139
|
variant="outline"
|
|
173
140
|
size="sm"
|
|
@@ -176,8 +143,8 @@ export default function BillingPage() {
|
|
|
176
143
|
</Button>
|
|
177
144
|
</div>
|
|
178
145
|
))}
|
|
179
|
-
<Button
|
|
180
|
-
onClick={handlePaymentMethodUpdate}
|
|
146
|
+
<Button
|
|
147
|
+
onClick={() => handlePaymentMethodUpdate()}
|
|
181
148
|
disabled={loading}
|
|
182
149
|
variant="outline"
|
|
183
150
|
className="w-full"
|
|
@@ -232,87 +199,60 @@ export default function BillingPage() {
|
|
|
232
199
|
{/* Payment Method Modal */}
|
|
233
200
|
<Modal
|
|
234
201
|
isOpen={showPaymentMethodModal}
|
|
235
|
-
onClose={() => {
|
|
236
|
-
setShowPaymentMethodModal(false);
|
|
237
|
-
setEditingPaymentMethod(null);
|
|
238
|
-
}}
|
|
202
|
+
onClose={() => { setShowPaymentMethodModal(false); setEditingPaymentMethod(null); }}
|
|
239
203
|
title={editingPaymentMethod ? "Edit Payment Method" : "Add Payment Method"}
|
|
240
|
-
size="lg"
|
|
241
204
|
>
|
|
242
|
-
<
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
className="space-y-4"
|
|
251
|
-
>
|
|
252
|
-
<FormSection title="Card Information">
|
|
253
|
-
<FormField
|
|
254
|
-
name="cardNumber"
|
|
255
|
-
type="creditCard"
|
|
256
|
-
label="Card Number"
|
|
257
|
-
placeholder="1234 5678 9012 3456"
|
|
258
|
-
validation={['required', 'creditCard']}
|
|
259
|
-
disabled={loading}
|
|
260
|
-
/>
|
|
261
|
-
|
|
205
|
+
<form onSubmit={handlePaymentMethodSubmit} className="space-y-4">
|
|
206
|
+
<div>
|
|
207
|
+
<h3 className="font-semibold mb-3">Card Information</h3>
|
|
208
|
+
<div className="space-y-3">
|
|
209
|
+
<div>
|
|
210
|
+
<Label htmlFor="cardNumber">Card Number</Label>
|
|
211
|
+
<Input id="cardNumber" name="cardNumber" placeholder="1234 5678 9012 3456" required disabled={loading} />
|
|
212
|
+
</div>
|
|
262
213
|
<div className="grid grid-cols-2 gap-4">
|
|
263
|
-
<
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
disabled={loading}
|
|
270
|
-
|
|
271
|
-
<FormField
|
|
272
|
-
name="cvc"
|
|
273
|
-
type="text"
|
|
274
|
-
label="CVC"
|
|
275
|
-
placeholder="123"
|
|
276
|
-
validation={['required', 'cvc']}
|
|
277
|
-
disabled={loading}
|
|
278
|
-
/>
|
|
214
|
+
<div>
|
|
215
|
+
<Label htmlFor="expiryDate">Expiry Date</Label>
|
|
216
|
+
<Input id="expiryDate" name="expiryDate" placeholder="MM/YY" required disabled={loading} />
|
|
217
|
+
</div>
|
|
218
|
+
<div>
|
|
219
|
+
<Label htmlFor="cvc">CVC</Label>
|
|
220
|
+
<Input id="cvc" name="cvc" placeholder="123" required disabled={loading} />
|
|
221
|
+
</div>
|
|
279
222
|
</div>
|
|
280
|
-
</
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
placeholder="Full name as it appears on card"
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
</FormSection>
|
|
314
|
-
</SingleStepForm>
|
|
315
|
-
</FormProvider>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
<div>
|
|
226
|
+
<h3 className="font-semibold mb-3">Billing Information</h3>
|
|
227
|
+
<div className="space-y-3">
|
|
228
|
+
<div>
|
|
229
|
+
<Label htmlFor="cardholderName">Cardholder Name</Label>
|
|
230
|
+
<Input id="cardholderName" name="cardholderName" placeholder="Full name as it appears on card" required disabled={loading} />
|
|
231
|
+
</div>
|
|
232
|
+
<div>
|
|
233
|
+
<Label htmlFor="billingAddress">Street Address</Label>
|
|
234
|
+
<Input id="billingAddress" name="billingAddress" placeholder="Street address" required disabled={loading} />
|
|
235
|
+
</div>
|
|
236
|
+
<div className="grid grid-cols-2 gap-4">
|
|
237
|
+
<div>
|
|
238
|
+
<Label htmlFor="city">City</Label>
|
|
239
|
+
<Input id="city" name="city" placeholder="City" required disabled={loading} />
|
|
240
|
+
</div>
|
|
241
|
+
<div>
|
|
242
|
+
<Label htmlFor="postalCode">ZIP/Postal Code</Label>
|
|
243
|
+
<Input id="postalCode" name="postalCode" placeholder="ZIP/Postal code" required disabled={loading} />
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
<label className="flex items-center gap-2">
|
|
247
|
+
<input type="checkbox" name="makeDefault" className="rounded" />
|
|
248
|
+
<span className="text-sm">Make this my default payment method</span>
|
|
249
|
+
</label>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
<Button type="submit" className="w-full" disabled={loading}>
|
|
253
|
+
{editingPaymentMethod ? "Update Payment Method" : "Add Payment Method"}
|
|
254
|
+
</Button>
|
|
255
|
+
</form>
|
|
316
256
|
</Modal>
|
|
317
257
|
|
|
318
258
|
{/* Plan Change Modal */}
|
|
@@ -320,104 +260,74 @@ export default function BillingPage() {
|
|
|
320
260
|
isOpen={showPlanChangeModal}
|
|
321
261
|
onClose={() => setShowPlanChangeModal(false)}
|
|
322
262
|
title="Change Subscription Plan"
|
|
323
|
-
size="xl"
|
|
324
263
|
>
|
|
325
|
-
<
|
|
326
|
-
<
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
description: 'Best for growing teams and businesses',
|
|
357
|
-
price: '$29/month',
|
|
358
|
-
features: [
|
|
359
|
-
'10,000 AI requests/month',
|
|
360
|
-
'Advanced AI models',
|
|
361
|
-
'Priority support',
|
|
362
|
-
'50GB storage',
|
|
363
|
-
'Team collaboration'
|
|
364
|
-
],
|
|
365
|
-
recommended: true
|
|
366
|
-
},
|
|
367
|
-
{
|
|
368
|
-
value: 'enterprise',
|
|
369
|
-
label: 'Enterprise Plan',
|
|
370
|
-
description: 'For large organizations',
|
|
371
|
-
price: 'Custom pricing',
|
|
372
|
-
features: [
|
|
373
|
-
'Unlimited AI requests',
|
|
374
|
-
'All AI models',
|
|
375
|
-
'Dedicated support',
|
|
376
|
-
'Unlimited storage',
|
|
377
|
-
'Advanced security'
|
|
378
|
-
]
|
|
379
|
-
}
|
|
380
|
-
]}
|
|
381
|
-
validation={['required']}
|
|
382
|
-
defaultValue="pro"
|
|
383
|
-
/>
|
|
384
|
-
</FormSection>
|
|
264
|
+
<form onSubmit={handlePlanChangeSubmit} className="space-y-6">
|
|
265
|
+
<div>
|
|
266
|
+
<h3 className="font-semibold mb-3">Select New Plan</h3>
|
|
267
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
268
|
+
{plans.map(plan => (
|
|
269
|
+
<label
|
|
270
|
+
key={plan.value}
|
|
271
|
+
className={`relative block p-4 border-2 rounded-xl cursor-pointer hover:border-primary transition-colors ${selectedPlan === plan.value ? 'border-primary bg-primary/5' : 'border-gray-200 dark:border-gray-700'}`}
|
|
272
|
+
>
|
|
273
|
+
<input
|
|
274
|
+
type="radio"
|
|
275
|
+
name="newPlan"
|
|
276
|
+
value={plan.value}
|
|
277
|
+
checked={selectedPlan === plan.value}
|
|
278
|
+
onChange={(e) => setSelectedPlan(e.target.value)}
|
|
279
|
+
className="sr-only"
|
|
280
|
+
required
|
|
281
|
+
/>
|
|
282
|
+
{plan.recommended && (
|
|
283
|
+
<span className="absolute -top-3 left-1/2 -translate-x-1/2 bg-primary text-primary-foreground text-xs px-2 py-1 rounded-full">Recommended</span>
|
|
284
|
+
)}
|
|
285
|
+
<h4 className="font-semibold">{plan.label}</h4>
|
|
286
|
+
<p className="text-2xl font-bold my-2">{plan.price}</p>
|
|
287
|
+
<p className="text-sm text-gray-600 mb-2">{plan.description}</p>
|
|
288
|
+
<ul className="text-sm space-y-1">
|
|
289
|
+
{plan.features.map(f => <li key={f}>✓ {f}</li>)}
|
|
290
|
+
</ul>
|
|
291
|
+
</label>
|
|
292
|
+
))}
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
385
295
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
296
|
+
<div>
|
|
297
|
+
<h3 className="font-semibold mb-3">Billing Frequency</h3>
|
|
298
|
+
<div className="space-y-2">
|
|
299
|
+
<label className="flex items-center gap-2">
|
|
300
|
+
<input type="radio" name="billingInterval" value="monthly" defaultChecked required />
|
|
301
|
+
<span className="text-sm">Monthly billing</span>
|
|
302
|
+
</label>
|
|
303
|
+
<label className="flex items-center gap-2">
|
|
304
|
+
<input type="radio" name="billingInterval" value="yearly" />
|
|
305
|
+
<span className="text-sm">Yearly billing (save 20%)</span>
|
|
306
|
+
</label>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
398
309
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
validation={['required']}
|
|
404
|
-
/>
|
|
405
|
-
</FormSection>
|
|
310
|
+
<label className="flex items-center gap-2">
|
|
311
|
+
<input type="checkbox" name="prorationPolicy" required className="rounded" />
|
|
312
|
+
<span className="text-sm">I understand that charges will be prorated for the current billing period</span>
|
|
313
|
+
</label>
|
|
406
314
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
</div>
|
|
315
|
+
<div className="bg-blue-50 dark:bg-blue-900/20 p-4 rounded-lg">
|
|
316
|
+
<h4 className="font-medium text-blue-900 dark:text-blue-100 mb-2">Plan Change Summary</h4>
|
|
317
|
+
<div className="text-sm text-blue-800 dark:text-blue-200 space-y-1">
|
|
318
|
+
<div>Current plan: Pro Plan ($29/month)</div>
|
|
319
|
+
<div>New plan: Will be calculated based on selection</div>
|
|
320
|
+
<div>Effective date: Immediate</div>
|
|
321
|
+
<div>Next billing date: {formatDate(new Date(Date.now() + 15 * 24 * 60 * 60 * 1000))}</div>
|
|
415
322
|
</div>
|
|
416
|
-
</
|
|
417
|
-
|
|
323
|
+
</div>
|
|
324
|
+
|
|
325
|
+
<Button type="submit" className="w-full" disabled={loading}>
|
|
326
|
+
Change Plan
|
|
327
|
+
</Button>
|
|
328
|
+
</form>
|
|
418
329
|
</Modal>
|
|
419
330
|
</div>
|
|
420
331
|
</div>
|
|
421
332
|
);
|
|
422
333
|
}
|
|
423
|
-
|
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
import { Suspense } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
Button,
|
|
4
|
-
Card,
|
|
5
|
-
DashboardLayout
|
|
6
|
-
CommandPalette,
|
|
7
|
-
Tour
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
DashboardLayout
|
|
8
6
|
} from '@digilogiclabs/saas-factory-ui'
|
|
9
|
-
import {
|
|
10
|
-
User,
|
|
11
|
-
Settings,
|
|
12
|
-
CreditCard,
|
|
13
|
-
Activity
|
|
14
|
-
Home,
|
|
15
|
-
Brain,
|
|
16
|
-
Users,
|
|
17
|
-
BarChart,
|
|
18
|
-
Plus,
|
|
19
|
-
Search
|
|
7
|
+
import {
|
|
8
|
+
User,
|
|
9
|
+
Settings,
|
|
10
|
+
CreditCard,
|
|
11
|
+
Activity
|
|
20
12
|
} from 'lucide-react'
|
|
21
13
|
import { requireAuth } from '@/lib/auth-server'
|
|
22
14
|
import Link from 'next/link'
|
|
@@ -107,40 +99,8 @@ export default async function DashboardPage() {
|
|
|
107
99
|
// Server-side authentication requirement
|
|
108
100
|
const user = await requireAuth()
|
|
109
101
|
|
|
110
|
-
const sidebarNavigation = [
|
|
111
|
-
{ name: 'Overview', href: '/dashboard', icon: Home, current: true },
|
|
112
|
-
{ name: 'Profile', href: '/profile', icon: User },
|
|
113
|
-
{ name: 'Settings', href: '/settings', icon: Settings },
|
|
114
|
-
{ name: 'Billing', href: '/billing', icon: CreditCard },
|
|
115
|
-
{ name: 'Analytics', href: '/analytics', icon: BarChart }
|
|
116
|
-
]
|
|
117
|
-
|
|
118
|
-
const tourSteps = [
|
|
119
|
-
{
|
|
120
|
-
target: '[data-tour="overview"]',
|
|
121
|
-
title: 'Dashboard Overview',
|
|
122
|
-
content: 'Get a quick overview of your account stats and recent activity.'
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
target: '[data-tour="stats"]',
|
|
126
|
-
title: 'Account Statistics',
|
|
127
|
-
content: 'View your key metrics and performance indicators here.'
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
target: '[data-tour="actions"]',
|
|
131
|
-
title: 'Quick Actions',
|
|
132
|
-
content: 'Access your most commonly used features from these cards.'
|
|
133
|
-
}
|
|
134
|
-
]
|
|
135
|
-
|
|
136
102
|
return (
|
|
137
|
-
<DashboardLayout
|
|
138
|
-
navigation={sidebarNavigation}
|
|
139
|
-
headerActions={[
|
|
140
|
-
<CommandPalette key="command-palette" />,
|
|
141
|
-
<Tour key="tour" steps={tourSteps} />
|
|
142
|
-
]}
|
|
143
|
-
>
|
|
103
|
+
<DashboardLayout>
|
|
144
104
|
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
|
145
105
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
146
106
|
{/* Header */}
|