Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 

156 Zeilen
4.1 KiB

  1. import { TimeEntry, RecordTimesheetInput } from "@/app/api/timesheets/actions";
  2. import { manhourFormatter, shortDateFormatter } from "@/app/utils/formatUtil";
  3. import { Add, Edit } from "@mui/icons-material";
  4. import {
  5. Box,
  6. Button,
  7. Card,
  8. CardContent,
  9. IconButton,
  10. Typography,
  11. } from "@mui/material";
  12. import dayjs from "dayjs";
  13. import React, { useCallback, useMemo, useState } from "react";
  14. import { useFormContext } from "react-hook-form";
  15. import { useTranslation } from "react-i18next";
  16. import { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
  17. import TimesheetEditModal, {
  18. Props as TimesheetEditModalProps,
  19. } from "./TimesheetEditModal";
  20. import TimeEntryCard from "./TimeEntryCard";
  21. interface Props {
  22. date: string;
  23. allProjects: ProjectWithTasks[];
  24. assignedProjects: AssignedProject[];
  25. }
  26. const MobileTimesheetEntry: React.FC<Props> = ({
  27. date,
  28. allProjects,
  29. assignedProjects,
  30. }) => {
  31. const {
  32. t,
  33. i18n: { language },
  34. } = useTranslation("home");
  35. const projectMap = useMemo(() => {
  36. return allProjects.reduce<{
  37. [id: ProjectWithTasks["id"]]: ProjectWithTasks;
  38. }>((acc, project) => {
  39. return { ...acc, [project.id]: project };
  40. }, {});
  41. }, [allProjects]);
  42. const dayJsObj = dayjs(date);
  43. const { watch, setValue } = useFormContext<RecordTimesheetInput>();
  44. const currentEntries = watch(date);
  45. // Edit modal
  46. const [editModalProps, setEditModalProps] = useState<
  47. Partial<TimesheetEditModalProps>
  48. >({});
  49. const [editModalOpen, setEditModalOpen] = useState(false);
  50. const openEditModal = useCallback(
  51. (defaultValues?: TimeEntry) => () => {
  52. setEditModalProps({
  53. defaultValues,
  54. onDelete: defaultValues
  55. ? () => {
  56. setValue(
  57. date,
  58. currentEntries.filter((entry) => entry.id !== defaultValues.id),
  59. );
  60. setEditModalOpen(false);
  61. }
  62. : undefined,
  63. });
  64. setEditModalOpen(true);
  65. },
  66. [currentEntries, date, setValue],
  67. );
  68. const closeEditModal = useCallback(() => {
  69. setEditModalOpen(false);
  70. }, []);
  71. const onSaveEntry = useCallback(
  72. (entry: TimeEntry) => {
  73. const existingEntry = currentEntries.find((e) => e.id === entry.id);
  74. if (existingEntry) {
  75. setValue(
  76. date,
  77. currentEntries.map((e) => ({
  78. ...(e.id === existingEntry.id ? entry : e),
  79. })),
  80. );
  81. } else {
  82. setValue(date, [...currentEntries, entry]);
  83. }
  84. setEditModalOpen(false);
  85. },
  86. [currentEntries, date, setValue],
  87. );
  88. return (
  89. <>
  90. <Typography
  91. paddingInline={2}
  92. variant="overline"
  93. color={dayJsObj.day() === 0 ? "error.main" : undefined}
  94. >
  95. {shortDateFormatter(language).format(dayJsObj.toDate())}
  96. </Typography>
  97. <Box
  98. paddingInline={2}
  99. flex={1}
  100. display="flex"
  101. flexDirection="column"
  102. gap={2}
  103. overflow="scroll"
  104. >
  105. {currentEntries.length ? (
  106. currentEntries.map((entry, index) => {
  107. const project = entry.projectId
  108. ? projectMap[entry.projectId]
  109. : undefined;
  110. const task = project?.tasks.find((t) => t.id === entry.taskId);
  111. return (
  112. <TimeEntryCard
  113. key={`${entry.id}-${index}`}
  114. project={project}
  115. task={task}
  116. entry={entry}
  117. onEdit={openEditModal(entry)}
  118. />
  119. );
  120. })
  121. ) : (
  122. <Typography variant="body2" display="block">
  123. {t("Add some time entries!")}
  124. </Typography>
  125. )}
  126. <Box>
  127. <Button startIcon={<Add />} onClick={openEditModal()}>
  128. {t("Record leave")}
  129. </Button>
  130. </Box>
  131. <TimesheetEditModal
  132. allProjects={allProjects}
  133. assignedProjects={assignedProjects}
  134. open={editModalOpen}
  135. onClose={closeEditModal}
  136. onSave={onSaveEntry}
  137. {...editModalProps}
  138. />
  139. </Box>
  140. </>
  141. );
  142. };
  143. export default MobileTimesheetEntry;