Shared:Calendar:Add scroll to calendar.

This commit is contained in:
Vlada Gazizova 2024-08-23 16:53:42 +03:00
parent 1bfa73ac4b
commit 49b78e1e15
10 changed files with 122 additions and 52 deletions

View File

@ -2,11 +2,13 @@ import IconCalendar from "PUBLIC_DIR/images/calendar.info.panel.react.svg?url";
import { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef } from "react";
import styled, { css } from "styled-components"; import styled, { css } from "styled-components";
import moment from "moment"; import moment from "moment";
import {Calendar} from "@docspace/shared/components/calendar" import { Calendar } from "@docspace/shared/components/calendar";
import { Portal } from "@docspace/shared/components/portal";
import { isMobile } from "@docspace/shared/utils"; import { isMobile } from "@docspace/shared/utils";
import { ReactSVG } from "react-svg"; import { ReactSVG } from "react-svg";
const heightCalendar = 376;
const heightCalendarMobile = 420;
const StyledCalendarComponent = styled.div` const StyledCalendarComponent = styled.div`
position: relative; position: relative;
@ -17,8 +19,10 @@ const StyledCalendarComponent = styled.div`
const StyledCalendar = styled(Calendar)` const StyledCalendar = styled(Calendar)`
position: absolute; position: absolute;
top: 134px; top: 20px;
right: 16px; right: -30px;
height: ${(props) => props.height + "px"};
${(props) => ${(props) =>
props.isMobile && props.isMobile &&
@ -27,24 +31,42 @@ const StyledCalendar = styled(Calendar)`
bottom: 0; bottom: 0;
top: auto; top: auto;
right: auto; right: auto;
left: 0;
height: ${heightCalendarMobile + "px"};
`} `}
`; `;
const CalendarComponent = ({ roomCreationDate, setCalendarDay }) => { const CalendarComponent = ({ roomCreationDate, setCalendarDay }) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [selectedDate, setSelectedDate] = useState(null); const [selectedDate, setSelectedDate] = useState(null);
const [height, setHeight] = useState(heightCalendar);
const calendarRef = useRef(); const calendarRef = useRef();
const calendarButtonRef = useRef(); const calendarButtonRef = useRef();
useEffect(() => { useEffect(() => {
document.addEventListener("click", handleClick, { capture: true }); document.addEventListener("click", handleClick, { capture: true });
window.addEventListener("resize", onChangeHeight);
onChangeHeight();
return () => { return () => {
document.removeEventListener("click", handleClick, { capture: true }); document.removeEventListener("click", handleClick, { capture: true });
window.removeEventListener("resize", onChangeHeight);
setCalendarDay(null); setCalendarDay(null);
}; };
}, []); }, []);
const onChangeHeight = () => {
const hightTop = calendarButtonRef?.current?.getBoundingClientRect().top;
const hightIconCalendar = 20;
const hightWindow = document.documentElement.clientHeight;
const hightScroll = hightWindow - hightIconCalendar - hightTop;
if (hightScroll !== heightCalendar && hightScroll > heightCalendar) {
setHeight(heightCalendar);
} else setHeight(hightScroll);
};
const handleClick = (e) => { const handleClick = (e) => {
!calendarButtonRef?.current?.contains(e.target) && !calendarButtonRef?.current?.contains(e.target) &&
!calendarRef?.current?.contains(e.target) && !calendarRef?.current?.contains(e.target) &&
@ -74,17 +96,15 @@ const CalendarComponent = ({ roomCreationDate, setCalendarDay }) => {
</div> </div>
{isOpen && ( {isOpen && (
<Portal <StyledCalendar
element={ height={height}
<StyledCalendar setSelectedDate={onDateSet}
setSelectedDate={onDateSet} selectedDate={selectedDate}
selectedDate={selectedDate} minDate={new Date(formattedRoomCreationDate)}
minDate={new Date(formattedRoomCreationDate)} maxDate={new Date()}
maxDate={new Date()} forwardedRef={calendarRef}
forwardedRef={calendarRef} isMobile={isMobile()}
isMobile={isMobile()} isScroll={!isMobile()}
/>
}
/> />
)} )}
</StyledCalendarComponent> </StyledCalendarComponent>

View File

@ -78,6 +78,7 @@ ButtonsContainer.displayName = "ButtonsContainer";
const CalendarContainer = styled.div<{ const CalendarContainer = styled.div<{
isMobile?: boolean; isMobile?: boolean;
big?: boolean; big?: boolean;
isScroll?: boolean;
}>` }>`
${(props) => ${(props) =>
!props.isMobile && !props.isMobile &&
@ -109,19 +110,37 @@ const CalendarContainer = styled.div<{
props.big ? "repeat(4, 1fr)" : "repeat(7, 1fr)"}; props.big ? "repeat(4, 1fr)" : "repeat(7, 1fr)"};
box-sizing: border-box; box-sizing: border-box;
padding: ${(props) => (props.big ? "14px 6px 6px 6px" : "0 6px")}; padding: ${(props) => (props.big ? "14px 6px 6px 6px" : "0 6px")};
${(props) =>
props.isScroll &&
css`
margin-bottom: 28px;
`};
`; `;
CalendarContainer.defaultProps = { theme: Base }; CalendarContainer.defaultProps = { theme: Base };
const Container = styled.div<{ isMobile?: boolean }>` const Container = styled.div<{ isMobile?: boolean; isScroll?: boolean }>`
box-sizing: border-box; box-sizing: border-box;
width: ${(props) => (props.isMobile ? "100%" : "362px")}; width: ${(props) => (props.isMobile ? "100%" : "362px")};
height: ${(props) => (props.isMobile ? "420px" : "376px")}; height: ${(props) => (props.isMobile ? "420px" : "376px")};
padding: ${(props) => (props.isMobile ? "16px" : "30px 28px 28px 28px")}; padding: ${(props) =>
props.isMobile
? "16px"
: props.isScroll
? "0px 0px 0px 28px"
: "30px 28px 28px 28px"};
box-shadow: ${(props) => props.theme.calendar.boxShadow}; box-shadow: ${(props) => props.theme.calendar.boxShadow};
border-radius: 6px; border-radius: 6px;
z-index: 320; z-index: 320;
background-color: ${(props) => props.theme.backgroundColor}; background-color: ${(props) => props.theme.backgroundColor};
${(props) =>
props.isScroll &&
css`
header {
padding: 30px 23px 0 12px !important;
}
`};
`; `;
Container.defaultProps = { theme: Base }; Container.defaultProps = { theme: Base };
@ -317,6 +336,7 @@ Weekday.defaultProps = { theme: Base };
const StyledContainerTheme = styled(Container)<{ const StyledContainerTheme = styled(Container)<{
$currentColorScheme?: TColorScheme; $currentColorScheme?: TColorScheme;
isMobile?: boolean; isMobile?: boolean;
isScroll?: boolean;
}>` }>`
${HeaderActionIcon} { ${HeaderActionIcon} {
border-color: ${(props) => props.$currentColorScheme?.main?.accent}; border-color: ${(props) => props.$currentColorScheme?.main?.accent};

View File

@ -30,6 +30,7 @@ import { useTheme } from "styled-components";
import moment from "moment"; import moment from "moment";
import "moment/locale/ar-sa"; import "moment/locale/ar-sa";
import { Scrollbar } from "@docspace/shared/components/scrollbar";
import { Days, Months, Years } from "./sub-components"; import { Days, Months, Years } from "./sub-components";
import { getValidDates } from "./utils"; import { getValidDates } from "./utils";
@ -49,6 +50,7 @@ const Calendar = ({
onChange, onChange,
isMobile, isMobile,
forwardedRef, forwardedRef,
isScroll = false,
}: CalendarProps) => { }: CalendarProps) => {
moment.locale(locale); moment.locale(locale);
@ -105,6 +107,49 @@ const Calendar = ({
setObservedDate(date); setObservedDate(date);
}, [initialDate, maxDate, minDate]); }, [initialDate, maxDate, minDate]);
const CalendarBodyNode =
selectedScene === 0 ? (
<Days
observedDate={observedDate}
setObservedDate={setObservedDate}
setSelectedScene={setSelectedScene}
selectedDate={selectedDate}
handleDateChange={handleDateChange}
minDate={resultMinDate}
maxDate={resultMaxDate}
isMobile={isMobile || false}
isScroll={isScroll}
/>
) : selectedScene === 1 ? (
<Months
observedDate={observedDate}
setObservedDate={setObservedDate}
setSelectedScene={setSelectedScene}
selectedDate={selectedDate}
minDate={resultMinDate}
maxDate={resultMaxDate}
isMobile={isMobile || false}
isScroll={isScroll}
/>
) : (
<Years
observedDate={observedDate}
setObservedDate={setObservedDate}
setSelectedScene={setSelectedScene}
selectedDate={selectedDate}
minDate={resultMinDate}
maxDate={resultMaxDate}
isMobile={isMobile || false}
isScroll={isScroll}
/>
);
const CalendarNode = isScroll ? (
<Scrollbar>{CalendarBodyNode}</Scrollbar>
) : (
CalendarBodyNode
);
return ( return (
<StyledContainerTheme <StyledContainerTheme
id={id} id={id}
@ -114,39 +159,9 @@ const Calendar = ({
ref={forwardedRef} ref={forwardedRef}
$currentColorScheme={theme?.currentColorScheme} $currentColorScheme={theme?.currentColorScheme}
data-testid="calendar" data-testid="calendar"
isScroll={isScroll}
> >
{selectedScene === 0 ? ( {CalendarNode}
<Days
observedDate={observedDate}
setObservedDate={setObservedDate}
setSelectedScene={setSelectedScene}
selectedDate={selectedDate}
handleDateChange={handleDateChange}
minDate={resultMinDate}
maxDate={resultMaxDate}
isMobile={isMobile || false}
/>
) : selectedScene === 1 ? (
<Months
observedDate={observedDate}
setObservedDate={setObservedDate}
setSelectedScene={setSelectedScene}
selectedDate={selectedDate}
minDate={resultMinDate}
maxDate={resultMaxDate}
isMobile={isMobile || false}
/>
) : (
<Years
observedDate={observedDate}
setObservedDate={setObservedDate}
setSelectedScene={setSelectedScene}
selectedDate={selectedDate}
minDate={resultMinDate}
maxDate={resultMaxDate}
isMobile={isMobile || false}
/>
)}
</StyledContainerTheme> </StyledContainerTheme>
); );
}; };

View File

@ -49,6 +49,7 @@ export interface CalendarProps {
initialDate?: moment.Moment | Date; initialDate?: moment.Moment | Date;
isMobile?: boolean; isMobile?: boolean;
forwardedRef?: React.RefObject<HTMLDivElement>; forwardedRef?: React.RefObject<HTMLDivElement>;
isScroll?: boolean;
} }
export interface DaysProps { export interface DaysProps {
@ -60,6 +61,7 @@ export interface DaysProps {
minDate: moment.Moment; minDate: moment.Moment;
maxDate: moment.Moment; maxDate: moment.Moment;
isMobile: boolean; isMobile: boolean;
isScroll?: boolean;
} }
export interface DaysHeaderProps { export interface DaysHeaderProps {
@ -78,6 +80,7 @@ export interface DaysBodyProps {
minDate: moment.Moment; minDate: moment.Moment;
maxDate: moment.Moment; maxDate: moment.Moment;
isMobile: boolean; isMobile: boolean;
isScroll?: boolean;
} }
export interface HeaderButtonsProps { export interface HeaderButtonsProps {
@ -96,6 +99,7 @@ export interface MonthsProps {
minDate: moment.Moment; minDate: moment.Moment;
maxDate: moment.Moment; maxDate: moment.Moment;
isMobile: boolean; isMobile: boolean;
isScroll?: boolean;
} }
export interface MonthsBodyProps { export interface MonthsBodyProps {
@ -106,6 +110,7 @@ export interface MonthsBodyProps {
minDate: moment.Moment; minDate: moment.Moment;
maxDate: moment.Moment; maxDate: moment.Moment;
isMobile: boolean; isMobile: boolean;
isScroll?: boolean;
} }
export interface MonthsHeaderProps { export interface MonthsHeaderProps {
@ -125,6 +130,7 @@ export interface YearsProps {
minDate: moment.Moment; minDate: moment.Moment;
maxDate: moment.Moment; maxDate: moment.Moment;
isMobile: boolean; isMobile: boolean;
isScroll?: boolean;
} }
export interface YearsHeaderProps { export interface YearsHeaderProps {

View File

@ -38,6 +38,7 @@ export const Days = ({
minDate, minDate,
maxDate, maxDate,
isMobile, isMobile,
isScroll,
}: DaysProps) => { }: DaysProps) => {
return ( return (
<> <>
@ -56,6 +57,7 @@ export const Days = ({
minDate={minDate} minDate={minDate}
maxDate={maxDate} maxDate={maxDate}
isMobile={isMobile} isMobile={isMobile}
isScroll={isScroll}
/> />
</> </>
); );

View File

@ -37,6 +37,7 @@ export const DaysBody = ({
minDate, minDate,
maxDate, maxDate,
isMobile, isMobile,
isScroll,
}: DaysBodyProps) => { }: DaysBodyProps) => {
const daysElements = getDayElements( const daysElements = getDayElements(
observedDate, observedDate,
@ -49,7 +50,7 @@ export const DaysBody = ({
const weekdayElements = getWeekdayElements(isMobile); const weekdayElements = getWeekdayElements(isMobile);
return ( return (
<CalendarContainer isMobile={isMobile}> <CalendarContainer isMobile={isMobile} isScroll={isScroll}>
{weekdayElements} {daysElements} {weekdayElements} {daysElements}
</CalendarContainer> </CalendarContainer>
); );

View File

@ -38,6 +38,7 @@ export const Months = ({
minDate, minDate,
maxDate, maxDate,
isMobile, isMobile,
isScroll,
}: MonthsProps) => { }: MonthsProps) => {
return ( return (
<> <>
@ -57,6 +58,7 @@ export const Months = ({
minDate={minDate} minDate={minDate}
maxDate={maxDate} maxDate={maxDate}
isMobile={isMobile} isMobile={isMobile}
isScroll={isScroll}
/> />
</> </>
); );

View File

@ -37,6 +37,7 @@ export const MonthsBody = ({
minDate, minDate,
maxDate, maxDate,
isMobile, isMobile,
isScroll,
}: MonthsBodyProps) => { }: MonthsBodyProps) => {
const months = getCalendarMonths(observedDate); const months = getCalendarMonths(observedDate);
const monthsElements = getMonthElements( const monthsElements = getMonthElements(
@ -50,7 +51,7 @@ export const MonthsBody = ({
); );
return ( return (
<CalendarContainer big isMobile={isMobile}> <CalendarContainer big isMobile={isMobile} isScroll={isScroll}>
{monthsElements} {monthsElements}
</CalendarContainer> </CalendarContainer>
); );

View File

@ -37,6 +37,7 @@ export const Years = ({
minDate, minDate,
maxDate, maxDate,
isMobile, isMobile,
isScroll,
}: YearsProps) => { }: YearsProps) => {
return ( return (
<> <>
@ -55,6 +56,7 @@ export const Years = ({
minDate={minDate} minDate={minDate}
maxDate={maxDate} maxDate={maxDate}
isMobile={isMobile} isMobile={isMobile}
isScroll={isScroll}
/> />
</> </>
); );

View File

@ -38,6 +38,7 @@ export const YearsBody = ({
minDate, minDate,
maxDate, maxDate,
isMobile, isMobile,
isScroll,
}: YearsProps) => { }: YearsProps) => {
const years = getCalendarYears(observedDate); const years = getCalendarYears(observedDate);
const yearElements = getYearElements( const yearElements = getYearElements(
@ -51,7 +52,7 @@ export const YearsBody = ({
); );
return ( return (
<CalendarContainer big isMobile={isMobile}> <CalendarContainer big isMobile={isMobile} isScroll={isScroll}>
{yearElements} {yearElements}
</CalendarContainer> </CalendarContainer>
); );