@digilogiclabs/create-saas-app 2.10.0 → 2.11.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.
Files changed (60) hide show
  1. package/README.md +153 -113
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/cli/commands/create.d.ts.map +1 -1
  4. package/dist/cli/commands/create.js +2 -6
  5. package/dist/cli/commands/create.js.map +1 -1
  6. package/dist/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
  7. package/dist/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
  8. package/dist/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
  9. package/dist/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
  10. package/dist/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
  11. package/dist/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
  12. package/dist/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
  13. package/dist/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
  14. package/dist/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
  15. package/dist/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
  16. package/dist/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
  17. package/dist/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
  18. package/dist/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
  19. package/dist/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
  20. package/dist/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
  21. package/dist/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
  22. package/dist/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
  23. package/dist/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
  24. package/dist/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
  25. package/dist/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
  26. package/dist/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
  27. package/dist/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
  28. package/dist/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
  29. package/dist/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
  30. package/dist/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
  31. package/dist/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
  32. package/dist/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
  33. package/package.json +1 -1
  34. package/src/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
  35. package/src/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
  36. package/src/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
  37. package/src/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
  38. package/src/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
  39. package/src/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
  40. package/src/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
  41. package/src/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
  42. package/src/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
  43. package/src/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
  44. package/src/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
  45. package/src/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
  46. package/src/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
  47. package/src/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
  48. package/src/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
  49. package/src/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
  50. package/src/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
  51. package/src/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
  52. package/src/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
  53. package/src/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
  54. package/src/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
  55. package/src/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
  56. package/src/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
  57. package/src/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
  58. package/src/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
  59. package/src/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
  60. package/src/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
