fb920a92e7
* Refactor task count * Fixed show page rerender * Less rerenders and way better title and body UX * Finished breaking down activity editor subscriptions * Removed console.log * Last console.log * Fixed bugs and cleaned
236 lines
6.8 KiB
TypeScript
236 lines
6.8 KiB
TypeScript
import { Tooltip } from 'react-tooltip';
|
|
import { useTheme } from '@emotion/react';
|
|
import styled from '@emotion/styled';
|
|
import { useRecoilValue } from 'recoil';
|
|
|
|
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
|
import { timelineActivityWithoutTargetsFamilyState } from '@/activities/timeline/states/timelineActivityFirstLevelFamilySelector';
|
|
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
|
import { IconCheckbox, IconNotes } from '@/ui/display/icon';
|
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
|
import { Avatar } from '@/users/components/Avatar';
|
|
import {
|
|
beautifyExactDateTime,
|
|
beautifyPastDateRelativeToNow,
|
|
} from '~/utils/date-utils';
|
|
|
|
const StyledAvatarContainer = styled.div`
|
|
align-items: center;
|
|
display: flex;
|
|
height: 26px;
|
|
justify-content: center;
|
|
user-select: none;
|
|
width: 26px;
|
|
z-index: 2;
|
|
`;
|
|
|
|
const StyledIconContainer = styled.div`
|
|
align-items: center;
|
|
color: ${({ theme }) => theme.font.color.tertiary};
|
|
display: flex;
|
|
height: 16px;
|
|
justify-content: center;
|
|
text-decoration-line: underline;
|
|
width: 16px;
|
|
`;
|
|
|
|
const StyledActivityTitle = styled.div`
|
|
color: ${({ theme }) => theme.font.color.secondary};
|
|
cursor: pointer;
|
|
display: flex;
|
|
flex: 1;
|
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const StyledActivityLink = styled.div`
|
|
color: ${({ theme }) => theme.font.color.secondary};
|
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
|
overflow: hidden;
|
|
text-decoration-line: underline;
|
|
text-overflow: ellipsis;
|
|
`;
|
|
|
|
const StyledItemContainer = styled.div`
|
|
align-content: center;
|
|
align-items: center;
|
|
color: ${({ theme }) => theme.font.color.tertiary};
|
|
display: flex;
|
|
flex: 1;
|
|
gap: ${({ theme }) => theme.spacing(1)};
|
|
span {
|
|
color: ${({ theme }) => theme.font.color.secondary};
|
|
}
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const StyledItemTitleContainer = styled.div`
|
|
display: flex;
|
|
flex: 1;
|
|
flex-flow: row ${() => (useIsMobile() ? 'wrap' : 'nowrap')};
|
|
gap: ${({ theme }) => theme.spacing(1)};
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const StyledItemAuthorText = styled.div`
|
|
display: flex;
|
|
gap: ${({ theme }) => theme.spacing(1)};
|
|
`;
|
|
|
|
const StyledItemTitle = styled.div`
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const StyledItemTitleDate = styled.div`
|
|
align-items: center;
|
|
color: ${({ theme }) => theme.font.color.tertiary};
|
|
display: flex;
|
|
gap: ${({ theme }) => theme.spacing(2)};
|
|
justify-content: flex-end;
|
|
margin-left: auto;
|
|
`;
|
|
|
|
const StyledVerticalLineContainer = styled.div`
|
|
align-items: center;
|
|
align-self: stretch;
|
|
display: flex;
|
|
gap: ${({ theme }) => theme.spacing(2)};
|
|
justify-content: center;
|
|
width: 26px;
|
|
z-index: 2;
|
|
`;
|
|
|
|
const StyledVerticalLine = styled.div`
|
|
align-self: stretch;
|
|
background: ${({ theme }) => theme.border.color.light};
|
|
flex-shrink: 0;
|
|
width: 2px;
|
|
`;
|
|
|
|
const StyledTooltip = styled(Tooltip)`
|
|
background-color: ${({ theme }) => theme.background.primary};
|
|
|
|
box-shadow: 0px 2px 4px 3px
|
|
${({ theme }) => theme.background.transparent.light};
|
|
|
|
box-shadow: 2px 4px 16px 6px
|
|
${({ theme }) => theme.background.transparent.light};
|
|
|
|
color: ${({ theme }) => theme.font.color.primary};
|
|
|
|
opacity: 1;
|
|
padding: ${({ theme }) => theme.spacing(2)};
|
|
`;
|
|
|
|
const StyledTimelineItemContainer = styled.div<{ isGap?: boolean }>`
|
|
align-items: center;
|
|
align-self: stretch;
|
|
display: flex;
|
|
gap: ${({ theme }) => theme.spacing(4)};
|
|
height: ${({ isGap, theme }) =>
|
|
isGap ? (useIsMobile() ? theme.spacing(6) : theme.spacing(3)) : 'auto'};
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
`;
|
|
|
|
type TimelineActivityProps = {
|
|
isLastActivity?: boolean;
|
|
activityId: string;
|
|
};
|
|
|
|
export const TimelineActivity = ({
|
|
isLastActivity,
|
|
activityId,
|
|
}: TimelineActivityProps) => {
|
|
const activityForTimeline = useRecoilValue(
|
|
timelineActivityWithoutTargetsFamilyState(activityId),
|
|
);
|
|
|
|
const beautifiedCreatedAt = activityForTimeline
|
|
? beautifyPastDateRelativeToNow(activityForTimeline.createdAt)
|
|
: '';
|
|
const exactCreatedAt = activityForTimeline
|
|
? beautifyExactDateTime(activityForTimeline.createdAt)
|
|
: '';
|
|
const openActivityRightDrawer = useOpenActivityRightDrawer();
|
|
const theme = useTheme();
|
|
|
|
const activityFromStore = useRecoilValue(
|
|
recordStoreFamilyState(activityForTimeline?.id ?? ''),
|
|
);
|
|
|
|
if (!activityForTimeline) {
|
|
return <></>;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<StyledTimelineItemContainer>
|
|
<StyledAvatarContainer>
|
|
<Avatar
|
|
avatarUrl={activityForTimeline.author?.avatarUrl}
|
|
placeholder={activityForTimeline.author?.name.firstName ?? ''}
|
|
size="sm"
|
|
type="rounded"
|
|
/>
|
|
</StyledAvatarContainer>
|
|
<StyledItemContainer>
|
|
<StyledItemTitleContainer>
|
|
<StyledItemAuthorText>
|
|
<span>
|
|
{activityForTimeline.author?.name.firstName}{' '}
|
|
{activityForTimeline.author?.name.lastName}
|
|
</span>
|
|
created a {activityForTimeline.type.toLowerCase()}
|
|
</StyledItemAuthorText>
|
|
<StyledItemTitle>
|
|
<StyledIconContainer>
|
|
{activityForTimeline.type === 'Note' && (
|
|
<IconNotes size={theme.icon.size.sm} />
|
|
)}
|
|
{activityForTimeline.type === 'Task' && (
|
|
<IconCheckbox size={theme.icon.size.sm} />
|
|
)}
|
|
</StyledIconContainer>
|
|
{(activityForTimeline.type === 'Note' ||
|
|
activityForTimeline.type === 'Task') && (
|
|
<StyledActivityTitle
|
|
onClick={() =>
|
|
openActivityRightDrawer(activityForTimeline.id)
|
|
}
|
|
>
|
|
“
|
|
<StyledActivityLink
|
|
title={activityFromStore?.title ?? '(No Title)'}
|
|
>
|
|
{activityFromStore?.title ?? '(No Title)'}
|
|
</StyledActivityLink>
|
|
“
|
|
</StyledActivityTitle>
|
|
)}
|
|
</StyledItemTitle>
|
|
</StyledItemTitleContainer>
|
|
<StyledItemTitleDate id={`id-${activityForTimeline.id}`}>
|
|
{beautifiedCreatedAt}
|
|
</StyledItemTitleDate>
|
|
<StyledTooltip
|
|
anchorSelect={`#id-${activityForTimeline.id}`}
|
|
content={exactCreatedAt}
|
|
clickable
|
|
noArrow
|
|
/>
|
|
</StyledItemContainer>
|
|
</StyledTimelineItemContainer>
|
|
{!isLastActivity && (
|
|
<StyledTimelineItemContainer isGap>
|
|
<StyledVerticalLineContainer>
|
|
<StyledVerticalLine></StyledVerticalLine>
|
|
</StyledVerticalLineContainer>
|
|
</StyledTimelineItemContainer>
|
|
)}
|
|
</>
|
|
);
|
|
};
|