Skip to content

Commit

Permalink
✨(frontend) add meeting register form
Browse files Browse the repository at this point in the history
add a form which enables the user to register the meeting
  • Loading branch information
karabij committed Dec 12, 2022
1 parent 26278f4 commit b639d4e
Show file tree
Hide file tree
Showing 31 changed files with 1,049 additions and 298 deletions.
2 changes: 2 additions & 0 deletions src/frontend/magnify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@testing-library/react": "13.3.0",
"@testing-library/user-event": "14.2.1",
"@types/jest": "28.1.1",
"@types/luxon": "^3.1.0",
"@types/react": "18.0.12",
"@types/react-time-picker": "^4.0.2",
"@types/styled-components": "5.1.25",
Expand All @@ -57,6 +58,7 @@
"jest": "28.1.1",
"jest-css-modules": "2.1.0",
"jest-environment-jsdom": "28.1.1",
"luxon": "^3.1.1",
"msw": "0.47.4",
"postcss": "8.4.14",
"prettier": "2.7.0",
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import withFormik from '@bbbtech/storybook-formik';
import { ComponentMeta, ComponentStory } from '@storybook/react';
import React from 'react';
import FormikDateTimePicker from './FormikDateTimePicker';

export default {
title: 'Formik/DateTimePicker',
component: FormikDateTimePicker,
decorators: [withFormik],
initialValues: { date: new Date() },
} as ComponentMeta<typeof FormikDateTimePicker>;

const Template: ComponentStory<typeof FormikDateTimePicker> = (args, context) => (
<div>
{context.parameters.title}
<FormikDateTimePicker {...args} />
</div>
);

export const basicDateTimePicker = Template.bind({});

basicDateTimePicker.args = {
timeName: 'time',
dateName: 'date',
frenchSuggestions: ['14:00', '15:00'],
localTimeSuggestions: ['2:00 PM', '3:00 PM'],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { ErrorMessage, useField, useFormikContext } from 'formik';
import { DateInput, DropButton, Box, Text } from 'grommet';
import { CaretDown } from 'grommet-icons';
import { DateTime, Settings } from 'luxon';
import React, { FunctionComponent, useState } from 'react';
import { useIntl } from 'react-intl';
import TimePicker, { TimePickerValue } from 'react-time-picker';
import SuggestionButton from './SuggestionButton';

export interface formikDateTimePickerProps {
dateName: string;
timeName: string;
frenchSuggestions: string[];
localTimeSuggestions: string[];
label: string;
}

const nextYear = new Date();
nextYear.setFullYear(new Date().getFullYear() + 1);

const FormikDateTimePicker: FunctionComponent<formikDateTimePickerProps> = ({ ...props }) => {
const [open, setOpen] = useState<boolean | undefined>(undefined);
const [dateField] = useField(props.dateName);
const [timeField] = useField(props.timeName);

const formikContext = useFormikContext();
const intl = useIntl();
Settings.defaultLocale = intl.locale;

const isToday =
DateTime.fromISO(dateField.value).toFormat('MM-dd-yyyy') ==
DateTime.now().toFormat('MM-dd-yyyy');
const beforeToday =
DateTime.fromISO(dateField.value).toFormat('MM-dd-yyyy') <
DateTime.now().toFormat('MM-dd-yyyy');

const onTimeChange = (value: string) => {
formikContext.setFieldValue(props.timeName, value.toString());
setOpen(false);
};

const onDateChange = (event: { value: string | string[] }) => {
let value: string;
if (Array.isArray(event.value)) {
value = '';
if (event.value.length > 0) {
value = event.value[0];
}
} else {
value = event.value;
}
formikContext.setFieldValue(props.dateName, value);
};

React.useEffect(() => {
console.log(formikContext.errors, formikContext.values);
}, [formikContext.values, formikContext.errors]);

const suggestionButtons = props.localTimeSuggestions.map((value: string, index: number) => (
<SuggestionButton
key={value}
beforeToday={beforeToday}
buttonValue={value}
choiceValue={timeField.value}
frenchButtonValue={props.frenchSuggestions[index]}
isToday={isToday}
onClick={onTimeChange}
/>
));

return (
<Box gap={'5px'}>
{props.label != '' && (
<label htmlFor={props.dateName}>
<Text size={'xsmall'} weight={'bold'}>
{props.label}
</Text>
</label>
)}
<div>
<Box align="center" basis="1" direction="column" gap="small">
<DateInput
{...dateField}
format={intl.locale === 'fr' ? 'jj/mm/aaaa' : 'yyyy/mm/dd'}
name={props.dateName}
onChange={onDateChange}
value={dateField.value ? new Date(dateField.value).toISOString() : ''}
calendarProps={{
bounds: [new Date().toISOString(), nextYear.toISOString()],
size: 'small',
}}
></DateInput>

<Box align="center" direction="row" gap="small">
<TimePicker
{...timeField}
disableClock
locale={intl.locale}
name={props.timeName}
onChange={(value: TimePickerValue) => onTimeChange(value.toString())}
></TimePicker>
<DropButton
dropAlign={{ top: 'bottom' }}
onClose={() => setOpen(false)}
open={open}
dropContent={
<Box align="center" basis="small" direction="column" gap="5px">
{suggestionButtons}
</Box>
}
onOpen={() => {
setOpen(true);
}}
>
<CaretDown size="15px" />
</DropButton>
</Box>
</Box>
</div>
</Box>
);
};

export default FormikDateTimePicker;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Box, Button, Text } from 'grommet';
import { normalizeColor } from 'grommet/utils';
import { DateTime } from 'luxon';
import React, { FunctionComponent, ReactElement } from 'react';
import { useTheme } from 'styled-components';
import { mergeDateTime } from './utils';

