create-bluecopa-react-app 1.0.4 → 1.0.6
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 +47 -10
- package/bin/create-bluecopa-react-app.js +257 -51
- package/package.json +6 -5
- package/templates/latest/Agent.md +254 -0
- package/templates/latest/Dockerfile +22 -0
- package/templates/latest/README.md +157 -221
- package/templates/latest/app/app.css +134 -0
- package/templates/latest/app/app.tsx +46 -0
- package/templates/latest/app/components/app-sidebar.tsx +174 -0
- package/templates/latest/app/components/chart-area-interactive.tsx +290 -0
- package/templates/latest/app/components/data-table.tsx +807 -0
- package/templates/latest/app/components/nav-documents.tsx +92 -0
- package/templates/latest/app/components/nav-main.tsx +56 -0
- package/templates/latest/app/components/nav-secondary.tsx +42 -0
- package/templates/latest/app/components/nav-user.tsx +112 -0
- package/templates/latest/app/components/section-cards.tsx +102 -0
- package/templates/latest/app/components/site-header.tsx +19 -0
- package/templates/latest/app/components/ui/avatar.tsx +53 -0
- package/templates/latest/app/components/ui/badge.tsx +46 -0
- package/templates/latest/app/components/ui/breadcrumb.tsx +109 -0
- package/templates/latest/app/components/ui/button.tsx +58 -0
- package/templates/latest/app/components/ui/card.tsx +92 -0
- package/templates/latest/app/components/ui/chart.tsx +352 -0
- package/templates/latest/app/components/ui/checkbox.tsx +30 -0
- package/templates/latest/app/components/ui/drawer.tsx +139 -0
- package/templates/latest/app/components/ui/dropdown-menu.tsx +258 -0
- package/templates/latest/app/components/ui/input.tsx +21 -0
- package/templates/latest/app/components/ui/label.tsx +24 -0
- package/templates/latest/app/components/ui/select.tsx +183 -0
- package/templates/latest/app/components/ui/separator.tsx +26 -0
- package/templates/latest/app/components/ui/sheet.tsx +139 -0
- package/templates/latest/app/components/ui/sidebar.tsx +731 -0
- package/templates/latest/app/components/ui/skeleton.tsx +13 -0
- package/templates/latest/app/components/ui/sonner.tsx +23 -0
- package/templates/latest/app/components/ui/table.tsx +117 -0
- package/templates/latest/app/components/ui/tabs.tsx +66 -0
- package/templates/latest/app/components/ui/toggle-group.tsx +73 -0
- package/templates/latest/app/components/ui/toggle.tsx +47 -0
- package/templates/latest/app/components/ui/tooltip.tsx +59 -0
- package/templates/latest/app/dashboard/data.json +614 -0
- package/templates/latest/app/hooks/use-bluecopa-user.ts +37 -0
- package/templates/latest/app/hooks/use-mobile.ts +19 -0
- package/templates/latest/{src → app}/lib/utils.ts +1 -1
- package/templates/latest/app/main.tsx +12 -0
- package/templates/latest/app/routes/home.tsx +40 -0
- package/templates/latest/app/routes.tsx +15 -0
- package/templates/latest/{src → app}/single-spa.tsx +38 -28
- package/templates/latest/components.json +22 -0
- package/templates/latest/dist/assets/__federation_expose_App-DRwKKpS2.js +91 -0
- package/templates/latest/dist/assets/__federation_fn_import-CzfA7kmP.js +438 -0
- package/templates/latest/dist/assets/__federation_shared_react-Bp6HVBS4.js +16 -0
- package/templates/latest/dist/assets/__federation_shared_react-dom-BCcRGiYp.js +17 -0
- package/templates/latest/dist/assets/client-DgSav55y.js +12658 -0
- package/templates/latest/dist/assets/home-DOL6GrYV.js +54951 -0
- package/templates/latest/dist/assets/index-BzNimew1.js +69 -0
- package/templates/latest/dist/assets/index-DMFtQdNS.js +412 -0
- package/templates/latest/dist/assets/index-DdYpcDMk.js +60 -0
- package/templates/latest/dist/assets/remoteEntry.js +88 -0
- package/templates/latest/dist/assets/style-36A39bNN.css +3683 -0
- package/templates/latest/dist/avatars/shadcn.svg +6 -0
- package/templates/latest/dist/favicon.ico +0 -0
- package/templates/latest/dist/index.html +19 -0
- package/templates/latest/index.html +1 -1
- package/templates/latest/package-lock.json +1227 -3353
- package/templates/latest/package.json +47 -43
- package/templates/latest/pnpm-lock.yaml +4767 -0
- package/templates/latest/preview/index.html +32 -2
- package/templates/latest/public/avatars/shadcn.svg +6 -0
- package/templates/latest/public/favicon.ico +0 -0
- package/templates/latest/tsconfig.json +18 -11
- package/templates/latest/vite.config.ts +41 -41
- package/templates/latest/.env.example +0 -14
- package/templates/latest/.eslintrc.cjs +0 -42
- package/templates/latest/AGENT.md +0 -284
- package/templates/latest/clean.sh +0 -39
- package/templates/latest/postcss.config.cjs +0 -6
- package/templates/latest/public/bluecopa-logo.svg +0 -30
- package/templates/latest/public/favicon-32x32.png +0 -0
- package/templates/latest/public/favicon-96x96.png +0 -0
- package/templates/latest/setup.sh +0 -55
- package/templates/latest/src/App.tsx +0 -15
- package/templates/latest/src/components/layout/dashboard-header.tsx +0 -139
- package/templates/latest/src/components/layout/dashboard-layout.tsx +0 -29
- package/templates/latest/src/components/layout/sidebar.tsx +0 -54
- package/templates/latest/src/components/page/dashboard.tsx +0 -1506
- package/templates/latest/src/components/page/navbar.tsx +0 -104
- package/templates/latest/src/components/tables/data-grid.tsx +0 -439
- package/templates/latest/src/components/ui/alert.tsx +0 -59
- package/templates/latest/src/components/ui/avatar.tsx +0 -50
- package/templates/latest/src/components/ui/badge.tsx +0 -36
- package/templates/latest/src/components/ui/bluecopa-logo.tsx +0 -54
- package/templates/latest/src/components/ui/button.tsx +0 -58
- package/templates/latest/src/components/ui/card.tsx +0 -79
- package/templates/latest/src/components/ui/dropdown-menu.tsx +0 -200
- package/templates/latest/src/components/ui/input.tsx +0 -24
- package/templates/latest/src/components/ui/label.tsx +0 -23
- package/templates/latest/src/components/ui/select.tsx +0 -29
- package/templates/latest/src/hooks/use-api.ts +0 -55
- package/templates/latest/src/index.css +0 -59
- package/templates/latest/src/main.tsx +0 -13
- package/templates/latest/src/pages/Dashboard.tsx +0 -13
- package/templates/latest/src/pages/Home.tsx +0 -622
- package/templates/latest/src/providers/query-provider.tsx +0 -48
- package/templates/latest/src/types/api.ts +0 -78
- package/templates/latest/src/vite-env.d.ts +0 -11
- package/templates/latest/tailwind.config.js +0 -88
- package/templates/latest/tsconfig.app.json +0 -26
- package/templates/latest/tsconfig.node.json +0 -10
|
@@ -1,622 +0,0 @@
|
|
|
1
|
-
import { Link } from "react-router-dom";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import {
|
|
4
|
-
Card,
|
|
5
|
-
CardContent,
|
|
6
|
-
CardDescription,
|
|
7
|
-
CardHeader,
|
|
8
|
-
CardTitle,
|
|
9
|
-
} from "@/components/ui/card";
|
|
10
|
-
import { Button } from "@/components/ui/button";
|
|
11
|
-
import { Input } from "@/components/ui/input";
|
|
12
|
-
import { Label } from "@/components/ui/label";
|
|
13
|
-
import { Select } from "@/components/ui/select";
|
|
14
|
-
import {
|
|
15
|
-
ArrowRight,
|
|
16
|
-
BarChart3,
|
|
17
|
-
Package,
|
|
18
|
-
Mail,
|
|
19
|
-
Star,
|
|
20
|
-
Truck,
|
|
21
|
-
Users,
|
|
22
|
-
ShoppingCart,
|
|
23
|
-
CreditCard,
|
|
24
|
-
FileText,
|
|
25
|
-
} from "lucide-react";
|
|
26
|
-
import { BluecopaLogo } from "@/components/ui/bluecopa-logo";
|
|
27
|
-
import { useUserData } from "@/hooks/use-api";
|
|
28
|
-
|
|
29
|
-
const stats = [
|
|
30
|
-
{ name: "Automated Processes", value: "284", change: "+12%", trend: "up" },
|
|
31
|
-
{ name: "Time Saved", value: "1,230 hrs", change: "+8%", trend: "up" },
|
|
32
|
-
{ name: "Accuracy Rate", value: "99.8%", change: "+0.5%", trend: "up" },
|
|
33
|
-
{
|
|
34
|
-
name: "Processing Speed",
|
|
35
|
-
value: "85% faster",
|
|
36
|
-
change: "+12%",
|
|
37
|
-
trend: "up",
|
|
38
|
-
},
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
export default function Home() {
|
|
42
|
-
const { data: userData } = useUserData();
|
|
43
|
-
|
|
44
|
-
// Form states
|
|
45
|
-
const [contactForm, setContactForm] = useState({
|
|
46
|
-
name: '',
|
|
47
|
-
email: '',
|
|
48
|
-
message: ''
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const [productForm, setProductForm] = useState({
|
|
52
|
-
name: '',
|
|
53
|
-
category: '',
|
|
54
|
-
price: '',
|
|
55
|
-
description: ''
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const [customerForm, setCustomerForm] = useState({
|
|
59
|
-
firstName: '',
|
|
60
|
-
lastName: '',
|
|
61
|
-
email: '',
|
|
62
|
-
phone: '',
|
|
63
|
-
company: ''
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Extract user from the API response structure
|
|
67
|
-
const user = userData?.user;
|
|
68
|
-
const organization = userData?.organization;
|
|
69
|
-
|
|
70
|
-
// Create display values with proper fallbacks
|
|
71
|
-
const getDisplayName = () => {
|
|
72
|
-
if (!user) return "Loading...";
|
|
73
|
-
|
|
74
|
-
// If firstName and lastName are the same as email, just use email
|
|
75
|
-
if (user.firstName === user.email && user.lastName === user.email) {
|
|
76
|
-
return user.email;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Try to construct name from firstName and lastName
|
|
80
|
-
const fullName = `${user.firstName || ""} ${user.lastName || ""}`.trim();
|
|
81
|
-
return fullName || user.email;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const displayName = getDisplayName();
|
|
85
|
-
const displayRole = organization?.name || "User"; // Use organization name as role
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50">
|
|
89
|
-
{/* Header with user info */}
|
|
90
|
-
<header className="bg-white border-b border-gray-200 sticky top-0 z-50">
|
|
91
|
-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
92
|
-
<div className="flex justify-between items-center h-16">
|
|
93
|
-
<div className="flex items-center space-x-4">
|
|
94
|
-
<BluecopaLogo className="h-6 w-6 text-white" />
|
|
95
|
-
<div>
|
|
96
|
-
<h1 className="text-xl font-bold text-gray-900">Bluecopa</h1>
|
|
97
|
-
<p className="text-sm text-gray-500">Your analytics platform</p>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
|
|
101
|
-
<div className="flex items-center space-x-4">
|
|
102
|
-
<div className="text-right">
|
|
103
|
-
<p className="text-sm font-medium text-gray-900">
|
|
104
|
-
{displayName}
|
|
105
|
-
</p>
|
|
106
|
-
<p className="text-xs text-gray-500">{displayRole}</p>
|
|
107
|
-
</div>
|
|
108
|
-
<div className="w-10 h-10 bg-gray-200 rounded-full flex items-center justify-center">
|
|
109
|
-
<span className="text-sm font-medium text-gray-600">
|
|
110
|
-
{displayName
|
|
111
|
-
.split(" ")
|
|
112
|
-
.map((n: string) => n[0])
|
|
113
|
-
.join("")}
|
|
114
|
-
</span>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
</div>
|
|
118
|
-
</div>
|
|
119
|
-
</header>
|
|
120
|
-
|
|
121
|
-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
122
|
-
{/* Hero Section */}
|
|
123
|
-
<div className="text-center mb-12">
|
|
124
|
-
<h1 className="text-4xl font-bold text-gray-900 mb-4">
|
|
125
|
-
Welcome to Bluecopa
|
|
126
|
-
</h1>
|
|
127
|
-
<p className="text-xl text-gray-600 mb-8 max-w-3xl mx-auto">
|
|
128
|
-
AI-powered close automation for modern finance teams. Streamline
|
|
129
|
-
your order-to-cash, procure-to-pay, and record-to-report processes
|
|
130
|
-
with intelligent automation and real-time insights.
|
|
131
|
-
</p>
|
|
132
|
-
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
|
133
|
-
<Link to="/dashboard">
|
|
134
|
-
<Button size="lg" className="bg-blue-600 hover:bg-blue-700">
|
|
135
|
-
Go to Dashboard
|
|
136
|
-
<ArrowRight className="ml-2 h-4 w-4" />
|
|
137
|
-
</Button>
|
|
138
|
-
</Link>
|
|
139
|
-
<Button variant="outline" size="lg">
|
|
140
|
-
Request Demo
|
|
141
|
-
</Button>
|
|
142
|
-
</div>
|
|
143
|
-
</div>
|
|
144
|
-
|
|
145
|
-
{/* Stats Overview */}
|
|
146
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
|
|
147
|
-
{stats.map((stat, index) => (
|
|
148
|
-
<Card key={index}>
|
|
149
|
-
<CardContent className="pt-6">
|
|
150
|
-
<div className="flex items-center justify-between">
|
|
151
|
-
<div>
|
|
152
|
-
<p className="text-sm font-medium text-gray-600">
|
|
153
|
-
{stat.name}
|
|
154
|
-
</p>
|
|
155
|
-
<p className="text-2xl font-bold text-gray-900">
|
|
156
|
-
{stat.value}
|
|
157
|
-
</p>
|
|
158
|
-
</div>
|
|
159
|
-
<div
|
|
160
|
-
className={`text-sm font-medium ${
|
|
161
|
-
stat.trend === "up" ? "text-green-600" : "text-red-600"
|
|
162
|
-
}`}
|
|
163
|
-
>
|
|
164
|
-
{stat.change}
|
|
165
|
-
</div>
|
|
166
|
-
</div>
|
|
167
|
-
</CardContent>
|
|
168
|
-
</Card>
|
|
169
|
-
))}
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
{/* Recent Activity & Quick Actions */}
|
|
173
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
174
|
-
<Card>
|
|
175
|
-
<CardHeader>
|
|
176
|
-
<CardTitle>Recent Orders</CardTitle>
|
|
177
|
-
<CardDescription>
|
|
178
|
-
Latest customer orders requiring attention
|
|
179
|
-
</CardDescription>
|
|
180
|
-
</CardHeader>
|
|
181
|
-
<CardContent>
|
|
182
|
-
<div className="space-y-4">
|
|
183
|
-
<div className="flex items-center justify-between p-3 bg-gray-50 rounded">
|
|
184
|
-
<div>
|
|
185
|
-
<p className="font-medium">#ORD-2847</p>
|
|
186
|
-
<p className="text-sm text-gray-500">John Doe - $156.99</p>
|
|
187
|
-
</div>
|
|
188
|
-
<div className="flex items-center space-x-2">
|
|
189
|
-
<span className="px-2 py-1 bg-green-100 text-green-800 text-xs rounded-full">
|
|
190
|
-
Paid
|
|
191
|
-
</span>
|
|
192
|
-
<Truck className="h-4 w-4 text-gray-400" />
|
|
193
|
-
</div>
|
|
194
|
-
</div>
|
|
195
|
-
<div className="flex items-center justify-between p-3 bg-gray-50 rounded">
|
|
196
|
-
<div>
|
|
197
|
-
<p className="font-medium">#ORD-2846</p>
|
|
198
|
-
<p className="text-sm text-gray-500">Jane Smith - $89.50</p>
|
|
199
|
-
</div>
|
|
200
|
-
<div className="flex items-center space-x-2">
|
|
201
|
-
<span className="px-2 py-1 bg-yellow-100 text-yellow-800 text-xs rounded-full">
|
|
202
|
-
Processing
|
|
203
|
-
</span>
|
|
204
|
-
<Package className="h-4 w-4 text-gray-400" />
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
<div className="flex items-center justify-between p-3 bg-gray-50 rounded">
|
|
208
|
-
<div>
|
|
209
|
-
<p className="font-medium">#ORD-2845</p>
|
|
210
|
-
<p className="text-sm text-gray-500">
|
|
211
|
-
Mike Johnson - $234.75
|
|
212
|
-
</p>
|
|
213
|
-
</div>
|
|
214
|
-
<div className="flex items-center space-x-2">
|
|
215
|
-
<span className="px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-full">
|
|
216
|
-
Shipped
|
|
217
|
-
</span>
|
|
218
|
-
<Star className="h-4 w-4 text-yellow-400" />
|
|
219
|
-
</div>
|
|
220
|
-
</div>
|
|
221
|
-
</div>
|
|
222
|
-
</CardContent>
|
|
223
|
-
</Card>
|
|
224
|
-
|
|
225
|
-
<Card>
|
|
226
|
-
<CardHeader>
|
|
227
|
-
<CardTitle>Quick Actions</CardTitle>
|
|
228
|
-
<CardDescription>
|
|
229
|
-
Common tasks to help you manage your store
|
|
230
|
-
</CardDescription>
|
|
231
|
-
</CardHeader>
|
|
232
|
-
<CardContent>
|
|
233
|
-
<div className="grid grid-cols-2 gap-4">
|
|
234
|
-
<Button
|
|
235
|
-
variant="outline"
|
|
236
|
-
className="h-20 flex flex-col items-center justify-center"
|
|
237
|
-
>
|
|
238
|
-
<Package className="h-6 w-6 mb-2" />
|
|
239
|
-
<span>Add Product</span>
|
|
240
|
-
</Button>
|
|
241
|
-
<Button
|
|
242
|
-
variant="outline"
|
|
243
|
-
className="h-20 flex flex-col items-center justify-center"
|
|
244
|
-
>
|
|
245
|
-
<Users className="h-6 w-6 mb-2" />
|
|
246
|
-
<span>Add Customer</span>
|
|
247
|
-
</Button>
|
|
248
|
-
<Button
|
|
249
|
-
variant="outline"
|
|
250
|
-
className="h-20 flex flex-col items-center justify-center"
|
|
251
|
-
>
|
|
252
|
-
<BarChart3 className="h-6 w-6 mb-2" />
|
|
253
|
-
<span>View Reports</span>
|
|
254
|
-
</Button>
|
|
255
|
-
<Button
|
|
256
|
-
variant="outline"
|
|
257
|
-
className="h-20 flex flex-col items-center justify-center"
|
|
258
|
-
>
|
|
259
|
-
<ShoppingCart className="h-6 w-6 mb-2" />
|
|
260
|
-
<span>Process Order</span>
|
|
261
|
-
</Button>
|
|
262
|
-
</div>
|
|
263
|
-
</CardContent>
|
|
264
|
-
</Card>
|
|
265
|
-
</div>
|
|
266
|
-
|
|
267
|
-
{/* Form Components Section */}
|
|
268
|
-
<div className="mt-12">
|
|
269
|
-
<div className="text-center mb-8">
|
|
270
|
-
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
|
271
|
-
Form Components Sample
|
|
272
|
-
</h2>
|
|
273
|
-
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
|
|
274
|
-
Sample forms demonstrating various input components and layouts
|
|
275
|
-
</p>
|
|
276
|
-
</div>
|
|
277
|
-
|
|
278
|
-
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
279
|
-
{/* Contact Form */}
|
|
280
|
-
<Card>
|
|
281
|
-
<CardHeader>
|
|
282
|
-
<CardTitle className="flex items-center">
|
|
283
|
-
<Mail className="h-5 w-5 mr-2 text-blue-600" />
|
|
284
|
-
Contact Form
|
|
285
|
-
</CardTitle>
|
|
286
|
-
<CardDescription>
|
|
287
|
-
Basic contact form with validation
|
|
288
|
-
</CardDescription>
|
|
289
|
-
</CardHeader>
|
|
290
|
-
<CardContent className="space-y-4">
|
|
291
|
-
<div>
|
|
292
|
-
<Label htmlFor="contact-name">Name</Label>
|
|
293
|
-
<Input
|
|
294
|
-
id="contact-name"
|
|
295
|
-
placeholder="Enter your name"
|
|
296
|
-
value={contactForm.name}
|
|
297
|
-
onChange={(e) =>
|
|
298
|
-
setContactForm({ ...contactForm, name: e.target.value })
|
|
299
|
-
}
|
|
300
|
-
/>
|
|
301
|
-
</div>
|
|
302
|
-
<div>
|
|
303
|
-
<Label htmlFor="contact-email">Email</Label>
|
|
304
|
-
<Input
|
|
305
|
-
id="contact-email"
|
|
306
|
-
type="email"
|
|
307
|
-
placeholder="Enter your email"
|
|
308
|
-
value={contactForm.email}
|
|
309
|
-
onChange={(e) =>
|
|
310
|
-
setContactForm({ ...contactForm, email: e.target.value })
|
|
311
|
-
}
|
|
312
|
-
/>
|
|
313
|
-
</div>
|
|
314
|
-
<div>
|
|
315
|
-
<Label htmlFor="contact-message">Message</Label>
|
|
316
|
-
<textarea
|
|
317
|
-
id="contact-message"
|
|
318
|
-
className="flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
319
|
-
placeholder="Type your message here..."
|
|
320
|
-
value={contactForm.message}
|
|
321
|
-
onChange={(e) =>
|
|
322
|
-
setContactForm({
|
|
323
|
-
...contactForm,
|
|
324
|
-
message: e.target.value,
|
|
325
|
-
})
|
|
326
|
-
}
|
|
327
|
-
/>
|
|
328
|
-
</div>
|
|
329
|
-
<Button className="w-full bg-blue-600 hover:bg-blue-700">
|
|
330
|
-
<Mail className="mr-2 h-4 w-4" />
|
|
331
|
-
Send Message
|
|
332
|
-
</Button>
|
|
333
|
-
</CardContent>
|
|
334
|
-
</Card>
|
|
335
|
-
|
|
336
|
-
{/* Product Form */}
|
|
337
|
-
<Card>
|
|
338
|
-
<CardHeader>
|
|
339
|
-
<CardTitle className="flex items-center">
|
|
340
|
-
<Package className="h-5 w-5 mr-2 text-green-600" />
|
|
341
|
-
Add Product
|
|
342
|
-
</CardTitle>
|
|
343
|
-
<CardDescription>
|
|
344
|
-
Product creation form with select dropdown
|
|
345
|
-
</CardDescription>
|
|
346
|
-
</CardHeader>
|
|
347
|
-
<CardContent className="space-y-4">
|
|
348
|
-
<div>
|
|
349
|
-
<Label htmlFor="product-name">Product Name</Label>
|
|
350
|
-
<Input
|
|
351
|
-
id="product-name"
|
|
352
|
-
placeholder="Enter product name"
|
|
353
|
-
value={productForm.name}
|
|
354
|
-
onChange={(e) =>
|
|
355
|
-
setProductForm({ ...productForm, name: e.target.value })
|
|
356
|
-
}
|
|
357
|
-
/>
|
|
358
|
-
</div>
|
|
359
|
-
<div>
|
|
360
|
-
<Label htmlFor="product-category">Category</Label>
|
|
361
|
-
<Select
|
|
362
|
-
id="product-category"
|
|
363
|
-
value={productForm.category}
|
|
364
|
-
onChange={(e) =>
|
|
365
|
-
setProductForm({
|
|
366
|
-
...productForm,
|
|
367
|
-
category: e.target.value,
|
|
368
|
-
})
|
|
369
|
-
}
|
|
370
|
-
>
|
|
371
|
-
<option value="">Select a category</option>
|
|
372
|
-
<option value="electronics">Electronics</option>
|
|
373
|
-
<option value="clothing">Clothing</option>
|
|
374
|
-
<option value="books">Books</option>
|
|
375
|
-
<option value="home">Home & Garden</option>
|
|
376
|
-
<option value="sports">Sports</option>
|
|
377
|
-
</Select>
|
|
378
|
-
</div>
|
|
379
|
-
<div>
|
|
380
|
-
<Label htmlFor="product-price">Price</Label>
|
|
381
|
-
<Input
|
|
382
|
-
id="product-price"
|
|
383
|
-
type="number"
|
|
384
|
-
placeholder="0.00"
|
|
385
|
-
value={productForm.price}
|
|
386
|
-
onChange={(e) =>
|
|
387
|
-
setProductForm({ ...productForm, price: e.target.value })
|
|
388
|
-
}
|
|
389
|
-
/>
|
|
390
|
-
</div>
|
|
391
|
-
<div>
|
|
392
|
-
<Label htmlFor="product-description">Description</Label>
|
|
393
|
-
<textarea
|
|
394
|
-
id="product-description"
|
|
395
|
-
className="flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
396
|
-
placeholder="Product description..."
|
|
397
|
-
value={productForm.description}
|
|
398
|
-
onChange={(e) =>
|
|
399
|
-
setProductForm({
|
|
400
|
-
...productForm,
|
|
401
|
-
description: e.target.value,
|
|
402
|
-
})
|
|
403
|
-
}
|
|
404
|
-
/>
|
|
405
|
-
</div>
|
|
406
|
-
<Button className="w-full bg-green-600 hover:bg-green-700">
|
|
407
|
-
<Package className="mr-2 h-4 w-4" />
|
|
408
|
-
Add Product
|
|
409
|
-
</Button>
|
|
410
|
-
</CardContent>
|
|
411
|
-
</Card>
|
|
412
|
-
|
|
413
|
-
{/* Customer Form */}
|
|
414
|
-
<Card>
|
|
415
|
-
<CardHeader>
|
|
416
|
-
<CardTitle className="flex items-center">
|
|
417
|
-
<Users className="h-5 w-5 mr-2 text-purple-600" />
|
|
418
|
-
Customer Details
|
|
419
|
-
</CardTitle>
|
|
420
|
-
<CardDescription>
|
|
421
|
-
Customer information form with multiple fields
|
|
422
|
-
</CardDescription>
|
|
423
|
-
</CardHeader>
|
|
424
|
-
<CardContent className="space-y-4">
|
|
425
|
-
<div className="grid grid-cols-2 gap-4">
|
|
426
|
-
<div>
|
|
427
|
-
<Label htmlFor="customer-firstname">First Name</Label>
|
|
428
|
-
<Input
|
|
429
|
-
id="customer-firstname"
|
|
430
|
-
placeholder="First name"
|
|
431
|
-
value={customerForm.firstName}
|
|
432
|
-
onChange={(e) =>
|
|
433
|
-
setCustomerForm({
|
|
434
|
-
...customerForm,
|
|
435
|
-
firstName: e.target.value,
|
|
436
|
-
})
|
|
437
|
-
}
|
|
438
|
-
/>
|
|
439
|
-
</div>
|
|
440
|
-
<div>
|
|
441
|
-
<Label htmlFor="customer-lastname">Last Name</Label>
|
|
442
|
-
<Input
|
|
443
|
-
id="customer-lastname"
|
|
444
|
-
placeholder="Last name"
|
|
445
|
-
value={customerForm.lastName}
|
|
446
|
-
onChange={(e) =>
|
|
447
|
-
setCustomerForm({
|
|
448
|
-
...customerForm,
|
|
449
|
-
lastName: e.target.value,
|
|
450
|
-
})
|
|
451
|
-
}
|
|
452
|
-
/>
|
|
453
|
-
</div>
|
|
454
|
-
</div>
|
|
455
|
-
<div>
|
|
456
|
-
<Label htmlFor="customer-email">Email</Label>
|
|
457
|
-
<Input
|
|
458
|
-
id="customer-email"
|
|
459
|
-
type="email"
|
|
460
|
-
placeholder="customer@example.com"
|
|
461
|
-
value={customerForm.email}
|
|
462
|
-
onChange={(e) =>
|
|
463
|
-
setCustomerForm({
|
|
464
|
-
...customerForm,
|
|
465
|
-
email: e.target.value,
|
|
466
|
-
})
|
|
467
|
-
}
|
|
468
|
-
/>
|
|
469
|
-
</div>
|
|
470
|
-
<div>
|
|
471
|
-
<Label htmlFor="customer-phone">Phone</Label>
|
|
472
|
-
<Input
|
|
473
|
-
id="customer-phone"
|
|
474
|
-
type="tel"
|
|
475
|
-
placeholder="+1 (555) 123-4567"
|
|
476
|
-
value={customerForm.phone}
|
|
477
|
-
onChange={(e) =>
|
|
478
|
-
setCustomerForm({
|
|
479
|
-
...customerForm,
|
|
480
|
-
phone: e.target.value,
|
|
481
|
-
})
|
|
482
|
-
}
|
|
483
|
-
/>
|
|
484
|
-
</div>
|
|
485
|
-
<div>
|
|
486
|
-
<Label htmlFor="customer-company">Company</Label>
|
|
487
|
-
<Input
|
|
488
|
-
id="customer-company"
|
|
489
|
-
placeholder="Company name (optional)"
|
|
490
|
-
value={customerForm.company}
|
|
491
|
-
onChange={(e) =>
|
|
492
|
-
setCustomerForm({
|
|
493
|
-
...customerForm,
|
|
494
|
-
company: e.target.value,
|
|
495
|
-
})
|
|
496
|
-
}
|
|
497
|
-
/>
|
|
498
|
-
</div>
|
|
499
|
-
<Button className="w-full bg-purple-600 hover:bg-purple-700">
|
|
500
|
-
<Users className="mr-2 h-4 w-4" />
|
|
501
|
-
Save Customer
|
|
502
|
-
</Button>
|
|
503
|
-
</CardContent>
|
|
504
|
-
</Card>
|
|
505
|
-
</div>
|
|
506
|
-
|
|
507
|
-
{/* Additional Form Examples */}
|
|
508
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 mt-8">
|
|
509
|
-
{/* Payment Form */}
|
|
510
|
-
<Card>
|
|
511
|
-
<CardHeader>
|
|
512
|
-
<CardTitle className="flex items-center">
|
|
513
|
-
<CreditCard className="h-5 w-5 mr-2 text-indigo-600" />
|
|
514
|
-
Payment Information
|
|
515
|
-
</CardTitle>
|
|
516
|
-
<CardDescription>
|
|
517
|
-
Credit card and billing details form
|
|
518
|
-
</CardDescription>
|
|
519
|
-
</CardHeader>
|
|
520
|
-
<CardContent className="space-y-4">
|
|
521
|
-
<div>
|
|
522
|
-
<Label htmlFor="card-number">Card Number</Label>
|
|
523
|
-
<Input
|
|
524
|
-
id="card-number"
|
|
525
|
-
placeholder="1234 5678 9012 3456"
|
|
526
|
-
maxLength={19}
|
|
527
|
-
/>
|
|
528
|
-
</div>
|
|
529
|
-
<div className="grid grid-cols-2 gap-4">
|
|
530
|
-
<div>
|
|
531
|
-
<Label htmlFor="expiry">Expiry Date</Label>
|
|
532
|
-
<Input id="expiry" placeholder="MM/YY" maxLength={5} />
|
|
533
|
-
</div>
|
|
534
|
-
<div>
|
|
535
|
-
<Label htmlFor="cvv">CVV</Label>
|
|
536
|
-
<Input id="cvv" placeholder="123" maxLength={4} />
|
|
537
|
-
</div>
|
|
538
|
-
</div>
|
|
539
|
-
<div>
|
|
540
|
-
<Label htmlFor="cardholder">Cardholder Name</Label>
|
|
541
|
-
<Input id="cardholder" placeholder="John Doe" />
|
|
542
|
-
</div>
|
|
543
|
-
<Button className="w-full bg-indigo-600 hover:bg-indigo-700">
|
|
544
|
-
<CreditCard className="mr-2 h-4 w-4" />
|
|
545
|
-
Process Payment
|
|
546
|
-
</Button>
|
|
547
|
-
</CardContent>
|
|
548
|
-
</Card>
|
|
549
|
-
|
|
550
|
-
{/* Settings Form */}
|
|
551
|
-
<Card>
|
|
552
|
-
<CardHeader>
|
|
553
|
-
<CardTitle className="flex items-center">
|
|
554
|
-
<FileText className="h-5 w-5 mr-2 text-orange-600" />
|
|
555
|
-
Settings Form
|
|
556
|
-
</CardTitle>
|
|
557
|
-
<CardDescription>
|
|
558
|
-
Configuration form with checkboxes and switches
|
|
559
|
-
</CardDescription>
|
|
560
|
-
</CardHeader>
|
|
561
|
-
<CardContent className="space-y-4">
|
|
562
|
-
<div>
|
|
563
|
-
<Label htmlFor="store-name">Store Name</Label>
|
|
564
|
-
<Input id="store-name" placeholder="Your Store Name" />
|
|
565
|
-
</div>
|
|
566
|
-
<div>
|
|
567
|
-
<Label htmlFor="timezone">Timezone</Label>
|
|
568
|
-
<Select id="timezone">
|
|
569
|
-
<option value="">Select timezone</option>
|
|
570
|
-
<option value="utc">UTC</option>
|
|
571
|
-
<option value="est">Eastern Standard Time</option>
|
|
572
|
-
<option value="pst">Pacific Standard Time</option>
|
|
573
|
-
<option value="cst">Central Standard Time</option>
|
|
574
|
-
</Select>
|
|
575
|
-
</div>
|
|
576
|
-
<div className="space-y-3">
|
|
577
|
-
<Label>Notifications</Label>
|
|
578
|
-
<div className="space-y-2">
|
|
579
|
-
<div className="flex items-center space-x-2">
|
|
580
|
-
<input
|
|
581
|
-
type="checkbox"
|
|
582
|
-
id="email-notifications"
|
|
583
|
-
className="rounded"
|
|
584
|
-
/>
|
|
585
|
-
<Label htmlFor="email-notifications" className="text-sm">
|
|
586
|
-
Email notifications
|
|
587
|
-
</Label>
|
|
588
|
-
</div>
|
|
589
|
-
<div className="flex items-center space-x-2">
|
|
590
|
-
<input
|
|
591
|
-
type="checkbox"
|
|
592
|
-
id="sms-notifications"
|
|
593
|
-
className="rounded"
|
|
594
|
-
/>
|
|
595
|
-
<Label htmlFor="sms-notifications" className="text-sm">
|
|
596
|
-
SMS notifications
|
|
597
|
-
</Label>
|
|
598
|
-
</div>
|
|
599
|
-
<div className="flex items-center space-x-2">
|
|
600
|
-
<input
|
|
601
|
-
type="checkbox"
|
|
602
|
-
id="push-notifications"
|
|
603
|
-
className="rounded"
|
|
604
|
-
/>
|
|
605
|
-
<Label htmlFor="push-notifications" className="text-sm">
|
|
606
|
-
Push notifications
|
|
607
|
-
</Label>
|
|
608
|
-
</div>
|
|
609
|
-
</div>
|
|
610
|
-
</div>
|
|
611
|
-
<Button className="w-full bg-orange-600 hover:bg-orange-700">
|
|
612
|
-
<FileText className="mr-2 h-4 w-4" />
|
|
613
|
-
Save Settings
|
|
614
|
-
</Button>
|
|
615
|
-
</CardContent>
|
|
616
|
-
</Card>
|
|
617
|
-
</div>
|
|
618
|
-
</div>
|
|
619
|
-
</div>
|
|
620
|
-
</div>
|
|
621
|
-
);
|
|
622
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { ReactQueryDevtools, reactQuery, copaSetConfig } from "@bluecopa/react";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
|
-
|
|
4
|
-
const { QueryClient, QueryClientProvider } = reactQuery;
|
|
5
|
-
|
|
6
|
-
export default function QueryProvider({
|
|
7
|
-
children,
|
|
8
|
-
}: {
|
|
9
|
-
children: React.ReactNode;
|
|
10
|
-
}) {
|
|
11
|
-
const [queryClient] = useState(
|
|
12
|
-
() =>
|
|
13
|
-
new QueryClient({
|
|
14
|
-
defaultOptions: {
|
|
15
|
-
queries: {
|
|
16
|
-
staleTime: 60 * 1000, // 1 minute
|
|
17
|
-
refetchOnWindowFocus: false,
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
})
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
let copaUser: any = {};
|
|
25
|
-
try {
|
|
26
|
-
const copaToken = import.meta.env.VITE_BLUECOPA_API_TOKEN
|
|
27
|
-
? atob(import.meta.env.VITE_BLUECOPA_API_TOKEN)
|
|
28
|
-
: "{}";
|
|
29
|
-
|
|
30
|
-
copaUser = JSON.parse(copaToken);
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.warn("Failed to parse VITE_BLUECOPA_API_TOKEN:", error);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
copaSetConfig({
|
|
36
|
-
apiBaseUrl: import.meta.env.VITE_BLUECOPA_API_URL || "https://develop.bluecopa.com/api/v1",
|
|
37
|
-
workspaceId: import.meta.env.VITE_BLUECOPA_WORKSPACE_ID || "",
|
|
38
|
-
accessToken: copaUser?.accessToken || "",
|
|
39
|
-
});
|
|
40
|
-
}, []);
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<QueryClientProvider client={queryClient}>
|
|
44
|
-
{children}
|
|
45
|
-
<ReactQueryDevtools initialIsOpen={false} />
|
|
46
|
-
</QueryClientProvider>
|
|
47
|
-
);
|
|
48
|
-
}
|