Skip to content

Commit

Permalink
Merge branch 'main' into filter_endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
cw00dw0rd committed Mar 17, 2021
2 parents 51bba69 + 45f23a9 commit 4f06e00
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 88 deletions.
22 changes: 22 additions & 0 deletions workspaces/frontend-react/src/hooks/useOnClickOutside.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { useEffect } = require('react');

const useonClickOutside = (ref, callback) => {
useEffect(() => {
/**
* Alert if clicked on outside of element
*/
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
callback();
}
};
// Bind the event listener
document.addEventListener('mousedown', handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref, callback]);
};

export default useonClickOutside;
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
import React, { useEffect, useState } from 'react';
import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { Form } from 'react-bulma-components';
import Calendar from 'react-calendar';
import 'react-calendar/dist/Calendar.css';
import './date-picker.scss';
import useonClickOutside from 'hooks/useOnClickOutside';

const DatePicker = ({ placeholder = undefined, name = undefined, value = undefined, onChange }) => {
const [showCalendar, setShowCalendar] = useState(false);

useEffect(() => {
if (!showCalendar) {
return () => {
return null;
};
}
const ref = useRef();

const hide = () => {
setShowCalendar(false);
};
// Trick to close on click outside
setTimeout(() => {
window.addEventListener('click', hide);
}, 100);
return () => {
return window.removeEventListener('click', hide);
};
}, [showCalendar]);
useonClickOutside(ref, () => {
setShowCalendar(false);
});

const onSelectDate = (newValue) => {
setShowCalendar(false);
Expand All @@ -38,16 +26,12 @@ const DatePicker = ({ placeholder = undefined, name = undefined, value = undefin
};

return (
<div className="date-picker">
<div ref={ref} className="date-picker">
<Form.Input
onChange={() => {
return null;
}}
value={value ? value.toLocaleString().split(' ').shift() : ''}
placeholder={placeholder}
autoComplete="off"
autoCapitalize="off"
name={name}
readOnly
onFocus={() => {
return setShowCalendar(true);
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { Form, Loader } from 'react-bulma-components';
import * as api from 'services/api';
import { Autocomplete } from 'components/autocomplete';

const DestinationPicker = ({ value, onChange, onSelect }) => {
const [destinations, setDestinations] = useState({
options: [],
selected: undefined,
});
const [showAutocomplete, setShowAutocomplete] = useState(false);

useEffect(async () => {
if (!value || !showAutocomplete) {
setDestinations({
options: [],
selected: undefined,
});
return;
}
setDestinations({
options: [{ isLoading: true }],
selected: undefined,
});
const options = await api.autocomplete({ term: value });
setDestinations({
options,
selected: undefined,
});
}, [value, showAutocomplete]);

return (
<div style={{ position: 'relative ' }}>
<Form.Input
onFocus={() => {
setShowAutocomplete(true);
}}
onBlur={() => {
setShowAutocomplete(false);
}}
autoComplete="off"
autoCapitalize="off"
onChange={onChange}
value={value}
name="destination"
placeholder="I want to go to"
/>
{showAutocomplete && (
<Autocomplete options={destinations.options} onSelect={onSelect}>
{(option) => {
if (option.isLoading) {
return (
<div style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Loader color="primary" />
</div>
);
}
return <div>{option.name}</div>;
}}
</Autocomplete>
)}
</div>
);
};

DestinationPicker.propTypes = {
value: PropTypes.string,
onChange: PropTypes.func.isRequired,
onSelect: PropTypes.func.isRequired,
};

export default DestinationPicker;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import DestinationPicker from './destination-picker';

export default DestinationPicker;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import TravelersPicker from './travelers-picker';

export default TravelersPicker;
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { Box, Form, Tag } from 'react-bulma-components';
import useonClickOutside from 'hooks/useOnClickOutside';

import './travelers-picker.scss';

const getTextValue = (value) => {
if (value.adults === 0) {
return '';
}
if (value.adults === 1 && value.children === 0) {
return 'and I will travel alone';
}

return `and we are ${value.adults} adult${value.adults > 1 ? 's' : ''} ${value.children > 0 ? `and ${value.children} children` : ''}`.trim();
};

const TravelersPicker = ({ value, onChange }) => {
const ref = useRef();
const [showPicker, setShowPicker] = useState(false);
const valueInText = getTextValue(value);

useonClickOutside(ref, () => {
setShowPicker(false);
});

const onIncrease = (event) => {
onChange({
target: {
name: 'travelers',
value: {
...value,
[event.target.dataset.name]: value[event.target.dataset.name] + 1,
},
},
});
};

const onDecrease = (event) => {
if (!value[event.target.dataset.name]) {
return;
}
onChange({
target: {
name: 'travelers',
value: {
...value,
[event.target.dataset.name]: value[event.target.dataset.name] - 1,
},
},
});
};

return (
<div className="travelers-picker" ref={ref} style={{ position: 'relative ' }}>
<Form.Input
onFocus={() => {
return setShowPicker(true);
}}
readOnly
autoComplete="off"
onChange={onChange}
value={valueInText}
name="travelers"
placeholder="and we are 2 adults an a child"
/>
{showPicker && (
<Box className="picker">
<div className="row">
<div>Adults</div>
<div className="count-selector">
<Tag data-name="adults" onClick={onDecrease}>
-
</Tag>{' '}
{value.adults}{' '}
<Tag data-name="adults" onClick={onIncrease}>
+
</Tag>
</div>
</div>
<div className="row">
<div>Children</div>
<div className="count-selector">
<Tag data-name="children" onClick={onDecrease}>
-
</Tag>{' '}
{value.children}{' '}
<Tag data-name="children" onClick={onIncrease}>
+
</Tag>
</div>
</div>
</Box>
)}
</div>
);
};

TravelersPicker.propTypes = {
value: PropTypes.shape({
adults: PropTypes.number,
children: PropTypes.number,
}),
onChange: PropTypes.func.isRequired,
};

export default TravelersPicker;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@import "variables.scss";

.travelers-picker {
.picker {
position: absolute;
top: calc(100% + 0.5rem);
left: 0;
right: 0;
z-index: 1;
.row {
display: flex;
justify-content: space-between;
padding: 0.75rem;
&:first-child {
border-bottom: 1px solid $grey-lighter;
}
}
.count-selector {
* {
margin: 0 0.5rem;
}
.tag {
cursor: pointer;
&:hover {
background-color: $grey-light;
}
}
}
}
}
Loading

0 comments on commit 4f06e00

Please sign in to comment.