FPSMS-frontend
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 

150 строки
4.2 KiB

  1. "use client";
  2. import ClearIcon from "@mui/icons-material/Clear";
  3. import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
  4. import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
  5. import SearchIcon from "@mui/icons-material/Search";
  6. import {
  7. Box,
  8. IconButton,
  9. InputAdornment,
  10. Paper,
  11. TextField,
  12. Tooltip,
  13. Typography,
  14. } from "@mui/material";
  15. import { useTranslation } from "react-i18next";
  16. type Props = {
  17. query: string;
  18. matchCount: number;
  19. activeIndex: number;
  20. onQueryChange: (value: string) => void;
  21. onPrev: () => void;
  22. onNext: () => void;
  23. onClear: () => void;
  24. };
  25. /** FP-MTMS Version Checklist | Functions Ref. No. 15 | v1.0.0 | 2026-07-17 */
  26. const ItemTracingFlowGraphSearch: React.FC<Props> = ({
  27. query,
  28. matchCount,
  29. activeIndex,
  30. onQueryChange,
  31. onPrev,
  32. onNext,
  33. onClear,
  34. }) => {
  35. const { t } = useTranslation("itemTracing");
  36. const trimmed = query.trim();
  37. const hasQuery = trimmed.length > 0;
  38. const matchLabel =
  39. matchCount > 0
  40. ? t("flowGraphSearchMatch", { current: activeIndex + 1, total: matchCount })
  41. : hasQuery
  42. ? t("flowGraphSearchNoMatch")
  43. : "";
  44. const handleKeyDown = (event: React.KeyboardEvent) => {
  45. if (event.key === "Enter") {
  46. event.preventDefault();
  47. if (event.shiftKey) onPrev();
  48. else onNext();
  49. } else if (event.key === "Escape") {
  50. event.preventDefault();
  51. onClear();
  52. }
  53. };
  54. return (
  55. <Paper
  56. elevation={2}
  57. sx={{
  58. p: 1,
  59. minWidth: 280,
  60. maxWidth: 360,
  61. bgcolor: "background.paper",
  62. }}
  63. >
  64. <TextField
  65. size="small"
  66. fullWidth
  67. value={query}
  68. placeholder={t("flowGraphSearchPlaceholder")}
  69. onChange={(e) => onQueryChange(e.target.value)}
  70. onKeyDown={handleKeyDown}
  71. InputProps={{
  72. startAdornment: (
  73. <InputAdornment position="start" sx={{ mr: 0.5 }}>
  74. <SearchIcon fontSize="small" sx={{ color: "text.secondary" }} />
  75. </InputAdornment>
  76. ),
  77. endAdornment: hasQuery ? (
  78. <InputAdornment position="end">
  79. <Tooltip title={t("flowGraphSearchClear")}>
  80. <IconButton size="small" edge="end" onClick={onClear} aria-label={t("flowGraphSearchClear")}>
  81. <ClearIcon fontSize="small" />
  82. </IconButton>
  83. </Tooltip>
  84. </InputAdornment>
  85. ) : undefined,
  86. }}
  87. sx={{
  88. "& .MuiOutlinedInput-root": {
  89. alignItems: "center",
  90. },
  91. "& .MuiOutlinedInput-input": {
  92. color: "text.secondary",
  93. py: "8.5px",
  94. lineHeight: 1.4375,
  95. },
  96. "& .MuiOutlinedInput-input::placeholder": {
  97. color: "text.disabled",
  98. opacity: 1,
  99. },
  100. "& .MuiInputAdornment-root": {
  101. height: "100%",
  102. maxHeight: "none",
  103. alignItems: "center",
  104. },
  105. }}
  106. />
  107. {hasQuery && (
  108. <Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mt: 0.75, gap: 1 }}>
  109. <Typography variant="caption" color={matchCount > 0 ? "text.secondary" : "error"} noWrap>
  110. {matchLabel}
  111. </Typography>
  112. <Box sx={{ display: "flex", flexShrink: 0 }}>
  113. <Tooltip title={t("flowGraphSearchPrev")}>
  114. <span>
  115. <IconButton
  116. size="small"
  117. onClick={onPrev}
  118. disabled={matchCount === 0}
  119. aria-label={t("flowGraphSearchPrev")}
  120. >
  121. <KeyboardArrowUpIcon fontSize="small" />
  122. </IconButton>
  123. </span>
  124. </Tooltip>
  125. <Tooltip title={t("flowGraphSearchNext")}>
  126. <span>
  127. <IconButton
  128. size="small"
  129. onClick={onNext}
  130. disabled={matchCount === 0}
  131. aria-label={t("flowGraphSearchNext")}
  132. >
  133. <KeyboardArrowDownIcon fontSize="small" />
  134. </IconButton>
  135. </span>
  136. </Tooltip>
  137. </Box>
  138. </Box>
  139. )}
  140. </Paper>
  141. );
  142. };
  143. export default ItemTracingFlowGraphSearch;