mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-08 17:03:53 +00:00
event list style
change user flow
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
import style from './List.module.css';
|
||||
export default function BlockBlock() {
|
||||
return <div className={style.blockContainer} />;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { IconButton } from '@chakra-ui/button';
|
||||
import { AddIcon, MinusIcon } from '@chakra-ui/icons';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import { useNumberInput } from '@chakra-ui/number-input';
|
||||
import {
|
||||
Slider,
|
||||
SliderFilledTrack,
|
||||
SliderThumb,
|
||||
SliderTrack,
|
||||
} from '@chakra-ui/slider';
|
||||
import { useState } from 'react';
|
||||
import style from './List.module.css';
|
||||
|
||||
export default function DelayBlock() {
|
||||
const [delay, setDelay] = useState(0);
|
||||
const { getIncrementButtonProps, getDecrementButtonProps } = useNumberInput({
|
||||
step: 1,
|
||||
defaultValue: 0,
|
||||
min: -60,
|
||||
max: 60,
|
||||
});
|
||||
|
||||
const inc = getIncrementButtonProps();
|
||||
const dec = getDecrementButtonProps();
|
||||
|
||||
const populateDelay = (val) => {
|
||||
console.log('set delay in parent', val);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={style.delayContainer}>
|
||||
<div className={style.delayValue}>{`${delay} min`}</div>
|
||||
<Slider
|
||||
defaultValue={0}
|
||||
min={-60}
|
||||
max={60}
|
||||
step={5}
|
||||
onChange={(val) => setDelay(val)}
|
||||
onChangeEnd={(val) => populateDelay(val)}
|
||||
>
|
||||
<SliderTrack bg='orange.100'>
|
||||
<Box position='relative' right={10} />
|
||||
<SliderFilledTrack bg='orange' />
|
||||
</SliderTrack>
|
||||
<SliderThumb boxSize={4} />
|
||||
</Slider>
|
||||
<div className={style.actionOverlay}>
|
||||
<IconButton size='xs' icon={<MinusIcon />} colorScheme='red' />
|
||||
<IconButton size='xs' icon={<AddIcon />} colorScheme='blue' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,44 +1,40 @@
|
||||
import { Table, Thead, Tbody, Tr, Th } from '@chakra-ui/react';
|
||||
import { AddIcon, AttachmentIcon, DownloadIcon } from '@chakra-ui/icons';
|
||||
import { Button, IconButton } from '@chakra-ui/react';
|
||||
import { useContext } from 'react';
|
||||
import { EventContext } from '../../../app/context/eventContext';
|
||||
import { EventListContext } from '../../../app/context/eventListContext';
|
||||
import EventListItem from './EventListItem';
|
||||
import { sortByDate, sortByNumber } from './listUtils';
|
||||
import { sortByNumber } from './listUtils';
|
||||
import style from './List.module.css';
|
||||
import DelayBlock from './DelayBlock';
|
||||
import BlockBlock from './BlockBlock';
|
||||
|
||||
export default function EventList(props) {
|
||||
const [events] = useContext(EventListContext);
|
||||
const [event, setEvent] = useContext(EventContext);
|
||||
|
||||
const handleSetSelected = (id) => {
|
||||
setEvent(events.filter((e) => e.id === id)[0]);
|
||||
props.setFormMode('edit');
|
||||
};
|
||||
|
||||
const disabled = props.formMode !== null;
|
||||
const [, setEvent] = useContext(EventContext);
|
||||
|
||||
return (
|
||||
<Table variant='simple' size='sm'>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>Event Title</Th>
|
||||
<Th>Event Subtitle</Th>
|
||||
<Th>Presenter Name</Th>
|
||||
<Th>Time Start</Th>
|
||||
<Th>Time End</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{sortByNumber(events).map((e) => (
|
||||
<EventListItem
|
||||
key={e.id}
|
||||
data={e}
|
||||
disabled={disabled}
|
||||
selectedId={event?.id}
|
||||
setSelected={handleSetSelected}
|
||||
/>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
<>
|
||||
<div className={style.headerButtons}>
|
||||
<Button size='sm' rightIcon={<AttachmentIcon />}>
|
||||
Upload
|
||||
</Button>
|
||||
<Button size='sm' rightIcon={<DownloadIcon />}>
|
||||
Download
|
||||
</Button>
|
||||
<IconButton size='sm' icon={<AddIcon />} colorScheme='blue' />
|
||||
</div>
|
||||
<div className={style.eventContainer}>
|
||||
<EventListItem />
|
||||
|
||||
<EventListItem />
|
||||
<DelayBlock />
|
||||
|
||||
<EventListItem />
|
||||
<BlockBlock />
|
||||
|
||||
<EventListItem />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,50 +1,94 @@
|
||||
import { IconButton } from '@chakra-ui/button';
|
||||
import { Td, Tr } from '@chakra-ui/table';
|
||||
import { format } from 'date-fns';
|
||||
import { timeFormat } from '../../../common/dateConfig';
|
||||
import { LockIcon, ChevronRightIcon } from '@chakra-ui/icons';
|
||||
import {
|
||||
AddIcon,
|
||||
ChevronDownIcon,
|
||||
ChevronUpIcon,
|
||||
MinusIcon,
|
||||
NotAllowedIcon,
|
||||
TimeIcon,
|
||||
} from '@chakra-ui/icons';
|
||||
import {
|
||||
IconButton,
|
||||
Editable,
|
||||
EditablePreview,
|
||||
EditableInput,
|
||||
} from '@chakra-ui/react';
|
||||
import { useState } from 'react';
|
||||
import style from './List.module.css';
|
||||
|
||||
export default function EventListItem(props) {
|
||||
const isSelected = props.selectedId === props.data.id;
|
||||
console.log(props);
|
||||
const [more, setMore] = useState(false);
|
||||
const [armed, setArmed] = useState(false);
|
||||
|
||||
return (
|
||||
<Tr
|
||||
style={
|
||||
isSelected
|
||||
? { backgroundColor: '#b2f5ea' }
|
||||
: { backgroundColor: 'white' }
|
||||
}
|
||||
>
|
||||
<Td>{props.data.title}</Td>
|
||||
<Td>{props.data.subtitle}</Td>
|
||||
<Td>{props.data.presenter}</Td>
|
||||
<Td>
|
||||
{props.data.timeStart && format(props.data.timeStart, timeFormat)}
|
||||
</Td>
|
||||
<Td>{props.data?.timeEnd && format(props.data?.timeEnd, timeFormat)}</Td>{' '}
|
||||
<Td>{props.data?.timerDuration}</Td>
|
||||
<Td>
|
||||
<IconButton
|
||||
colorScheme='teal'
|
||||
variant={isSelected ? 'solid' : 'outline'}
|
||||
onClick={() => props.setSelected(props.data.id)}
|
||||
disabled={props.disabled}
|
||||
size='sm'
|
||||
aria-label='Select Item'
|
||||
icon={<LockIcon />}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<IconButton
|
||||
colorScheme='teal'
|
||||
variant={isSelected ? 'solid' : 'outline'}
|
||||
onClick={() => props.setSelected(props.data.id)}
|
||||
disabled={props.disabled}
|
||||
size='sm'
|
||||
aria-label='Select Item'
|
||||
icon={<ChevronRightIcon />}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
<div className={armed ? style.eventRowActive : style.eventRow}>
|
||||
<div
|
||||
className={armed ? style.armActive : style.arm}
|
||||
onClick={() => setArmed(!armed)}
|
||||
/>
|
||||
<div className={style.time}>
|
||||
<Editable defaultValue='11:20' style={{ textAlign: 'center' }}>
|
||||
<EditablePreview />
|
||||
<EditableInput />
|
||||
</Editable>
|
||||
</div>
|
||||
<div className={style.rowDetailed}>
|
||||
{more ? (
|
||||
<div className={style.detailedContainer}>
|
||||
<div style={{ display: 'block' }}>
|
||||
<span className={style.detailedTitleUnderlined}>Title</span>
|
||||
<Editable
|
||||
defaultValue='Event Title'
|
||||
style={{ display: 'inline' }}
|
||||
>
|
||||
<EditablePreview />
|
||||
<EditableInput style={{width:'15em'}} />
|
||||
</Editable>
|
||||
</div>
|
||||
<div style={{ display: 'block' }}>
|
||||
<span className={style.detailedTitleUnderlined}>Subtitle</span>
|
||||
<Editable
|
||||
defaultValue='Event Subtitle'
|
||||
style={{ display: 'inline' }}
|
||||
>
|
||||
<EditablePreview />
|
||||
<EditableInput style={{width:'15em'}} />
|
||||
</Editable>
|
||||
</div>
|
||||
<div style={{ display: 'block' }}>
|
||||
<span className={style.detailedTitleUnderlined}>Presenter</span>
|
||||
<Editable
|
||||
defaultValue='Presenter Name'
|
||||
style={{ display: 'inline' }}
|
||||
>
|
||||
<EditablePreview style={{}} />
|
||||
<EditableInput style={{width:'15em'}} />
|
||||
</Editable>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className={style.titleContainer}>
|
||||
<div>
|
||||
<span className={style.detailedTitle}>Title</span>
|
||||
<Editable
|
||||
defaultValue='Event Title'
|
||||
style={{ display: 'inline' }}
|
||||
>
|
||||
<EditablePreview />
|
||||
<EditableInput style={{width:'15em'}} />
|
||||
</Editable>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={style.more} onClick={() => setMore(!more)}>
|
||||
{more ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.actionOverlay}>
|
||||
<IconButton size='xs' icon={<MinusIcon />} colorScheme='red' />
|
||||
<IconButton size='xs' icon={<AddIcon />} colorScheme='blue' />
|
||||
<IconButton size='xs' icon={<TimeIcon />} colorScheme='yellow' />
|
||||
<IconButton size='xs' icon={<NotAllowedIcon />} colorScheme='purple' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/* ============= EVENT LIST ============= */
|
||||
.headerButtons {
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
align-content: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.eventContainer {
|
||||
}
|
||||
|
||||
/* ============= EVENT ITEM ============= */
|
||||
|
||||
.eventRow,
|
||||
.eventRowActive {
|
||||
margin: 0.2em 0;
|
||||
padding: 0.2em 0.5em;
|
||||
position: relative;
|
||||
top: 1em;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 2em 5em 1fr auto;
|
||||
gap: 0.5em;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.eventRow {
|
||||
background-color: #0001;
|
||||
}
|
||||
|
||||
.eventRowActive {
|
||||
background-color: #b2f5eaaa;
|
||||
}
|
||||
|
||||
.arm,
|
||||
.armActive {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.arm {
|
||||
background-color: #888;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
|
||||
.armActive {
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(22, 255, 0, 1) 0%,
|
||||
rgba(50, 255, 31, 1) 49%,
|
||||
rgba(0, 0, 0, 1) 65%,
|
||||
rgba(0, 255, 156, 0.7083333333333333) 81%
|
||||
);
|
||||
border: 1px solid #256e62;
|
||||
}
|
||||
|
||||
.time,
|
||||
.titleContainer,
|
||||
.detailedContainer {
|
||||
background-color: #fff8;
|
||||
border: 1px solid #0001;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 4em;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.rowDetailed {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.titleContainer,
|
||||
.detailedContainer {
|
||||
width: 90%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.detailedContainer > div,
|
||||
.titleContainer > div {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.detailedTitle,
|
||||
.detailedTitleUnderlined {
|
||||
padding-left: 1em;
|
||||
font-size: 0.8em;
|
||||
color: #888;
|
||||
display: inline-block;
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.detailedTitleUnderlined {
|
||||
border-bottom: 1px solid #0001;
|
||||
}
|
||||
|
||||
.more {
|
||||
position: absolute;
|
||||
right: 0.25em;
|
||||
top: 0em;
|
||||
}
|
||||
|
||||
.actionOverlay {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 0.5em;
|
||||
align-content: center;
|
||||
align-self: center;
|
||||
|
||||
opacity: 0.6;
|
||||
transition: linear 0.1s;
|
||||
}
|
||||
|
||||
.eventRow:hover > .actionOverlay {
|
||||
opacity: 0.9;
|
||||
transition: linear 0.1s;
|
||||
}
|
||||
|
||||
.actionOverlay:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* ============= DELAY BLOCK ============= */
|
||||
.delayContainer {
|
||||
position: relative;
|
||||
top: 1em;
|
||||
margin: 0.2em 0;
|
||||
padding: 0.2em 1em;
|
||||
width: 100%;
|
||||
background-color: #ecc94baa;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
border: 1px solid #0001;
|
||||
border-top: 8px solid #ecc94b;
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin: auto;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.delayValue {
|
||||
color: #000;
|
||||
background-color: #fff5;
|
||||
border-radius: 4px;
|
||||
padding: 0.2em;
|
||||
text-align: center;
|
||||
width: 6em;
|
||||
border: 1px solid #0001;
|
||||
}
|
||||
|
||||
/* ============= BLOCK BLOCK ============= */
|
||||
.blockContainer {
|
||||
position: relative;
|
||||
top: 1em;
|
||||
margin: 0.2em 0;
|
||||
padding: 0.2em 1em;
|
||||
width: 100%;
|
||||
background-color: #805ad5aa;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
height: 2em;
|
||||
border: 1px solid #0001;
|
||||
border-bottom: 8px solid #805ad5;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
Reference in New Issue
Block a user