@@ -0,0 +1,160 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { Button, Card } from '@digilogiclabs/saas-factory-ui'
5
+ import { Package, ChevronDown, ChevronUp, ShoppingBag } from 'lucide-react'
6
+ import Link from 'next/link'
7
+
8
+ interface OrderItem {
9
+ name: string
10
+ vendor: string
11
+ price: number
12
+ quantity: number
13
+ }
14
+
15
+ interface Order {
16
+ id: string
17
+ date: string
18
+ status: 'Delivered' | 'Processing' | 'Shipped'
19
+ total: number
20
+ items: OrderItem[]
21
+ }
22
+
23
+ const ORDERS: Order[] = [
24
+ {
25
+ id: 'ORD-2024-001',
26
+ date: 'Mar 15, 2024',
27
+ status: 'Delivered',
28
+ total: 179.98,
29
+ items: [
30
+ { name: 'Premium Widget Pro', vendor: 'TechCo', price: 49.99, quantity: 1 },
31
+ { name: 'Developer Toolkit', vendor: 'DevTools', price: 129.99, quantity: 1 },
32
+ ],
33
+ },
34
+ {
35
+ id: 'ORD-2024-002',
36
+ date: 'Mar 18, 2024',
37
+ status: 'Shipped',
38
+ total: 79.99,
39
+ items: [
40
+ { name: 'UI Design Pack', vendor: 'CreativeStudio', price: 79.99, quantity: 1 },
41
+ ],
42
+ },
43
+ {
44
+ id: 'ORD-2024-003',
45
+ date: 'Mar 20, 2024',
46
+ status: 'Processing',
47
+ total: 239.97,
48
+ items: [
49
+ { name: 'Analytics Dashboard', vendor: 'DataCorp', price: 199.99, quantity: 1 },
50
+ { name: 'Marketing Templates', vendor: 'GrowthLab', price: 39.99, quantity: 1 },
51
+ ],
52
+ },
53
+ ]
54
+
55
+ const STATUS_STYLES: Record<Order['status'], string> = {
56
+ Delivered: 'bg-green-500/10 text-green-600',
57
+ Processing: 'bg-blue-500/10 text-blue-600',
58
+ Shipped: 'bg-amber-500/10 text-amber-600',
59
+ }
60
+
61
+ function OrderCard({ order }: { order: Order }) {
62
+ const [expanded, setExpanded] = useState(false)
63
+
64
+ return (
65
+ <Card className="overflow-hidden">
66
+ <button
67
+ onClick={() => setExpanded(!expanded)}
68
+ className="w-full p-6 text-left cursor-pointer"
69
+ >
70
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
71
+ <div className="flex items-center gap-4">
72
+ <div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0">
73
+ <Package className="w-5 h-5 text-primary" />
74
+ </div>
75
+ <div>
76
+ <p className="font-semibold text-foreground">{order.id}</p>
77
+ <p className="text-sm text-muted-foreground">{order.date}</p>
78
+ </div>
79
+ </div>
80
+
81
+ <div className="flex items-center gap-4 sm:gap-6">
82
+ <span className={`px-3 py-1 text-xs font-medium rounded-full ${STATUS_STYLES[order.status]}`}>
83
+ {order.status}
84
+ </span>
85
+ <span className="text-sm text-muted-foreground">
86
+ {order.items.length} {order.items.length === 1 ? 'item' : 'items'}
87
+ </span>
88
+ <span className="font-bold text-foreground">${order.total.toFixed(2)}</span>
89
+ {expanded ? (
90
+ <ChevronUp className="w-4 h-4 text-muted-foreground" />
91
+ ) : (
92
+ <ChevronDown className="w-4 h-4 text-muted-foreground" />
93
+ )}
94
+ </div>
95
+ </div>
96
+ </button>
97
+
98
+ {expanded && (
99
+ <div className="border-t border-border px-6 pb-6">
100
+ <div className="space-y-3 pt-4">
101
+ {order.items.map((item, index) => (
102
+ <div key={index} className="flex items-center gap-4">
103
+ <div className="w-12 h-12 bg-muted rounded-lg flex-shrink-0" />
104
+ <div className="flex-1">
105
+ <p className="font-medium text-foreground">{item.name}</p>
106
+ <p className="text-sm text-muted-foreground">by {item.vendor}</p>
107
+ </div>
108
+ <div className="text-right">
109
+ <p className="font-medium text-foreground">${item.price.toFixed(2)}</p>
110
+ <p className="text-sm text-muted-foreground">Qty: {item.quantity}</p>
111
+ </div>
112
+ </div>
113
+ ))}
114
+ </div>
115
+ </div>
116
+ )}
117
+ </Card>
118
+ )
119
+ }
120
+
121
+ export default function OrdersPage() {
122
+ // Note: In production, wrap with requireAuth() in a server component parent
123
+ // or use a layout-level auth check. This page uses 'use client' for expand/collapse.
124
+ const orders = ORDERS
125
+
126
+ return (
127
+ <div className="min-h-screen bg-background">
128
+ <div className="max-w-4xl mx-auto px-4 py-8">
129
+ {/* Header */}
130
+ <div className="mb-8">
131
+ <h1 className="text-3xl font-bold text-foreground">Your Orders</h1>
132
+ <p className="text-muted-foreground mt-1">
133
+ {orders.length} {orders.length === 1 ? 'order' : 'orders'}
134
+ </p>
135
+ </div>
136
+
137
+ {orders.length === 0 ? (
138
+ <Card className="p-12 text-center">
139
+ <ShoppingBag className="w-16 h-16 mx-auto mb-4 text-muted-foreground" />
140
+ <h2 className="text-xl font-semibold text-foreground mb-2">
141
+ No orders yet
142
+ </h2>
143
+ <p className="text-muted-foreground mb-6">
144
+ When you make a purchase, your orders will appear here.
145
+ </p>
146
+ <Link href="/products">
147
+ <Button>Browse Products</Button>
148
+ </Link>
149
+ </Card>
150
+ ) : (
151
+ <div className="space-y-4">
152
+ {orders.map((order) => (
153
+ <OrderCard key={order.id} order={order} />
154
+ ))}
155
+ </div>
156
+ )}
157
+ </div>
158
+ </div>
159
+ )
160
+ }
@@ -0,0 +1,218 @@
1
+ import { Button, Card } from '@digilogiclabs/saas-factory-ui'
2
+ import { ArrowLeft, Star, ShoppingCart, MessageCircle, ShoppingBag } from 'lucide-react'
3
+ import Link from 'next/link'
4
+
5
+ const PRODUCTS: Record<string, {
6
+ id: string
7
+ name: string
8
+ price: number
9
+ vendor: string
10
+ rating: number
11
+ reviews: number
12
+ category: string
13
+ description: string
14
+ features: string[]
15
+ }> = {
16
+ '1': {
17
+ id: '1',
18
+ name: 'Premium Widget Pro',
19
+ price: 49.99,
20
+ vendor: 'TechCo',
21
+ rating: 4.8,
22
+ reviews: 124,
23
+ category: 'Software',
24
+ description: 'A comprehensive widget toolkit that helps developers build beautiful, responsive interfaces in minutes. Includes 50+ pre-built components, dark mode support, and full TypeScript definitions. Perfect for startups and teams looking to ship faster without sacrificing quality.',
25
+ features: ['50+ Pre-built Components', 'Dark Mode Support', 'TypeScript Definitions', 'Lifetime Updates'],
26
+ },
27
+ '2': {
28
+ id: '2',
29
+ name: 'Developer Toolkit',
30
+ price: 129.99,
31
+ vendor: 'DevTools',
32
+ rating: 4.9,
33
+ reviews: 87,
34
+ category: 'Software',
35
+ description: 'The ultimate developer toolkit packed with debugging utilities, code generators, and productivity boosters. Streamline your development workflow with intelligent code analysis, automated refactoring tools, and seamless CI/CD integration.',
36
+ features: ['Code Generator', 'Debugging Utilities', 'CI/CD Integration', 'Team Collaboration'],
37
+ },
38
+ '3': {
39
+ id: '3',
40
+ name: 'UI Design Pack',
41
+ price: 79.99,
42
+ vendor: 'CreativeStudio',
43
+ rating: 4.7,
44
+ reviews: 203,
45
+ category: 'Templates',
46
+ description: 'A stunning collection of UI design templates for web and mobile applications. Each template is fully customizable and built with modern design principles. Includes Figma source files, responsive layouts, and component documentation.',
47
+ features: ['Figma Source Files', 'Responsive Layouts', 'Component Docs', '100+ Screens'],
48
+ },
49
+ '4': {
50
+ id: '4',
51
+ name: 'Analytics Dashboard',
52
+ price: 199.99,
53
+ vendor: 'DataCorp',
54
+ rating: 4.6,
55
+ reviews: 56,
56
+ category: 'Software',
57
+ description: 'Real-time analytics dashboard with advanced data visualization capabilities. Track key metrics, create custom reports, and share insights with your team. Supports multiple data sources and provides AI-powered trend analysis.',
58
+ features: ['Real-time Analytics', 'Custom Reports', 'AI Trend Analysis', 'Multi-source Support'],
59
+ },
60
+ '5': {
61
+ id: '5',
62
+ name: 'Marketing Templates',
63
+ price: 39.99,
64
+ vendor: 'GrowthLab',
65
+ rating: 4.5,
66
+ reviews: 312,
67
+ category: 'Templates',
68
+ description: 'Ready-to-use marketing templates for landing pages, email campaigns, and social media. Conversion-optimized designs backed by A/B testing data from thousands of campaigns.',
69
+ features: ['Landing Pages', 'Email Templates', 'Social Media Kit', 'A/B Tested Designs'],
70
+ },
71
+ }
72
+
73
+ const RELATED_PRODUCTS = [
74
+ { id: '2', name: 'Developer Toolkit', price: 129.99, vendor: 'DevTools', rating: 4.9, category: 'Software' },
75
+ { id: '3', name: 'UI Design Pack', price: 79.99, vendor: 'CreativeStudio', rating: 4.7, category: 'Templates' },
76
+ { id: '5', name: 'Marketing Templates', price: 39.99, vendor: 'GrowthLab', rating: 4.5, category: 'Templates' },
77
+ ]
78
+
79
+ function StarRating({ rating, reviews }: { rating: number; reviews: number }) {
80
+ return (
81
+ <div className="flex items-center gap-2">
82
+ <div className="flex items-center">
83
+ {[...Array(5)].map((_, i) => (
84
+ <Star
85
+ key={i}
86
+ className={`w-5 h-5 ${
87
+ i < Math.floor(rating)
88
+ ? 'text-amber-500 fill-amber-500'
89
+ : i < rating
90
+ ? 'text-amber-500 fill-amber-500/50'
91
+ : 'text-muted-foreground/30'
92
+ }`}
93
+ />
94
+ ))}
95
+ </div>
96
+ <span className="text-sm text-muted-foreground">
97
+ {rating} ({reviews} reviews)
98
+ </span>
99
+ </div>
100
+ )
101
+ }
102
+
103
+ export default async function ProductDetailPage({
104
+ params,
105
+ }: {
106
+ params: Promise<{ id: string }>
107
+ }) {
108
+ const { id } = await params
109
+ const product = PRODUCTS[id] || PRODUCTS['1']
110
+
111
+ const relatedProducts = RELATED_PRODUCTS.filter(p => p.id !== product.id).slice(0, 3)
112
+
113
+ return (
114
+ <div className="min-h-screen bg-background">
115
+ <div className="max-w-7xl mx-auto px-4 py-8">
116
+ {/* Back Link */}
117
+ <Link
118
+ href="/products"
119
+ className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground mb-6 transition-colors"
120
+ >
121
+ <ArrowLeft className="w-4 h-4 mr-1" />
122
+ Back to Products
123
+ </Link>
124
+
125
+ {/* Product Detail */}
126
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-16">
127
+ {/* Product Image */}
128
+ <div className="aspect-video bg-muted rounded-xl flex items-center justify-center border border-border">
129
+ <div className="text-center">
130
+ <ShoppingBag className="w-16 h-16 mx-auto text-muted-foreground/30 mb-2" />
131
+ <p className="text-sm text-muted-foreground">Product Preview</p>
132
+ </div>
133
+ </div>
134
+
135
+ {/* Product Info */}
136
+ <div>
137
+ <div className="mb-4">
138
+ <span className="inline-block px-3 py-1 text-xs font-medium bg-primary text-primary-foreground rounded-full mb-3">
139
+ {product.category}
140
+ </span>
141
+ <h1 className="text-2xl font-bold text-foreground mb-2">
142
+ {product.name}
143
+ </h1>
144
+ <p className="text-muted-foreground">
145
+ by {product.vendor}
146
+ </p>
147
+ </div>
148
+
149
+ <StarRating rating={product.rating} reviews={product.reviews} />
150
+
151
+ <p className="text-3xl font-bold text-primary mt-4 mb-6">
152
+ ${product.price}
153
+ </p>
154
+
155
+ <p className="text-muted-foreground leading-relaxed mb-6">
156
+ {product.description}
157
+ </p>
158
+
159
+ {/* Features */}
160
+ <div className="mb-6">
161
+ <h3 className="text-sm font-semibold text-foreground mb-3">What&apos;s Included</h3>
162
+ <ul className="grid grid-cols-2 gap-2">
163
+ {product.features.map((feature) => (
164
+ <li key={feature} className="flex items-center text-sm text-muted-foreground">
165
+ <span className="w-1.5 h-1.5 bg-primary rounded-full mr-2 flex-shrink-0" />
166
+ {feature}
167
+ </li>
168
+ ))}
169
+ </ul>
170
+ </div>
171
+
172
+ {/* Actions */}
173
+ <div className="flex gap-3">
174
+ <Button size="lg" className="flex-1">
175
+ <ShoppingCart className="w-4 h-4 mr-2" />
176
+ Add to Cart
177
+ </Button>
178
+ <Button variant="outline" size="lg" className="flex-1">
179
+ <MessageCircle className="w-4 h-4 mr-2" />
180
+ Contact Vendor
181
+ </Button>
182
+ </div>
183
+ </div>
184
+ </div>
185
+
186
+ {/* Related Products */}
187
+ <div>
188
+ <h2 className="text-2xl font-bold text-foreground mb-6">Related Products</h2>
189
+ <div className="grid grid-cols-1 sm:grid-cols-3 gap-6">
190
+ {relatedProducts.map((item) => (
191
+ <Card key={item.id} className="overflow-hidden hover:shadow-lg transition-shadow">
192
+ <div className="aspect-square bg-muted relative">
193
+ <span className="absolute top-2 left-2 bg-primary text-primary-foreground text-xs px-2 py-1 rounded">
194
+ {item.category}
195
+ </span>
196
+ </div>
197
+ <div className="p-4">
198
+ <h3 className="font-semibold text-foreground mb-1">{item.name}</h3>
199
+ <p className="text-sm text-muted-foreground mb-2">by {item.vendor}</p>
200
+ <div className="flex items-center justify-between mb-3">
201
+ <span className="text-lg font-bold text-primary">${item.price}</span>
202
+ <div className="flex items-center text-amber-500">
203
+ <Star className="w-4 h-4 fill-current" />
204
+ <span className="text-sm ml-1">{item.rating}</span>
205
+ </div>
206
+ </div>
207
+ <Link href={`/products/${item.id}`}>
208
+ <Button variant="outline" size="sm" className="w-full">View Details</Button>
209
+ </Link>
210
+ </div>
211
+ </Card>
212
+ ))}
213
+ </div>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ )
218
+ }
@@ -0,0 +1,150 @@
1
+ import { Button, Card } from '@digilogiclabs/saas-factory-ui'
2
+ import { User, Bell, CreditCard } from 'lucide-react'
3
+ import { requireAuth } from '@/lib/auth-server'
4
+
5
+ function ToggleSwitch({ defaultChecked = false }: { defaultChecked?: boolean }) {
6
+ return (
7
+ <label className="relative inline-flex items-center cursor-pointer">
8
+ <input type="checkbox" className="sr-only peer" defaultChecked={defaultChecked} />
9
+ <div className="w-11 h-6 bg-muted rounded-full peer peer-checked:bg-primary peer-focus:ring-2 peer-focus:ring-ring after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-background after:border after:border-border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full" />
10
+ </label>
11
+ )
12
+ }
13
+
14
+ export default async function SettingsPage() {
15
+ const user = await requireAuth()
16
+
17
+ return (
18
+ <div className="min-h-screen bg-background">
19
+ <div className="max-w-3xl mx-auto px-4 py-8">
20
+ {/* Header */}
21
+ <div className="mb-8">
22
+ <h1 className="text-3xl font-bold text-foreground">Settings</h1>
23
+ <p className="text-muted-foreground mt-1">
24
+ Manage your account preferences
25
+ </p>
26
+ </div>
27
+
28
+ <div className="space-y-6">
29
+ {/* Profile Section */}
30
+ <Card className="p-6">
31
+ <div className="flex items-center gap-3 mb-6">
32
+ <User className="w-5 h-5 text-primary" />
33
+ <h2 className="text-lg font-semibold text-foreground">Profile</h2>
34
+ </div>
35
+
36
+ <div className="space-y-4">
37
+ {/* Avatar */}
38
+ <div className="flex items-center gap-4 mb-6">
39
+ <div className="w-16 h-16 bg-muted rounded-full flex items-center justify-center border border-border">
40
+ <User className="w-8 h-8 text-muted-foreground" />
41
+ </div>
42
+ <Button variant="outline" size="sm">Change Avatar</Button>
43
+ </div>
44
+
45
+ {/* Name */}
46
+ <div>
47
+ <label htmlFor="name" className="block text-sm font-medium text-foreground mb-1.5">
48
+ Display Name
49
+ </label>
50
+ <input
51
+ id="name"
52
+ type="text"
53
+ defaultValue={user.name || ''}
54
+ placeholder="Your name"
55
+ className="w-full px-4 py-2 border border-input rounded-lg focus:ring-2 focus:ring-ring bg-background text-foreground"
56
+ />
57
+ </div>
58
+
59
+ {/* Email (read-only) */}
60
+ <div>
61
+ <label htmlFor="email" className="block text-sm font-medium text-foreground mb-1.5">
62
+ Email Address
63
+ </label>
64
+ <input
65
+ id="email"
66
+ type="email"
67
+ value={user.email || ''}
68
+ readOnly
69
+ className="w-full px-4 py-2 border border-input rounded-lg bg-muted text-muted-foreground cursor-not-allowed"
70
+ />
71
+ <p className="text-xs text-muted-foreground mt-1">
72
+ Email cannot be changed. Contact support if you need to update it.
73
+ </p>
74
+ </div>
75
+ </div>
76
+ </Card>
77
+
78
+ {/* Notification Preferences */}
79
+ <Card className="p-6">
80
+ <div className="flex items-center gap-3 mb-6">
81
+ <Bell className="w-5 h-5 text-primary" />
82
+ <h2 className="text-lg font-semibold text-foreground">Notifications</h2>
83
+ </div>
84
+
85
+ <div className="space-y-4">
86
+ <div className="flex items-center justify-between py-2">
87
+ <div>
88
+ <p className="font-medium text-foreground">Order Updates</p>
89
+ <p className="text-sm text-muted-foreground">
90
+ Get notified when your order status changes
91
+ </p>
92
+ </div>
93
+ <ToggleSwitch defaultChecked />
94
+ </div>
95
+
96
+ <div className="border-t border-border" />
97
+
98
+ <div className="flex items-center justify-between py-2">
99
+ <div>
100
+ <p className="font-medium text-foreground">Marketing Emails</p>
101
+ <p className="text-sm text-muted-foreground">
102
+ Receive deals, promotions, and product recommendations
103
+ </p>
104
+ </div>
105
+ <ToggleSwitch />
106
+ </div>
107
+
108
+ <div className="border-t border-border" />
109
+
110
+ <div className="flex items-center justify-between py-2">
111
+ <div>
112
+ <p className="font-medium text-foreground">Vendor Messages</p>
113
+ <p className="text-sm text-muted-foreground">
114
+ Get notified when a vendor replies to your message
115
+ </p>
116
+ </div>
117
+ <ToggleSwitch defaultChecked />
118
+ </div>
119
+ </div>
120
+ </Card>
121
+
122
+ {/* Payment Methods */}
123
+ <Card className="p-6">
124
+ <div className="flex items-center gap-3 mb-6">
125
+ <CreditCard className="w-5 h-5 text-primary" />
126
+ <h2 className="text-lg font-semibold text-foreground">Payment Methods</h2>
127
+ </div>
128
+
129
+ <div className="text-center py-6">
130
+ <CreditCard className="w-12 h-12 mx-auto mb-3 text-muted-foreground/50" />
131
+ <p className="text-muted-foreground mb-4">
132
+ No payment methods saved yet
133
+ </p>
134
+ <Button variant="outline">
135
+ Add Payment Method
136
+ </Button>
137
+ </div>
138
+ </Card>
139
+
140
+ {/* Save Button */}
141
+ <div className="flex justify-end">
142
+ <Button size="lg">
143
+ Save Changes
144
+ </Button>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ )
150
+ }
@@ -0,0 +1,133 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { Button, Card, CardContent } from '@digilogiclabs/saas-factory-ui'
5
+ import { ShoppingBag } from 'lucide-react'
6
+ import { useRouter } from 'next/navigation'
7
+ import Link from 'next/link'
8
+
9
+ export default function SignupPage() {
10
+ const [email, setEmail] = useState('')
11
+ const [password, setPassword] = useState('')
12
+ const [confirmPassword, setConfirmPassword] = useState('')
13
+ const [error, setError] = useState('')
14
+ const [loading, setLoading] = useState(false)
15
+ const router = useRouter()
16
+
17
+ const handleSubmit = async (e: React.FormEvent) => {
18
+ e.preventDefault()
19
+ setError('')
20
+ if (password !== confirmPassword) {
21
+ setError('Passwords do not match')
22
+ return
23
+ }
24
+ setLoading(true)
25
+ try {
26
+ const res = await fetch('/api/auth', {
27
+ method: 'POST',
28
+ headers: { 'Content-Type': 'application/json' },
29
+ body: JSON.stringify({ email, password, action: 'signup' }),
30
+ })
31
+ if (!res.ok) {
32
+ const data = await res.json()
33
+ throw new Error(data.error || 'Failed to create account')
34
+ }
35
+ router.push('/dashboard')
36
+ router.refresh()
37
+ } catch (err) {
38
+ setError(err instanceof Error ? err.message : 'Failed to create account')
39
+ } finally {
40
+ setLoading(false)
41
+ }
42
+ }
43
+
44
+ return (
45
+ <div className="min-h-screen flex items-center justify-center bg-background px-4">
46
+ <div className="w-full max-w-md">
47
+ {/* Logo */}
48
+ <Link href="/" className="flex items-center justify-center gap-2 mb-8 hover:opacity-80 transition-opacity">
49
+ <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-brand-from via-brand-via to-brand-to flex items-center justify-center">
50
+ <ShoppingBag className="w-5 h-5 text-white" />
51
+ </div>
52
+ <span className="font-bold text-xl">Marketplace</span>
53
+ </Link>
54
+
55
+ <Card className="border border-border">
56
+ <CardContent className="p-8">
57
+ <div className="text-center mb-8">
58
+ <h1 className="text-2xl font-bold">Create your account</h1>
59
+ <p className="text-muted-foreground mt-2">Start buying and selling today</p>
60
+ </div>
61
+
62
+ {error && (
63
+ <div className="bg-destructive/10 text-destructive p-3 rounded-lg mb-6 text-sm" role="alert">
64
+ {error}
65
+ </div>
66
+ )}
67
+
68
+ <form onSubmit={handleSubmit} className="space-y-4">
69
+ <div>
70
+ <label htmlFor="email" className="block text-sm font-medium mb-1.5">
71
+ Email
72
+ </label>
73
+ <input
74
+ id="email"
75
+ type="email"
76
+ value={email}
77
+ onChange={(e) => setEmail(e.target.value)}
78
+ className="w-full px-3 py-2.5 rounded-lg border border-input bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-shadow"
79
+ placeholder="you@example.com"
80
+ required
81
+ />
82
+ </div>
83
+
84
+ <div>
85
+ <label htmlFor="password" className="block text-sm font-medium mb-1.5">
86
+ Password
87
+ </label>
88
+ <input
89
+ id="password"
90
+ type="password"
91
+ value={password}
92
+ onChange={(e) => setPassword(e.target.value)}
93
+ className="w-full px-3 py-2.5 rounded-lg border border-input bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-shadow"
94
+ placeholder="Minimum 8 characters"
95
+ required
96
+ minLength={8}
97
+ />
98
+ </div>
99
+
100
+ <div>
101
+ <label htmlFor="confirmPassword" className="block text-sm font-medium mb-1.5">
102
+ Confirm Password
103
+ </label>
104
+ <input
105
+ id="confirmPassword"
106
+ type="password"
107
+ value={confirmPassword}
108
+ onChange={(e) => setConfirmPassword(e.target.value)}
109
+ className="w-full px-3 py-2.5 rounded-lg border border-input bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-shadow"
110
+ placeholder="Re-enter your password"
111
+ required
112
+ />
113
+ </div>
114
+
115
+ <Button type="submit" className="w-full h-11 text-base cursor-pointer hover:brightness-110 active:scale-[0.98] transition-all duration-200" disabled={loading}>
116
+ {loading ? 'Creating account...' : 'Create Account'}
117
+ </Button>
118
+ </form>
119
+
120
+ <div className="mt-6 text-center">
121
+ <p className="text-muted-foreground text-sm">
122
+ Already have an account?{' '}
123
+ <Link href="/login" className="text-primary hover:underline font-medium">
124
+ Sign in
125
+ </Link>
126
+ </p>
127
+ </div>
128
+ </CardContent>
129
+ </Card>
130
+ </div>
131
+ </div>
132
+ )
133
+ }