diff --git a/apps/remix/app/components/general/template/template-page-view-documents-table.tsx b/apps/remix/app/components/general/template/template-page-view-documents-table.tsx
index 9974cb5a4..e4a1fc048 100644
--- a/apps/remix/app/components/general/template/template-page-view-documents-table.tsx
+++ b/apps/remix/app/components/general/template/template-page-view-documents-table.tsx
@@ -56,8 +56,11 @@ export const TemplatePageViewDocumentsTable = ({
const team = useCurrentTeam();
- const parsedSearchParams = ZDocumentSearchParamsSchema.parse(
- Object.fromEntries(searchParams ?? []),
+ const searchParamsString = searchParams.toString();
+
+ const parsedSearchParams = useMemo(
+ () => ZDocumentSearchParamsSchema.parse(Object.fromEntries(searchParams)),
+ [searchParamsString],
);
const { data, isLoading, isLoadingError } = trpc.document.findDocumentsInternal.useQuery(
@@ -174,7 +177,7 @@ export const TemplatePageViewDocumentsTable = ({
),
},
] satisfies DataTableColumnDef<(typeof results)['data'][number]>[];
- }, []);
+ }, [_, i18n, team?.url]);
return (
diff --git a/apps/remix/app/components/tables/documents-table-toolbar.tsx b/apps/remix/app/components/tables/documents-table-toolbar.tsx
index fd9380a4e..47c9d0906 100644
--- a/apps/remix/app/components/tables/documents-table-toolbar.tsx
+++ b/apps/remix/app/components/tables/documents-table-toolbar.tsx
@@ -36,9 +36,11 @@ export const DocumentsTableToolbar = ({
const query = searchParams.get('query') ?? '';
const period = searchParams.get('period') ?? '';
+ const statusParam = searchParams.get('status');
+ const senderIdsParam = searchParams.get('senderIds');
- const selectedStatusValues = parseToStringArray(searchParams.get('status'));
- const selectedSenderValues = parseToStringArray(searchParams.get('senderIds'));
+ const selectedStatusValues = useMemo(() => parseToStringArray(statusParam), [statusParam]);
+ const selectedSenderValues = useMemo(() => parseToStringArray(senderIdsParam), [senderIdsParam]);
const [searchTerm, setSearchTerm] = useState(query);
const debouncedSearchTerm = useDebouncedValue(searchTerm, 500);
@@ -56,8 +58,11 @@ export const DocumentsTableToolbar = ({
return;
}
- updateSearchParams({ query: debouncedSearchTerm || undefined, page: undefined });
- }, [debouncedSearchTerm, query, searchTerm]);
+ updateSearchParams(
+ { query: debouncedSearchTerm || undefined, page: undefined },
+ { replace: true },
+ );
+ }, [debouncedSearchTerm, query, searchTerm, updateSearchParams]);
const { data: members } = trpc.team.member.getMany.useQuery(
{
@@ -118,7 +123,7 @@ export const DocumentsTableToolbar = ({
className="absolute inset-y-0 end-0 flex w-9 items-center justify-center text-muted-foreground hover:text-foreground"
onClick={() => {
setSearchTerm('');
- updateSearchParams({ query: undefined, page: undefined });
+ updateSearchParams({ query: undefined, page: undefined }, { replace: true });
}}
>
@@ -133,10 +138,13 @@ export const DocumentsTableToolbar = ({
counts={statusCounts}
showSearch={false}
onSelectedValuesChange={(values) => {
- updateSearchParams({
- status: toCommaSeparatedSearchParam(values),
- page: undefined,
- });
+ updateSearchParams(
+ {
+ status: toCommaSeparatedSearchParam(values),
+ page: undefined,
+ },
+ { replace: true },
+ );
}}
/>
@@ -147,10 +155,13 @@ export const DocumentsTableToolbar = ({
selectedValues={selectedSenderValues}
showSearch
onSelectedValuesChange={(values) => {
- updateSearchParams({
- senderIds: toCommaSeparatedSearchParam(values),
- page: undefined,
- });
+ updateSearchParams(
+ {
+ senderIds: toCommaSeparatedSearchParam(values),
+ page: undefined,
+ },
+ { replace: true },
+ );
}}
/>
)}
@@ -164,10 +175,13 @@ export const DocumentsTableToolbar = ({
onSelectedValuesChange={(values) => {
const nextPeriod = values[0];
- updateSearchParams({
- period: nextPeriod ?? undefined,
- page: undefined,
- });
+ updateSearchParams(
+ {
+ period: nextPeriod ?? undefined,
+ page: undefined,
+ },
+ { replace: true },
+ );
}}
/>
diff --git a/apps/remix/app/components/tables/template-documents-table-toolbar.tsx b/apps/remix/app/components/tables/template-documents-table-toolbar.tsx
index b68d3e014..f79db8e3c 100644
--- a/apps/remix/app/components/tables/template-documents-table-toolbar.tsx
+++ b/apps/remix/app/components/tables/template-documents-table-toolbar.tsx
@@ -25,9 +25,11 @@ export const TemplateDocumentsTableToolbar = () => {
const query = searchParams.get('query') ?? '';
const period = searchParams.get('period') ?? '';
+ const statusParam = searchParams.get('status');
+ const sourceParam = searchParams.get('source');
- const selectedStatusValues = parseToStringArray(searchParams.get('status'));
- const selectedSourceValues = parseToStringArray(searchParams.get('source'));
+ const selectedStatusValues = useMemo(() => parseToStringArray(statusParam), [statusParam]);
+ const selectedSourceValues = useMemo(() => parseToStringArray(sourceParam), [sourceParam]);
const [searchTerm, setSearchTerm] = useState(query);
const debouncedSearchTerm = useDebouncedValue(searchTerm, 500);
@@ -45,8 +47,11 @@ export const TemplateDocumentsTableToolbar = () => {
return;
}
- updateSearchParams({ query: debouncedSearchTerm || undefined, page: undefined });
- }, [debouncedSearchTerm, query, searchTerm]);
+ updateSearchParams(
+ { query: debouncedSearchTerm || undefined, page: undefined },
+ { replace: true },
+ );
+ }, [debouncedSearchTerm, query, searchTerm, updateSearchParams]);
const statusOptions = useMemo(
() => [
@@ -131,7 +136,7 @@ export const TemplateDocumentsTableToolbar = () => {
className="absolute inset-y-0 end-0 flex w-9 items-center justify-center text-muted-foreground hover:text-foreground"
onClick={() => {
setSearchTerm('');
- updateSearchParams({ query: undefined, page: undefined });
+ updateSearchParams({ query: undefined, page: undefined }, { replace: true });
}}
>
@@ -145,10 +150,13 @@ export const TemplateDocumentsTableToolbar = () => {
selectedValues={selectedStatusValues}
showSearch={false}
onSelectedValuesChange={(values) => {
- updateSearchParams({
- status: toCommaSeparatedSearchParam(values),
- page: undefined,
- });
+ updateSearchParams(
+ {
+ status: toCommaSeparatedSearchParam(values),
+ page: undefined,
+ },
+ { replace: true },
+ );
}}
/>
@@ -158,10 +166,13 @@ export const TemplateDocumentsTableToolbar = () => {
selectedValues={selectedSourceValues}
showSearch={false}
onSelectedValuesChange={(values) => {
- updateSearchParams({
- source: toCommaSeparatedSearchParam(values),
- page: undefined,
- });
+ updateSearchParams(
+ {
+ source: toCommaSeparatedSearchParam(values),
+ page: undefined,
+ },
+ { replace: true },
+ );
}}
/>
@@ -174,10 +185,13 @@ export const TemplateDocumentsTableToolbar = () => {
onSelectedValuesChange={(values) => {
const nextPeriod = values[0];
- updateSearchParams({
- period: nextPeriod ?? undefined,
- page: undefined,
- });
+ updateSearchParams(
+ {
+ period: nextPeriod ?? undefined,
+ page: undefined,
+ },
+ { replace: true },
+ );
}}
/>
diff --git a/apps/remix/app/components/tables/templates-table-toolbar.tsx b/apps/remix/app/components/tables/templates-table-toolbar.tsx
index d872f1c8b..048476880 100644
--- a/apps/remix/app/components/tables/templates-table-toolbar.tsx
+++ b/apps/remix/app/components/tables/templates-table-toolbar.tsx
@@ -22,7 +22,9 @@ export const TemplatesTableToolbar = () => {
const updateSearchParams = useUpdateSearchParams();
const query = searchParams.get('query') ?? '';
- const selectedTypeValues = parseToStringArray(searchParams.get('type'));
+ const typeParam = searchParams.get('type');
+
+ const selectedTypeValues = useMemo(() => parseToStringArray(typeParam), [typeParam]);
const [searchTerm, setSearchTerm] = useState(query);
const debouncedSearchTerm = useDebouncedValue(searchTerm, 500);
@@ -40,8 +42,11 @@ export const TemplatesTableToolbar = () => {
return;
}
- updateSearchParams({ query: debouncedSearchTerm || undefined, page: undefined });
- }, [debouncedSearchTerm, query, searchTerm]);
+ updateSearchParams(
+ { query: debouncedSearchTerm || undefined, page: undefined },
+ { replace: true },
+ );
+ }, [debouncedSearchTerm, query, searchTerm, updateSearchParams]);
const typeOptions = useMemo(
() => [
@@ -91,7 +96,7 @@ export const TemplatesTableToolbar = () => {
className="absolute inset-y-0 end-0 flex w-9 items-center justify-center text-muted-foreground hover:text-foreground"
onClick={() => {
setSearchTerm('');
- updateSearchParams({ query: undefined, page: undefined });
+ updateSearchParams({ query: undefined, page: undefined }, { replace: true });
}}
>
@@ -105,10 +110,13 @@ export const TemplatesTableToolbar = () => {
selectedValues={selectedTypeValues}
showSearch={false}
onSelectedValuesChange={(values) => {
- updateSearchParams({
- type: toCommaSeparatedSearchParam(values),
- page: undefined,
- });
+ updateSearchParams(
+ {
+ type: toCommaSeparatedSearchParam(values),
+ page: undefined,
+ },
+ { replace: true },
+ );
}}
/>
diff --git a/packages/lib/client-only/hooks/use-update-search-params.ts b/packages/lib/client-only/hooks/use-update-search-params.ts
index 0f59ed6fa..5983db085 100644
--- a/packages/lib/client-only/hooks/use-update-search-params.ts
+++ b/packages/lib/client-only/hooks/use-update-search-params.ts
@@ -1,3 +1,5 @@
+import { useCallback, useRef } from 'react';
+
import type { NavigateOptions } from 'react-router';
import { useSearchParams } from 'react-router';
@@ -7,20 +9,29 @@ type UpdateSearchParamsOptions = Pick {
const [searchParams, setSearchParams] = useSearchParams();
- return (params: SearchParamValues, options?: UpdateSearchParamsOptions) => {
- const nextSearchParams = new URLSearchParams(searchParams?.toString() ?? '');
+ const searchParamsRef = useRef(searchParams);
+ searchParamsRef.current = searchParams;
- Object.entries(params).forEach(([key, value]) => {
- if (value === undefined || value === null) {
- nextSearchParams.delete(key);
- } else {
- nextSearchParams.set(key, String(value));
- }
- });
+ const defaultOptionsRef = useRef(defaultOptions);
+ defaultOptionsRef.current = defaultOptions;
- setSearchParams(nextSearchParams, {
- ...defaultOptions,
- ...options,
- });
- };
+ return useCallback(
+ (params: SearchParamValues, options?: UpdateSearchParamsOptions) => {
+ const nextSearchParams = new URLSearchParams(searchParamsRef.current?.toString() ?? '');
+
+ Object.entries(params).forEach(([key, value]) => {
+ if (value === undefined || value === null) {
+ nextSearchParams.delete(key);
+ } else {
+ nextSearchParams.set(key, String(value));
+ }
+ });
+
+ setSearchParams(nextSearchParams, {
+ ...defaultOptionsRef.current,
+ ...options,
+ });
+ },
+ [setSearchParams],
+ );
};
diff --git a/packages/lib/server-only/document/find-documents.ts b/packages/lib/server-only/document/find-documents.ts
index 43d6366f7..b53fe0baa 100644
--- a/packages/lib/server-only/document/find-documents.ts
+++ b/packages/lib/server-only/document/find-documents.ts
@@ -16,6 +16,7 @@ export type PeriodSelectorValue = '' | 'all' | '7d' | '14d' | '30d';
export type FindDocumentsOptions = {
userId: number;
teamId?: number;
+ team?: Awaited>;
templateId?: number;
source?: DocumentSource | DocumentSource[];
status?: ExtendedDocumentStatus | ExtendedDocumentStatus[];
@@ -34,6 +35,7 @@ export type FindDocumentsOptions = {
export const findDocuments = async ({
userId,
teamId,
+ team: preloadedTeam,
templateId,
source,
status,
@@ -45,25 +47,19 @@ export const findDocuments = async ({
query = '',
folderId,
}: FindDocumentsOptions) => {
- const user = await prisma.user.findFirstOrThrow({
- where: {
- id: userId,
- },
- select: {
- id: true,
- email: true,
- name: true,
- },
- });
-
- let team = null;
-
- if (teamId !== undefined) {
- team = await getTeamById({
- userId,
- teamId,
- });
- }
+ const [user, team] = await Promise.all([
+ prisma.user.findFirstOrThrow({
+ where: {
+ id: userId,
+ },
+ select: {
+ id: true,
+ email: true,
+ name: true,
+ },
+ }),
+ preloadedTeam ?? (teamId !== undefined ? getTeamById({ userId, teamId }) : null),
+ ]);
const orderByColumn = orderBy?.column ?? 'createdAt';
const orderByDirection = orderBy?.direction ?? 'desc';
diff --git a/packages/trpc/server/document-router/find-documents-internal.ts b/packages/trpc/server/document-router/find-documents-internal.ts
index 2dfb38254..5a15c4c01 100644
--- a/packages/trpc/server/document-router/find-documents-internal.ts
+++ b/packages/trpc/server/document-router/find-documents-internal.ts
@@ -37,8 +37,10 @@ export const findDocumentsInternalRoute = authenticatedProcedure
folderId,
};
+ let team: Awaited> | undefined;
+
if (teamId) {
- const team = await getTeamById({ userId: user.id, teamId });
+ team = await getTeamById({ userId: user.id, teamId });
getStatOptions.team = {
teamId: team.id,
@@ -55,6 +57,7 @@ export const findDocumentsInternalRoute = authenticatedProcedure
findDocuments({
userId: user.id,
teamId,
+ team,
query,
templateId,
page,