diff --git a/client/src/common/components/buttons/AddIconBtn.jsx b/client/src/common/components/buttons/AddIconBtn.jsx new file mode 100644 index 000000000..f9bf88287 --- /dev/null +++ b/client/src/common/components/buttons/AddIconBtn.jsx @@ -0,0 +1,13 @@ +import { IconButton } from '@chakra-ui/button'; +import { FiPlus } from "react-icons/fi"; + +export default function AddIconBtn(props) { + return ( + } + colorScheme='blue' + onClick={() => props.clickHandler} + /> + ); +} diff --git a/client/src/common/components/buttons/BlockIconBtn.jsx b/client/src/common/components/buttons/BlockIconBtn.jsx new file mode 100644 index 000000000..a77364947 --- /dev/null +++ b/client/src/common/components/buttons/BlockIconBtn.jsx @@ -0,0 +1,13 @@ +import { IconButton } from '@chakra-ui/button'; +import { FiMinusCircle } from 'react-icons/fi'; + +export default function BlockIconBtn(props) { + return ( + } + colorScheme='purple' + onClick={() => props.clickHandler} + /> + ); +} diff --git a/client/src/common/components/buttons/DelayIconBtn.jsx b/client/src/common/components/buttons/DelayIconBtn.jsx new file mode 100644 index 000000000..d2c64c8ba --- /dev/null +++ b/client/src/common/components/buttons/DelayIconBtn.jsx @@ -0,0 +1,13 @@ +import { IconButton } from '@chakra-ui/button'; +import { FiClock } from 'react-icons/fi'; + +export default function DelayIconBtn(props) { + return ( + } + colorScheme='yellow' + onClick={() => props.clickHandler} + /> + ); +} diff --git a/client/src/common/components/buttons/DeleteIconBtn.jsx b/client/src/common/components/buttons/DeleteIconBtn.jsx new file mode 100644 index 000000000..32fb320c2 --- /dev/null +++ b/client/src/common/components/buttons/DeleteIconBtn.jsx @@ -0,0 +1,13 @@ +import { IconButton } from '@chakra-ui/button'; +import { FiMinus } from 'react-icons/fi'; + +export default function DeleteIconBtn(props) { + return ( + } + colorScheme='red' + onClick={() => props.clickHandler} + /> + ); +} diff --git a/client/src/common/components/eventTimes/EventTimes.jsx b/client/src/common/components/eventTimes/EventTimes.jsx new file mode 100644 index 000000000..fe707dc99 --- /dev/null +++ b/client/src/common/components/eventTimes/EventTimes.jsx @@ -0,0 +1,24 @@ +import EditableTimer from '../../input/EditableTimer'; +import DelayValue from '../../input/DelayValue'; + +export default function EventTimes(props) { + const { updateValues, delay, timeStart, timeEnd } = props; + + return ( + <> + + + + + ); +} diff --git a/client/src/common/dateConfig.js b/client/src/common/dateConfig.js index 1980c28c2..dc6531a75 100644 --- a/client/src/common/dateConfig.js +++ b/client/src/common/dateConfig.js @@ -1,17 +1,22 @@ -import { addMinutes, format, parseISO } from "date-fns"; +import { addMinutes, format, parseISO } from 'date-fns'; export const timeFormat = 'HH:mm'; export const timeFormatSeconds = 'HH:mm:ss'; - // make date with string +// make date with string export const timeToDate = (time) => { const today = new Date(); return new Date(today.toDateString() + ' ' + time); }; +// utility to parse and format +export const dateToTime = (time) => { + const fTime = parseISO(time, 1); + return format(fTime, timeFormat); +}; + // small shorthand for adding delay and formatting date export const addAndFormat = (time, delay) => { const fTime = parseISO(time, 1); return format(addMinutes(fTime, delay), timeFormat); }; - diff --git a/client/src/common/input/DelayValue.jsx b/client/src/common/input/DelayValue.jsx new file mode 100644 index 000000000..3ecd5acc3 --- /dev/null +++ b/client/src/common/input/DelayValue.jsx @@ -0,0 +1,11 @@ +import style from './EditableTimer.module.css'; + +export default function DelayValue(props) { + const { delay } = props; + const delayed = delay > 0; + return ( +
+ {delayed && {`+ ${delay}`}} +
+ ); +} diff --git a/client/src/common/input/EditableText.jsx b/client/src/common/input/EditableText.jsx new file mode 100644 index 000000000..3ec553e0c --- /dev/null +++ b/client/src/common/input/EditableText.jsx @@ -0,0 +1,22 @@ +import { Editable, EditableInput, EditablePreview } from '@chakra-ui/editable'; +import style from './EditableText.module.css'; + +export default function EditableText(props) { + const { label, defaultValue, placeholder, handleSubmit } = props; + return ( +
+ + {label} + + handleSubmit(v)} + defaultValue={defaultValue} + placeholder={placeholder} + style={{ display: 'inline' }} + > + + + +
+ ); +} diff --git a/client/src/common/input/EditableText.module.css b/client/src/common/input/EditableText.module.css new file mode 100644 index 000000000..52383f94a --- /dev/null +++ b/client/src/common/input/EditableText.module.css @@ -0,0 +1,13 @@ +.title, +.titleUnderlined { + padding-left: 1em; + font-size: 0.8em; + color: #888; + display: inline-block; + width: 6em; + cursor: default; +} + +.titleUnderlined { + border-bottom: 1px solid #0001; +} \ No newline at end of file diff --git a/client/src/common/input/EditableTimer.jsx b/client/src/common/input/EditableTimer.jsx new file mode 100644 index 000000000..7d44ee8bb --- /dev/null +++ b/client/src/common/input/EditableTimer.jsx @@ -0,0 +1,60 @@ +import { Editable, EditableInput, EditablePreview } from '@chakra-ui/editable'; +import { useEffect, useState } from 'react'; +import { addAndFormat, timeToDate, dateToTime } from '../dateConfig'; +import style from './EditableTimer.module.css'; + +export default function EditableTimer(props) { + const { name, updateValues, time, delay } = props; + const [value, setValue] = useState(''); + const [showValue, setShowValue] = useState(''); + + // prepare time fields + useEffect(() => { + setValue(addAndFormat(time, delay)); + }, [time, delay]); + + const handleSubmit = (submitedVal) => { + console.log('edit: on submit'); + + if (submitedVal === value) return; + + updateValues(name, timeToDate(submitedVal)); + setValue(addAndFormat(time, delay)); + }; + + const showNormal = () => { + console.log('edit: on edit'); + setValue(dateToTime(time)); + }; + + const handleChange = (submitedVal) => { + console.log('edit: change handler', submitedVal); + setValue(submitedVal); + }; + + const handleBlur = () => { + console.log('edit: onBlur'); + setValue(addAndFormat(time, delay)); + }; + + console.log('hh', value, time); + + return ( +
+ handleSubmit(v)} + onChange={(v) => handleChange(v)} + onBlur={(v) => handleBlur(v)} + value={value} + placeholder='--:--' + style={{ textAlign: 'center' }} + className={delay > 0 && style.delayedEditable} + > + + + +
+ ); +} diff --git a/client/src/common/input/EditableTimer.module.css b/client/src/common/input/EditableTimer.module.css new file mode 100644 index 000000000..a38ee9ade --- /dev/null +++ b/client/src/common/input/EditableTimer.module.css @@ -0,0 +1,21 @@ +.time { + background-color: #fff8; + border: 1px solid #0001; + border-radius: 4px; + width: 5em; + height: fit-content; +} + +.delayedEditable { + background-color: #ecc94b22; +} + +.delayValue { + font-size: 14px; + line-height: 2em; + color: #555; + background-color: #ffeaa066; + border-radius: 4px; + text-align: center; + border: 1px solid #0001; +} diff --git a/client/src/features/editors/list/DelayBlock.jsx b/client/src/features/editors/list/DelayBlock.jsx index 370d26d54..f4d7c7412 100644 --- a/client/src/features/editors/list/DelayBlock.jsx +++ b/client/src/features/editors/list/DelayBlock.jsx @@ -30,6 +30,12 @@ export default function DelayBlock(props) { useEffect(() => { setDelay(data.timerDuration); }, [data]); + const addHandler = () => { + eventsHandler('add', { type: 'block', order: index + 1 }); + }; + const deleteHandler = () => { + eventsHandler('delete', data.id); + }; return (
@@ -49,11 +55,6 @@ export default function DelayBlock(props) {
- } - colorScheme='red' - onClick={() => eventsHandler('delete', data.id)} /> + +
); diff --git a/client/src/features/editors/list/EventBlock.jsx b/client/src/features/editors/list/EventBlock.jsx index df10ec466..15fb5a73e 100644 --- a/client/src/features/editors/list/EventBlock.jsx +++ b/client/src/features/editors/list/EventBlock.jsx @@ -1,34 +1,19 @@ -import { - AddIcon, - ChevronDownIcon, - ChevronUpIcon, - MinusIcon, - NotAllowedIcon, - TimeIcon, -} from '@chakra-ui/icons'; -import { - IconButton, - Editable, - EditablePreview, - EditableInput, -} from '@chakra-ui/react'; -import { useEffect, useState } from 'react'; -import { addAndFormat, timeToDate } from '../../../common/dateConfig'; +import { FiChevronDown, FiChevronUp } from 'react-icons/fi'; +import { Editable, EditablePreview, EditableInput } from '@chakra-ui/react'; +import { useState } from 'react'; +import AddIconBtn from '../../../common/components/buttons/AddIconBtn'; +import BlockIconBtn from '../../../common/components/buttons/BlockIconBtn'; +import DelayIconBtn from '../../../common/components/buttons/DelayIconBtn'; +import DeleteIconBtn from '../../../common/components/buttons/DeleteIconBtn'; +import EventTimes from '../../../common/components/eventTimes/EventTimes'; import { showErrorToast } from '../../../common/helpers/toastManager'; import style from './List.module.css'; +import EditableText from '../../../common/input/EditableText'; export default function EventBlock(props) { const { data, selected, delay, index, eventsHandler } = props; const [more, setMore] = useState(false); - const [timeStart, setTimeStart] = useState(0); - const [timeEnd, setTimeEnd] = useState(addAndFormat(data.timeEnd, delay)); - - // prepare time fields - useEffect(() => { - setTimeStart(addAndFormat(data.timeStart, delay)); - setTimeEnd(addAndFormat(data.timeEnd, delay)); - }, [data, delay]); const updateValues = (field, value) => { // validate field @@ -43,129 +28,84 @@ export default function EventBlock(props) { } }; + const addHandler = () => { + eventsHandler('add', { type: 'block', order: index + 1 }); + }; + const delayHandler = () => { + eventsHandler('add', { type: 'delay', order: index + 1 }); + }; + const blockHandler = () => { + eventsHandler('add', { type: 'block', order: index + 1 }); + }; + const deleteHandler = () => { + eventsHandler('delete', data.id); + }; + + const handleTitleSubmit = (v) => { + updateValues('title', v); + }; + + const handleSubtitleSubmit = (v) => { + updateValues('subtitle', v); + }; + + const handlePresenterSubmit = (v) => { + updateValues('presenter', v); + }; + return ( -
-
-
- updateValues('timeStart', timeToDate(v))} - value={timeStart} - onChange={(val) => setTimeStart(val)} - placeholder='--:--' - style={{ textAlign: 'center' }} - className={delay > 0 && style.delayedEditable} - > - - - -
-
- updateValues('timeEnd', timeToDate(v))} - value={timeEnd} - onChange={(val) => setTimeEnd(val)} - placeholder='--:--' - style={{ textAlign: 'center' }} - className={delay > 0 && style.delayedEditable} - > - - - -
-
- {more ? ( -
-
- Title - updateValues('title', v)} - defaultValue={data.title} - placeholder='Add title' - style={{ display: 'inline' }} - > - - - -
-
- Subtitle - updateValues('subtitle', v)} - defaultValue={data.subtitle} - placeholder='Add subtitle' - style={{ display: 'inline' }} - > - - - -
-
- Presenter - updateValues('presenter', v)} - defaultValue={data.presenter} - placeholder='Add presenter name' - style={{ display: 'inline' }} - > - - - -
-
- ) : ( -
-
- Title - updateValues('title', v)} - defaultValue={data.title} - placeholder='Add title' - style={{ display: 'inline' }} - id='title' - > - - - -
-
- )} -
setMore(!more)}> - {more ? : } +
+ +
+ {more ? ( +
+ + +
-
-
- } - colorScheme='red' - onClick={() => eventsHandler('delete', data.id)} - /> - } - colorScheme='blue' - onClick={() => - eventsHandler('add', { type: 'event', order: index + 1 }) - } - /> - } - colorScheme='yellow' - onClick={() => - eventsHandler('add', { type: 'delay', order: index + 1 }) - } - /> - } - colorScheme='purple' - onClick={() => - eventsHandler('add', { type: 'block', order: index + 1 }) - } - /> + ) : ( +
+ +
+ )} +
setMore(!more)}> + {more ? : }
- +
+ + + + +
+
); } diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx index 87f0a9b03..3b1cbfa40 100644 --- a/client/src/features/editors/list/EventList.jsx +++ b/client/src/features/editors/list/EventList.jsx @@ -1,7 +1,7 @@ -import EventListItem from './EventListItem'; import style from './List.module.css'; import DelayBlock from './DelayBlock'; import BlockBlock from './BlockBlock'; +import EventBlock from './EventBlock'; export default function EventList(props) { const { events, selected, eventsHandler } = props; @@ -19,7 +19,7 @@ export default function EventList(props) { if (e.type === 'event') { eventCount = eventCount + 1; return ( - { + eventsHandler('add', { type: 'event', order: 0 }); + }; + return (
@@ -45,12 +50,7 @@ export default function EventListMenu(props) { Download CSV - } - colorScheme='blue' - onClick={() => eventsHandler('add', { type: 'event', order: 0 })} - /> +
); }