Skip to content

Commit

Permalink
localization with next-i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjie Velarde committed Oct 14, 2021
1 parent 706c087 commit 7f37186
Show file tree
Hide file tree
Showing 27 changed files with 233 additions and 115 deletions.
15 changes: 4 additions & 11 deletions components/BookButton/BookButton.test.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import { render, screen, waitFor } from '../../test-utils/testing-library-utils';
import userEvent from '@testing-library/user-event';
// import { Router } from 'react-router-dom';
// import {createMemoryHistory} from 'history';
import BookButton from '.';
import mockDoctor from '../../test-utils/mockDoctor.json';

test('renders and toggles modal area', async () => {
// const history = createMemoryHistory();
render(
// <Router history={history}>
<BookButton doctor={mockDoctor}/>
// </Router>
);

const button = screen.getByRole('button', {name: /book appointment/i} );
render(<BookButton doctor={mockDoctor}/>);

const button = screen.getByRole('button', {name: /booking.trigger/i} );
expect(button).toBeInTheDocument();

const modalHidden = screen.queryByTestId(/booking-modal/i);
Expand All @@ -33,7 +26,7 @@ test('renders and toggles modal area', async () => {
const closeModal = screen.getByRole('button', {name: /close/i} );
expect(closeModal).toBeInTheDocument();

const confirmButton = screen.getByRole('button', {name: /confirm/i} );
const confirmButton = screen.getByRole('button', {name: /booking.confirm/i} );
expect(confirmButton).toBeInTheDocument();

const doctorName = screen.getByText(`DR. ${mockDoctor.name.toUpperCase()}`);
Expand Down
10 changes: 6 additions & 4 deletions components/BookButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {useState} from 'react';
import { useState } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'next-i18next';
import Modal from 'react-bootstrap/Modal';
import BookForm from '../BookForm';
import { useAppContext } from '../../context';
Expand All @@ -11,8 +12,9 @@ interface Props {
label?: string;
}

const BookButton = ({ doctor, label = 'Book Appointment' }: Props) => {
const BookButton = ({ doctor, label = 'booking.trigger' }: Props) => {
const [show, setShow] = useState(false);
const { t } = useTranslation('common');
const { resetSysError } = useAppContext();

const handleClose = () => {
Expand All @@ -23,8 +25,8 @@ const BookButton = ({ doctor, label = 'Book Appointment' }: Props) => {

return (
<>
<SC.Trigger variant="primary" onClick={handleShow} aria-label={label}>
{label}
<SC.Trigger variant="primary" onClick={handleShow} aria-label={t(label)}>
{t(label)}
</SC.Trigger>

<Modal show={show} onHide={handleClose} data-testid="booking-modal">
Expand Down
15 changes: 4 additions & 11 deletions components/BookForm/BookForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import { screen, renderWithFormik, waitFor } from '../../test-utils/testing-library-utils';
// import { Router } from 'react-router-dom';
// import {createMemoryHistory} from 'history';
import BookForm from '.';
import mockDoctor from '../../test-utils/mockDoctor.json';

test('renders with necessary elements', async () => {
// const history = createMemoryHistory();
renderWithFormik(
// <Router history={history}>
<BookForm doctor={mockDoctor} />
// </Router>
);
renderWithFormik(<BookForm doctor={mockDoctor} />);

const confirmButton = screen.getByRole('button', {name: /confirm/i} );
const confirmButton = screen.getByRole('button', {name: /booking.confirm/i} );
expect(confirmButton).toBeInTheDocument();

await waitFor(async () => {
Expand All @@ -21,10 +14,10 @@ test('renders with necessary elements', async () => {
expect(timeSlots.length).toBeGreaterThan(0);
});

const nameField = screen.getByRole('textbox', {name: /your name/i});
const nameField = screen.getByRole('textbox', {name: /booking.name/i});
expect(nameField).toBeInTheDocument();

const timeSlotCombo = screen.getByRole('combobox', {name: /time slot/i});
const timeSlotCombo = screen.getByRole('combobox', {name: /booking.start/i});
expect(timeSlotCombo).toBeInTheDocument();

const datePicker = screen.getByText(/date/i);
Expand Down
14 changes: 8 additions & 6 deletions components/BookForm/FormUI.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'next-i18next';
import Form from 'react-bootstrap/Form';
import { useFormikContext, Field, ErrorMessage } from 'formik';
import { useDoctor } from '../../hooks/useDoctor';
Expand All @@ -22,6 +23,7 @@ const FormUI = ({ doctor }: Props) => {
setFieldValue,
isSubmitting,
} = useFormikContext<Booking>();
const { t } = useTranslation('common');

const { today, restDays, isClinicOpen, activeStartDate } = useDoctor(doctor);
const [bookingDate, setBookingDate] = useState(activeStartDate);
Expand All @@ -34,18 +36,18 @@ const FormUI = ({ doctor }: Props) => {
return (
<>
<SC.FormGroup className={`mb-3${touched.name && errors.name ? ' error': ''}`} controlId="name">
<Form.Label>Your name</Form.Label>
<Form.Label>{t('booking.name')}</Form.Label>
<Field
component={Form.Control}
placeholder="Your name"
placeholder={t('booking.name')}
defaultValue={values.name}
onChange={handleChange}
onBlur={handleBlur}
/>
<ErrorMessage name="name" component={SC.Error} />
</SC.FormGroup>
<Form.Group className="mb-3">
<Form.Label>Date</Form.Label>
<Form.Label>{t('booking.date')}</Form.Label>
<SC.DatePicker
calendarType="US"
onChange={(v: Date) => {
Expand All @@ -65,22 +67,22 @@ const FormUI = ({ doctor }: Props) => {
/>
</Form.Group>
<SC.FormGroup className={`mb-3${touched.start && errors.start ? ' error': ''}`} controlId="start">
<Form.Label>Time Slot</Form.Label>
<Form.Label>{t('booking.start')}</Form.Label>
<Field
component={FormSelect}
defaultValue={values.start}
onChange={handleChange}
onBlur={handleBlur}
>
<option value=''>Choose Time</option>
<option value=''>{t('booking.start.choose')}</option>
{getDaySchedule(doctor, today, bookingDate)}
</Field>
<ErrorMessage name="start" component={SC.Error} />
</SC.FormGroup>
<Field type="hidden" name="date" value={getFormattedDate(bookingDate)} />
<Field type="hidden" name="doctorId" value={doctor.id} />
<SC.Confirm variant="primary" type="submit" disabled={isSubmitting}>
Confirm
{t('booking.confirm')}
</SC.Confirm>
</>
);
Expand Down
11 changes: 2 additions & 9 deletions components/BookForm/ThankYou.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { screen, renderWithFormik } from '../../test-utils/testing-library-utils';
// import { Router } from 'react-router-dom';
// import {createMemoryHistory} from 'history';
import ThankYou from './ThankYou';

jest.mock('formik', () => ({
Expand All @@ -16,13 +14,8 @@ jest.mock('formik', () => ({
}));

test('renders with default label', async () => {
// const history = createMemoryHistory();
renderWithFormik(
// <Router history={history}>
<ThankYou />
// </Router>
);
renderWithFormik(<ThankYou />);

const thankYou = screen.getByText(/thank you/i);
const thankYou = screen.getByText(/booking.thankyou/i);
expect(thankYou).toBeInTheDocument();
});
4 changes: 3 additions & 1 deletion components/BookForm/ThankYou.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { useFormikContext } from 'formik';
import { useTranslation } from 'next-i18next';
import { Booking } from '../../types';

const ThankYou = () => {
const { values } = useFormikContext<Booking>();
const { t } = useTranslation('common');

return <div>
<p>Thank you { values.name }, your appointment has been booked on { values.date } at { values.start }</p>
<p>{t('booking.thankyou', values)}</p>
</div>;
}

Expand Down
8 changes: 5 additions & 3 deletions components/BookForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'next-i18next';
import Alert from 'react-bootstrap/Alert';
import { Formik, Form } from 'formik';
import { useAppContext } from '../../context';
Expand All @@ -23,14 +24,15 @@ const BookForm = ({ doctor }: Props) => {
status: '',
message: ''
});
const { t } = useTranslation('common');

const validateForm = (values: FormFields) => {
const errors: FormFields = {};
if (!values.name) {
errors.name = 'Please enter your name';
errors.name = t('booking.error.name.required');
}
if (!values.start) {
errors.start = 'Please choose a time slot';
errors.start = t('booking.error.start.required');
}
return errors;
};
Expand All @@ -45,7 +47,7 @@ const BookForm = ({ doctor }: Props) => {
await createBooking(values);
setStatus({
status: 'SUCCESS',
message: 'Booking Created'
message: t('booking.alert.success')
});
} catch (e: any) {
setStatus({
Expand Down
9 changes: 1 addition & 8 deletions components/Doctor/Doctor.error.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { render, screen, waitFor } from '../../test-utils/testing-library-utils';
// import { Router } from 'react-router-dom';
// import {createMemoryHistory} from 'history';
import getConfig from 'next/config';
import { rest } from 'msw';
import { server } from '../../test-utils/mockServer';
Expand Down Expand Up @@ -28,12 +26,7 @@ server.resetHandlers(

test('handles system error', async () => {

// const history = createMemoryHistory();
render(
// <Router history={history}>
<Doctor />
// </Router>
);
render(<Doctor />);

await waitFor(async () => {
const alert = await screen.findByRole('alert');
Expand Down
11 changes: 2 additions & 9 deletions components/Doctor/Doctor.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { render, screen, waitForElementToBeRemoved } from '../../test-utils/testing-library-utils';
// import { Router } from 'react-router-dom';
// import {createMemoryHistory} from 'history';
import Doctor from '.';
import mockDoctor from '../../test-utils/mockDoctor.json';

Expand All @@ -14,15 +12,10 @@ jest.mock('next/router', () => ({
}));

test('renders doctor page', async () => {
// const history = createMemoryHistory();

render(
// <Router history={history}>
<Doctor />
// </Router>
);
render(<Doctor />);

const headerLink = screen.getByRole('link', { name: /book-a-doctor/i });
const headerLink = screen.getByRole('link', { name: /main-title/i });
expect(headerLink).toBeInTheDocument();

await waitForElementToBeRemoved(() => screen.getByTestId(/spinner/i));
Expand Down
14 changes: 8 additions & 6 deletions components/Doctor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect } from 'react';
import { useRouter } from 'next/router'
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faUserMd, faMapMarkerAlt } from '@fortawesome/free-solid-svg-icons';
import Table from 'react-bootstrap/Table';
Expand All @@ -18,6 +19,7 @@ const Doctor = () => {
const { id } = router.query;

const { state, fetchDoctor } = useAppContext();
const { t } = useTranslation('common');

useEffect(() => {
async function fetchData() {
Expand All @@ -31,8 +33,8 @@ const Doctor = () => {
return sortOpeningHours(state.doctor.opening_hours).map(slot => {
return <SC.TableRow key={slot.day} data-testid="slot-row">
<td>{slot.day}</td>
<td>{slot.isClosed ? 'Closed' : formatTime(slot.start)}</td>
<td>{slot.isClosed ? 'Closed' : formatTime(slot.end)}</td>
<td>{slot.isClosed ? t('opening-hours.closed') : formatTime(slot.start)}</td>
<td>{slot.isClosed ? t('opening-hours.closed') : formatTime(slot.end)}</td>
</SC.TableRow>;
});
};
Expand All @@ -58,9 +60,9 @@ const Doctor = () => {
<Table striped bordered hover size="sm" aria-label="opening-hours">
<thead>
<SC.TableRow>
<th>Day</th>
<th>Opening</th>
<th>Closing</th>
<th>{t('opening-hours.day')}</th>
<th>{t('opening-hours.start')}</th>
<th>{t('opening-hours.end')}</th>
</SC.TableRow>
</thead>
<tbody>
Expand Down
2 changes: 1 addition & 1 deletion components/DoctorCard/DoctorCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ test('renders with default label', async () => {
const title = screen.getByRole('heading', {name: /fake doctor/i} );
expect(title).toBeInTheDocument();

const openingHoursTitle = screen.getByRole('heading', {name: /opening hours/i} );
const openingHoursTitle = screen.getByRole('heading', {name: /opening-hours/i} );
expect(openingHoursTitle).toBeInTheDocument();
});
14 changes: 8 additions & 6 deletions components/DoctorCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import Link from 'next/link';
import { useTranslation } from 'next-i18next';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faUserMd, faMapMarkerAlt } from '@fortawesome/free-solid-svg-icons';
import Accordion from 'react-bootstrap/Accordion';
Expand All @@ -15,14 +16,15 @@ interface Props {
}

const DoctorCard = ({ doctor }: Props) => {
const { t } = useTranslation('common');
const { fullAddress, sortedOpeningHours } = useDoctor(doctor);

const showOpeningHours = () => {
return sortedOpeningHours.map(slot => {
return <SC.TableRow key={slot.day}>
<td>{slot.day}</td>
<td>{slot.isClosed ? 'Closed' : formatTime(slot.start)}</td>
<td>{slot.isClosed ? 'Closed' : formatTime(slot.end)}</td>
<td>{slot.isClosed ? t('opening-hours.closed') : formatTime(slot.start)}</td>
<td>{slot.isClosed ? t('opening-hours.closed') : formatTime(slot.end)}</td>
</SC.TableRow>;
});
};
Expand All @@ -47,14 +49,14 @@ const DoctorCard = ({ doctor }: Props) => {
</Link>
<Accordion>
<SC.AccordionItem eventKey="0">
<SC.AccordionHeader>Opening Hours</SC.AccordionHeader>
<SC.AccordionHeader>{t('opening-hours')}</SC.AccordionHeader>
<SC.AccordionBody>
<Table striped bordered hover size="sm">
<thead>
<SC.TableRow>
<th>Day</th>
<th>Opening</th>
<th>Closing</th>
<th>{t('opening-hours.day')}</th>
<th>{t('opening-hours.start')}</th>
<th>{t('opening-hours.end')}</th>
</SC.TableRow>
</thead>
<tbody>
Expand Down
7 changes: 1 addition & 6 deletions components/Doctors/Doctors.error.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@ test('handles system error', async () => {
rest.get(`${baseUrl}${doctorPath}`, (req, res, ctx) => res(ctx.status(500)))
);

// const history = createMemoryHistory();
render(
// <Router history={history}>
<Doctors />
// </Router>
);
render(<Doctors />);

await waitForElementToBeRemoved(() => screen.getByTestId(/spinner/i));

Expand Down
Loading

0 comments on commit 7f37186

Please sign in to comment.