diff --git a/src/components/admin/admin-cards-section.tsx b/src/components/admin/admin-cards-section.tsx index 3e1ae35..bc4c6e6 100644 --- a/src/components/admin/admin-cards-section.tsx +++ b/src/components/admin/admin-cards-section.tsx @@ -22,7 +22,6 @@ import { CardBadges } from "@/components/card-badges"; import { ColumnFilterCombobox } from "@/components/column-filter-combobox"; import { PaginationControls } from "@/components/data-table/pagination-controls"; import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; import { Table, TableBody, @@ -39,7 +38,8 @@ import { DialogFooter, } from "@/components/ui/dialog"; import { AdminFeedback } from "@/components/admin/admin-feedback"; -import { Plus, Pencil, Trash2, Search } from "lucide-react"; +import { Plus, Pencil, Trash2 } from "lucide-react"; +import { CollectionSearchInput } from "@/components/collection-search-input"; import { useTranslations } from "@/i18n/client"; import { useCollectionUrlFilters } from "@/hooks/use-collection-url-filters"; import { useCardBadgeLabels } from "@/hooks/use-card-badge-labels"; @@ -242,18 +242,14 @@ export function AdminCardsSection({ onSuccessDismiss={() => setSuccess(null)} /> -
- - - updateFilters({ search: e.target.value, page: 1 }) - } - className="pl-9" - aria-label={t("admin.cards.search")} - /> -
+ + applyAdminFilters({ search: value }, { immediate: true }) + } + label={t("admin.cards.search")} + placeholder={t("admin.cards.search")} + />
void; - label: string; - placeholder: string; -}) { - const [inputValue, setInputValue] = useState(urlValue); - const [prevUrlValue, setPrevUrlValue] = useState(urlValue); - // Tracks the value we last sent via onSearch — distinguishes our own - // URL updates from external navigation/resets. - const [sentValue, setSentValue] = useState(urlValue); - const debounceRef = useRef | null>(null); - - // getDerivedStateFromProps: sync input when URL changes externally. - if (prevUrlValue !== urlValue) { - setPrevUrlValue(urlValue); - if (sentValue !== urlValue) { - setInputValue(urlValue); - } - } - - function handleChange(newValue: string) { - setInputValue(newValue); - if (debounceRef.current) clearTimeout(debounceRef.current); - debounceRef.current = setTimeout(() => { - setSentValue(newValue); - onSearch(newValue); - }, 300); - } - - return ( - - ); -} - const SORT_COLUMN_KEYS = [ "player", "team", @@ -308,7 +253,7 @@ export function CardTable({ return (
- updateFilters({ search: value }, { immediate: true }) diff --git a/src/components/collection-search-input.tsx b/src/components/collection-search-input.tsx new file mode 100644 index 0000000..01100f5 --- /dev/null +++ b/src/components/collection-search-input.tsx @@ -0,0 +1,53 @@ +"use client"; + +import { useRef, useState } from "react"; +import { SearchField } from "@/components/search-field"; + +/** + * Champ de recherche collection/admin : état local + debounce 300 ms, + * puis sync URL via le callback parent (`immediate: true` recommandé). + */ +export function CollectionSearchInput({ + urlValue, + onSearch, + label, + placeholder, + className, +}: { + urlValue: string; + onSearch: (value: string) => void; + label: string; + placeholder: string; + className?: string; +}) { + const [inputValue, setInputValue] = useState(urlValue); + const [prevUrlValue, setPrevUrlValue] = useState(urlValue); + const [sentValue, setSentValue] = useState(urlValue); + const debounceRef = useRef | null>(null); + + if (prevUrlValue !== urlValue) { + setPrevUrlValue(urlValue); + if (sentValue !== urlValue) { + setInputValue(urlValue); + } + } + + function handleChange(newValue: string) { + setInputValue(newValue); + if (debounceRef.current) clearTimeout(debounceRef.current); + debounceRef.current = setTimeout(() => { + setSentValue(newValue); + onSearch(newValue); + }, 300); + } + + return ( + + ); +}