Skip to content

Commit 9bf9cf9

Browse files
authored
Merge pull request #812 from Merit-Systems/staging
Staging
2 parents 42dd793 + e3f65ed commit 9bf9cf9

62 files changed

Lines changed: 1788 additions & 745 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/scan/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
},
2323
"dependencies": {
2424
"@agentcash/discovery": "1.6.3",
25+
"@neondatabase/serverless": "catalog:prisma",
2526
"@agentcash/router": "1.3.3",
2627
"@ai-sdk/openai": "^2.0.52",
2728
"@ai-sdk/react": "^2.0.68",
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use client';
2+
3+
import { DataTable } from '@/components/ui/data-table';
4+
5+
import { useSellersSorting } from '@/app/(app)/_contexts/sorting/sellers/hook';
6+
import { useTimeRangeContext } from '@/app/(app)/_contexts/time-range/hook';
7+
import { useChain } from '@/app/(app)/_contexts/chain/hook';
8+
9+
import {
10+
featuredServiceColumns as columns,
11+
type FeaturedServiceItem,
12+
} from '@/app/(app)/(home)/(overview)/_components/sellers/featured-columns';
13+
import { api } from '@/trpc/client';
14+
15+
interface Props {
16+
originUrls: string[];
17+
}
18+
19+
export const DiscoverSellersTable: React.FC<Props> = ({ originUrls }) => {
20+
const { sorting } = useSellersSorting();
21+
const { timeframe } = useTimeRangeContext();
22+
const { chain } = useChain();
23+
24+
const [topSellers] = api.public.sellers.bazaar.list.useSuspenseQuery({
25+
chain,
26+
pagination: {
27+
page_size: 100,
28+
},
29+
timeframe,
30+
sorting,
31+
originUrls,
32+
});
33+
34+
return (
35+
<DataTable
36+
columns={columns}
37+
data={topSellers.items as FeaturedServiceItem[]}
38+
pageSize={15}
39+
/>
40+
);
41+
};
42+
43+
export const LoadingDiscoverSellersTable = () => {
44+
return (
45+
<DataTable columns={columns} data={[]} loadingRowCount={15} isLoading />
46+
);
47+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use client';
2+
3+
import { useDiscoverSearch } from './discover-search-context';
4+
import { DiscoverSearchResults } from './discover-search';
5+
6+
interface Props {
7+
children: React.ReactNode;
8+
}
9+
10+
/**
11+
* Switches between default home content and search results.
12+
*/
13+
export const DiscoverPageContent = ({ children }: Props) => {
14+
const { isSearching } = useDiscoverSearch();
15+
16+
if (isSearching) {
17+
return <DiscoverSearchResults />;
18+
}
19+
20+
return <>{children}</>;
21+
};
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
'use client';
2+
3+
import {
4+
createContext,
5+
useCallback,
6+
useContext,
7+
useEffect,
8+
useState,
9+
} from 'react';
10+
import { useRouter, useSearchParams } from 'next/navigation';
11+
12+
interface DiscoverSearchContextValue {
13+
input: string;
14+
setInput: (value: string) => void;
15+
query: string;
16+
isSearching: boolean;
17+
isDirty: boolean;
18+
submit: () => void;
19+
clear: () => void;
20+
}
21+
22+
const DiscoverSearchContext = createContext<DiscoverSearchContextValue | null>(
23+
null
24+
);
25+
26+
export const useDiscoverSearch = () => {
27+
const ctx = useContext(DiscoverSearchContext);
28+
if (!ctx)
29+
throw new Error(
30+
'useDiscoverSearch must be used within DiscoverSearchProvider'
31+
);
32+
return ctx;
33+
};
34+
35+
export const DiscoverSearchProvider = ({
36+
children,
37+
}: {
38+
children: React.ReactNode;
39+
}) => {
40+
const router = useRouter();
41+
const searchParams = useSearchParams();
42+
const initialQuery = searchParams.get('q') ?? '';
43+
44+
const [input, setInputRaw] = useState(initialQuery);
45+
const [query, setQuery] = useState(initialQuery);
46+
47+
// Sync local state when URL search params change externally (e.g. home button click)
48+
useEffect(() => {
49+
const urlQuery = searchParams.get('q') ?? '';
50+
if (urlQuery !== query) {
51+
setQuery(urlQuery);
52+
setInputRaw(urlQuery);
53+
}
54+
// eslint-disable-next-line react-hooks/exhaustive-deps
55+
}, [searchParams]);
56+
57+
const setInput = useCallback(
58+
(value: string) => {
59+
setInputRaw(value);
60+
if (value.trim().length === 0 && query.length > 0) {
61+
setQuery('');
62+
router.replace('/', { scroll: false });
63+
}
64+
},
65+
[query, router]
66+
);
67+
68+
const submit = useCallback(() => {
69+
const trimmed = input.trim();
70+
if (trimmed.length > 0) {
71+
setQuery(trimmed);
72+
router.replace(`/?q=${encodeURIComponent(trimmed)}`, { scroll: false });
73+
}
74+
}, [input, router]);
75+
76+
const clear = useCallback(() => {
77+
setInputRaw('');
78+
setQuery('');
79+
router.replace('/', { scroll: false });
80+
}, [router]);
81+
82+
const isSearching = query.length > 0;
83+
const isDirty = input.trim() !== query;
84+
85+
return (
86+
<DiscoverSearchContext.Provider
87+
value={{ input, setInput, query, isSearching, isDirty, submit, clear }}
88+
>
89+
{children}
90+
</DiscoverSearchContext.Provider>
91+
);
92+
};

0 commit comments

Comments
 (0)