Connect Schedule to API and
This commit is contained in:
parent
3356c380d7
commit
017f6e3869
16
src/App.js
16
src/App.js
@ -21,9 +21,15 @@ const existingUser = JSON.parse(localStorage.getItem('user'));
|
|||||||
export default function App() {
|
export default function App() {
|
||||||
const [isAuthenticated, setIsAuthenticated] = useState(!!existingToken);
|
const [isAuthenticated, setIsAuthenticated] = useState(!!existingToken);
|
||||||
const [currentUser, setCurrentUser] = useState(existingUser || '');
|
const [currentUser, setCurrentUser] = useState(existingUser || '');
|
||||||
|
|
||||||
const [possibleDates, setPossibleDates] = useState();
|
const [possibleDates, setPossibleDates] = useState();
|
||||||
// const [currentMeeting, setCurrentMeeting] = useState();
|
const [currentMeeting, setCurrentMeeting] = useState({
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
timezone: '',
|
||||||
|
duration: 0,
|
||||||
|
status: 0,
|
||||||
|
});
|
||||||
|
|
||||||
const [authToken, setAuthToken] = useState(existingToken || '');
|
const [authToken, setAuthToken] = useState(existingToken || '');
|
||||||
|
|
||||||
@ -68,13 +74,15 @@ export default function App() {
|
|||||||
component={Schedule}
|
component={Schedule}
|
||||||
possibleDates={possibleDates}
|
possibleDates={possibleDates}
|
||||||
setPossibleDates={setPossibleDates}
|
setPossibleDates={setPossibleDates}
|
||||||
|
currentMeeting={currentMeeting}
|
||||||
|
setCurrentMeeting={setCurrentMeeting}
|
||||||
/>
|
/>
|
||||||
<PrivateRoute path='/invite' component={Invite} />
|
|
||||||
<PrivateRoute
|
<PrivateRoute
|
||||||
path='/availability'
|
path='/availability'
|
||||||
component={Availability}
|
component={Availability}
|
||||||
|
possibleDates={possibleDates}
|
||||||
/>
|
/>
|
||||||
<PrivateRoute path='/schedule' component={Schedule} />
|
<PrivateRoute path='/invite' component={Invite} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
</AuthContext.Provider>
|
</AuthContext.Provider>
|
||||||
|
@ -8,10 +8,9 @@ const PrivateRoute = ({ component: Component, ...rest }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Route
|
<Route
|
||||||
{...rest}
|
|
||||||
render={(props) =>
|
render={(props) =>
|
||||||
isAuthenticated ? (
|
isAuthenticated ? (
|
||||||
<Component {...props} />
|
<Component {...rest} {...props} />
|
||||||
) : (
|
) : (
|
||||||
<Redirect to='/login' />
|
<Redirect to='/login' />
|
||||||
)
|
)
|
||||||
|
@ -1,23 +1,13 @@
|
|||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import { InputGroup, Icon } from 'rsuite';
|
import { InputGroup, Icon } from 'rsuite';
|
||||||
|
|
||||||
import { durations } from '../../assets/data/durations';
|
import { durations } from '../../assets/data/durations';
|
||||||
|
|
||||||
export default function DurationSelector() {
|
export default function DurationSelector({
|
||||||
const [durationIdx, setDurationIdx] = useState(0);
|
durationIdx,
|
||||||
|
handleDecrement,
|
||||||
const handleIncrement = () => {
|
handleIncrement,
|
||||||
if (durationIdx <= durations.length - 2) {
|
}) {
|
||||||
setDurationIdx(durationIdx + 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDecrement = () => {
|
|
||||||
if (durationIdx > 0) {
|
|
||||||
setDurationIdx(durationIdx - 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputGroup style={{ background: 'white' }}>
|
<InputGroup style={{ background: 'white' }}>
|
||||||
<InputGroup.Button onClick={handleDecrement}>
|
<InputGroup.Button onClick={handleDecrement}>
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { API_URL } from '../constants';
|
import { API_URL } from '../constants';
|
||||||
|
|
||||||
|
const existingToken = JSON.parse(localStorage.getItem('token'));
|
||||||
|
|
||||||
export const backend = axios.create({
|
export const backend = axios.create({
|
||||||
baseURL: API_URL,
|
baseURL: API_URL,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-type': 'application/json',
|
'Content-type': 'application/json',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (existingToken) {
|
||||||
|
backend.defaults.headers['Authorization'] = existingToken;
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@ import { NavBar, TimezonePicker, IntervalSelector } from '../components';
|
|||||||
import './styles/Availability.less';
|
import './styles/Availability.less';
|
||||||
import './styles/layout.less';
|
import './styles/layout.less';
|
||||||
|
|
||||||
export default function Availability() {
|
export default function Availability({ possibleDates }) {
|
||||||
const [availability, setAvailability] = useState([...availabilityList]);
|
const [availability, setAvailability] = useState([...availabilityList]);
|
||||||
|
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
ControlLabel,
|
ControlLabel,
|
||||||
Input,
|
|
||||||
HelpBlock,
|
HelpBlock,
|
||||||
Button,
|
Button,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
@ -12,6 +11,7 @@ import {
|
|||||||
FormGroup,
|
FormGroup,
|
||||||
} from 'rsuite';
|
} from 'rsuite';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NavBar,
|
NavBar,
|
||||||
@ -20,19 +20,36 @@ import {
|
|||||||
DurationSelector,
|
DurationSelector,
|
||||||
SelectedDates,
|
SelectedDates,
|
||||||
} from '../components';
|
} from '../components';
|
||||||
|
import { backend } from '../helpers/http-common';
|
||||||
|
import { durations } from '../assets/data/durations';
|
||||||
import './styles/Schedule.less';
|
import './styles/Schedule.less';
|
||||||
|
|
||||||
export default function Schedule() {
|
export default function Schedule({
|
||||||
|
possibleDates,
|
||||||
|
setPossibleDates,
|
||||||
|
currentMeeting,
|
||||||
|
setCurrentMeeting,
|
||||||
|
}) {
|
||||||
const [eventsList, setEventsList] = useState([]);
|
const [eventsList, setEventsList] = useState([]);
|
||||||
const [datesList, setDatesList] = useState(eventsToDates(eventsList));
|
const [datesList, setDatesList] = useState(eventsToDates(eventsList));
|
||||||
|
const [durationIdx, setDurationIdx] = useState(0);
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Push the selected dates up the state tree
|
||||||
|
// but keep all related logic here
|
||||||
|
setPossibleDates(datesList)
|
||||||
|
}, [datesList, setPossibleDates])
|
||||||
|
|
||||||
|
// EVENTS & DATES
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let updatedDates = eventsToDates(eventsList).sort();
|
let updatedDates = eventsToDates(eventsList).sort();
|
||||||
setDatesList(updatedDates);
|
setDatesList(updatedDates);
|
||||||
}, [eventsList]);
|
}, [eventsList]);
|
||||||
|
|
||||||
const handleSelect = (info) => {
|
const handleSelectDates = (info) => {
|
||||||
let updatedEvents = [];
|
let updatedEvents = [];
|
||||||
let datesList = new Set();
|
let datesList = new Set();
|
||||||
|
|
||||||
@ -90,10 +107,6 @@ export default function Schedule() {
|
|||||||
setEventsList(updatedEvents);
|
setEventsList(updatedEvents);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClear = () => {
|
|
||||||
setEventsList([]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = (date) => {
|
const handleDelete = (date) => {
|
||||||
let currentEvent = {
|
let currentEvent = {
|
||||||
start: date.toFormat('yyyy-MM-dd'),
|
start: date.toFormat('yyyy-MM-dd'),
|
||||||
@ -117,6 +130,65 @@ export default function Schedule() {
|
|||||||
setEventsList(updatedEvents);
|
setEventsList(updatedEvents);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
setEventsList([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// MEETING
|
||||||
|
const handleSchedule = () => {
|
||||||
|
backend
|
||||||
|
.post('/meetings', currentMeeting)
|
||||||
|
.then((response) => {
|
||||||
|
history.push('/availability');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setError('Failed to add new account.');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectTimezone = (value, item, event) => {
|
||||||
|
setCurrentMeeting({
|
||||||
|
...currentMeeting,
|
||||||
|
timezone: item.timezone,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClean = (event) => {
|
||||||
|
setCurrentMeeting({
|
||||||
|
...currentMeeting,
|
||||||
|
timezone: '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeMeeting = (value, evt) => {
|
||||||
|
setCurrentMeeting({
|
||||||
|
...currentMeeting,
|
||||||
|
[evt.target.name]: value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleIncrement = () => {
|
||||||
|
if (durationIdx <= durations.length - 2) {
|
||||||
|
setDurationIdx(durationIdx + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentMeeting({
|
||||||
|
...currentMeeting,
|
||||||
|
duration: durations[durationIdx].duration,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDecrement = () => {
|
||||||
|
if (durationIdx > 0) {
|
||||||
|
setDurationIdx(durationIdx - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentMeeting({
|
||||||
|
...currentMeeting,
|
||||||
|
duration: durations[durationIdx].duration,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NavBar title='Schedule a meeting' />
|
<NavBar title='Schedule a meeting' />
|
||||||
@ -125,27 +197,42 @@ export default function Schedule() {
|
|||||||
<div className={'meeting-info'}>
|
<div className={'meeting-info'}>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<ControlLabel>Title</ControlLabel>
|
<ControlLabel>Title</ControlLabel>
|
||||||
<FormControl name='title' type='text' />
|
<FormControl
|
||||||
|
name='title'
|
||||||
|
type='text'
|
||||||
|
formValue={currentMeeting.title}
|
||||||
|
onChange={handleChangeMeeting}
|
||||||
|
/>
|
||||||
<HelpBlock>This field is required</HelpBlock>
|
<HelpBlock>This field is required</HelpBlock>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<ControlLabel>Description</ControlLabel>
|
<ControlLabel>Description</ControlLabel>
|
||||||
<Input
|
<FormControl
|
||||||
name='description'
|
name='description'
|
||||||
componentClass='textarea'
|
componentClass='textarea'
|
||||||
type='text'
|
type='text'
|
||||||
rows={3}
|
rows={3}
|
||||||
placeholder='(optional)'
|
placeholder='(optional)'
|
||||||
|
formValue={currentMeeting.description}
|
||||||
|
onChange={handleChangeMeeting}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<div className='meeting-options-inline'>
|
<div className='meeting-options-inline'>
|
||||||
<FormGroup className='meeting-timezone'>
|
<FormGroup className='meeting-timezone'>
|
||||||
<ControlLabel>Timezone</ControlLabel>
|
<ControlLabel>Timezone</ControlLabel>
|
||||||
<TimezonePicker />
|
<TimezonePicker
|
||||||
|
handleSelect={handleSelectTimezone}
|
||||||
|
handleClean={handleClean}
|
||||||
|
timezone={currentMeeting.timezone}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup className='meeting-duration'>
|
<FormGroup className='meeting-duration'>
|
||||||
<ControlLabel>Duration</ControlLabel>
|
<ControlLabel>Duration</ControlLabel>
|
||||||
<DurationSelector />
|
<DurationSelector
|
||||||
|
durationIdx={durationIdx}
|
||||||
|
handleDecrement={handleDecrement}
|
||||||
|
handleIncrement={handleIncrement}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</div>
|
||||||
<ButtonGroup justified>
|
<ButtonGroup justified>
|
||||||
@ -163,9 +250,13 @@ export default function Schedule() {
|
|||||||
size='lg'
|
size='lg'
|
||||||
block
|
block
|
||||||
disabled={datesList.length === 0}
|
disabled={datesList.length === 0}
|
||||||
|
onClick={handleSchedule}
|
||||||
>
|
>
|
||||||
Confirm dates
|
Confirm dates
|
||||||
</Button>
|
</Button>
|
||||||
|
{error && (
|
||||||
|
<Message type='error' description={error} />
|
||||||
|
)}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<div className={'selected-dates'}></div>
|
<div className={'selected-dates'}></div>
|
||||||
{datesList.length > 0 && (
|
{datesList.length > 0 && (
|
||||||
@ -185,7 +276,7 @@ export default function Schedule() {
|
|||||||
/>
|
/>
|
||||||
<DaySelector
|
<DaySelector
|
||||||
eventsList={eventsList}
|
eventsList={eventsList}
|
||||||
handleSelect={handleSelect}
|
handleSelect={handleSelectDates}
|
||||||
handleClear={handleClear}
|
handleClear={handleClear}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user