selected event is context + some cleanup

This commit is contained in:
cv
2021-03-24 23:27:28 +01:00
parent d5721f0479
commit e32c439d83
6 changed files with 142 additions and 91 deletions
+9 -6
View File
@@ -1,17 +1,20 @@
import { Route } from 'react-router'; import { Route } from 'react-router';
import './App.css'; import './App.css';
import { EventProvider } from './app/context/eventContext';
import { EventListProvider } from './app/context/eventListContext'; import { EventListProvider } from './app/context/eventListContext';
import Editor from './features/editors/Editor'; import Editor from './features/editors/Editor';
import DefaultPresenter from './features/viewers/DefaultPresenter'; import DefaultPresenter from './features/viewers/DefaultPresenter';
function App() { function App() {
return ( return (
<div className='App'> <EventProvider>
<Route path='/' exact component={DefaultPresenter} /> <div className='App'>
<EventListProvider> {/* <Route path='/' exact component={DefaultPresenter} /> */}
<Route path='/editor' exact component={Editor} /> <EventListProvider>
</EventListProvider> <Route path='/editor' exact component={Editor} />
</div> </EventListProvider>
</div>
</EventProvider>
); );
} }
+13
View File
@@ -0,0 +1,13 @@
import { createContext, useState } from 'react';
export const EventContext = createContext();
export function EventProvider(props) {
const [event, setEvent] = useState(null);
return (
<EventContext.Provider value={[event, setEvent]}>
{props.children}
</EventContext.Provider>
);
}
+62 -49
View File
@@ -1,53 +1,45 @@
import { Button } from '@chakra-ui/button'; import { Button } from '@chakra-ui/button';
import { ArrowForwardIcon } from '@chakra-ui/icons'; import { ArrowForwardIcon } from '@chakra-ui/icons';
import { Flex, Heading } from '@chakra-ui/layout'; import { Grid, GridItem, Heading } from '@chakra-ui/layout';
import { SimpleGrid } from '@chakra-ui/layout';
import { Box } from '@chakra-ui/layout'; import { Box } from '@chakra-ui/layout';
import { useContext } from 'react';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { sampleData } from '../../app/sampleData'; import { EventContext } from '../../app/context/eventContext';
import NumberedText from '../../common/components/text/NumberedText'; import NumberedText from '../../common/components/text/NumberedText';
import PlaybackControl from '../control/PlaybackControl';
import EventForm from '../form/EventForm'; import EventForm from '../form/EventForm';
import MessageForm from '../form/MessageForm';
import PreviewContainer from '../viewers/PreviewContainer'; import PreviewContainer from '../viewers/PreviewContainer';
import styles from './Editor.module.css'; import styles from './Editor.module.css';
import EventList from './list/EventList'; import EventList from './list/EventList';
export default function Editor() { export default function Editor() {
const [data, setData] = useState(sampleData);
const [selectedData, setSelectedData] = useState(null);
const [selectedEvent, setSelectedEvent] = useState(null);
const [formMode, setFormMode] = useState(null); const [formMode, setFormMode] = useState(null);
const [event] = useContext(EventContext);
useEffect(() => { useEffect(() => {
if (selectedEvent === null) { if (event === null) {
setSelectedData(null);
setFormMode(null); setFormMode(null);
} else { } else {
const se = data.events.filter((d) => d.id === selectedEvent);
if (se.length > 0) setSelectedData(se[0]);
setFormMode('edit'); setFormMode('edit');
} }
}, [data, selectedEvent]); }, [event]);
return ( return (
<SimpleGrid <Grid
minChildWidth='120px' templateRows='60% 40%'
spacing='40px' templateColumns='repeat(3, 1fr)'
gap={5}
className={styles.mainContainer} className={styles.mainContainer}
> >
<Box className={styles.editor} borderRadius='0.5em'> <GridItem rowSpan={2} colSpan={1}>
<Heading style={{ paddingBottom: '0.25em' }}>List Events</Heading> <Box className={styles.editor} borderRadius='0.5em'>
<NumberedText <Heading style={{ paddingBottom: '0.25em' }}>List Events</Heading>
number={1} <NumberedText
text={'Select event or click Add Event to create new'} number={1}
/> text={'Select event or click Add Event to create new'}
<div className={styles.content}>
<EventList
data={data}
selected={selectedEvent}
setSelectedEvent={setSelectedEvent}
formMode={formMode}
/> />
<div className={styles.buttonContainer}> <div className={styles.cornerButtonContainer}>
<Button <Button
colorScheme='teal' colorScheme='teal'
variant={formMode === 'add' ? 'solid' : 'outline'} variant={formMode === 'add' ? 'solid' : 'outline'}
@@ -58,29 +50,50 @@ export default function Editor() {
Add Event Add Event
</Button> </Button>
</div> </div>
</div>
</Box>
<Box className={styles.editor} borderRadius='0.5em'> <div className={styles.content}>
<Heading style={{ paddingBottom: '0.25em' }}>Event Details</Heading> <EventList formMode={formMode} setFormMode={setFormMode} />
<NumberedText number={2} text={'Edit event info'} /> </div>
<div className={styles.content}> </Box>
<EventForm </GridItem>
data={selectedData}
formMode={formMode}
setFormMode={setFormMode}
setSelectedEvent={setSelectedEvent}
/>
</div>
</Box>
<Box className={styles.editor} borderRadius='0.5em' overflowX='auto'> <GridItem colStart={2} rowSpan={1} colSpan={1}>
<Heading style={{ paddingBottom: '0.25em' }}>List Events</Heading> <Box className={styles.editor} borderRadius='0.5em'>
<NumberedText number={3} text={'Preview layout'} /> <Heading style={{ paddingBottom: '0.25em' }}>Event Details</Heading>
<div className={styles.content}> <NumberedText number={2} text={'Edit event info'} />
<PreviewContainer data={selectedData} /> <div className={styles.content}>
</div> <EventForm formMode={formMode} setFormMode={setFormMode} />
</Box> </div>
</SimpleGrid> </Box>
</GridItem>
<GridItem colStart={3} rowStart={1} rowSpan={1} colSpan={1}>
<Box className={styles.editor} borderRadius='0.5em' overflowX='auto'>
<Heading style={{ paddingBottom: '0.25em' }}>Screens</Heading>
<NumberedText number={3} text={'Preview layout'} />
<div className={styles.content}>
{/* <PreviewContainer data={selectedData} /> */}
</div>
</Box>
</GridItem>
<GridItem colStart={2} rowStart={2} rowSpan={1} colSpan={1}>
<Box className={styles.editor} borderRadius='0.5em'>
<Heading style={{ paddingBottom: '0.25em' }}>Screen Messages</Heading>
<NumberedText number={3} text={'Show / Hide messages on screens'} />
<div className={styles.content}></div>
<MessageForm />
</Box>
</GridItem>
<GridItem colStart={3} rowStart={2} rowSpan={1} colSpan={1}>
<Box className={styles.editor} borderRadius='0.5em'>
<Heading style={{ paddingBottom: '0.25em' }}>Time Control</Heading>
<NumberedText number={0} text={'Control Timer'} />
<div className={styles.content}></div>
<PlaybackControl />
</Box>
</GridItem>
</Grid>
); );
} }
+12 -6
View File
@@ -1,14 +1,20 @@
import { Table, Thead, Tbody, Tr, Th } from '@chakra-ui/react'; import { Table, Thead, Tbody, Tr, Th } from '@chakra-ui/react';
import { useContext } from 'react'; import { useContext } from 'react';
import { EventContext } from '../../../app/context/eventContext';
import { EventListContext } from '../../../app/context/eventListContext'; import { EventListContext } from '../../../app/context/eventListContext';
import EventListItem from './EventListItem'; import EventListItem from './EventListItem';
import { sortByDate } from './listUtils'; import { sortByDate } from './listUtils';
export default function EventList(props) { export default function EventList(props) {
const [events, setEvents] = useContext(EventListContext); const [events, ] = useContext(EventListContext);
const [event, setEvent] = useContext(EventContext);
console.log('e', events); const handleSetSelected = (id) => {
console.log('sort', sortByDate(events)); setEvent(events.filter((e) => e.id === id)[0]);
props.setFormMode('edit');
};
const disabled = props.formMode !== null;
return ( return (
<Table variant='simple' size='sm'> <Table variant='simple' size='sm'>
@@ -26,9 +32,9 @@ export default function EventList(props) {
<EventListItem <EventListItem
key={e.id} key={e.id}
data={e} data={e}
selected={props.selected} disabled={disabled}
setSelectedEvent={props.setSelectedEvent} selectedId={event?.id}
formMode={props.formMode} setSelected={handleSetSelected}
/> />
))} ))}
</Tbody> </Tbody>
+5 -5
View File
@@ -5,11 +5,11 @@ import { timeFormat } from '../../../common/dateConfig';
import { ChevronRightIcon } from '@chakra-ui/icons'; import { ChevronRightIcon } from '@chakra-ui/icons';
export default function EventListItem(props) { export default function EventListItem(props) {
const selected = props.selected === props.data.id const isSelected = props.selectedId === props.data.id;
return ( return (
<Tr <Tr
style={ style={
selected isSelected
? { backgroundColor: '#b2f5ea' } ? { backgroundColor: '#b2f5ea' }
: { backgroundColor: 'white' } : { backgroundColor: 'white' }
} }
@@ -21,9 +21,9 @@ export default function EventListItem(props) {
<Td> <Td>
<IconButton <IconButton
colorScheme='teal' colorScheme='teal'
variant={selected ? 'solid' : 'outline'} variant={isSelected ? 'solid' : 'outline'}
onClick={() => props.setSelectedEvent(props.data.id)} onClick={() => props.setSelected(props.data.id)}
disabled={props.formMode !== null} disabled={props.disabled}
size='sm' size='sm'
aria-label='Select Item' aria-label='Select Item'
icon={<ChevronRightIcon />} icon={<ChevronRightIcon />}
+41 -25
View File
@@ -1,33 +1,48 @@
import { Button } from '@chakra-ui/button'; import { Button } from '@chakra-ui/button';
import { Form, Formik } from 'formik'; import { Form, Formik } from 'formik';
import { useContext, useState } from 'react'; import { useContext, useEffect, useState } from 'react';
import ReactDatePicker from 'react-datepicker';
import DatePicker from 'react-datepicker'; import DatePicker from 'react-datepicker';
import * as Yup from 'yup'; import * as Yup from 'yup';
import { EventContext } from '../../app/context/eventContext';
import { EventListContext } from '../../app/context/eventListContext'; import { EventListContext } from '../../app/context/eventListContext';
import ChakraInput from '../../common/input/ChakraInput'; import ChakraInput from '../../common/input/ChakraInput';
import ChakraNumberInput from '../../common/input/ChakraNumberInput'; import ChakraNumberInput from '../../common/input/ChakraNumberInput';
import TimeInput from '../../common/input/TimeInput'; import TimeInput from '../../common/input/TimeInput';
import styles from './EventForm.module.css'; import styles from './EventForm.module.css';
const sampleInitialValues = {
title: '',
subtitle: '',
presenter: '',
timeStart: new Date(),
timeEnd: new Date(),
timerDuration: 5,
};
export default function EventForm(props) { export default function EventForm(props) {
const [events, setEvents] = useContext(EventListContext); const [event, setEvent] = useContext(EventContext);
const today = new Date(); const [, setEvents] = useContext(EventListContext);
const initialValues = props.data ?? { const [initialValues, setInitialValues] = useState(null);
title: '',
subtitle: '', useEffect(() => {
presenter: '', if (props.formMode === 'edit') setInitialValues(event);
timeStart: today, else if (props.formMode === 'add') setInitialValues(sampleInitialValues);
timeEnd: today, else if (props.formMode === null) setInitialValues(null);
timerDuration: 30, }, [event, props.formMode]);
};
// TODO: Cleanup
if (props.formMode === null || initialValues === null)
return <div>Replace with nice empty illustration</div>;
else if (props.formMode === 'edit' && event === null) {
return <div>Replace with nice empty illustration also</div>;
}
const validationSchema = Yup.object({ const validationSchema = Yup.object({
title: Yup.string().required('An event requires a title'), title: Yup.string().required('An event requires a title'),
subtitle: Yup.string(), subtitle: Yup.string(),
presenter: Yup.string(), presenter: Yup.string(),
timeStart: Yup.date().nullable(), timeStart: Yup.date(),
timeEnd: Yup.date(),
timerDuration: Yup.number() timerDuration: Yup.number()
.min(1) .min(1)
.max(60) .max(60)
@@ -35,12 +50,12 @@ export default function EventForm(props) {
}); });
const submitForm = (values) => { const submitForm = (values) => {
console.log('called submit');
// prevent default stops page from refreshing, necessary? // prevent default stops page from refreshing, necessary?
console.log('form', values);
// update form state // update form state
props.setFormMode(null); props.setFormMode(null);
props.setSelectedEvent(null);
// are we updating or creating new? // are we updating or creating new?
@@ -58,17 +73,14 @@ export default function EventForm(props) {
const cancelForm = () => { const cancelForm = () => {
props.setFormMode(null); props.setFormMode(null);
props.setSelectedEvent(null); setEvent(null);
setInitialValues(null);
}; };
if (props.data === null || props.data === undefined) {
if (props.formMode === null)
return <div>Replace with nice empty illustration</div>;
}
return ( return (
<div> <div>
<Formik <Formik
enableReinitialize={true}
initialValues={initialValues} initialValues={initialValues}
validationSchema={validationSchema} validationSchema={validationSchema}
onSubmit={(values, actions) => { onSubmit={(values, actions) => {
@@ -76,7 +88,10 @@ export default function EventForm(props) {
submitForm(values); submitForm(values);
}, 100); }, 100);
}} }}
onReset={(values) => cancelForm()} // FIX: This kept being called on render
// onReset={() => {
// cancelForm();
// }}
> >
{(props) => ( {(props) => (
<Form onSubmit={props.handleSubmit}> <Form onSubmit={props.handleSubmit}>
@@ -109,9 +124,10 @@ export default function EventForm(props) {
<Button <Button
variant='outline' variant='outline'
disabled={props.isSubmitting} disabled={props.isSubmitting}
type='reset' // type='reset'
onClick={() => cancelForm()}
> >
Cancel Back
</Button> </Button>
<Button <Button
colorScheme='teal' colorScheme='teal'