@tscircuit/fake-snippets 0.0.67 → 0.0.68
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/bun.lock +19 -66
- package/dist/bundle.js +1 -1
- package/package.json +2 -3
- package/src/App.tsx +0 -4
- package/src/components/CmdKMenu.tsx +19 -19
- package/src/components/FAQ.tsx +3 -1
- package/src/components/FileSidebar.tsx +50 -1
- package/src/components/Header2.tsx +20 -9
- package/src/components/JLCPCBImportDialog.tsx +13 -16
- package/src/components/ViewPackagePage/components/important-files-view.tsx +1 -1
- package/src/components/ViewPackagePage/components/package-header.tsx +1 -1
- package/src/components/dialogs/confirm-delete-package-dialog.tsx +8 -0
- package/src/components/dialogs/edit-package-details-dialog.tsx +145 -138
- package/src/components/package-port/CodeAndPreview.tsx +40 -19
- package/src/components/package-port/CodeEditor.tsx +8 -27
- package/src/components/package-port/EditorNav.tsx +1 -11
- package/src/hooks/useFileManagement.ts +59 -0
- package/src/lib/utils/isValidFileName.ts +5 -0
- package/src/pages/dashboard.tsx +1 -0
- package/src/pages/quickstart.tsx +5 -5
- package/src/pages/search.tsx +1 -1
- package/src/pages/user-profile.tsx +1 -0
- package/src/components/OrderPreviewContent.tsx +0 -61
- package/src/components/ViewSnippetSidebar.tsx +0 -162
- package/src/components/dialogs/create-order-dialog.tsx +0 -146
- package/src/pages/preview.tsx +0 -44
- package/src/pages/view-order.tsx +0 -111
package/src/pages/quickstart.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { useQuery } from "react-query"
|
|
|
3
3
|
import { useAxios } from "@/hooks/use-axios"
|
|
4
4
|
import Header from "@/components/Header"
|
|
5
5
|
import Footer from "@/components/Footer"
|
|
6
|
-
import { Package
|
|
6
|
+
import { Package } from "fake-snippets-api/lib/db/schema"
|
|
7
7
|
import { Button } from "@/components/ui/button"
|
|
8
8
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
|
9
9
|
import { TypeBadge } from "@/components/TypeBadge"
|
|
@@ -48,7 +48,7 @@ export const QuickstartPage = () => {
|
|
|
48
48
|
<Header />
|
|
49
49
|
<div className="container mx-auto px-4 py-8">
|
|
50
50
|
<div className="mb-8 hidden md:block">
|
|
51
|
-
<h2 className="text-xl font-semibold mb-4">Recent
|
|
51
|
+
<h2 className="text-xl font-semibold mb-4">Recent Packages</h2>
|
|
52
52
|
{isLoading ? (
|
|
53
53
|
<div>Loading...</div>
|
|
54
54
|
) : (
|
|
@@ -63,7 +63,7 @@ export const QuickstartPage = () => {
|
|
|
63
63
|
.map((pkg) => (
|
|
64
64
|
<PrefetchPageLink
|
|
65
65
|
key={pkg.package_id}
|
|
66
|
-
href={`/editor?
|
|
66
|
+
href={`/editor?package_id=${pkg.package_id}`}
|
|
67
67
|
>
|
|
68
68
|
<Card className="hover:shadow-md transition-shadow rounded-md flex flex-col h-full">
|
|
69
69
|
<CardHeader className="pb-0 p-4">
|
|
@@ -85,7 +85,7 @@ export const QuickstartPage = () => {
|
|
|
85
85
|
</div>
|
|
86
86
|
|
|
87
87
|
<div className="mb-8">
|
|
88
|
-
<h2 className="text-xl font-semibold mb-4">Start Blank
|
|
88
|
+
<h2 className="text-xl font-semibold mb-4">Start Blank Packages</h2>
|
|
89
89
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
90
90
|
{blankTemplates.map((template, index) => (
|
|
91
91
|
<PrefetchPageLink
|
|
@@ -117,7 +117,7 @@ export const QuickstartPage = () => {
|
|
|
117
117
|
</div>
|
|
118
118
|
|
|
119
119
|
<div className="mt-12">
|
|
120
|
-
<h2 className="text-xl font-semibold mb-4">Import as
|
|
120
|
+
<h2 className="text-xl font-semibold mb-4">Import as Package</h2>
|
|
121
121
|
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
|
122
122
|
{[
|
|
123
123
|
{ name: "KiCad Footprint", type: "footprint" },
|
package/src/pages/search.tsx
CHANGED
|
@@ -97,7 +97,7 @@ export const SearchPage = () => {
|
|
|
97
97
|
<div className="mb-6">
|
|
98
98
|
<div className="flex items-center gap-2 mb-3">
|
|
99
99
|
<h1 className="text-3xl font-bold text-gray-900">
|
|
100
|
-
Search
|
|
100
|
+
Search Packages
|
|
101
101
|
</h1>
|
|
102
102
|
</div>
|
|
103
103
|
<div className="flex flex-col sm:flex-row gap-4 mb-4">
|
|
@@ -212,6 +212,7 @@ export const UserProfilePage = () => {
|
|
|
212
212
|
<DeleteDialog
|
|
213
213
|
packageId={packageToDelete.package_id}
|
|
214
214
|
packageName={packageToDelete.unscoped_name}
|
|
215
|
+
packageOwner={packageToDelete.owner_github_username ?? ""}
|
|
215
216
|
refetchUserPackages={refetchUserPackages}
|
|
216
217
|
/>
|
|
217
218
|
)}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import React from "react"
|
|
2
|
-
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
|
3
|
-
import { PCBViewer } from "@tscircuit/pcb-viewer"
|
|
4
|
-
import { CadViewer } from "@tscircuit/3d-viewer"
|
|
5
|
-
import { CircuitJsonTableViewer } from "./TableViewer/CircuitJsonTableViewer"
|
|
6
|
-
import { AnyCircuitElement } from "circuit-json"
|
|
7
|
-
|
|
8
|
-
interface OrderPreviewContentProps {
|
|
9
|
-
circuitJson: AnyCircuitElement[] | null
|
|
10
|
-
className?: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const OrderPreviewContent: React.FC<OrderPreviewContentProps> = ({
|
|
14
|
-
circuitJson,
|
|
15
|
-
className,
|
|
16
|
-
}) => {
|
|
17
|
-
return (
|
|
18
|
-
<div className={className}>
|
|
19
|
-
<Tabs defaultValue="pcb" className="w-full">
|
|
20
|
-
<TabsList>
|
|
21
|
-
<TabsTrigger value="pcb">PCB</TabsTrigger>
|
|
22
|
-
<TabsTrigger value="cad">3D</TabsTrigger>
|
|
23
|
-
<TabsTrigger value="json-table">JSON</TabsTrigger>
|
|
24
|
-
</TabsList>
|
|
25
|
-
<TabsContent value="pcb">
|
|
26
|
-
<div className="h-[500px] shadow overflow-hidden sm:rounded-lg mb-6">
|
|
27
|
-
{circuitJson ? (
|
|
28
|
-
<PCBViewer height={500} circuitJson={circuitJson} />
|
|
29
|
-
) : (
|
|
30
|
-
<div className="flex items-center justify-center h-full bg-gray-100">
|
|
31
|
-
No PCB data available
|
|
32
|
-
</div>
|
|
33
|
-
)}
|
|
34
|
-
</div>
|
|
35
|
-
</TabsContent>
|
|
36
|
-
<TabsContent value="cad">
|
|
37
|
-
<div className="h-[500px] shadow overflow-hidden sm:rounded-lg mb-6">
|
|
38
|
-
{circuitJson ? (
|
|
39
|
-
<CadViewer soup={circuitJson as any} />
|
|
40
|
-
) : (
|
|
41
|
-
<div className="flex items-center justify-center h-full bg-gray-100">
|
|
42
|
-
No 3D data available
|
|
43
|
-
</div>
|
|
44
|
-
)}
|
|
45
|
-
</div>
|
|
46
|
-
</TabsContent>
|
|
47
|
-
<TabsContent value="json-table">
|
|
48
|
-
<div className="h-[500px] shadow overflow-hidden sm:rounded-lg mb-6">
|
|
49
|
-
{circuitJson ? (
|
|
50
|
-
<CircuitJsonTableViewer elements={circuitJson} />
|
|
51
|
-
) : (
|
|
52
|
-
<div className="flex items-center justify-center h-full bg-gray-100">
|
|
53
|
-
No JSON data available
|
|
54
|
-
</div>
|
|
55
|
-
)}
|
|
56
|
-
</div>
|
|
57
|
-
</TabsContent>
|
|
58
|
-
</Tabs>
|
|
59
|
-
</div>
|
|
60
|
-
)
|
|
61
|
-
}
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"
|
|
2
|
-
import { useCurrentSnippet } from "@/hooks/use-current-snippet"
|
|
3
|
-
import { useToast } from "@/hooks/use-toast"
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
5
|
-
import { AtSign, Bot, Clock, Code, File, GitFork, Package } from "lucide-react"
|
|
6
|
-
import { useFilesDialog } from "./dialogs/files-dialog"
|
|
7
|
-
import { PrefetchPageLink } from "./PrefetchPageLink"
|
|
8
|
-
|
|
9
|
-
export default function ViewSnippetSidebar({
|
|
10
|
-
className,
|
|
11
|
-
}: {
|
|
12
|
-
className?: string
|
|
13
|
-
}) {
|
|
14
|
-
const { snippet } = useCurrentSnippet()
|
|
15
|
-
const { toast } = useToast()
|
|
16
|
-
const { Dialog: FilesDialog, openDialog: openFilesDialog } = useFilesDialog()
|
|
17
|
-
const { copyToClipboard } = useCopyToClipboard()
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<div
|
|
21
|
-
className={cn(
|
|
22
|
-
"w-64 h-full bg-gray-100 text-gray-700 flex flex-col flex-shrink-0",
|
|
23
|
-
"hidden sm:block h-screen sticky top-0",
|
|
24
|
-
className,
|
|
25
|
-
)}
|
|
26
|
-
>
|
|
27
|
-
<nav className="flex-grow overflow-y-auto">
|
|
28
|
-
<ul className="p-2 space-y-2">
|
|
29
|
-
{[
|
|
30
|
-
{
|
|
31
|
-
icon: <Code className="w-5 h-5" />,
|
|
32
|
-
label: "Edit Code",
|
|
33
|
-
href: `/editor?snippet_id=${snippet?.snippet_id}`,
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
icon: <Bot className="w-5 h-5" />,
|
|
37
|
-
label: "Edit with AI",
|
|
38
|
-
badge: "AI",
|
|
39
|
-
href: `/ai?snippet_id=${snippet?.snippet_id}`,
|
|
40
|
-
},
|
|
41
|
-
// {
|
|
42
|
-
// icon: <GitHubLogoIcon className="w-5 h-5" />,
|
|
43
|
-
// label: "Github",
|
|
44
|
-
// },
|
|
45
|
-
{
|
|
46
|
-
icon: <GitFork className="w-5 h-5" />,
|
|
47
|
-
label: "Forks",
|
|
48
|
-
notImplemented: true,
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
icon: <AtSign className="w-5 h-5" />,
|
|
52
|
-
label: "References",
|
|
53
|
-
notImplemented: true,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
icon: <Package className="w-5 h-5" />,
|
|
57
|
-
label: "Dependencies",
|
|
58
|
-
notImplemented: true,
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
icon: <Clock className="w-5 h-5" />,
|
|
62
|
-
label: "Versions",
|
|
63
|
-
notImplemented: true,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
icon: <File className="w-5 h-5" />,
|
|
67
|
-
label: "Files",
|
|
68
|
-
onClick: () => {
|
|
69
|
-
if (snippet) {
|
|
70
|
-
openFilesDialog()
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
// { icon: <Settings className="w-5 h-5" />, label: "Settings" },
|
|
75
|
-
].map((item, index) => (
|
|
76
|
-
<li key={index}>
|
|
77
|
-
<PrefetchPageLink
|
|
78
|
-
href={item.href ?? "#"}
|
|
79
|
-
onClick={
|
|
80
|
-
item.notImplemented
|
|
81
|
-
? () => {
|
|
82
|
-
toast({
|
|
83
|
-
title: "Not Implemented!",
|
|
84
|
-
description: (
|
|
85
|
-
<div>
|
|
86
|
-
The {item.label} selection is not implemented yet.
|
|
87
|
-
Help us out!{" "}
|
|
88
|
-
<a
|
|
89
|
-
className="text-blue-500 hover:underline font-semibold"
|
|
90
|
-
href="https://github.com/tscircuit/tscircuit.com"
|
|
91
|
-
>
|
|
92
|
-
Check out our Github
|
|
93
|
-
</a>
|
|
94
|
-
</div>
|
|
95
|
-
),
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
: item.onClick
|
|
99
|
-
}
|
|
100
|
-
className="flex items-center gap-3 px-2 py-1.5 hover:bg-gray-200 rounded-md"
|
|
101
|
-
>
|
|
102
|
-
{item.icon}
|
|
103
|
-
<span className="text-sm">{item.label}</span>
|
|
104
|
-
{item.badge && (
|
|
105
|
-
<span className="ml-auto bg-blue-500 text-white text-xs px-1.5 py-0.5 rounded">
|
|
106
|
-
{item.badge}
|
|
107
|
-
</span>
|
|
108
|
-
)}
|
|
109
|
-
</PrefetchPageLink>
|
|
110
|
-
</li>
|
|
111
|
-
))}
|
|
112
|
-
</ul>
|
|
113
|
-
</nav>
|
|
114
|
-
<div className="p-4 border-t border-gray-200 space-y-4">
|
|
115
|
-
<div className="space-y-1">
|
|
116
|
-
<div className="text-xs font-medium">Copy embed code</div>
|
|
117
|
-
<div
|
|
118
|
-
className="text-[0.5em] p-2 rounded-sm bg-blue-50 border border-blue-200 cursor-pointer font-mono whitespace-nowrap overflow-hidden text-ellipsis"
|
|
119
|
-
onClick={() => {
|
|
120
|
-
const embedCode = `<iframe src="${window.location.origin}/preview?snippet_id=${snippet?.snippet_id}" width="100%" height="500" frameborder="0"></iframe>`
|
|
121
|
-
navigator.clipboard.writeText(embedCode)
|
|
122
|
-
toast({
|
|
123
|
-
title: "Copied!",
|
|
124
|
-
description: "Embed code copied to clipboard",
|
|
125
|
-
})
|
|
126
|
-
}}
|
|
127
|
-
>
|
|
128
|
-
{`<iframe src="${window.location.origin}/preview?snippet_id=${snippet?.snippet_id}" width="100%" height="500" frameborder="0"></iframe>`}
|
|
129
|
-
</div>
|
|
130
|
-
</div>
|
|
131
|
-
<div className="space-y-1">
|
|
132
|
-
<div className="text-xs font-medium">Copy import code</div>
|
|
133
|
-
<div
|
|
134
|
-
className="text-[0.5em] p-2 rounded-sm bg-blue-50 border border-blue-200 cursor-pointer font-mono whitespace-nowrap overflow-hidden text-ellipsis"
|
|
135
|
-
onClick={() =>
|
|
136
|
-
copyToClipboard(
|
|
137
|
-
`import CircuitModule from "@tsci/${snippet?.owner_name}.${snippet?.unscoped_name}"`,
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
>
|
|
141
|
-
import CircuitModule from "@tsci/{snippet?.owner_name}.
|
|
142
|
-
{snippet?.unscoped_name}"
|
|
143
|
-
</div>
|
|
144
|
-
</div>
|
|
145
|
-
<div className="space-y-1">
|
|
146
|
-
<div className="text-xs font-medium">Copy install command</div>
|
|
147
|
-
<div
|
|
148
|
-
className="text-[0.5em] p-2 rounded-sm bg-blue-50 border border-blue-200 cursor-pointer font-mono whitespace-nowrap overflow-hidden text-ellipsis"
|
|
149
|
-
onClick={() =>
|
|
150
|
-
copyToClipboard(
|
|
151
|
-
`tsci add @tsci/${snippet?.owner_name}.${snippet?.unscoped_name}`,
|
|
152
|
-
)
|
|
153
|
-
}
|
|
154
|
-
>
|
|
155
|
-
tsci add @tsci/{snippet?.owner_name}.{snippet?.unscoped_name}
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
159
|
-
{snippet && <FilesDialog snippetId={snippet.snippet_id} />}
|
|
160
|
-
</div>
|
|
161
|
-
)
|
|
162
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog"
|
|
2
|
-
import { Button } from "../ui/button"
|
|
3
|
-
import { Checkbox } from "../ui/checkbox"
|
|
4
|
-
import { useState, useEffect } from "react"
|
|
5
|
-
import { createUseDialog } from "./create-use-dialog"
|
|
6
|
-
import { useAxios } from "@/hooks/use-axios"
|
|
7
|
-
import { useToast } from "@/hooks/use-toast"
|
|
8
|
-
import { useQueryClient } from "react-query"
|
|
9
|
-
|
|
10
|
-
export const CreateOrderDialog = ({
|
|
11
|
-
open,
|
|
12
|
-
onOpenChange,
|
|
13
|
-
}: {
|
|
14
|
-
open: boolean
|
|
15
|
-
onOpenChange: (open: boolean) => void
|
|
16
|
-
}) => {
|
|
17
|
-
const axios = useAxios()
|
|
18
|
-
const { toast } = useToast()
|
|
19
|
-
const qc = useQueryClient()
|
|
20
|
-
const [pending, setPending] = useState(false)
|
|
21
|
-
const [checkpoints, setCheckpoints] = useState({
|
|
22
|
-
shipping: false,
|
|
23
|
-
errors: false,
|
|
24
|
-
parts: false,
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (open) {
|
|
29
|
-
validateCheckpoints()
|
|
30
|
-
}
|
|
31
|
-
}, [open])
|
|
32
|
-
|
|
33
|
-
const validateCheckpoints = async () => {
|
|
34
|
-
try {
|
|
35
|
-
// Placeholder: Check if shipping information is in profile
|
|
36
|
-
const hasShippingInfo = await checkShippingInfo()
|
|
37
|
-
|
|
38
|
-
// Placeholder: Check if PCB has no errors
|
|
39
|
-
const hasNoErrors = await checkPCBErrors()
|
|
40
|
-
|
|
41
|
-
// Placeholder: Check if all parts are available at PCB fab
|
|
42
|
-
const allPartsAvailable = await checkPartsAvailability()
|
|
43
|
-
|
|
44
|
-
setCheckpoints({
|
|
45
|
-
shipping: hasShippingInfo,
|
|
46
|
-
errors: hasNoErrors,
|
|
47
|
-
parts: allPartsAvailable,
|
|
48
|
-
})
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error("Error validating checkpoints:", error)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const checkShippingInfo = async () => {
|
|
55
|
-
// Placeholder: Implement actual check for shipping info
|
|
56
|
-
return true
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const checkPCBErrors = async () => {
|
|
60
|
-
// Placeholder: Implement actual check for PCB errors
|
|
61
|
-
return true
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const checkPartsAvailability = async () => {
|
|
65
|
-
// Placeholder: Implement actual check for parts availability
|
|
66
|
-
return true
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const handleSubmit = async () => {
|
|
70
|
-
try {
|
|
71
|
-
setPending(true)
|
|
72
|
-
// TODO: Implement order submission logic
|
|
73
|
-
onOpenChange(false)
|
|
74
|
-
setPending(false)
|
|
75
|
-
toast({
|
|
76
|
-
title: "Order submitted",
|
|
77
|
-
description: "Your order has been successfully submitted.",
|
|
78
|
-
})
|
|
79
|
-
qc.invalidateQueries({ queryKey: ["orders"] })
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error("Error submitting order:", error)
|
|
82
|
-
toast({
|
|
83
|
-
title: "Error",
|
|
84
|
-
description: "Failed to submit the order. Please try again.",
|
|
85
|
-
variant: "destructive",
|
|
86
|
-
})
|
|
87
|
-
} finally {
|
|
88
|
-
setPending(false)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
94
|
-
<DialogContent>
|
|
95
|
-
<DialogHeader>
|
|
96
|
-
<DialogTitle>Create Order</DialogTitle>
|
|
97
|
-
</DialogHeader>
|
|
98
|
-
<p className="text-sm text-gray-500 mb-4">
|
|
99
|
-
Order the circuit board fully assembled from a PCB fabricator
|
|
100
|
-
</p>
|
|
101
|
-
<div className="space-y-4">
|
|
102
|
-
<div className="flex items-center space-x-2">
|
|
103
|
-
<Checkbox id="shipping" checked={checkpoints.shipping} />
|
|
104
|
-
<label
|
|
105
|
-
htmlFor="shipping"
|
|
106
|
-
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
107
|
-
>
|
|
108
|
-
Shipping Information in Profile
|
|
109
|
-
</label>
|
|
110
|
-
</div>
|
|
111
|
-
<div className="flex items-center space-x-2">
|
|
112
|
-
<Checkbox id="errors" checked={checkpoints.errors} />
|
|
113
|
-
<label
|
|
114
|
-
htmlFor="errors"
|
|
115
|
-
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
116
|
-
>
|
|
117
|
-
PCB Has No Errors
|
|
118
|
-
</label>
|
|
119
|
-
</div>
|
|
120
|
-
<div className="flex items-center space-x-2">
|
|
121
|
-
<Checkbox id="parts" checked={checkpoints.parts} />
|
|
122
|
-
<label
|
|
123
|
-
htmlFor="parts"
|
|
124
|
-
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
125
|
-
>
|
|
126
|
-
All parts available at PCB fabricator
|
|
127
|
-
</label>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
<div className="flex justify-end space-x-2 mt-4">
|
|
131
|
-
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
132
|
-
Cancel
|
|
133
|
-
</Button>
|
|
134
|
-
<Button
|
|
135
|
-
onClick={handleSubmit}
|
|
136
|
-
disabled={pending || !Object.values(checkpoints).every(Boolean)}
|
|
137
|
-
>
|
|
138
|
-
{pending ? "Submitting..." : "Submit Order"}
|
|
139
|
-
</Button>
|
|
140
|
-
</div>
|
|
141
|
-
</DialogContent>
|
|
142
|
-
</Dialog>
|
|
143
|
-
)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export const useCreateOrderDialog = createUseDialog(CreateOrderDialog)
|
package/src/pages/preview.tsx
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { useSnippet } from "@/hooks/use-snippet"
|
|
2
|
-
import { useUrlParams } from "@/hooks/use-url-params"
|
|
3
|
-
import { CircuitJsonPreview } from "@tscircuit/runframe"
|
|
4
|
-
import { Loader2 } from "lucide-react"
|
|
5
|
-
|
|
6
|
-
export const PreviewPage = () => {
|
|
7
|
-
const urlParams = useUrlParams()
|
|
8
|
-
const snippetId = urlParams.snippet_id
|
|
9
|
-
const { data: snippet, isLoading, error } = useSnippet(snippetId)
|
|
10
|
-
|
|
11
|
-
if (isLoading) {
|
|
12
|
-
return (
|
|
13
|
-
<div className="w-full h-screen flex items-center justify-center">
|
|
14
|
-
<Loader2 className="w-8 h-8 animate-spin" />
|
|
15
|
-
</div>
|
|
16
|
-
)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (error) {
|
|
20
|
-
return (
|
|
21
|
-
<div className="w-full h-screen flex items-center justify-center text-red-500">
|
|
22
|
-
Error loading snippet: {error.message}
|
|
23
|
-
</div>
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (!snippet) {
|
|
28
|
-
return (
|
|
29
|
-
<div className="w-full h-screen flex items-center justify-center text-gray-500">
|
|
30
|
-
Snippet not found
|
|
31
|
-
</div>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (!snippet.circuit_json) {
|
|
36
|
-
return (
|
|
37
|
-
<div className="w-full h-screen flex items-center justify-center text-gray-500">
|
|
38
|
-
No circuit data available
|
|
39
|
-
</div>
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return <CircuitJsonPreview circuitJson={snippet.circuit_json as any} />
|
|
44
|
-
}
|
package/src/pages/view-order.tsx
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import React from "react"
|
|
2
|
-
import { useQuery } from "react-query"
|
|
3
|
-
import { useAxios } from "@/hooks/use-axios"
|
|
4
|
-
import Header from "@/components/Header"
|
|
5
|
-
import Footer from "@/components/Footer"
|
|
6
|
-
import { Order } from "fake-snippets-api/lib/db/schema"
|
|
7
|
-
import { Link, useParams } from "wouter"
|
|
8
|
-
import { Button } from "@/components/ui/button"
|
|
9
|
-
import { OrderPreviewContent } from "@/components/OrderPreviewContent"
|
|
10
|
-
import { AnyCircuitElement } from "circuit-json"
|
|
11
|
-
|
|
12
|
-
export const ViewOrderPage = () => {
|
|
13
|
-
const { orderId } = useParams()
|
|
14
|
-
const axios = useAxios()
|
|
15
|
-
|
|
16
|
-
const {
|
|
17
|
-
data: order,
|
|
18
|
-
isLoading,
|
|
19
|
-
error,
|
|
20
|
-
} = useQuery<Order>(
|
|
21
|
-
["order", orderId],
|
|
22
|
-
async () => {
|
|
23
|
-
const response = await axios.get(`/orders/get?order_id=${orderId}`)
|
|
24
|
-
return response.data.order
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
enabled: !!orderId,
|
|
28
|
-
},
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
if (isLoading) {
|
|
32
|
-
return <div>Loading order...</div>
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (error) {
|
|
36
|
-
return <div>Error loading order: {(error as Error).message}</div>
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!order) {
|
|
40
|
-
return <div>Order not found</div>
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div>
|
|
45
|
-
<Header />
|
|
46
|
-
<div className="container mx-auto px-4 py-4">
|
|
47
|
-
<h1 className="text-3xl font-bold mb-6">Order Details</h1>
|
|
48
|
-
<div className="flex flex-col md:flex-row gap-6">
|
|
49
|
-
<div className="w-full md:w-1/2 md:max-w-[50%]">
|
|
50
|
-
<div className="bg-white shadow overflow-hidden sm:rounded-lg mb-6">
|
|
51
|
-
<div className="px-4 py-5 sm:px-6">
|
|
52
|
-
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
|
53
|
-
Order #{order.order_id}
|
|
54
|
-
</h3>
|
|
55
|
-
<p className="mt-1 max-w-2xl text-sm text-gray-500">
|
|
56
|
-
Created at: {new Date(order.created_at).toLocaleString()}
|
|
57
|
-
</p>
|
|
58
|
-
</div>
|
|
59
|
-
<div className="border-t border-gray-200">
|
|
60
|
-
<dl>
|
|
61
|
-
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
|
62
|
-
<dt className="text-sm font-medium text-gray-500">
|
|
63
|
-
Status
|
|
64
|
-
</dt>
|
|
65
|
-
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
|
66
|
-
{order.is_running ? "Running" : "Finished"}
|
|
67
|
-
</dd>
|
|
68
|
-
</div>
|
|
69
|
-
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
|
70
|
-
<dt className="text-sm font-medium text-gray-500">
|
|
71
|
-
Started at
|
|
72
|
-
</dt>
|
|
73
|
-
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
|
74
|
-
{order.started_at
|
|
75
|
-
? new Date(order.started_at).toLocaleString()
|
|
76
|
-
: "Not started"}
|
|
77
|
-
</dd>
|
|
78
|
-
</div>
|
|
79
|
-
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
|
80
|
-
<dt className="text-sm font-medium text-gray-500">
|
|
81
|
-
Pending Validation
|
|
82
|
-
</dt>
|
|
83
|
-
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
|
84
|
-
{order.completed_at
|
|
85
|
-
? new Date(order.completed_at).toLocaleString()
|
|
86
|
-
: "Not finished"}
|
|
87
|
-
</dd>
|
|
88
|
-
</div>
|
|
89
|
-
</dl>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
<div className="mt-6">
|
|
93
|
-
<Link href={`/my-orders`}>
|
|
94
|
-
<Button variant="outline" onClick={() => window.history.back()}>
|
|
95
|
-
Back to Orders
|
|
96
|
-
</Button>
|
|
97
|
-
</Link>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
<div className="w-full md:w-1/2 md:max-w-[50%]">
|
|
101
|
-
<OrderPreviewContent
|
|
102
|
-
circuitJson={order.circuit_json as AnyCircuitElement[]}
|
|
103
|
-
className="h-[calc(100vh-200px)]"
|
|
104
|
-
/>
|
|
105
|
-
</div>
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
<Footer />
|
|
109
|
-
</div>
|
|
110
|
-
)
|
|
111
|
-
}
|