Skip to content

Commit

Permalink
initial commit on a fresh branch
Browse files Browse the repository at this point in the history
  • Loading branch information
chryslovelace committed Oct 9, 2023
1 parent 83c419c commit 631a123
Show file tree
Hide file tree
Showing 7 changed files with 1,532 additions and 1,450 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@testing-library/user-event": "^14.2.0",
"axios": "^0.27.2",
"classnames": "^2.2.6",
"date-fns": "^2.30.0",
"downshift": "^6.1.7",
"formik": "^2.1.5",
"mirador": "^3.3.0",
Expand All @@ -19,6 +20,7 @@
"react": "^16.13.1",
"react-accessible-dropdown-menu-hook": "^3.2.0",
"react-aria-live": "^2.0.5",
"react-datepicker": "^4.20.0",
"react-dom": "^16.13.1",
"react-google-recaptcha": "^2.1.0",
"react-helmet": "^6.1.0",
Expand Down
4 changes: 2 additions & 2 deletions src/components/Inputs/__tests__/Inputs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ it('renders checkbox props correctly', () => {

it('renders date props correctly', () => {
act(() => {
render(<I18nApp ReactComponent={<DateInput label='Select a date' id='1' />} />, container)
render(<I18nApp ReactComponent={<DateInput label='Select a date' id='1' handleChange={jest.fn()} />} />, container)
})

const label = document.querySelector('label')
expect(label.textContent).toBe('Select a date')

const input = document.querySelector('.dp__input')
const input = document.querySelector('.dp__wrapper')
expect(input.id).toBe('1')
})

Expand Down
66 changes: 21 additions & 45 deletions src/components/Inputs/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import React from 'react'
import React, {useEffect, useState} from 'react'
import PropTypes from 'prop-types'
import {
DatePicker,
DatePickerInput,
DatePickerMonth,
DatePickerTable,
DatePickerButton,
DatePickerCalendar} from '@reecelucas/react-datepicker'
import DatePicker from 'react-datepicker'
import {useSelect} from 'downshift'
import MaterialIcon from '../MaterialIcon'
import classnames from 'classnames'
Expand Down Expand Up @@ -62,54 +56,36 @@ CheckBoxInput.defaultProps = {
checked: true,
}

export const DateInput = props => (
export const DateInput = ({className, defaultDate, handleChange, helpText, id, label, ...props}) => {
const [startDate, setStartDate] = useState(defaultDate || new Date())

useEffect(() => {
handleChange(startDate)
}, [startDate, setStartDate])

return (
<>
<label htmlFor={id}>{label}</label>
<DatePicker
className='mb-2'
initialDate={new Date()}
minDate={new Date()}
onSelect={date => props.handleChange(date)}>
<label htmlFor={props.id}>{props.label}</label>
<DatePickerInput
className='dp__input'
dateFormat={'MM/dd/yyyy'}
id={props.id}
name={props.name} />
<DatePickerCalendar className='dp__calendar py-20 px-20'>
<div className='dp__top-bar mb-12'>
<DatePickerButton
className='dp__button py-2 px-6'
aria-label={t({
comment: 'Aria label for Calendar button',
message: 'Switch to the previous month.'
})}
updateMonth={({ prev }) => prev()} >
<MaterialIcon icon='west' />
</DatePickerButton>
<DatePickerMonth className='dp__month px-16 py-0' />
<DatePickerButton
className='dp__button py-2 px-6'
aria-label={t({
comment: 'Aria label for Calendar button',
message: 'Switch to the next month.'
})}
updateMonth={({ next }) => next()} >
<MaterialIcon icon='east' />
</DatePickerButton>
</div>
<DatePickerTable className='dp__table' />
</DatePickerCalendar>
className={className || 'dp__wrapper'}
selected={startDate}
showTimeSelect='true'
onChange={date => setStartDate(date)}
dateFormat="yyyy-MM-dd h:mm aa"
id={id}
{...props}>
</DatePicker>
{props.helpText && <p className='input__help-text' aria-describedby={`desc-${props.id}`}>{props.helpText}</p>}
{helpText && <p className='input__help-text' aria-describedby={`desc-${id}`}>{helpText}</p>}
</>
)
)}

DateInput.propTypes = {
className: PropTypes.string,
handleChange: PropTypes.func,
helpText: PropTypes.string,
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
defaultDate: PropTypes.instanceOf(Date),
};


Expand Down
1 change: 1 addition & 0 deletions src/components/ModalMyList/__tests__/ModalMyList.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ beforeEach(() => {
return Promise.reject(new Error('not found'))
}
})
axios.get.mockImplementation((url) => Promise.resolve({data:[]}))
})

