AdminSearchComponent.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. "use client";
  2. import { useState, useEffect } from "react";
  3. import { Input, Button, Spinner } from "@nextui-org/react";
  4. import { BsFiletypePdf } from "react-icons/bs";
  5. import { FcFolder } from "react-icons/fc";
  6. import { useRouter, useSearchParams } from "next/navigation";
  7. export default function AdminSearchComponent({ searchResults }) {
  8. const [query, setQuery] = useState("");
  9. const [loading, setLoading] = useState(false);
  10. const [hasSearched, setHasSearched] = useState(false);
  11. const router = useRouter();
  12. const searchParams = useSearchParams();
  13. useEffect(() => {
  14. if (searchParams.get("query")) {
  15. setLoading(false);
  16. setHasSearched(true);
  17. }
  18. }, [searchParams]);
  19. const handleSearch = () => {
  20. if (query) {
  21. setLoading(true);
  22. setHasSearched(false);
  23. router.push(`?query=${query}`);
  24. }
  25. };
  26. const handleKeyPress = (e) => {
  27. if (e.key === "Enter") {
  28. handleSearch();
  29. }
  30. };
  31. const formatSearchResult = (filePath) => {
  32. const pathSegments = filePath.split("\\");
  33. const fileName = pathSegments.pop();
  34. const folderPath = pathSegments.join("\\");
  35. return { folderPath, fileName, pathSegments };
  36. };
  37. const handleFolderClick = (pathSegments) => {
  38. const newPath = pathSegments.join("/");
  39. router.push(`/admin-view/${newPath}`);
  40. };
  41. return (
  42. <div>
  43. <div className="flex justify-center gap-4 mb-4">
  44. <Input
  45. clearable
  46. placeholder="Suchbegrif eingeben für Dateien aus dieser Niederlassung"
  47. value={query}
  48. onChange={(e) => setQuery(e.target.value)}
  49. onKeyPress={handleKeyPress}
  50. classNames={{
  51. label: "text-black/70",
  52. input: ["bg-white", "text-black", "placeholder:text-gray-500"],
  53. inputWrapper: ["shadow-md", "bg-white", "!cursor-text"],
  54. }}
  55. />
  56. <Button auto onPress={handleSearch} disabled={loading} color="primary">
  57. Suchen
  58. </Button>
  59. </div>
  60. {loading && (
  61. <div className="flex justify-center mt-24">
  62. <Spinner
  63. size="lg"
  64. label="Alle Dokumente werden durchgesucht. Das kann einen Moment dauern"
  65. color="primary"
  66. labelColor="foreground"
  67. />
  68. </div>
  69. )}
  70. {!loading && hasSearched && searchResults && searchResults.length > 0 ? (
  71. <div className="mt-10 flex flex-wrap gap-4 ps-4">
  72. {searchResults.map((filePath, index) => {
  73. const { folderPath, fileName, pathSegments } =
  74. formatSearchResult(filePath);
  75. return (
  76. <div
  77. key={index}
  78. className="p-4 border rounded-lg shadow-md flex flex-col w-auto max-w-full bg-slate-100"
  79. >
  80. <div
  81. className="flex items-center cursor-pointer hover:bg-sky-200 p-2 rounded-md overflow-x-auto break-words"
  82. onClick={() => handleFolderClick(pathSegments)}
  83. >
  84. <FcFolder className="mr-2 text-2xl flex-shrink-0" />
  85. <span className="text-left text-sm text-stone-950">
  86. {folderPath}
  87. </span>
  88. </div>
  89. <div className="flex items-center mt-2">
  90. <a
  91. href={`/api/files/${filePath}`}
  92. target="_blank"
  93. rel="noopener noreferrer"
  94. className="flex items-center hover:bg-sky-200 p-2 rounded-md cursor-pointer overflow-x-auto break-words"
  95. >
  96. <BsFiletypePdf className="text-red-500 mr-2 text-xl flex-shrink-0" />
  97. <span className="text-left text-sm text-stone-950">
  98. {fileName}
  99. </span>
  100. </a>
  101. </div>
  102. </div>
  103. );
  104. })}
  105. </div>
  106. ) : (
  107. !loading &&
  108. hasSearched && <p className="mt-4 text-sm">Keine Treffer gefunden.</p>
  109. )}
  110. </div>
  111. );
  112. }