inventorySearch.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536
  1. import type { InventorySpool } from '../api/client';
  2. import { resolveSpoolColorName } from './colors';
  3. /**
  4. * Return true when spool matches the search query across all searchable text fields.
  5. * Case-insensitive. Empty query always returns true.
  6. */
  7. export function spoolMatchesQuery(spool: InventorySpool, query: string): boolean {
  8. if (!query) return true;
  9. const q = query.toLowerCase();
  10. return (
  11. String(spool.id).includes(q) ||
  12. spool.material.toLowerCase().includes(q) ||
  13. (spool.brand?.toLowerCase().includes(q) ?? false) ||
  14. // Both the stored name and the displayed one. They differ often: a Bambu
  15. // tag may carry no colour name or an internal code, and Spoolman has no
  16. // such field, so what the list shows is usually resolved from the swatch's
  17. // hex. Searching only the stored value means typing what you can plainly
  18. // read finds nothing (#3090).
  19. (spool.color_name?.toLowerCase().includes(q) ?? false) ||
  20. (resolveSpoolColorName(spool.color_name, spool.rgba, spool.color_name_is_synthesized)
  21. ?.toLowerCase()
  22. .includes(q) ??
  23. false) ||
  24. (spool.subtype?.toLowerCase().includes(q) ?? false) ||
  25. (spool.note?.toLowerCase().includes(q) ?? false) ||
  26. (spool.slicer_filament_name?.toLowerCase().includes(q) ?? false) ||
  27. (spool.storage_location?.toLowerCase().includes(q) ?? false)
  28. );
  29. }
  30. /** Filter a spool list by a free-text search query. */
  31. export function filterSpoolsByQuery(spools: InventorySpool[], query: string): InventorySpool[] {
  32. if (!query) return spools;
  33. return spools.filter((spool) => spoolMatchesQuery(spool, query));
  34. }