Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 

161 wiersze
4.6 KiB

  1. "use client";
  2. import { StaffResult } from "@/app/api/staff";
  3. import React, { useCallback, useEffect, useMemo, useState } from "react";
  4. import SearchBox, { Criterion } from "../SearchBox/index";
  5. import { useTranslation } from "react-i18next";
  6. import SearchResults, { Column } from "../SearchResults/index";
  7. import EditNote from "@mui/icons-material/EditNote";
  8. import DeleteIcon from "@mui/icons-material/Delete";
  9. import { deleteStaff } from "@/app/api/staff/actions";
  10. import { useRouter } from "next/navigation";
  11. import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
  12. import Person from '@mui/icons-material/Person';
  13. import { MAINTAIN_STAFF, MAINTAIN_USER } from "@/middleware";
  14. import { TeamResult } from "@/app/api/team";
  15. import { Grade } from "@/app/api/grades";
  16. import { PositionResult } from "@/app/api/positions";
  17. interface Props {
  18. staff: StaffResult[];
  19. teams: TeamResult[]
  20. grades: Grade[]
  21. positions: PositionResult[]
  22. abilities: String[]
  23. }
  24. type SearchQuery = Partial<Omit<StaffResult, "id">>;
  25. type SearchParamNames = keyof SearchQuery;
  26. const StaffSearch: React.FC<Props> = ({ staff, teams, grades, positions, abilities }) => {
  27. const { t } = useTranslation();
  28. const [filteredStaff, setFilteredStaff] = useState(staff);
  29. const router = useRouter();
  30. const teamCombo = teams.map(t => `${t.name} - ${t.code}`)
  31. const gradeCombo = grades.map(g => `${g.name}`)
  32. const positionCombo = positions.map(p => `${p.name}`)
  33. const maintainUser = abilities.includes(MAINTAIN_USER)
  34. const maintainStaff = abilities.includes(MAINTAIN_STAFF)
  35. const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
  36. () => [
  37. {
  38. label: t("Team"),
  39. paramName: "team",
  40. type: "select",
  41. options: teamCombo,
  42. },
  43. {
  44. label: t("Staff Name"),
  45. paramName: "name",
  46. type: "text",
  47. },
  48. {
  49. label: t("Staff ID"),
  50. paramName: "staffId",
  51. type: "text",
  52. },
  53. {
  54. label: t("Grade"),
  55. paramName: "grade",
  56. type: "select",
  57. options: gradeCombo,
  58. },
  59. {
  60. label: t("Current Position"),
  61. paramName: "currentPosition",
  62. type: "select",
  63. options: positionCombo,
  64. },
  65. ],
  66. [t]
  67. );
  68. const onStaffClick = useCallback(
  69. (staff: StaffResult) => {
  70. // console.log(staff);
  71. const id = staff.id;
  72. router.push(`/settings/staff/edit?id=${id}`);
  73. },
  74. [router, t]
  75. );
  76. const onUserClick = useCallback(
  77. (staff: StaffResult) => {
  78. // console.log(staff);
  79. router.push(`/settings/staff/user?id=${staff.userId}`);
  80. },
  81. [router, t]
  82. );
  83. const deleteClick = useCallback((staff: StaffResult) => {
  84. deleteDialog(async () => {
  85. await deleteStaff(staff.id);
  86. successDialog(t("Delete Success"), t);
  87. }, t);
  88. }, []);
  89. useEffect(() => {
  90. setFilteredStaff(staff)
  91. }, [staff]);
  92. const columns = useMemo<Column<StaffResult>[]>(
  93. () => [
  94. {
  95. name: "action",
  96. label: t("Actions"),
  97. onClick: onStaffClick,
  98. buttonIcon: <EditNote />,
  99. isHidden: !maintainStaff,
  100. },
  101. {
  102. name: "id",
  103. label: t("Users"),
  104. onClick: onUserClick,
  105. buttonIcon: <Person />,
  106. isHidden: !maintainUser,
  107. },
  108. { name: "team", label: t("Team") },
  109. { name: "name", label: t("Staff Name") },
  110. { name: "staffId", label: t("Staff ID") },
  111. { name: "grade", label: t("Grade") },
  112. { name: "currentPosition", label: t("Current Position") },
  113. {
  114. name: "action",
  115. label: t("Actions"),
  116. onClick: deleteClick,
  117. buttonIcon: <DeleteIcon />,
  118. color: "error",
  119. isHidden: !maintainStaff,
  120. },
  121. ],
  122. [t, onStaffClick, deleteClick]
  123. );
  124. // postData.teamId = team[index].id
  125. return (
  126. <>
  127. <SearchBox
  128. criteria={searchCriteria}
  129. onSearch={(query) => {
  130. // console.log(teamCombo.findIndex(team => team === query.team))
  131. setFilteredStaff(
  132. staff.filter(
  133. (s) =>
  134. s.staffId.toLowerCase().includes(query.staffId.toLowerCase())
  135. && s.name.toLowerCase().includes(query.name.toLowerCase())
  136. && (query.team === "All" || s.teamId === teams[teamCombo.findIndex(team => team === query.team)].id)
  137. && (query.grade === "All" || s.grade === query.grade)
  138. && (query.currentPosition === "All" || s.currentPosition === query.currentPosition)
  139. )
  140. );
  141. }}
  142. />
  143. <SearchResults<StaffResult> items={filteredStaff} columns={columns} />
  144. </>
  145. );
  146. };
  147. export default StaffSearch;