import type { FC, ReactNode } from 'react'; import { Box, Paper, styled, Typography } from '@mui/material'; import Timeline from '@mui/lab/Timeline'; import MuiTimelineItem, { timelineItemClasses } from '@mui/lab/TimelineItem'; import TimelineSeparator from '@mui/lab/TimelineSeparator'; import TimelineDot from '@mui/lab/TimelineDot'; import TimelineConnector from '@mui/lab/TimelineConnector'; import TimelineContent from '@mui/lab/TimelineContent'; import type { ChangeRequestSchedule, ChangeRequestState, ChangeRequestType, } from '../../changeRequest.types'; import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip.tsx'; import ErrorIcon from '@mui/icons-material/Error'; import { useLocationSettings } from 'hooks/useLocationSettings'; import { formatDateYMDHM } from 'utils/formatDate.ts'; export type ISuggestChangeTimelineProps = { timestamps?: ChangeRequestType['stateTransitionTimestamps']; // todo: update with flag `timestampsInChangeRequestTimeline` } & ( | { state: Exclude; schedule?: undefined; } | { state: 'Scheduled'; schedule: ChangeRequestSchedule; } ); const StyledTimelineContent = styled(TimelineContent)(({ theme }) => ({ display: 'flex', flexDirection: 'column', })); const StyledPaper = styled(Paper)(({ theme }) => ({ marginTop: theme.spacing(2), borderRadius: `${theme.shape.borderRadiusLarge}px`, })); const StyledBox = styled(Box)(({ theme }) => ({ padding: theme.spacing(2), marginBottom: `-${theme.spacing(4)}`, })); const StyledSubtitle = styled(Box)(({ theme }) => ({ display: 'flex', flexDirection: 'row', alignItems: 'flex-end', })); const StyledTimeline = styled(Timeline)(() => ({ [`& .${timelineItemClasses.root}:before`]: { flex: 0, padding: 0, }, })); const steps: ChangeRequestState[] = [ 'Draft', 'In review', 'Approved', 'Applied', ]; const rejectedSteps: ChangeRequestState[] = ['Draft', 'In review', 'Rejected']; const scheduledSteps: ChangeRequestState[] = [ 'Draft', 'In review', 'Approved', 'Scheduled', 'Applied', ]; export const determineColor = ( changeRequestState: ChangeRequestState, changeRequestStateIndex: number, displayStage: ChangeRequestState, displayStageIndex: number, ) => { if (changeRequestState === 'Cancelled') return 'grey'; if (changeRequestState === 'Rejected') return displayStage === 'Rejected' ? 'error' : 'success'; if ( changeRequestStateIndex !== -1 && changeRequestStateIndex >= displayStageIndex ) return 'success'; if (changeRequestStateIndex + 1 === displayStageIndex) return 'primary'; return 'grey'; }; export const ChangeRequestTimeline: FC = ({ state, schedule, timestamps, }) => { let data: ChangeRequestState[]; switch (state) { case 'Rejected': data = rejectedSteps; break; case 'Scheduled': data = scheduledSteps; break; default: data = steps; } const activeIndex = data.findIndex((item) => item === state); return ( {data.map((title, index) => { const timestampComponent = index <= activeIndex && timestamps?.[title] ? ( ); }; const Time = styled(({ dateTime, ...props }: { dateTime: string }) => { const { locationSettings } = useLocationSettings(); const displayTime = formatDateYMDHM( new Date(dateTime || ''), locationSettings.locale, ); return ( ); })(({ theme }) => ({ color: theme.palette.text.secondary, fontSize: theme.typography.body2.fontSize, })); const TimelineItem = ({ color, title, shouldConnectToNextItem, timestamp, timelineDotProps = {}, }: { color: 'primary' | 'success' | 'grey' | 'error' | 'warning'; title: string; shouldConnectToNextItem: boolean; timestamp?: ReactNode; timelineDotProps: { [key: string]: string | undefined }; }) => { return ( {shouldConnectToNextItem && } {title} {timestamp} ); }; export const getScheduleProps = (schedule: ChangeRequestSchedule) => { const Subtitle = ({ prefix }: { prefix: string }) => ( <> {prefix}