kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: web infinite loading
rodzic
01b8063d68
commit
c171ee61cf
|
@ -99,8 +99,8 @@ export const teamSlugSchema = z
|
|||
})
|
||||
|
||||
export const paginationSchema = z.object({
|
||||
offset: z.number().int().nonnegative().default(0).optional(),
|
||||
limit: z.number().int().positive().max(100).default(10).optional(),
|
||||
offset: z.coerce.number().int().nonnegative().default(0).optional(),
|
||||
limit: z.coerce.number().int().positive().max(100).default(10).optional(),
|
||||
sort: z.enum(['asc', 'desc']).default('desc').optional(),
|
||||
sortBy: z.enum(['createdAt', 'updatedAt']).default('createdAt').optional()
|
||||
})
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
"posthog-js": "^1.252.0",
|
||||
"react": "catalog:",
|
||||
"react-dom": "catalog:",
|
||||
"react-infinite-scroll-hook": "^6.0.0",
|
||||
"react-lottie-player": "^2.1.0",
|
||||
"react-use": "^17.6.0",
|
||||
"sonner": "^2.0.5",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
'use client'
|
||||
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useInfiniteQuery } from '@tanstack/react-query'
|
||||
import Link from 'next/link'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
|
||||
import { useAuthenticatedAgentic } from '@/components/agentic-provider'
|
||||
import { LoadingIndicator } from '@/components/loading-indicator'
|
||||
|
@ -9,22 +10,51 @@ import { toastError } from '@/lib/notifications'
|
|||
|
||||
export function AppIndex() {
|
||||
const ctx = useAuthenticatedAgentic()
|
||||
const limit = 10
|
||||
const {
|
||||
data: projects,
|
||||
data,
|
||||
isLoading,
|
||||
isError
|
||||
} = useQuery({
|
||||
isError,
|
||||
hasNextPage,
|
||||
fetchNextPage,
|
||||
isFetchingNextPage
|
||||
} = useInfiniteQuery({
|
||||
queryKey: ['projects'],
|
||||
queryFn: () =>
|
||||
ctx?.api
|
||||
.listProjects({ populate: ['lastPublishedDeployment'] })
|
||||
queryFn: ({ pageParam = 0 }) =>
|
||||
ctx!.api
|
||||
.listProjects({
|
||||
populate: ['lastPublishedDeployment'],
|
||||
offset: pageParam,
|
||||
limit
|
||||
})
|
||||
.then(async (projects) => {
|
||||
return {
|
||||
projects,
|
||||
offset: pageParam,
|
||||
limit,
|
||||
nextOffset:
|
||||
projects.length >= limit ? pageParam + projects.length : undefined
|
||||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
void toastError(err, { label: 'Failed to fetch projects' })
|
||||
throw err
|
||||
}),
|
||||
enabled: !!ctx
|
||||
getNextPageParam: (lastGroup) => lastGroup?.nextOffset,
|
||||
enabled: !!ctx,
|
||||
initialPageParam: 0
|
||||
})
|
||||
|
||||
const [sentryRef] = useInfiniteScroll({
|
||||
loading: isLoading || isFetchingNextPage,
|
||||
hasNextPage,
|
||||
onLoadMore: fetchNextPage,
|
||||
disabled: !ctx || isError,
|
||||
rootMargin: '0px 0px 200px 0px'
|
||||
})
|
||||
|
||||
const projects = data ? data.pages.flatMap((p) => p.projects) : []
|
||||
|
||||
return (
|
||||
<>
|
||||
<section>
|
||||
|
@ -44,7 +74,7 @@ export function AppIndex() {
|
|||
|
||||
{isError ? (
|
||||
<p>Error fetching projects</p>
|
||||
) : !projects?.length ? (
|
||||
) : !projects.length ? (
|
||||
<p>
|
||||
No projects found. Create your first project to get started!
|
||||
</p>
|
||||
|
@ -71,6 +101,12 @@ export function AppIndex() {
|
|||
)}
|
||||
</Link>
|
||||
))}
|
||||
|
||||
{hasNextPage && (
|
||||
<div ref={sentryRef} className=''>
|
||||
{isLoading || (isFetchingNextPage && <LoadingIndicator />)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -19,7 +19,7 @@ export function AppProjectIndex({
|
|||
} = useQuery({
|
||||
queryKey: ['project', projectIdentifier],
|
||||
queryFn: () =>
|
||||
ctx?.api
|
||||
ctx!.api
|
||||
.getProjectByIdentifier({
|
||||
projectIdentifier,
|
||||
populate: ['lastPublishedDeployment']
|
||||
|
|
|
@ -20,7 +20,6 @@ export default async function AppProjectIndexPage({
|
|||
const namespace = decodeURIComponent(rawNamespace)
|
||||
const projectName = decodeURIComponent(rawProjectName)
|
||||
|
||||
console.log('parsing project identifier', { namespace, projectName })
|
||||
const { projectIdentifier } = parseProjectIdentifier(
|
||||
`${namespace}/${projectName}`,
|
||||
{ strict: true }
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
await new Promise((resolve) => setTimeout(resolve, 2000))
|
||||
console.log(projects)
|
||||
const p = [
|
||||
{
|
||||
id: 'proj_pk4ui2lpcepx1aaf21zlf0lj' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:23.948105',
|
||||
updatedAt: '2025-06-16 01:50:23.948105',
|
||||
identifier: '@dev/test-everything-openapi',
|
||||
name: 'test-everything-openapi',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_ub815xwoj8bzj1gqdlfzim91',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_j5lvlamp2fax4n7kx09eypjx' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:20.288698',
|
||||
updatedAt: '2025-06-16 01:50:20.288698',
|
||||
identifier: '@dev/test-basic-mcp',
|
||||
name: 'test-basic-mcp',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_krkn9nedwes1s662kky7a991',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_xrt1zzegoa3sun3kynh7itss' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:17.138037',
|
||||
updatedAt: '2025-06-16 01:50:17.138037',
|
||||
identifier: '@dev/test-basic-openapi',
|
||||
name: 'test-basic-openapi',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_frbnya7wukdto64y93osfp8a',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_pk4ui2lpcepx1aaf21zlf0lj' + 'foo' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:23.948105',
|
||||
updatedAt: '2025-06-16 01:50:23.948105',
|
||||
identifier: '@dev/test-everything-openapi',
|
||||
name: 'test-everything-openapi',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_ub815xwoj8bzj1gqdlfzim91',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_j5lvlamp2fax4n7kx09eypjx' + 'foo' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:20.288698',
|
||||
updatedAt: '2025-06-16 01:50:20.288698',
|
||||
identifier: '@dev/test-basic-mcp',
|
||||
name: 'test-basic-mcp',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_krkn9nedwes1s662kky7a991',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_xrt1zzegoa3sun3kynh7itss' + 'foo' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:17.138037',
|
||||
updatedAt: '2025-06-16 01:50:17.138037',
|
||||
identifier: '@dev/test-basic-openapi',
|
||||
name: 'test-basic-openapi',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_frbnya7wukdto64y93osfp8a',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_pk4ui2lpcepx1aaf21zlf0lj' + 'bar' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:23.948105',
|
||||
updatedAt: '2025-06-16 01:50:23.948105',
|
||||
identifier: '@dev/test-everything-openapi',
|
||||
name: 'test-everything-openapi',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_ub815xwoj8bzj1gqdlfzim91',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_j5lvlamp2fax4n7kx09eypjx' + 'bar' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:20.288698',
|
||||
updatedAt: '2025-06-16 01:50:20.288698',
|
||||
identifier: '@dev/test-basic-mcp',
|
||||
name: 'test-basic-mcp',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_krkn9nedwes1s662kky7a991',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_xrt1zzegoa3sun3kynh7itss' + 'bar' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:17.138037',
|
||||
updatedAt: '2025-06-16 01:50:17.138037',
|
||||
identifier: '@dev/test-basic-openapi',
|
||||
name: 'test-basic-openapi',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_frbnya7wukdto64y93osfp8a',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
},
|
||||
{
|
||||
id: 'proj_pk4ui2lpcepx1aaf21zlf0lj' + 'baz' + pageParam,
|
||||
createdAt: '2025-06-16 01:50:23.948105',
|
||||
updatedAt: '2025-06-16 01:50:23.948105',
|
||||
identifier: '@dev/test-everything-openapi',
|
||||
name: 'test-everything-openapi',
|
||||
userId: 'user_x7awoo6vxk7acinkjx1fc6kf',
|
||||
lastDeploymentId: 'depl_ub815xwoj8bzj1gqdlfzim91',
|
||||
applicationFeePercent: 20,
|
||||
defaultPricingInterval: 'month',
|
||||
pricingCurrency: 'usd'
|
||||
}
|
||||
]
|
||||
if (pageParam < 200) {
|
||||
projects = p as any
|
||||
}
|
251
pnpm-lock.yaml
251
pnpm-lock.yaml
|
@ -6,252 +6,27 @@ settings:
|
|||
|
||||
catalogs:
|
||||
default:
|
||||
'@apideck/better-ajv-errors':
|
||||
specifier: ^0.3.6
|
||||
version: 0.3.6
|
||||
'@clack/prompts':
|
||||
specifier: ^0.11.0
|
||||
version: 0.11.0
|
||||
'@cloudflare/workers-types':
|
||||
specifier: ^4.20250614.0
|
||||
version: 4.20250614.0
|
||||
'@commander-js/extra-typings':
|
||||
specifier: ^14.0.0
|
||||
version: 14.0.0
|
||||
'@edge-runtime/vm':
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
'@fisch0920/config':
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2
|
||||
'@fisch0920/drizzle-orm':
|
||||
specifier: ^0.43.7
|
||||
version: 0.43.7
|
||||
'@fisch0920/drizzle-zod':
|
||||
specifier: ^0.7.9
|
||||
version: 0.7.9
|
||||
'@hono/node-server':
|
||||
specifier: ^1.14.4
|
||||
version: 1.14.4
|
||||
'@hono/sentry':
|
||||
specifier: ^1.2.2
|
||||
version: 1.2.2
|
||||
'@hono/zod-openapi':
|
||||
specifier: ^0.19.8
|
||||
version: 0.19.8
|
||||
'@hono/zod-validator':
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: ^1.12.3
|
||||
version: 1.12.3
|
||||
'@paralleldrive/cuid2':
|
||||
specifier: ^2.2.2
|
||||
version: 2.2.2
|
||||
'@react-email/components':
|
||||
specifier: ^0.0.42
|
||||
version: 0.0.42
|
||||
'@redocly/openapi-core':
|
||||
specifier: ^1.34.3
|
||||
version: 1.34.3
|
||||
'@sentry/cli':
|
||||
specifier: ^2.46.0
|
||||
version: 2.46.0
|
||||
'@sentry/cloudflare':
|
||||
specifier: ^9.29.0
|
||||
version: 9.29.0
|
||||
'@sentry/core':
|
||||
specifier: ^9.29.0
|
||||
version: 9.29.0
|
||||
'@sentry/node':
|
||||
specifier: ^9.29.0
|
||||
version: 9.29.0
|
||||
'@types/ms':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
'@types/node':
|
||||
specifier: ^24.0.1
|
||||
version: 24.0.1
|
||||
'@types/react':
|
||||
specifier: ^19.1.8
|
||||
version: 19.1.8
|
||||
'@types/react-dom':
|
||||
specifier: ^19.1.6
|
||||
version: 19.1.6
|
||||
'@types/semver':
|
||||
specifier: ^7.7.0
|
||||
version: 7.7.0
|
||||
agents:
|
||||
specifier: ^0.0.95
|
||||
version: 0.0.95
|
||||
ajv:
|
||||
specifier: ^8.17.1
|
||||
version: 8.17.1
|
||||
ajv-formats:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
camelcase:
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0
|
||||
commander:
|
||||
specifier: ^14.0.0
|
||||
version: 14.0.0
|
||||
conf:
|
||||
specifier: ^14.0.0
|
||||
version: 14.0.0
|
||||
decamelize:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0
|
||||
del-cli:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0
|
||||
drizzle-kit:
|
||||
specifier: ^0.31.1
|
||||
version: 0.31.1
|
||||
drizzle-orm:
|
||||
specifier: ^0.44.2
|
||||
version: 0.44.2
|
||||
email-validator:
|
||||
specifier: ^2.0.4
|
||||
version: 2.0.4
|
||||
eslint:
|
||||
specifier: ^9.29.0
|
||||
version: 9.29.0
|
||||
eslint-plugin-drizzle:
|
||||
specifier: ^0.2.3
|
||||
version: 0.2.3
|
||||
eventid:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
exit-hook:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
fast-content-type-parse:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
fast-uri:
|
||||
specifier: ^3.0.6
|
||||
version: 3.0.6
|
||||
fastmcp:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
get-port:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
hono:
|
||||
specifier: ^4.7.11
|
||||
version: 4.7.11
|
||||
knip:
|
||||
specifier: ^5.61.0
|
||||
version: 5.61.0
|
||||
ky:
|
||||
specifier: 1.8.1
|
||||
version: 1.8.1
|
||||
lint-staged:
|
||||
specifier: ^16.1.1
|
||||
version: 16.1.1
|
||||
ms:
|
||||
specifier: ^2.1.3
|
||||
version: 2.1.3
|
||||
npm-run-all2:
|
||||
specifier: ^8.0.4
|
||||
version: 8.0.4
|
||||
octokit:
|
||||
specifier: ^5.0.3
|
||||
version: 5.0.3
|
||||
only-allow:
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1
|
||||
open:
|
||||
specifier: ^10.1.2
|
||||
version: 10.1.2
|
||||
openapi-typescript:
|
||||
specifier: ^7.8.0
|
||||
version: 7.8.0
|
||||
ora:
|
||||
specifier: ^8.2.0
|
||||
version: 8.2.0
|
||||
p-all:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
p-map:
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.3
|
||||
parse-json:
|
||||
specifier: ^8.3.0
|
||||
version: 8.3.0
|
||||
plur:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0
|
||||
postgres:
|
||||
specifier: ^3.4.7
|
||||
version: 3.4.7
|
||||
prettier:
|
||||
specifier: ^3.5.3
|
||||
version: 3.5.3
|
||||
react:
|
||||
specifier: ^19.1.0
|
||||
version: 19.1.0
|
||||
react-dom:
|
||||
specifier: ^19.1.0
|
||||
version: 19.1.0
|
||||
react-email:
|
||||
specifier: ^4.0.16
|
||||
version: 4.0.16
|
||||
resend:
|
||||
specifier: ^4.6.0
|
||||
version: 4.6.0
|
||||
restore-cursor:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0
|
||||
semver:
|
||||
specifier: ^7.7.2
|
||||
version: 7.7.2
|
||||
simple-git-hooks:
|
||||
specifier: ^2.13.0
|
||||
version: 2.13.0
|
||||
sort-keys:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0
|
||||
stripe:
|
||||
specifier: ^18.2.1
|
||||
version: 18.2.1
|
||||
tsup:
|
||||
specifier: ^8.5.0
|
||||
version: 8.5.0
|
||||
tsx:
|
||||
specifier: ^4.20.3
|
||||
version: 4.20.3
|
||||
turbo:
|
||||
specifier: ^2.5.4
|
||||
version: 2.5.4
|
||||
type-fest:
|
||||
specifier: ^4.41.0
|
||||
version: 4.41.0
|
||||
typescript:
|
||||
specifier: ^5.8.3
|
||||
version: 5.8.3
|
||||
unconfig:
|
||||
specifier: ^7.3.2
|
||||
version: 7.3.2
|
||||
vite-tsconfig-paths:
|
||||
specifier: ^5.1.4
|
||||
version: 5.1.4
|
||||
vitest:
|
||||
specifier: ^3.2.3
|
||||
version: 3.2.3
|
||||
wrangler:
|
||||
specifier: ^4.20.0
|
||||
version: 4.20.0
|
||||
zod:
|
||||
specifier: ^3.25.64
|
||||
version: 3.25.64
|
||||
zod-to-json-schema:
|
||||
specifier: ^3.24.5
|
||||
version: 3.24.5
|
||||
zod-validation-error:
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0
|
||||
|
||||
importers:
|
||||
|
||||
|
@ -572,6 +347,9 @@ importers:
|
|||
react-dom:
|
||||
specifier: 'catalog:'
|
||||
version: 19.1.0(react@19.1.0)
|
||||
react-infinite-scroll-hook:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
react-lottie-player:
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(react@19.1.0)
|
||||
|
@ -5945,6 +5723,18 @@ packages:
|
|||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
react-infinite-scroll-hook@6.0.0:
|
||||
resolution: {integrity: sha512-kg36byj9/YqPS9bv5u3fIUmn800NO6G4cA6d5DcsaBbm7qbMVxT8qy8Po7Xm0dWBJPFEk/g2arcMb9IorQdwsQ==}
|
||||
peerDependencies:
|
||||
react: '>=19'
|
||||
react-dom: '>=19'
|
||||
|
||||
react-intersection-observer-hook@4.0.0:
|
||||
resolution: {integrity: sha512-g9hWp741AA6w0RlGiaTtmIuceRd61q7soZmx2keB1OPstLcZffCKpTxWaYA2LVKNYME3B3ZOGwX3iuYyCBLAag==}
|
||||
peerDependencies:
|
||||
react: '>=19'
|
||||
react-dom: '>=19'
|
||||
|
||||
react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
|
||||
|
@ -11875,6 +11665,17 @@ snapshots:
|
|||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
react-infinite-scroll-hook@6.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
react-intersection-observer-hook: 4.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
|
||||
react-intersection-observer-hook@4.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
|
||||
react-is@16.13.1: {}
|
||||
|
||||
react-lottie-player@2.1.0(react@19.1.0):
|
||||
|
|
Ładowanie…
Reference in New Issue