Skip to content

Commit 0f6ac31

Browse files
committed
refactor(dashboard): streamline search query handling and URL synchronization in project display
1 parent c267fae commit 0f6ac31

File tree

1 file changed

+20
-54
lines changed
  • apps/dokploy/components/dashboard/projects

1 file changed

+20
-54
lines changed

apps/dokploy/components/dashboard/projects/show.tsx

Lines changed: 20 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from "lucide-react";
1212
import Link from "next/link";
1313
import { useRouter } from "next/router";
14-
import { useEffect, useMemo, useRef, useState } from "react";
14+
import { useEffect, useMemo, useState } from "react";
1515
import { toast } from "sonner";
1616
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
1717
import { DateTooltip } from "@/components/shared/date-tooltip";
@@ -66,16 +66,12 @@ export const ShowProjects = () => {
6666
const { data, isLoading } = api.project.all.useQuery();
6767
const { data: auth } = api.user.get.useQuery();
6868
const { mutateAsync } = api.project.remove.useMutation();
69-
const [searchQuery, setSearchQuery] = useState(() => {
70-
// Initialize from URL query parameter on mount
71-
if (typeof window !== "undefined") {
72-
const urlQuery = router.query.q;
73-
return typeof urlQuery === "string" ? urlQuery : "";
74-
}
75-
return "";
76-
});
69+
70+
const [searchQuery, setSearchQuery] = useState(
71+
router.isReady && typeof router.query.q === "string" ? router.query.q : "",
72+
);
7773
const debouncedSearchQuery = useDebounce(searchQuery, 500);
78-
const isUrlSync = useRef(false);
74+
7975
const [sortBy, setSortBy] = useState<string>(() => {
8076
if (typeof window !== "undefined") {
8177
return localStorage.getItem("projectsSort") || "createdAt-desc";
@@ -87,63 +83,33 @@ export const ShowProjects = () => {
8783
localStorage.setItem("projectsSort", sortBy);
8884
}, [sortBy]);
8985

90-
// Sync URL changes back to state (e.g., browser back/forward)
91-
// NOTE: This effect MUST appear before the URL sync effect below
92-
// because React executes effects in order. When the back button is pressed,
93-
// we need to set isUrlSync.current = true BEFORE the URL sync effect runs.
9486
useEffect(() => {
9587
if (!router.isReady) return;
96-
97-
const urlQuery = router.query.q;
98-
const urlSearchQuery = typeof urlQuery === "string" ? urlQuery : "";
99-
100-
// Update local state if URL changed externally (e.g., browser navigation)
101-
if (urlSearchQuery !== searchQuery) {
102-
isUrlSync.current = true;
103-
setSearchQuery(urlSearchQuery);
88+
const urlQuery = typeof router.query.q === "string" ? router.query.q : "";
89+
if (urlQuery !== searchQuery) {
90+
setSearchQuery(urlQuery);
10491
}
105-
// eslint-disable-next-line react-hooks/exhaustive-deps
10692
}, [router.isReady, router.query.q]);
10793

108-
// Sync search query to URL when debounced value changes
10994
useEffect(() => {
11095
if (!router.isReady) return;
96+
const urlQuery = typeof router.query.q === "string" ? router.query.q : "";
97+
if (debouncedSearchQuery === urlQuery) return;
11198

112-
// Skip if this change came from URL navigation (browser back/forward)
113-
if (isUrlSync.current) {
114-
isUrlSync.current = false;
115-
return;
99+
const newQuery = { ...router.query };
100+
if (debouncedSearchQuery) {
101+
newQuery.q = debouncedSearchQuery;
102+
} else {
103+
delete newQuery.q;
116104
}
117-
118-
const currentQuery = router.query.q;
119-
const normalizedCurrentQuery =
120-
typeof currentQuery === "string" ? currentQuery : "";
121-
122-
// Only update URL if the debounced value is different from current URL
123-
if (debouncedSearchQuery !== normalizedCurrentQuery) {
124-
const newQuery = { ...router.query };
125-
126-
if (debouncedSearchQuery) {
127-
newQuery.q = debouncedSearchQuery;
128-
} else {
129-
delete newQuery.q;
130-
}
131-
132-
router.push(
133-
{
134-
pathname: router.pathname,
135-
query: newQuery,
136-
},
137-
undefined,
138-
{ shallow: false },
139-
);
140-
}
141-
}, [debouncedSearchQuery, router]);
105+
router.replace({ pathname: router.pathname, query: newQuery }, undefined, {
106+
shallow: true,
107+
});
108+
}, [debouncedSearchQuery]);
142109

143110
const filteredProjects = useMemo(() => {
144111
if (!data) return [];
145112

146-
// First filter by search query
147113
const filtered = data.filter(
148114
(project) =>
149115
project.name

0 commit comments

Comments
 (0)