feat(tickets): contrôle « Trier par… » dans la barre de facettes (#21)
Ajoute le sélecteur de tri dans TicketFacetsBar et propage le critère
via useTicketSearch jusqu'à TicketsPanel et TicketPicker, sur le contrat
de tri backend (e523f44). Couvre le tri par les tests tickets et
TicketPicker.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -27,7 +27,7 @@ import type {
|
||||
TicketStatus,
|
||||
TicketSummary,
|
||||
} from "@/domain";
|
||||
import type { TicketListQuery } from "@/ports";
|
||||
import type { TicketListQuery, TicketListSort } from "@/ports";
|
||||
import { useGateways } from "@/app/di";
|
||||
|
||||
/**
|
||||
@ -70,6 +70,10 @@ export interface TicketSearchViewModel {
|
||||
toggleStatus: (status: TicketStatus) => void;
|
||||
togglePriority: (priority: TicketPriority) => void;
|
||||
clearFacets: () => void;
|
||||
/** Current sort (#21); `undefined` ⇒ the backend's historical order. */
|
||||
sort: TicketListSort | undefined;
|
||||
/** Sets the sort (or clears it); resets pagination to the first page. */
|
||||
setSort: (sort: TicketListSort | undefined) => void;
|
||||
/** True when the backend reported a further page (opaque cursor present). */
|
||||
hasMore: boolean;
|
||||
/** Loads and appends the next page (no-op when exhausted or busy). */
|
||||
@ -106,6 +110,9 @@ export function useTicketSearch(
|
||||
});
|
||||
const [text, setText] = useState(initialQuery?.text ?? "");
|
||||
const [debouncedText, setDebouncedText] = useState(text);
|
||||
const [sort, setSort] = useState<TicketListSort | undefined>(
|
||||
initialQuery?.sort,
|
||||
);
|
||||
|
||||
const [items, setItems] = useState<TicketSummary[]>([]);
|
||||
const [cursor, setCursor] = useState<string | undefined>(undefined);
|
||||
@ -130,8 +137,8 @@ export function useTicketSearch(
|
||||
// A key that changes whenever the effective query (minus cursor) changes, so
|
||||
// the first-page effect refetches exactly when a criterion moves.
|
||||
const queryKey = useMemo(
|
||||
() => JSON.stringify({ facets, text: debouncedText.trim(), limit }),
|
||||
[facets, debouncedText, limit],
|
||||
() => JSON.stringify({ facets, text: debouncedText.trim(), sort, limit }),
|
||||
[facets, debouncedText, sort, limit],
|
||||
);
|
||||
|
||||
// Guards against races: only the latest first-page/loadMore fetch may commit.
|
||||
@ -151,12 +158,13 @@ export function useTicketSearch(
|
||||
? { assignedAgentId: facets.assignedAgentId }
|
||||
: {}),
|
||||
...(trimmed ? { text: trimmed } : {}),
|
||||
...(sort ? { sort } : {}),
|
||||
...(limit ? { limit } : {}),
|
||||
// G3-bis: opaque token, relayed verbatim from the previous page only.
|
||||
...(nextCursor ? { cursor: nextCursor } : {}),
|
||||
};
|
||||
},
|
||||
[facets, debouncedText, limit],
|
||||
[facets, debouncedText, sort, limit],
|
||||
);
|
||||
|
||||
// First page: (re)fetch whenever the query key changes; replaces the list.
|
||||
@ -265,6 +273,8 @@ export function useTicketSearch(
|
||||
toggleStatus,
|
||||
togglePriority,
|
||||
clearFacets,
|
||||
sort,
|
||||
setSort,
|
||||
hasMore: cursor !== undefined,
|
||||
loadMore,
|
||||
resolve,
|
||||
|
||||
Reference in New Issue
Block a user