SearchForm.jsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. "use client";
  2. import React from "react";
  3. import { SEARCH_SCOPE } from "@/lib/frontend/search/urlState";
  4. import SearchQueryBox from "@/components/search/form/SearchQueryBox";
  5. import SearchScopeSelect from "@/components/search/form/SearchScopeSelect";
  6. import SearchLimitSelect from "@/components/search/form/SearchLimitSelect";
  7. import SearchSingleBranchCombobox from "@/components/search/form/SearchSingleBranchCombobox";
  8. import SearchMultiBranchPicker from "@/components/search/form/SearchMultiBranchPicker";
  9. export default function SearchForm({
  10. branch,
  11. qDraft,
  12. onQDraftChange,
  13. onSubmit,
  14. currentQuery,
  15. isSubmitting,
  16. isAdminDev,
  17. scope,
  18. onScopeChange,
  19. onSingleBranchChange,
  20. availableBranches,
  21. branchesStatus,
  22. selectedBranches,
  23. onToggleBranch,
  24. onClearAllBranches,
  25. limit,
  26. onLimitChange,
  27. }) {
  28. const canSearch = typeof qDraft === "string" && qDraft.trim().length > 0;
  29. return (
  30. <div className="space-y-4">
  31. <form
  32. onSubmit={(e) => {
  33. e.preventDefault();
  34. // UX rule:
  35. // - Only submit when the query is non-empty.
  36. // - This keeps the Search API safe and avoids accidental “match everything”.
  37. if (!canSearch) return;
  38. onSubmit();
  39. }}
  40. className="space-y-4"
  41. >
  42. {/*
  43. Layout goal (RHL-038):
  44. - Desktop: one row with (1) scope, (2) query, (3) limit
  45. - Mobile: natural stacking
  46. Implementation:
  47. - Use a responsive grid that becomes 3 columns on lg+
  48. - Align items to the bottom so labels line up nicely.
  49. */}
  50. <div className="flex items-start justify-between gap-3 flex-nowrap">
  51. <div className="flex justify-start gap-2 items-center">
  52. {/* 1) Scope (admin/dev only) */}
  53. {isAdminDev ? (
  54. <SearchScopeSelect
  55. branch={branch}
  56. scope={scope}
  57. onScopeChange={onScopeChange}
  58. isSubmitting={isSubmitting}
  59. />
  60. ) : null}
  61. {/*
  62. Admin/dev: SINGLE branch selection.
  63. We keep this *below* the main row so the top row stays exactly:
  64. Scope | Query | Limit
  65. */}
  66. {isAdminDev && scope === SEARCH_SCOPE.SINGLE ? (
  67. <div>
  68. <SearchSingleBranchCombobox
  69. branch={branch}
  70. branchesStatus={branchesStatus}
  71. availableBranches={availableBranches}
  72. onSingleBranchChange={onSingleBranchChange}
  73. isSubmitting={isSubmitting}
  74. />
  75. </div>
  76. ) : null}
  77. </div>
  78. <div className="flex flex-1">
  79. {/* 2) Query (always) */}
  80. <SearchQueryBox
  81. qDraft={qDraft}
  82. onQDraftChange={onQDraftChange}
  83. onSubmit={onSubmit}
  84. currentQuery={currentQuery}
  85. isSubmitting={isSubmitting}
  86. canSearch={canSearch}
  87. />
  88. </div>
  89. {/* 3) Limit (always) */}
  90. <SearchLimitSelect
  91. limit={limit}
  92. onLimitChange={onLimitChange}
  93. isSubmitting={isSubmitting}
  94. />
  95. </div>
  96. {/*
  97. Admin/dev: SINGLE branch selection.
  98. We keep this *below* the main row so the top row stays exactly:
  99. Scope | Query | Limit
  100. */}
  101. {/* {isAdminDev && scope === SEARCH_SCOPE.SINGLE ? (
  102. <div>
  103. <SearchSingleBranchCombobox
  104. branch={branch}
  105. branchesStatus={branchesStatus}
  106. availableBranches={availableBranches}
  107. onSingleBranchChange={onSingleBranchChange}
  108. isSubmitting={isSubmitting}
  109. />
  110. </div>
  111. ) : null} */}
  112. </form>
  113. {/* Multi scope branch picker remains below the form row (as requested). */}
  114. {isAdminDev && scope === SEARCH_SCOPE.MULTI ? (
  115. <SearchMultiBranchPicker
  116. branchesStatus={branchesStatus}
  117. availableBranches={availableBranches}
  118. selectedBranches={selectedBranches}
  119. onToggleBranch={onToggleBranch}
  120. onClearAllBranches={onClearAllBranches}
  121. isSubmitting={isSubmitting}
  122. />
  123. ) : null}
  124. </div>
  125. );
  126. }