Skip to content

Commit 0ac7911

Browse files
committed
Merge branch 'pr/54' into development
2 parents b0a9fe0 + 88ea9dd commit 0ac7911

File tree

2 files changed

+71
-11
lines changed

2 files changed

+71
-11
lines changed

app/(pages)/(main)/volunteering/logs/workLogInput.js

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11

2-
import { Box, Button, Skeleton, Stack, TextField, Typography } from "@mui/material";
2+
import { Button, Fab, Skeleton, Stack, TextField, Tooltip, Typography } from "@mui/material";
33
import { useState } from "react";
44
import { DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers";
55
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFnsV3";
66
import CustomAutoComplete from "@/app/components/input/CustomAutocomplete";
77
import CustomNumberInput from "@/app/components/input/CustomNumberInput";
88
import prismaRequest from "@/app/middleware/prisma/prismaRequest";
99
import locale from "date-fns/locale/en-GB";
10+
import { CalendarToday, PunchClock } from "@mui/icons-material";
1011

1112
export default function workLogInput(
1213
session,
@@ -17,8 +18,11 @@ export default function workLogInput(
1718
const [registeredFor, setRegisteredFor] = useState(null);
1819
const [selectedGroup, setSelectedGroup] = useState(null);
1920
const [selectedDateTime, setSelectedDateTime] = useState(new Date());
21+
const [endDateTime, setEndDateTime] = useState(new Date());
2022
const [hours, setHours] = useState(0);
2123
const [description, setDescription] = useState("");
24+
const [shouldInputHours, setShouldInputHours] = useState(false);
25+
const [endInputMethodTooltip, setEndInputMethodTooltip] = useState("Change to 'End of work'");
2226

2327
const [registeredForError, setRegisteredForError] = useState(false);
2428
const [selectedGroupError, setSelectedGroupError] = useState(false);
@@ -89,6 +93,21 @@ export default function workLogInput(
8993
}, 5000);
9094
};
9195

96+
const switchEndInputMethod = () => {
97+
if (!shouldInputHours) {
98+
setShouldInputHours(true);
99+
document.querySelector(".endDateTime").setAttribute("style", "display: inline");
100+
document.querySelector(".hours").setAttribute("style", "display: none");
101+
setEndInputMethodTooltip("Change to 'Hours worked'");
102+
103+
} else {
104+
setShouldInputHours(false);
105+
document.querySelector(".endDateTime").setAttribute("style", "display: none");
106+
document.querySelector(".hours").setAttribute("style", "display: inline");
107+
setEndInputMethodTooltip("Change to 'End of work'");
108+
}
109+
};
110+
92111
return (
93112
<Stack direction="column" spacing={1}>
94113
<Stack direction="column" spacing={2}>
@@ -116,15 +135,54 @@ export default function workLogInput(
116135
ampm={false}
117136
disableOpenPicker
118137
onChange={(e) => setSelectedDateTime(e)}
119-
/>
138+
/>
120139
</LocalizationProvider>
121-
<CustomNumberInput
122-
label="Hours worked"
123-
value={hours}
124-
setValue={setHours}
125-
check={(data) => data.match(/[^0-9.]/) || data.match(/[.]{2,}/g)}
126-
error={hoursError}
127-
/>
140+
<Stack
141+
direction="row"
142+
alignItems={"stretch"}
143+
>
144+
<LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={locale}>
145+
<DateTimePicker
146+
className="endDateTime"
147+
sx={{ display: "none" }}
148+
slotProps={{ textField: { fullWidth: true } }}
149+
label="End of work"
150+
value={endDateTime} // Replacing defaultValue to make it synced with the actual value
151+
ampm={false}
152+
disableOpenPicker
153+
onChange={(e) => {
154+
if (e < selectedDateTime) return; // Prevent endDateTime from being before startDateTime
155+
setEndDateTime(e);
156+
setHours(Math.round(((e - selectedDateTime) / 3600000) * 10) / 10) // Update hours
157+
}}
158+
/>
159+
</LocalizationProvider>
160+
<CustomNumberInput
161+
className="hours"
162+
label="Hours worked"
163+
value={hours}
164+
setValue={(value) => {setHours(value);}}
165+
check={(data) => data.match(/[^0-9.]/) || data.match(/[.]{2,}/g)}
166+
error={hoursError}
167+
/>
168+
<Tooltip
169+
className="endInputMethodTooltip"
170+
title={ endInputMethodTooltip }
171+
>
172+
<Fab
173+
className="endInputMethodChangeButton"
174+
size="small"
175+
color="primary"
176+
style={{
177+
marginLeft: "10px",
178+
padding: "10px",
179+
}}
180+
onClick={() => {switchEndInputMethod();}}
181+
>
182+
{ shouldInputHours ? <PunchClock /> : <CalendarToday /> }
183+
</Fab>
184+
</Tooltip>
185+
</Stack>
128186
<TextField
129187
label="Description"
130188
size="small"
@@ -171,7 +229,7 @@ function validateWorkLogRequest(
171229
registeredForError: registeredFor == null,
172230
selectedGroupError: selectedGroup == null,
173231
selectedDateTimeError: false, // TODO: add semester validation
174-
hoursError: hours <= 0 || hours > 24,
232+
hoursError: Number.isNaN(hours) || hours <= 0 || hours > 24,
175233
descriptionError: description.length == 0,
176234
};
177235

app/components/input/CustomNumberInput.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import { Component } from "react";
44

55
export default class CustomNumberInput extends Component {
66
render() {
7-
const { label, value, setValue, check, error } = this.props;
7+
const { label, value, setValue, check, error, className } = this.props;
88

99
return (
1010
<TextField
11+
className={className}
1112
label={label}
1213
size="small"
1314
InputLabelProps={{ shrink: true }}
1415
value={value}
1516
error={error}
1617
onFocus={(e) => e.target.select()}
18+
fullWidth
1719
onBlur={(e) => {
1820
let value = check(e.target.value) ? 0 : e.target.value;
1921
if (value === "") value = 0;

0 commit comments

Comments
 (0)