ghost-portal/packages/page-calendar/src/index.tsx
Jaco 27098f34b8
Bump deps (#9040)
* Bump deps

* Bumps

* Adjust

* Adjust

* Adjust test imports

* Adjust

* Re-adjust

* Fix frequency package name

* Adjust build

* Adjust

* Fix before import

* Adjust

* require script

* Adjust checks

* Linting fixes

* Fix json alongside other tests

* Move fixup script

* Remove main type: "module"

* Adjust (some) tests

* Adjust chartjs imports

* Bump deps

* Adjust

* Bump deps

* Adjust styled imports

* Bump deps

* Adjust
2023-02-20 11:38:52 +02:00

213 lines
5.2 KiB
TypeScript

// Copyright 2017-2023 @polkadot/app-calendar authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { DateState } from './types';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { styled, Tabs } from '@polkadot/react-components';
import Day from './Day';
import Month from './Month';
import { useTranslation } from './translate';
import UpcomingEvents from './UpcomingEvents';
import useScheduled from './useScheduled';
import { getDateState, nextMonth, prevMonth } from './util';
interface Props {
basePath: string;
className?: string;
}
const NOW_INC = 30 * 1000;
function CalendarApp ({ basePath, className }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const scheduled = useScheduled();
const [now, setNow] = useState(() => new Date());
const [dateState, setDateState] = useState(() => getDateState(now, now));
const [allEventsView, setAllEventsView] = useState(false);
const itemsRef = useRef([{
isRoot: true,
name: 'view',
text: t<string>('Upcoming events')
}]);
useEffect((): () => void => {
const intervalId = setInterval(() => setNow(new Date()), NOW_INC);
return (): void => {
clearInterval(intervalId);
};
}, []);
const [hasNextMonth, hasNextDay, lastDay] = useMemo(
() => {
const nextDay = new Date(dateState.dateSelected);
nextDay.setDate(nextDay.getDate() + 1);
const nextDayTime = nextDay.getTime();
const nextMonthTime = dateState.dateMonthNext.getTime();
const hasNextMonth = scheduled.some(({ dateTime }) => dateTime >= nextMonthTime);
const hasNextDay = hasNextMonth || scheduled.some(({ dateTime }) => dateTime >= nextDayTime);
const lastDay = hasNextMonth
? 42 // more than days in month
: scheduled.reduce((lastDay: number, { date }): number => {
return date.getFullYear() === dateState.dateMonth.getFullYear() && date.getMonth() === dateState.dateMonth.getMonth()
? Math.max(lastDay, date.getDate())
: lastDay;
}, 0);
return [hasNextMonth, hasNextDay, lastDay];
},
[dateState, scheduled]
);
const _nextMonth = useCallback(
() => setDateState(({ dateMonth, dateSelected }) => getDateState(nextMonth(dateMonth), dateSelected)),
[]
);
const _prevMonth = useCallback(
() => setDateState(({ dateMonth, dateSelected }) => getDateState(prevMonth(dateMonth), dateSelected)),
[]
);
const _nextDay = useCallback(
() => setDateState(({ dateSelected }): DateState => {
const date = new Date(dateSelected);
date.setDate(date.getDate() + 1);
return getDateState(date, date);
}),
[]
);
const _prevDay = useCallback(
() => setDateState(({ dateSelected }): DateState => {
const date = new Date(dateSelected);
date.setDate(date.getDate() - 1);
return getDateState(date, date);
}),
[]
);
const _setDay = useCallback(
(day: number) => setDateState(({ dateMonth }): DateState => {
const date = new Date(dateMonth);
date.setDate(day);
return getDateState(date, date);
}),
[]
);
const _setAllEventsView = useCallback(
(v: boolean) => setAllEventsView(v),
[]
);
return (
<StyledMain className={className}>
<Tabs
basePath={basePath}
items={itemsRef.current}
/>
<div className='calendarFlex'>
<Month
hasNextMonth={hasNextMonth}
lastDay={lastDay}
now={now}
scheduled={scheduled}
setDay={_setDay}
setNextMonth={_nextMonth}
setPrevMonth={_prevMonth}
state={dateState}
/>
<div className='wrapper-style'>
{allEventsView
? (
<UpcomingEvents
className='upcoming-events'
scheduled={scheduled}
setView={_setAllEventsView}
/>
)
: (
<Day
date={dateState.dateSelected}
hasNextDay={hasNextDay}
now={now}
scheduled={scheduled}
setNextDay={_nextDay}
setPrevDay={_prevDay}
setView={_setAllEventsView}
/>
)
}
</div>
</div>
</StyledMain>
);
}
const StyledMain = styled.main`
.calendarFlex {
align-items: flex-start;
display: flex;
flex-wrap: nowrap;
.wrapper-style {
flex: 1;
.upcoming-events {
position: relative;
max-width: 100%;
}
}
> div {
background-color: var(--bg-table);
border: 1px solid var(--border-table);
border-radius: 0.25rem;
&+div {
margin-left: 1.5rem;
}
.ui--Button-Group {
margin: 0;
}
}
h1 {
align-items: center;
border-bottom: 0.25rem solid var(--bg-page);
display: flex;
justify-content: space-between;
padding: 0.5rem 0.5rem 0.5rem 1rem;
> div:first-child {
align-items: center;
display: inline-flex;
}
.all-events-button {
margin-right: 1rem;
}
.ui--Button {
font-size: var(--font-size-small);
}
}
}
`;
export default React.memo(CalendarApp);