Skip to content

Commit

Permalink
4488 connect calendar tab to backend (#4624)
Browse files Browse the repository at this point in the history
* create states and hooks

* implement fetch more records

* add empty state

* update types

* fix error

* add fetchmoreloader and add scroll to container

* fix visibility in calendarEventFragment

* fix fetchMoreRecords

* update TIMELINE_CALENDAR_EVENTS_DEFAULT_PAGE_SIZE

* add test

* modify empty state subtitle

* replace entity by activityTargetableObject

* create useCustomResolver hook

* refactor

* refactoring

* use generic component

* rename FetchMoreLoader

* remove deprecated states and hooks

* fix typing

* update typing

* update error message

* renaming

* improve typing

* fix bug on contact creation from same company
  • Loading branch information
bosiraphael authored Mar 26, 2024
1 parent 5c5dcf5 commit fefa37b
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 222 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ import styled from '@emotion/styled';
import { format, getYear } from 'date-fns';

import { CalendarMonthCard } from '@/activities/calendar/components/CalendarMonthCard';
import { TIMELINE_CALENDAR_EVENTS_DEFAULT_PAGE_SIZE } from '@/activities/calendar/constants/Calendar';
import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext';
import { useCalendarEvents } from '@/activities/calendar/hooks/useCalendarEvents';
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
import { getTimelineCalendarEventsFromCompanyId } from '@/activities/calendar/queries/getTimelineCalendarEventsFromCompanyId';
import { getTimelineCalendarEventsFromPersonId } from '@/activities/calendar/queries/getTimelineCalendarEventsFromPersonId';
import { FetchMoreLoader } from '@/activities/components/CustomResolverFetchMoreLoader';
import { useCustomResolver } from '@/activities/hooks/useCustomResolver';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { H3Title } from '@/ui/display/typography/components/H3Title';
import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder';
import {
AnimatedPlaceholderEmptyContainer,
AnimatedPlaceholderEmptySubTitle,
AnimatedPlaceholderEmptyTextContainer,
AnimatedPlaceholderEmptyTitle,
} from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled';
import { Section } from '@/ui/layout/section/components/Section';
import { TimelineCalendarEventsWithTotal } from '~/generated/graphql';

const StyledContainer = styled.div`
box-sizing: border-box;
Expand All @@ -17,18 +29,39 @@ const StyledContainer = styled.div`
gap: ${({ theme }) => theme.spacing(8)};
padding: ${({ theme }) => theme.spacing(6)};
width: 100%;
overflow: scroll;
`;

const StyledYear = styled.span`
color: ${({ theme }) => theme.font.color.light};
`;

export const Calendar = () => {
const { records: calendarEvents } = useFindManyRecords<CalendarEvent>({
objectNameSingular: CoreObjectNameSingular.CalendarEvent,
orderBy: { startsAt: 'DescNullsLast', endsAt: 'DescNullsLast' },
useRecordsWithoutConnection: true,
});
export const Calendar = ({
targetableObject,
}: {
targetableObject: ActivityTargetableObject;
}) => {
const [query, queryName] =
targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Person
? [
getTimelineCalendarEventsFromPersonId,
'getTimelineCalendarEventsFromPersonId',
]
: [
getTimelineCalendarEventsFromCompanyId,
'getTimelineCalendarEventsFromCompanyId',
];

const { data, firstQueryLoading, isFetchingMore, fetchMoreRecords } =
useCustomResolver<TimelineCalendarEventsWithTotal>(
query,
queryName,
'timelineCalendarEvents',
targetableObject,
TIMELINE_CALENDAR_EVENTS_DEFAULT_PAGE_SIZE,
);

const { timelineCalendarEvents } = data?.[queryName] ?? {};

const {
calendarEventsByDayTime,
Expand All @@ -38,13 +71,30 @@ export const Calendar = () => {
monthTimes,
monthTimesByYear,
updateCurrentCalendarEvent,
} = useCalendarEvents(
calendarEvents.map((calendarEvent) => ({
...calendarEvent,
// TODO: retrieve CalendarChannel visibility from backend
visibility: 'SHARE_EVERYTHING',
})),
);
} = useCalendarEvents(timelineCalendarEvents || []);

if (firstQueryLoading) {
// TODO: implement loader
return;
}

if (!firstQueryLoading && !timelineCalendarEvents?.length) {
// TODO: change animated placeholder
return (
<AnimatedPlaceholderEmptyContainer>
<AnimatedPlaceholder type="noMatchRecord" />
<AnimatedPlaceholderEmptyTextContainer>
<AnimatedPlaceholderEmptyTitle>
No Events
</AnimatedPlaceholderEmptyTitle>
<AnimatedPlaceholderEmptySubTitle>
No events have been scheduled with this{' '}
{targetableObject.targetObjectNameSingular} yet.
</AnimatedPlaceholderEmptySubTitle>
</AnimatedPlaceholderEmptyTextContainer>
</AnimatedPlaceholderEmptyContainer>
);
}

return (
<CalendarContext.Provider
Expand Down Expand Up @@ -78,6 +128,10 @@ export const Calendar = () => {
</Section>
);
})}
<FetchMoreLoader
loading={isFetchingMore || firstQueryLoading}
onLastRowVisible={fetchMoreRecords}
/>
</StyledContainer>
</CalendarContext.Provider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import {
import { AnimatePresence, motion } from 'framer-motion';

import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext';
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
import { getCalendarEventEndDate } from '@/activities/calendar/utils/getCalendarEventEndDate';
import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate';
import { hasCalendarEventEnded } from '@/activities/calendar/utils/hasCalendarEventEnded';
import { hasCalendarEventStarted } from '@/activities/calendar/utils/hasCalendarEventStarted';
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';

type CalendarCurrentEventCursorProps = {
calendarEvent: CalendarEvent;
calendarEvent: TimelineCalendarEvent;
};

const StyledCurrentEventCursor = styled(motion.div)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import styled from '@emotion/styled';
import { differenceInSeconds, endOfDay, format } from 'date-fns';

import { CalendarEventRow } from '@/activities/calendar/components/CalendarEventRow';
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate';
import { CardContent } from '@/ui/layout/card/components/CardContent';
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';

type CalendarDayCardContentProps = {
calendarEvents: CalendarEvent[];
calendarEvents: TimelineCalendarEvent[];
divider?: boolean;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { useRecoilValue } from 'recoil';
import { CalendarCurrentEventCursor } from '@/activities/calendar/components/CalendarCurrentEventCursor';
import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext';
import { useOpenCalendarEventRightDrawer } from '@/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer';
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
import { getCalendarEventEndDate } from '@/activities/calendar/utils/getCalendarEventEndDate';
import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate';
import { hasCalendarEventEnded } from '@/activities/calendar/utils/hasCalendarEventEnded';
Expand All @@ -17,10 +16,11 @@ import { Card } from '@/ui/layout/card/components/Card';
import { CardContent } from '@/ui/layout/card/components/CardContent';
import { Avatar } from '@/users/components/Avatar';
import { AvatarGroup } from '@/users/components/AvatarGroup';
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';

type CalendarEventRowProps = {
calendarEvent: CalendarEvent;
calendarEvent: TimelineCalendarEvent;
className?: string;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const TIMELINE_CALENDAR_EVENTS_DEFAULT_PAGE_SIZE = 10;
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { createContext } from 'react';

import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';

type CalendarContextValue = {
calendarEventsByDayTime: Record<number, CalendarEvent[] | undefined>;
currentCalendarEvent?: CalendarEvent;
calendarEventsByDayTime: Record<number, TimelineCalendarEvent[] | undefined>;
currentCalendarEvent?: TimelineCalendarEvent;
displayCurrentEventCursor?: boolean;
getNextCalendarEvent: (
calendarEvent: CalendarEvent,
) => CalendarEvent | undefined;
calendarEvent: TimelineCalendarEvent,
) => TimelineCalendarEvent | undefined;
updateCurrentCalendarEvent: () => void;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ import { groupArrayItemsBy } from '~/utils/array/groupArrayItemsBy';
import { isDefined } from '~/utils/isDefined';
import { sortDesc } from '~/utils/sort';

export const useCalendarEvents = (calendarEvents: CalendarEvent[]) => {
type CalendarEventGeneric = Omit<
CalendarEvent,
'attendees' | 'externalCreatedAt'
>;

export const useCalendarEvents = <T extends CalendarEventGeneric>(
calendarEvents: T[],
) => {
const calendarEventsByDayTime = groupArrayItemsBy(
calendarEvents,
(calendarEvent) =>
Expand All @@ -29,14 +36,14 @@ export const useCalendarEvents = (calendarEvents: CalendarEvent[]) => {

const monthTimesByYear = groupArrayItemsBy(sortedMonthTimes, getYear);

const getPreviousCalendarEvent = (calendarEvent: CalendarEvent) => {
const getPreviousCalendarEvent = (calendarEvent: T) => {
const calendarEventIndex = calendarEvents.indexOf(calendarEvent);
return calendarEventIndex < calendarEvents.length - 1
? calendarEvents[calendarEventIndex + 1]
: undefined;
};

const getNextCalendarEvent = (calendarEvent: CalendarEvent) => {
const getNextCalendarEvent = (calendarEvent: T) => {
const calendarEventIndex = calendarEvents.indexOf(calendarEvent);
return calendarEventIndex > 0
? calendarEvents[calendarEventIndex - 1]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const calendarEventFragment = gql`
startsAt
endsAt
isFullDay
visibility
attendees {
...AttendeeFragment
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from '@emotion/styled';

import { GRAY_SCALE } from '@/ui/theme/constants/GrayScale';

type EmailThreadFetchMoreLoaderProps = {
type FetchMoreLoaderProps = {
loading: boolean;
onLastRowVisible: (...args: any[]) => any;
};
Expand All @@ -18,10 +18,10 @@ const StyledText = styled.div`
padding-left: ${({ theme }) => theme.spacing(2)};
`;

export const EmailThreadFetchMoreLoader = ({
export const FetchMoreLoader = ({
loading,
onLastRowVisible,
}: EmailThreadFetchMoreLoaderProps) => {
}: FetchMoreLoaderProps) => {
const { ref: tbodyRef } = useInView({
onChange: onLastRowVisible,
});
Expand Down
Loading

0 comments on commit fefa37b

Please sign in to comment.