Add selection control buttons

This commit is contained in:
Benji Grant 2023-06-18 10:27:58 +10:00
parent ebdf2cf52c
commit 7535a2a61e
3 changed files with 30 additions and 14 deletions

View file

@ -0,0 +1,5 @@
.selectionControls {
display: flex;
align-items: center;
gap: 1em;
}

View file

@ -1,12 +1,14 @@
import { Fragment, useCallback, useRef, useState } from 'react' import { Fragment, useCallback, useRef, useState } from 'react'
import Button from '/src/components/Button/Button'
import Content from '/src/components/Content/Content' import Content from '/src/components/Content/Content'
import GoogleCalendar from '/src/components/GoogleCalendar/GoogleCalendar' import GoogleCalendar from '/src/components/GoogleCalendar/GoogleCalendar'
import { usePalette } from '/src/hooks/usePalette' import { usePalette } from '/src/hooks/usePalette'
import { useTranslation } from '/src/i18n/client' import { useTranslation } from '/src/i18n/client'
import { calculateTable, makeClass, parseSpecificDate } from '/src/utils' import { calculateTable, makeClass, parseSpecificDate } from '/src/utils'
import styles from '../AvailabilityViewer/AvailabilityViewer.module.scss' import styles from './AvailabilityEditor.module.scss'
import viewerStyles from '../AvailabilityViewer/AvailabilityViewer.module.scss'
import Skeleton from '../AvailabilityViewer/components/Skeleton/Skeleton' import Skeleton from '../AvailabilityViewer/components/Skeleton/Skeleton'
interface AvailabilityEditorProps { interface AvailabilityEditorProps {
@ -35,7 +37,14 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
const palette = usePalette(2) const palette = usePalette(2)
return <> return <>
<Content isCentered>{t('you.info')}</Content> <Content isCentered>
<div>{t('you.info')}</div>
<div className={styles.selectionControls}>
<Button isSmall onClick={() => onChange(times)}>{t('you.select_all')}</Button>
<Button isSmall onClick={() => onChange([])}>{t('you.select_none')}</Button>
<Button isSmall onClick={() => onChange(times.filter(t => !value.includes(t)))}>{t('you.select_invert')}</Button>
</div>
</Content>
{times[0].length === 13 && <Content> {times[0].length === 13 && <Content>
<div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center', gap: 12 }}> <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center', gap: 12 }}>
<GoogleCalendar <GoogleCalendar
@ -48,13 +57,13 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
</div> </div>
</Content>} </Content>}
<div className={styles.wrapper}> <div className={viewerStyles.wrapper}>
<div> <div>
<div className={styles.heatmap}> <div className={viewerStyles.heatmap}>
<div className={styles.timeLabels}> <div className={viewerStyles.timeLabels}>
{table?.rows.map((row, i) => {table?.rows.map((row, i) =>
<div className={styles.timeSpace} key={i}> <div className={viewerStyles.timeSpace} key={i}>
{row && <label className={styles.timeLabel}> {row && <label className={viewerStyles.timeLabel}>
{row.label} {row.label}
</label>} </label>}
</div> </div>
@ -62,12 +71,12 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
</div> </div>
{table?.columns.map((column, x) => <Fragment key={x}> {table?.columns.map((column, x) => <Fragment key={x}>
{column ? <div className={styles.dateColumn}> {column ? <div className={viewerStyles.dateColumn}>
{column.header.dateLabel && <label className={styles.dateLabel}>{column.header.dateLabel}</label>} {column.header.dateLabel && <label className={viewerStyles.dateLabel}>{column.header.dateLabel}</label>}
<label className={styles.dayLabel}>{column.header.weekdayLabel}</label> <label className={viewerStyles.dayLabel}>{column.header.weekdayLabel}</label>
<div <div
className={styles.times} className={viewerStyles.times}
data-border-left={x === 0 || table.columns.at(x - 1) === null} data-border-left={x === 0 || table.columns.at(x - 1) === null}
data-border-right={x === table.columns.length - 1 || table.columns.at(x + 1) === null} data-border-right={x === table.columns.length - 1 || table.columns.at(x + 1) === null}
> >
@ -75,7 +84,7 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
if (y === column.cells.length - 1) return null if (y === column.cells.length - 1) return null
if (!cell) return <div if (!cell) return <div
className={makeClass(styles.timeSpace, styles.grey)} className={makeClass(viewerStyles.timeSpace, viewerStyles.grey)}
key={y} key={y}
title={t<string>('greyed_times')} title={t<string>('greyed_times')}
/> />
@ -87,7 +96,7 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
return <div return <div
key={y} key={y}
className={makeClass(styles.time, selecting.length === 0 && styles.editable)} className={makeClass(viewerStyles.time, selecting.length === 0 && viewerStyles.editable)}
style={{ style={{
backgroundColor: isSelected ? palette[1].string : palette[0].string, backgroundColor: isSelected ? palette[1].string : palette[0].string,
'--hover-color': isSelected ? palette[0].highlight : palette[1].highlight, '--hover-color': isSelected ? palette[0].highlight : palette[1].highlight,
@ -131,7 +140,7 @@ const AvailabilityEditor = ({ times, timezone, value = [], onChange, table }: Av
/> />
})} })}
</div> </div>
</div> : <div className={styles.columnSpacer} />} </div> : <div className={viewerStyles.columnSpacer} />}
</Fragment>) ?? <Skeleton isSpecificDates={times[0].length === 13} />} </Fragment>) ?? <Skeleton isSpecificDates={times[0].length === 13} />}
</div> </div>
</div> </div>

View file

@ -9,6 +9,8 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
flex-direction: column;
gap: 1em;
} }
.slim { .slim {