SearchResults.jsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. "use client";
  2. import React from "react";
  3. import { Loader2 } from "lucide-react";
  4. import ExplorerLoading from "@/components/explorer/states/ExplorerLoading";
  5. import ExplorerEmpty from "@/components/explorer/states/ExplorerEmpty";
  6. import ExplorerError from "@/components/explorer/states/ExplorerError";
  7. import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
  8. import { Button } from "@/components/ui/button";
  9. import {
  10. sortSearchItems,
  11. SEARCH_RESULTS_SORT,
  12. } from "@/lib/frontend/search/resultsSorting";
  13. import SearchResultsToolbar from "@/components/search/SearchResultsToolbar";
  14. import SearchResultsTable from "@/components/search/SearchResultsTable";
  15. export default function SearchResults({
  16. branch,
  17. scope,
  18. status,
  19. items,
  20. total,
  21. error,
  22. onRetry,
  23. nextCursor,
  24. onLoadMore,
  25. isLoadingMore,
  26. loadMoreError,
  27. }) {
  28. const [sortMode, setSortMode] = React.useState(SEARCH_RESULTS_SORT.RELEVANCE);
  29. const sortedItems = React.useMemo(() => {
  30. return sortSearchItems(items, sortMode);
  31. }, [items, sortMode]);
  32. if (status === "idle") {
  33. return (
  34. <ExplorerEmpty
  35. title="Suche starten"
  36. description="Bitte geben Sie einen Suchbegriff ein und klicken Sie auf „Suchen“."
  37. upHref={null}
  38. />
  39. );
  40. }
  41. if (status === "loading") {
  42. return <ExplorerLoading variant="table" count={8} />;
  43. }
  44. if (status === "error" && error) {
  45. return (
  46. <ExplorerError
  47. title={error.title}
  48. description={error.description}
  49. onRetry={onRetry}
  50. />
  51. );
  52. }
  53. const list = Array.isArray(sortedItems) ? sortedItems : [];
  54. if (list.length === 0) {
  55. return (
  56. <ExplorerEmpty
  57. title="Keine Treffer"
  58. description="Für Ihre Suche wurden keine Treffer gefunden."
  59. upHref={null}
  60. />
  61. );
  62. }
  63. return (
  64. <div className="space-y-4">
  65. <SearchResultsToolbar
  66. countLoaded={list.length}
  67. total={total}
  68. sortMode={sortMode}
  69. onSortModeChange={setSortMode}
  70. />
  71. <SearchResultsTable routeBranch={branch} scope={scope} items={list} />
  72. {loadMoreError ? (
  73. <Alert variant="destructive">
  74. <AlertTitle>{loadMoreError.title}</AlertTitle>
  75. <AlertDescription>{loadMoreError.description}</AlertDescription>
  76. </Alert>
  77. ) : null}
  78. {nextCursor ? (
  79. <div className="flex justify-center">
  80. <Button
  81. type="button"
  82. variant="outline"
  83. onClick={onLoadMore}
  84. disabled={isLoadingMore}
  85. title="Weitere Ergebnisse laden"
  86. >
  87. {isLoadingMore ? (
  88. <>
  89. <Loader2 className="h-4 w-4 animate-spin" />
  90. Lädt…
  91. </>
  92. ) : (
  93. "Mehr laden"
  94. )}
  95. </Button>
  96. </div>
  97. ) : null}
  98. </div>
  99. );
  100. }