frontend/src/screens/Availability.js

239 lines
5.5 KiB
JavaScript
Raw Normal View History

2020-08-27 12:51:58 +00:00
import React, { useState } from 'react';
2020-08-28 09:50:22 +00:00
import { Redirect, useHistory } from 'react-router-dom';
2020-06-03 09:14:04 +00:00
import {
Panel,
Form,
ControlLabel,
Button,
ButtonGroup,
Message,
FormGroup,
} from 'rsuite';
import {
NavBar,
TimezonePicker,
TimePicker,
IntervalSelector,
} from '../components';
2020-08-27 12:51:58 +00:00
import dtToUTC from '../helpers/datetimeToUTC';
import { backend } from '../helpers/http-common';
2020-08-21 23:08:18 +00:00
import './styles/Availability.less';
import './styles/layout.less';
2020-06-09 14:07:07 +00:00
2020-08-27 12:51:58 +00:00
// NOTES:
// Even though Fullcalendar is supposed to work with timezone,
// it seems the custom rendering code breaks it.
// Possible Dates ID are also striped by custom code.
// That's why timezone and possible dates id are only set when posting an availability.
export default function Availability({
currentUser,
possibleDates,
participant,
}) {
const [availability, setAvailability] = useState([]);
const [timezone, setTimezone] = useState(currentUser.timezone);
const [times, setTimes] = useState({
earliest: currentUser.earliest_time,
latest: currentUser.latest_time,
});
2020-08-28 09:50:22 +00:00
const [status, setStatus] = useState({
error: null,
success: null,
message: '',
});
const history = useHistory();
2020-06-03 09:14:04 +00:00
const handleClear = () => {
setAvailability([]);
};
2020-06-09 14:07:07 +00:00
const handleSelect = ({ start, end }) => {
setAvailability([
...availability,
{
start: start,
end: end,
},
]);
2020-06-03 09:14:04 +00:00
};
const handleSubmit = () => {
2020-08-28 09:50:22 +00:00
// Create a list of availability to post
const availabilityList = availability.map((event) => {
2020-08-27 12:51:58 +00:00
// Format start date to availability
const selectedDate = event.start.toISOString().substring(0, 10);
// Find the date id
const [date] = possibleDates.filter(
(date) => date.start === selectedDate,
);
2020-08-27 12:51:58 +00:00
return {
participant_id: participant.id,
2020-08-27 12:51:58 +00:00
possible_date_id: date.id,
preference: false, // set to 'true" when implementing preference
start_time: dtToUTC(event.start, timezone),
end_time: dtToUTC(event.end, timezone),
};
});
2020-08-28 09:50:22 +00:00
// Create availability post request
const postAvailability = (data) => {
return backend.post('/availability', data);
};
const requests = availabilityList.map((event) =>
postAvailability(event),
);
Promise.all(requests)
.then(function (results) {
// Add confirmation message
setStatus({
success: true,
error: false,
message: 'Your availability has been added to the meeting.',
});
})
.catch((error) => {
2020-08-28 09:50:22 +00:00
setStatus({
error: true,
success: false,
message:
"Your availability couldn't be added to the meeting.",
});
});
};
const handleSelectTimezone = (value, item, event) => {
setTimezone(item.timezone);
};
const handleClearTimezone = () => {
setTimezone(currentUser.timezone);
};
const handleEarliest = (value, item, event) => {
setTimes({
...times,
earliest: value,
});
};
const handleLatest = (value, item, event) => {
setTimes({
...times,
latest: value,
});
};
if (possibleDates.length === 0) {
return <Redirect to='/dashboard' />;
}
2020-06-03 09:14:04 +00:00
return (
<>
2020-08-19 18:04:52 +00:00
<NavBar title='Add your availability' />
2020-08-21 23:08:18 +00:00
<Panel className={'app-container'}>
2020-06-03 09:14:04 +00:00
<Form className={'av-container'}>
<div className={'av-details'}>
<FormGroup>
<ControlLabel>Earliest time</ControlLabel>
<TimePicker
time={times.earliest}
handleSelect={handleEarliest}
/>
2020-06-03 09:14:04 +00:00
</FormGroup>
<FormGroup>
<ControlLabel>Latest time</ControlLabel>
<TimePicker
time={times.latest}
handleSelect={handleLatest}
/>
2020-06-03 09:14:04 +00:00
</FormGroup>
<FormGroup className='av-timezone'>
<ControlLabel>Timezone</ControlLabel>
<TimezonePicker
timezone={timezone}
handleSelect={handleSelectTimezone}
handleClean={handleClearTimezone}
/>
2020-06-03 09:14:04 +00:00
</FormGroup>
<div className='av-controls'>
2020-08-28 09:50:22 +00:00
{!status.success && (
<ButtonGroup justified>
<Button
appearance='ghost'
block
size='lg'
disabled={availability.length === 0}
onClick={() => handleClear()}
>
Clear selection
</Button>
<Button
appearance='primary'
size='lg'
block
disabled={availability.length === 0}
onClick={handleSubmit}
>
Save your availability
</Button>
</ButtonGroup>
)}
{status.success && (
<ButtonGroup justified>
<Button
appearance='ghost'
size='lg'
block
onClick={() =>
history.push('dashboard')
}
2020-08-28 09:50:22 +00:00
>
Go to dashboard
</Button>
<Button
appearance='primary'
size='lg'
block
onClick={() => history.push('invite')}
>
Invite Participants
</Button>
</ButtonGroup>
)}
{(status.error || status.success) && (
<Message
type={status.success ? 'success' : 'error'}
description={status.message}
/>
)}
2020-06-03 09:14:04 +00:00
</div>
</div>
<div className={'interval-selector'}>
<Message
showIcon
type='info'
description='Select your availability on the calendar.'
2020-06-03 09:14:04 +00:00
/>
<IntervalSelector
selectedDates={possibleDates}
2020-06-09 14:07:07 +00:00
availability={availability}
setAvailability={setAvailability}
2020-06-03 09:14:04 +00:00
handleSelect={handleSelect}
handleClear={handleClear}
slotMinTime={times.earliest}
slotMaxTime={times.latest}
2020-06-03 09:14:04 +00:00
/>
</div>
</Form>
</Panel>
</>
);
}