afterEach(() => {
Expand Down
123 changes: 98 additions & 25 deletions src/components/ModalMyList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { ModalSavedItemList } from '../ModalSavedItem'
import { getFormattedDate } from '../Helpers'
import './styles.scss'
import { Plural, Trans, select, t } from '@lingui/macro'
import axios from 'axios'
import { addBusinessDays, parse, parseISO, startOfDay, isWithinInterval } from 'date-fns'


const SubmitListInput = ({ submitList }) => {
Expand Down Expand Up @@ -347,7 +349,95 @@ EmailModal.propTypes = {
toggleModal: PropTypes.func.isRequired,
}

export const ReadingRoomRequestModal = props => (
const ReadingRoomSelect = ({ readingRooms }) => {
const { setFieldValue } = useFormikContext();
const [site, setSite] = useState('');

const ReadingRoomLocations = readingRooms.map(readingRoom => ({
value: readingRoom.sites[0],
label: readingRoom.name,
}));
ReadingRoomLocations.unshift({
value: "",
label: t({message: "Please select a reading room"}),
});

useEffect(() => {
setFieldValue('site', site);
}, [site, setFieldValue]);

return (
<div className='form-group'>
<SelectInput
className='select__modal'
id='site'
label={t({message: 'Select Reading Room Location'})}
name='site'
onChange={({ selectedItem }) => setSite(selectedItem.value)}
options={ReadingRoomLocations}
required={true}
selectedItem={site || ''} />
<ErrorMessage
id='site-error'
name='site'
component='div'
className='modal-form__error' />
</div>
)
}

const ReadingRoomDateInput = ({ readingRoom }) => {
const { setFieldValue } = useFormikContext();

return (
<div className='form-group'>
<Field
component={DateInput}
handleChange={date => setFieldValue('scheduledDate', date)}
helpText={t({
comment: 'Helptext for scheduling date.',
message: 'Enter the date of your research visit (mm/dd/yyyy)'
})}
id='scheduledDate'
label={t({
comment: 'Label for scheduling date',
message: 'Scheduled Date *'
})}
type='date'
defaultDate={addBusinessDays(new Date(), readingRoom?.policies[0]?.appointmentMinLeadDays || 1)}
minDate={addBusinessDays(new Date(), readingRoom?.policies[0]?.appointmentMinLeadDays || 1)}
filterDate={date => readingRoom?.openHours.some(x => x.dayOfWeek === date.getDay())}
filterTime={date => {
if (readingRoom === undefined) return false;
const hours = readingRoom.openHours.find(x => x.dayOfWeek === date.getDay());
return isWithinInterval(date, {
start: parse(hours.openTime, "HH:mm:ss", date),
end: parse(hours.closeTime, "HH:mm:ss", date),
});
}}
excludeDateIntervals={readingRoom?.closures.map(closure => ({
start: startOfDay(parseISO(closure.startDate)),
end: startOfDay(parseISO(closure.endDate)),
}))} />
<ErrorMessage
id='scheduledDate-error'
name='scheduledDate'
component='div'
className='modal-form__error' />
</div>
)
}

export const ReadingRoomRequestModal = props => {
const [aeonReadingRooms, setAeonReadingRooms] = useState([]);

useEffect(() => {
axios.get(`${process.env.REACT_APP_REQUEST_BROKER_BASEURL}/reading-rooms`).then(response => {
setAeonReadingRooms(response.data);
});
}, []); // empty deps array means it runs once

return (
<ModalMyList
appElement={props.appElement}
title='Request in Reading Room'
Expand All @@ -365,6 +455,9 @@ export const ReadingRoomRequestModal = props => (
comment: 'Missing Scheduled Date error',
message: 'Please provide the date of your research visit.'
});
if (!values.site) errors.site = t({
message: 'Please select a location of a reading room.'
})
if (!values.recaptcha) errors.recaptcha = t({
message: 'Please complete this field.'
});
Expand Down Expand Up @@ -393,29 +486,9 @@ export const ReadingRoomRequestModal = props => (
})}
component='div'
className='input__error' />
<div className='form-group mx-0'>
<Field
component={DateInput}
handleChange={date => setFieldValue('scheduledDate', date)}
helpText={t({
comment: 'Helptext for scheduling date.',
message: 'Enter the date of your research visit (mm/dd/yyyy)'
})}
id='scheduledDate'
label={t({
comment: 'Label for scheduling date',
message: 'Scheduled Date *'
})}
type='date' />
<ErrorMessage
id='scheduledDate-error'
name={t({
comment: 'Name for scheduling date error',
message: 'scheduledDate'
})}
component='div'
className='input__error' />
</div>
<ReadingRoomSelect readingRooms={aeonReadingRooms} />
<ReadingRoomDateInput
readingRoom={aeonReadingRooms.find(room => room.sites[0] === values.site)} />
<FormGroup
label={t({
comment: 'Label for RAC staff message Form',
Expand Down Expand Up @@ -465,7 +538,7 @@ export const ReadingRoomRequestModal = props => (
</Formik>
}
/>
)
)}

ReadingRoomRequestModal.propTypes = {
appElement: PropTypes.object,
Expand Down
2 changes: 2 additions & 0 deletions src/components/PageMyList/__tests__/PageMyList.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ it('renders props correctly', async () => {
axios.get.mockImplementation((url) => {
if (url.includes('status')) {
return Promise.resolve({ data: { pong: true } })
} else if (url.includes('reading-rooms')) {
return Promise.resolve({data:[]})
} else {
return Promise.reject(new Error('not found'))
}
Expand Down
Loading

0 comments on commit 631a123

Please sign in to comment.