const today = DateTime.now().toISO();

export interface suggestionButtonProps {
buttonValue: string;
frenchButtonValue: string;
choiceValue: string;
onClick: (value: string) => void;
isToday: boolean;
beforeToday: boolean;
}

const SuggestionButton: FunctionComponent<suggestionButtonProps> = ({ ...props }): ReactElement => {
const isChosenButton: boolean = props.frenchButtonValue == props.choiceValue;
const chosenDateTime = mergeDateTime(today, props.frenchButtonValue);
const isButtonBeforeNow: boolean = chosenDateTime ? chosenDateTime < today : false;
const theme = useTheme();
return (
<Button
color={isChosenButton ? `${normalizeColor('light-2', theme)}` : 'black'}
disabled={props.beforeToday || (props.isToday && isButtonBeforeNow)}
fill={isChosenButton ? 'horizontal' : false}
justify="center"
margin={{ top: 'xsmall' }}
primary={isChosenButton}
onClick={() => {
props.onClick(props.frenchButtonValue);
console.log(`chosenDateTime : ${chosenDateTime}`);
}}
>
<Box alignContent="center" alignSelf="center">
<Text color="black" textAlign="center">
{props.buttonValue}
</Text>
</Box>
</Button>
);
};

export default SuggestionButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, formikDateTimePickerProps } from '../FormikDateTimePicker/FormikDateTimePicker';
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { DateTime, Duration } from 'luxon';

export const splitDateTime = (dateTimeISO: string | null): { date: string; time: string } => {
if (!dateTimeISO) {
return { date: '', time: '' };
}
const dateTime = DateTime.fromISO(dateTimeISO);
return {
date: dateTime.toISODate(),
time: dateTime.toLocaleString(DateTime.TIME_24_SIMPLE),
};
};

export const mergeDateTime = (
dateString: string | null,
timeString: string | null,
): string | null => {
if (!dateString || !timeString) {
return null;
}
try {
const time = Duration.fromISOTime(timeString);
const dateTime = DateTime.fromISO(dateString).set({
hour: time.hours,
minute: time.minutes,
});
return dateTime.toISO();
} catch (e) {
return null;
}
};
Loading

0 comments on commit b639d4e

Please sign in to comment.