@tscircuit/fake-snippets 0.0.109 → 0.0.111
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/.github/workflows/bun-formatcheck.yml +2 -2
- package/.github/workflows/bun-pver-release.yml +3 -3
- package/.github/workflows/bun-test.yml +1 -1
- package/.github/workflows/bun-typecheck.yml +2 -2
- package/.github/workflows/update-snapshots.yml +1 -1
- package/README.md +4 -0
- package/api/generated-index.js +37 -3
- package/biome.json +2 -1
- package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +32 -3
- package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
- package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
- package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
- package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
- package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
- package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +151 -0
- package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
- package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
- package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
- package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
- package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
- package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
- package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
- package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
- package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
- package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
- package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
- package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
- package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
- package/bun.lock +361 -453
- package/bunfig.toml +2 -1
- package/dist/bundle.js +1313 -639
- package/dist/index.d.ts +313 -6
- package/dist/index.js +328 -24
- package/dist/schema.d.ts +290 -1
- package/dist/schema.js +54 -1
- package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
- package/fake-snippets-api/lib/db/db-client.ts +219 -4
- package/fake-snippets-api/lib/db/schema.ts +63 -1
- package/fake-snippets-api/lib/db/seed.ts +100 -0
- package/fake-snippets-api/lib/middleware/with-session-auth.ts +60 -8
- package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
- package/fake-snippets-api/lib/public-mapping/public-map-org.ts +33 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
- package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
- package/fake-snippets-api/routes/api/orgs/create.ts +48 -0
- package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
- package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
- package/fake-snippets-api/routes/api/orgs/list_members.ts +60 -0
- package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
- package/fake-snippets-api/routes/api/orgs/update.ts +118 -0
- package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
- package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
- package/fake-snippets-api/routes/api/packages/create.ts +57 -10
- package/fake-snippets-api/routes/api/packages/get.ts +23 -0
- package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
- package/fake-snippets-api/routes/api/packages/list.ts +29 -2
- package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
- package/package.json +25 -19
- package/renovate.json +1 -1
- package/scripts/generate-sitemap.ts +1 -1
- package/src/App.tsx +27 -8
- package/src/ContextProviders.tsx +25 -2
- package/src/components/CircuitJsonImportDialog.tsx +1 -1
- package/src/components/CmdKMenu.tsx +281 -247
- package/src/components/DownloadButtonAndMenu.tsx +17 -5
- package/src/components/FileSidebar.tsx +11 -17
- package/src/components/Footer.tsx +8 -9
- package/src/components/Header.tsx +19 -32
- package/src/components/Header2.tsx +16 -32
- package/src/components/HeaderDropdown.tsx +13 -8
- package/src/components/HeaderLogin.tsx +43 -15
- package/src/components/NotFound.tsx +5 -5
- package/src/components/PackageBreadcrumb.tsx +6 -12
- package/src/components/PackageSearchResults.tsx +1 -1
- package/src/components/PrefetchPageLink.tsx +7 -1
- package/src/components/ProfileRouter.tsx +32 -0
- package/src/components/SearchComponent.tsx +12 -8
- package/src/components/SentryNotFoundReporter.tsx +44 -0
- package/src/components/UserCard.tsx +80 -0
- package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
- package/src/components/ViewPackagePage/components/important-files-view.tsx +105 -34
- package/src/components/ViewPackagePage/components/main-content-header.tsx +10 -6
- package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -1
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -19
- package/src/components/ViewPackagePage/components/package-header.tsx +25 -33
- package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -18
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +12 -5
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
- package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
- package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
- package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
- package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
- package/src/components/dialogs/import-component-dialog.tsx +16 -9
- package/src/components/dialogs/import-package-dialog.tsx +3 -2
- package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
- package/src/components/organization/OrganizationCard.tsx +206 -0
- package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
- package/src/components/organization/OrganizationHeader.tsx +154 -0
- package/src/components/organization/OrganizationMembers.tsx +146 -0
- package/src/components/package-port/CodeAndPreview.tsx +15 -12
- package/src/components/package-port/CodeEditor.tsx +4 -30
- package/src/components/package-port/CodeEditorHeader.tsx +123 -61
- package/src/components/package-port/EditorNav.tsx +32 -49
- package/src/components/preview/ConnectedPackagesList.tsx +8 -8
- package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
- package/src/components/preview/PackageReleasesDashboard.tsx +23 -11
- package/src/components/ui/tree-view.tsx +6 -3
- package/src/hooks/use-add-org-member-mutation.ts +51 -0
- package/src/hooks/use-create-org-mutation.ts +38 -0
- package/src/hooks/use-create-package-mutation.ts +3 -0
- package/src/hooks/use-current-package-release.ts +4 -3
- package/src/hooks/use-download-zip.ts +2 -2
- package/src/hooks/use-global-store.ts +6 -4
- package/src/hooks/use-hydration.ts +30 -0
- package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
- package/src/hooks/use-list-org-members.ts +27 -0
- package/src/hooks/use-list-user-orgs.ts +25 -0
- package/src/hooks/use-org-by-github-handle.ts +26 -0
- package/src/hooks/use-org.ts +24 -0
- package/src/hooks/use-organization.ts +42 -0
- package/src/hooks/use-package-as-snippet.ts +4 -2
- package/src/hooks/use-package-builds.ts +6 -2
- package/src/hooks/use-package-files.ts +5 -3
- package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
- package/src/hooks/use-package-release-images.ts +105 -0
- package/src/hooks/use-package-release.ts +2 -2
- package/src/hooks/use-package-stars.ts +80 -4
- package/src/hooks/use-preview-images.ts +6 -3
- package/src/hooks/use-remove-org-member-mutation.ts +32 -0
- package/src/hooks/use-update-ai-description-mutation.ts +42 -0
- package/src/hooks/use-update-org-mutation.ts +41 -0
- package/src/hooks/use-warn-user-on-page-change.ts +71 -4
- package/src/hooks/useFileManagement.ts +51 -22
- package/src/hooks/useOptimizedPackageFilesLoader.ts +11 -24
- package/src/hooks/usePackageFilesLoader.ts +2 -2
- package/src/hooks/useUpdatePackageFilesMutation.ts +13 -1
- package/src/lib/download-fns/download-gltf-from-circuit-json.ts +1 -1
- package/src/lib/download-fns/download-kicad-files.ts +22 -11
- package/src/lib/download-fns/download-step.ts +12 -0
- package/src/lib/normalize-svg-for-tile.ts +50 -0
- package/src/lib/posthog.ts +11 -9
- package/src/lib/react-query-api-failure-tracking.ts +148 -0
- package/src/lib/sentry.ts +14 -0
- package/src/lib/templates/blank-circuit-board-template.ts +0 -4
- package/src/lib/ts-lib-cache.ts +122 -7
- package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
- package/src/lib/utils/findTargetFile.ts +45 -10
- package/src/lib/utils/isComponentExported.ts +2 -1
- package/src/main.tsx +2 -1
- package/src/pages/create-organization.tsx +169 -0
- package/src/pages/dashboard.tsx +38 -6
- package/src/pages/datasheet.tsx +1 -1
- package/src/pages/datasheets.tsx +3 -3
- package/src/pages/editor.tsx +4 -6
- package/src/pages/landing.tsx +6 -6
- package/src/pages/latest.tsx +3 -0
- package/src/pages/organization-profile.tsx +199 -0
- package/src/pages/organization-settings.tsx +569 -0
- package/src/pages/package-editor.tsx +21 -21
- package/src/pages/preview-release.tsx +75 -145
- package/src/pages/quickstart.tsx +159 -123
- package/src/pages/release-detail.tsx +119 -31
- package/src/pages/search.tsx +197 -57
- package/src/pages/settings-redirect.tsx +44 -0
- package/src/pages/trending.tsx +29 -20
- package/src/pages/user-profile.tsx +58 -7
- package/src/pages/user-settings.tsx +161 -0
- package/src/pages/view-package.tsx +30 -16
- package/vite.config.ts +9 -0
- package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
- package/src/components/JLCPCBImportDialog.tsx +0 -280
- package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -113
- package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -56
- package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
- package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
- package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
- package/src/components/PageSearchComponent.tsx +0 -148
- package/src/pages/package-builds.tsx +0 -33
package/src/pages/dashboard.tsx
CHANGED
|
@@ -3,12 +3,11 @@ 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
|
|
7
|
-
import { Link } from "wouter"
|
|
6
|
+
import { Package } from "fake-snippets-api/lib/db/schema"
|
|
8
7
|
import { Edit2, KeyRound } from "lucide-react"
|
|
9
8
|
import { Button } from "@/components/ui/button"
|
|
10
9
|
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
11
|
-
import {
|
|
10
|
+
import { Link } from "wouter"
|
|
12
11
|
import { PackagesList } from "@/components/PackagesList"
|
|
13
12
|
import { Helmet } from "react-helmet-async"
|
|
14
13
|
import { useSignIn } from "@/hooks/use-sign-in"
|
|
@@ -16,9 +15,12 @@ import { useApiBaseUrl } from "@/hooks/use-packages-base-api-url"
|
|
|
16
15
|
import { useConfirmDeletePackageDialog } from "@/components/dialogs/confirm-delete-package-dialog"
|
|
17
16
|
import { PackageCardSkeleton } from "@/components/PackageCardSkeleton"
|
|
18
17
|
import { PackageCard } from "@/components/PackageCard"
|
|
18
|
+
import { useListUserOrgs } from "@/hooks/use-list-user-orgs"
|
|
19
|
+
import { OrganizationCard } from "@/components/organization/OrganizationCard"
|
|
19
20
|
|
|
20
21
|
export const DashboardPage = () => {
|
|
21
22
|
const axios = useAxios()
|
|
23
|
+
const { data: organizations } = useListUserOrgs()
|
|
22
24
|
|
|
23
25
|
const currentUser = useGlobalStore((s) => s.session?.github_username)
|
|
24
26
|
const isLoggedIn = Boolean(currentUser)
|
|
@@ -99,7 +101,9 @@ export const DashboardPage = () => {
|
|
|
99
101
|
</Helmet>
|
|
100
102
|
<Header />
|
|
101
103
|
<div className="container mx-auto px-4 py-8 min-h-[80vh]">
|
|
102
|
-
<
|
|
104
|
+
<div className="flex items-center justify-between mb-6">
|
|
105
|
+
<h1 className="text-3xl font-bold">Dashboard</h1>
|
|
106
|
+
</div>
|
|
103
107
|
<div className="flex md:flex-row flex-col">
|
|
104
108
|
<div className="md:w-3/4 p-0 md:pr-6">
|
|
105
109
|
{!isLoggedIn ? (
|
|
@@ -129,7 +133,7 @@ export const DashboardPage = () => {
|
|
|
129
133
|
{myPackages &&
|
|
130
134
|
myPackages.slice(0, 3).map((pkg) => (
|
|
131
135
|
<div key={pkg.package_id}>
|
|
132
|
-
<
|
|
136
|
+
<Link
|
|
133
137
|
href={`/editor?package_id=${pkg.package_id}`}
|
|
134
138
|
className="text-blue-600 hover:underline"
|
|
135
139
|
>
|
|
@@ -141,7 +145,7 @@ export const DashboardPage = () => {
|
|
|
141
145
|
{pkg.unscoped_name}
|
|
142
146
|
<Edit2 className="w-3 h-3 ml-2" />
|
|
143
147
|
</Button>
|
|
144
|
-
</
|
|
148
|
+
</Link>
|
|
145
149
|
</div>
|
|
146
150
|
))}
|
|
147
151
|
</div>
|
|
@@ -188,6 +192,34 @@ export const DashboardPage = () => {
|
|
|
188
192
|
View all packages
|
|
189
193
|
</Link>
|
|
190
194
|
)}
|
|
195
|
+
|
|
196
|
+
{/* Organizations Section */}
|
|
197
|
+
{organizations && organizations.length > 0 && (
|
|
198
|
+
<div className="mt-8">
|
|
199
|
+
<h2 className="text-sm font-bold mb-2 text-gray-700 border-b border-gray-200">
|
|
200
|
+
Your Organizations
|
|
201
|
+
</h2>
|
|
202
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
203
|
+
{organizations?.slice(0, 4).map((org: any, i: number) => (
|
|
204
|
+
<OrganizationCard
|
|
205
|
+
key={i}
|
|
206
|
+
organization={org}
|
|
207
|
+
withLink={true}
|
|
208
|
+
showStats={true}
|
|
209
|
+
showMembers={true}
|
|
210
|
+
/>
|
|
211
|
+
))}
|
|
212
|
+
</div>
|
|
213
|
+
{organizations && organizations.length > 4 && (
|
|
214
|
+
<Link
|
|
215
|
+
href="/organizations"
|
|
216
|
+
className="text-sm text-blue-600 hover:underline mt-2 inline-block"
|
|
217
|
+
>
|
|
218
|
+
View all organizations
|
|
219
|
+
</Link>
|
|
220
|
+
)}
|
|
221
|
+
</div>
|
|
222
|
+
)}
|
|
191
223
|
</>
|
|
192
224
|
)}
|
|
193
225
|
</div>
|
package/src/pages/datasheet.tsx
CHANGED
|
@@ -55,7 +55,7 @@ export const DatasheetPage = () => {
|
|
|
55
55
|
</div>
|
|
56
56
|
|
|
57
57
|
{datasheetQuery.isLoading ? (
|
|
58
|
-
<div className="flex flex-col items-center justify-center py-
|
|
58
|
+
<div className="flex flex-col items-center justify-center py-20">
|
|
59
59
|
<Loader2 className="w-10 h-10 animate-spin text-blue-500 mb-4" />
|
|
60
60
|
<h3 className="text-xl font-semibold mb-2">Loading Datasheet...</h3>
|
|
61
61
|
<p className="text-gray-500 max-w-md text-center">
|
package/src/pages/datasheets.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { useCreateDatasheet } from "@/hooks/use-create-datasheet"
|
|
|
5
5
|
import Header from "@/components/Header"
|
|
6
6
|
import Footer from "@/components/Footer"
|
|
7
7
|
import { Input } from "@/components/ui/input"
|
|
8
|
-
import { Search } from "lucide-react"
|
|
8
|
+
import { Loader2, Search } from "lucide-react"
|
|
9
9
|
import { Link, useLocation } from "wouter"
|
|
10
10
|
|
|
11
11
|
interface DatasheetSummary {
|
|
@@ -72,9 +72,9 @@ export const DatasheetsPage: React.FC = () => {
|
|
|
72
72
|
</div>
|
|
73
73
|
|
|
74
74
|
{isLoading ? (
|
|
75
|
-
<div className="text-center py-
|
|
75
|
+
<div className="text-center py-20 px-4">
|
|
76
76
|
<div className="bg-slate-50 inline-flex rounded-full p-4 mb-4">
|
|
77
|
-
<
|
|
77
|
+
<Loader2 className="size-8 animate-spin text-slate-400" />
|
|
78
78
|
</div>
|
|
79
79
|
<h3 className="text-xl font-medium text-slate-900 mb-2">
|
|
80
80
|
Loading Datasheets
|
package/src/pages/editor.tsx
CHANGED
|
@@ -2,12 +2,10 @@ import { CodeAndPreview } from "@/components/package-port/CodeAndPreview"
|
|
|
2
2
|
import Footer from "@/components/Footer"
|
|
3
3
|
import Header from "@/components/Header"
|
|
4
4
|
import { Helmet } from "react-helmet-async"
|
|
5
|
-
import {
|
|
6
|
-
import { usePackage } from "@/hooks/use-package"
|
|
5
|
+
import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
|
|
7
6
|
|
|
8
7
|
export const EditorPage = () => {
|
|
9
|
-
const {
|
|
10
|
-
const { data: pkg, isLoading, error } = usePackage(packageId)
|
|
8
|
+
const { packageInfo: pkg, error } = useCurrentPackageInfo()
|
|
11
9
|
|
|
12
10
|
const projectUrl = pkg
|
|
13
11
|
? `https://tscircuit.com/${pkg.owner_github_username}/${pkg.unscoped_name}`
|
|
@@ -27,12 +25,12 @@ export const EditorPage = () => {
|
|
|
27
25
|
/>
|
|
28
26
|
<meta
|
|
29
27
|
property="og:image"
|
|
30
|
-
content={`https://
|
|
28
|
+
content={`https://api.tscircuit.com/packages/images/${pkg.owner_github_username}/${pkg.unscoped_name}/pcb.png?fs_sha=${pkg.latest_package_release_fs_sha}`}
|
|
31
29
|
/>
|
|
32
30
|
<meta name="twitter:card" content="summary_large_image" />
|
|
33
31
|
<meta
|
|
34
32
|
name="twitter:image"
|
|
35
|
-
content={`https://
|
|
33
|
+
content={`https://api.tscircuit.com/packages/images/${pkg.owner_github_username}/${pkg.unscoped_name}/pcb.png?fs_sha=${pkg.latest_package_release_fs_sha}`}
|
|
36
34
|
/>
|
|
37
35
|
</>
|
|
38
36
|
)}
|
package/src/pages/landing.tsx
CHANGED
|
@@ -18,7 +18,7 @@ import { useGlobalStore } from "@/hooks/use-global-store"
|
|
|
18
18
|
import { navigate } from "wouter/use-browser-location"
|
|
19
19
|
import { FAQ } from "@/components/FAQ"
|
|
20
20
|
import { TrendingPackagesCarousel } from "@/components/TrendingPackagesCarousel"
|
|
21
|
-
import {
|
|
21
|
+
import { Link } from "wouter"
|
|
22
22
|
|
|
23
23
|
export function LandingPage() {
|
|
24
24
|
const signIn = useSignIn()
|
|
@@ -35,8 +35,8 @@ export function LandingPage() {
|
|
|
35
35
|
<link rel="preconnect" href="https://tscircuit.com" />
|
|
36
36
|
<link rel="dns-prefetch" href="https://tscircuit.com" />
|
|
37
37
|
|
|
38
|
-
<link rel="preconnect" href="https://
|
|
39
|
-
<link rel="dns-prefetch" href="https://
|
|
38
|
+
<link rel="preconnect" href="https://api.tscircuit.com" />
|
|
39
|
+
<link rel="dns-prefetch" href="https://api.tscircuit.com" />
|
|
40
40
|
</Helmet>
|
|
41
41
|
<Header2 />
|
|
42
42
|
<main className="flex-1">
|
|
@@ -53,7 +53,7 @@ export function LandingPage() {
|
|
|
53
53
|
AI codes electronics with tscircuit
|
|
54
54
|
</h1>
|
|
55
55
|
<p className="max-w-[600px] text-muted-foreground md:text-xl">
|
|
56
|
-
Build electronics with code
|
|
56
|
+
Build electronics with code and AI tools.
|
|
57
57
|
<br />
|
|
58
58
|
Render code into schematics, PCBs, 3D, fabrication files,
|
|
59
59
|
and more.
|
|
@@ -72,7 +72,7 @@ export function LandingPage() {
|
|
|
72
72
|
Get Started
|
|
73
73
|
</Button>
|
|
74
74
|
</a>
|
|
75
|
-
<
|
|
75
|
+
<Link
|
|
76
76
|
href="/seveibar/led-water-accelerometer#3d"
|
|
77
77
|
className="w-[70vw] min-[500px]:w-auto"
|
|
78
78
|
>
|
|
@@ -84,7 +84,7 @@ export function LandingPage() {
|
|
|
84
84
|
>
|
|
85
85
|
Open Online Example
|
|
86
86
|
</Button>
|
|
87
|
-
</
|
|
87
|
+
</Link>
|
|
88
88
|
<a
|
|
89
89
|
href="https://github.com/tscircuit/tscircuit"
|
|
90
90
|
target="_blank"
|
package/src/pages/latest.tsx
CHANGED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { useParams } from "wouter"
|
|
3
|
+
import Header from "@/components/Header"
|
|
4
|
+
import Footer from "@/components/Footer"
|
|
5
|
+
import { OrganizationHeader } from "@/components/organization/OrganizationHeader"
|
|
6
|
+
import { OrganizationMembers } from "@/components/organization/OrganizationMembers"
|
|
7
|
+
import { PackageCard } from "@/components/PackageCard"
|
|
8
|
+
import { Input } from "@/components/ui/input"
|
|
9
|
+
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
|
10
|
+
import {
|
|
11
|
+
Select,
|
|
12
|
+
SelectContent,
|
|
13
|
+
SelectItem,
|
|
14
|
+
SelectTrigger,
|
|
15
|
+
SelectValue,
|
|
16
|
+
} from "@/components/ui/select"
|
|
17
|
+
import { useListOrgMembers } from "@/hooks/use-list-org-members"
|
|
18
|
+
import { useOrgByGithubHandle } from "@/hooks/use-org-by-github-handle"
|
|
19
|
+
import { PackageCardSkeleton } from "@/components/PackageCardSkeleton"
|
|
20
|
+
import { useApiBaseUrl } from "@/hooks/use-packages-base-api-url"
|
|
21
|
+
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
22
|
+
import { Box } from "lucide-react"
|
|
23
|
+
import type { PublicOrgSchema, Package } from "fake-snippets-api/lib/db/schema"
|
|
24
|
+
import { NotFound } from "@/components/NotFound"
|
|
25
|
+
import { useQuery } from "react-query"
|
|
26
|
+
import { useAxios } from "@/hooks/use-axios"
|
|
27
|
+
|
|
28
|
+
export const OrganizationProfilePageContent = ({
|
|
29
|
+
org,
|
|
30
|
+
}: { org: PublicOrgSchema }) => {
|
|
31
|
+
const baseUrl = useApiBaseUrl()
|
|
32
|
+
const session = useGlobalStore((s) => s.session)
|
|
33
|
+
const axios = useAxios()
|
|
34
|
+
|
|
35
|
+
const [searchQuery, setSearchQuery] = useState("")
|
|
36
|
+
const [activeTab, setActiveTab] = useState("packages")
|
|
37
|
+
const [filter, setFilter] = useState("most-recent")
|
|
38
|
+
const [showAllMembers, setShowAllMembers] = useState(false)
|
|
39
|
+
|
|
40
|
+
const isCurrentUserOrganization = session?.account_id === org.owner_account_id
|
|
41
|
+
|
|
42
|
+
const { data: userPackages, isLoading: isLoadingUserPackages } = useQuery<
|
|
43
|
+
Package[]
|
|
44
|
+
>(
|
|
45
|
+
["userPackages", org.name],
|
|
46
|
+
async () => {
|
|
47
|
+
const response = await axios.post(`/packages/list`, {
|
|
48
|
+
owner_github_username: org.name,
|
|
49
|
+
})
|
|
50
|
+
return response.data.packages
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
enabled: Boolean(org.name),
|
|
54
|
+
refetchOnWindowFocus: false,
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
const filteredPackages = userPackages
|
|
59
|
+
?.filter((pkg) => {
|
|
60
|
+
return (
|
|
61
|
+
!searchQuery ||
|
|
62
|
+
pkg.unscoped_name
|
|
63
|
+
.toLowerCase()
|
|
64
|
+
.includes(searchQuery.toLowerCase().trim())
|
|
65
|
+
)
|
|
66
|
+
})
|
|
67
|
+
?.sort((a, b) => {
|
|
68
|
+
switch (filter) {
|
|
69
|
+
case "most-recent":
|
|
70
|
+
return b.updated_at.localeCompare(a.updated_at)
|
|
71
|
+
case "least-recent":
|
|
72
|
+
return a.updated_at.localeCompare(b.updated_at)
|
|
73
|
+
case "most-starred":
|
|
74
|
+
return (b.star_count || 0) - (a.star_count || 0)
|
|
75
|
+
case "a-z":
|
|
76
|
+
return a.unscoped_name.localeCompare(b.unscoped_name)
|
|
77
|
+
case "z-a":
|
|
78
|
+
return b.unscoped_name.localeCompare(a.unscoped_name)
|
|
79
|
+
default:
|
|
80
|
+
return 0
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div className="min-h-screen">
|
|
86
|
+
<Header />
|
|
87
|
+
|
|
88
|
+
<OrganizationHeader
|
|
89
|
+
organization={org}
|
|
90
|
+
isCurrentUserOrganization={isCurrentUserOrganization}
|
|
91
|
+
/>
|
|
92
|
+
|
|
93
|
+
<div className="container mx-auto px-4 py-8">
|
|
94
|
+
<div className="w-full">
|
|
95
|
+
<div className="w-full">
|
|
96
|
+
<Tabs
|
|
97
|
+
defaultValue="packages"
|
|
98
|
+
onValueChange={setActiveTab}
|
|
99
|
+
className="mb-6"
|
|
100
|
+
>
|
|
101
|
+
<TabsList>
|
|
102
|
+
<TabsTrigger
|
|
103
|
+
value="packages"
|
|
104
|
+
className="flex items-center gap-2"
|
|
105
|
+
>
|
|
106
|
+
Packages
|
|
107
|
+
</TabsTrigger>
|
|
108
|
+
<TabsTrigger
|
|
109
|
+
value="members"
|
|
110
|
+
className="flex items-center gap-2"
|
|
111
|
+
>
|
|
112
|
+
Members
|
|
113
|
+
</TabsTrigger>
|
|
114
|
+
</TabsList>
|
|
115
|
+
</Tabs>
|
|
116
|
+
|
|
117
|
+
{activeTab === "packages" && (
|
|
118
|
+
<div>
|
|
119
|
+
<div className="flex flex-col sm:flex-row gap-4 mb-6">
|
|
120
|
+
<Input
|
|
121
|
+
type="text"
|
|
122
|
+
placeholder="Search packages..."
|
|
123
|
+
value={searchQuery}
|
|
124
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
125
|
+
className="flex-1"
|
|
126
|
+
/>
|
|
127
|
+
<Select value={filter} onValueChange={setFilter}>
|
|
128
|
+
<SelectTrigger className="w-full sm:w-[180px]">
|
|
129
|
+
<SelectValue placeholder="Sort by" />
|
|
130
|
+
</SelectTrigger>
|
|
131
|
+
<SelectContent>
|
|
132
|
+
<SelectItem value="most-recent">Most Recent</SelectItem>
|
|
133
|
+
<SelectItem value="least-recent">Least Recent</SelectItem>
|
|
134
|
+
<SelectItem value="most-starred">Most Starred</SelectItem>
|
|
135
|
+
<SelectItem value="a-z">A-Z</SelectItem>
|
|
136
|
+
<SelectItem value="z-a">Z-A</SelectItem>
|
|
137
|
+
</SelectContent>
|
|
138
|
+
</Select>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
{isLoadingUserPackages ? (
|
|
142
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
143
|
+
{[...Array(6)].map((_, i) => (
|
|
144
|
+
<PackageCardSkeleton key={i} />
|
|
145
|
+
))}
|
|
146
|
+
</div>
|
|
147
|
+
) : (
|
|
148
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
149
|
+
{filteredPackages?.length !== 0 ? (
|
|
150
|
+
filteredPackages?.map((pkg) => (
|
|
151
|
+
<PackageCard
|
|
152
|
+
key={pkg.package_id}
|
|
153
|
+
pkg={pkg}
|
|
154
|
+
baseUrl={baseUrl}
|
|
155
|
+
showOwner={false}
|
|
156
|
+
isCurrentUserPackage={isCurrentUserOrganization}
|
|
157
|
+
/>
|
|
158
|
+
))
|
|
159
|
+
) : (
|
|
160
|
+
<div className="col-span-full flex justify-center">
|
|
161
|
+
<div className="flex flex-col items-center py-20 text-gray-500">
|
|
162
|
+
<Box className="mb-2" size={24} />
|
|
163
|
+
<span className="text-lg font-medium">
|
|
164
|
+
{searchQuery.trim()
|
|
165
|
+
? `No packages matching '${searchQuery.trim()}'`
|
|
166
|
+
: "No packages available"}
|
|
167
|
+
</span>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
)}
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
173
|
+
</div>
|
|
174
|
+
)}
|
|
175
|
+
|
|
176
|
+
{activeTab === "members" && (
|
|
177
|
+
<div>
|
|
178
|
+
<OrganizationMembers orgId={org.org_id} />
|
|
179
|
+
</div>
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<Footer />
|
|
186
|
+
</div>
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export const OrganizationProfilePage = () => {
|
|
191
|
+
const { username } = useParams()
|
|
192
|
+
const { data: organization } = useOrgByGithubHandle(username || null)
|
|
193
|
+
|
|
194
|
+
if (!organization) {
|
|
195
|
+
return <NotFound />
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return <OrganizationProfilePageContent org={organization} />
|
|
199
|
+
}
|