Skip to content

Commit

Permalink
Merge pull request #70 from RevelioStartup/feat/delete-timeline
Browse files Browse the repository at this point in the history
Feat/delete timeline
  • Loading branch information
carlenee authored May 7, 2024
2 parents 2d9fe9c + d8a653c commit 2bada46
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 61 deletions.
67 changes: 33 additions & 34 deletions __tests__/elements/calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import { useGetTimelinesByEventQuery } from '@/redux/api/timelineApi';
import Calendar from '@/components/elements/Timeline/Calendar';
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { useGetTimelinesByEventQuery } from '@/redux/api/timelineApi'
import Calendar from '@/components/elements/Timeline/Calendar'

// Mock the useGetTimelinesByEventQuery hook
jest.mock('@/redux/api/timelineApi', () => ({
useGetTimelinesByEventQuery: jest.fn(),
}));
}))

jest.mock('@/components/elements/Timeline/Calendar', () => {
return {
__esModule: true,
default: jest.fn(() => (
<div>
<div data-testid="calendar">Calendar Component</div>
<div>Task 1</div>
<div>Task 2</div>
</div>
)),
}
});

return {
__esModule: true,
default: jest.fn(() => (
<div>
<div data-testid="calendar">Calendar Component</div>
<div>Task 1</div>
<div>Task 2</div>
</div>
)),
}
})

describe('Calendar', () => {
beforeEach(() => {
// Mock the return value of useGetTimelinesByEventQuery
(useGetTimelinesByEventQuery as jest.Mock).mockReturnValue({
;(useGetTimelinesByEventQuery as jest.Mock).mockReturnValue({
data: [
{
id: '1',
Expand All @@ -42,26 +41,26 @@ describe('Calendar', () => {
},
],
isLoading: false,
});
});
})
})

afterEach(() => {
jest.clearAllMocks();
});
jest.clearAllMocks()
})

test('renders the calendar component', () => {
render(<Calendar eventId="123" />);
expect(screen.getByTestId('calendar')).toBeInTheDocument();
});
render(<Calendar eventId="123" />)
expect(screen.getByTestId('calendar')).toBeInTheDocument()
})

test('displays calendar events correctly', () => {
render(<Calendar eventId="123" />);
expect(screen.getByText('Task 1')).toBeInTheDocument();
expect(screen.getByText('Task 2')).toBeInTheDocument();
});
render(<Calendar eventId="123" />)
expect(screen.getByText('Task 1')).toBeInTheDocument()
expect(screen.getByText('Task 2')).toBeInTheDocument()
})

test('handles event clicks to show details in a modal', async () => {
render(<Calendar eventId="123" />);
fireEvent.click(screen.getByText('Task 1'));
});
});
render(<Calendar eventId="123" />)
fireEvent.click(screen.getByText('Task 1'))
})
})
66 changes: 66 additions & 0 deletions __tests__/timeline/timeline-delete.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react'
import { render, fireEvent, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Provider } from 'react-redux'
import { store } from '@/redux/store'
import TimelineDetailsModal from '@/components/elements/Timeline/TimelineDetailsModal'

jest.mock('@/redux/api/timelineApi', () => ({
useDeleteTimelineMutation: jest.fn(() => [
jest.fn().mockResolvedValue({}),
{ isLoading: false, isSuccess: false },
]),
}))

describe('TimelineDetailsModal', () => {
const mockOnClose = jest.fn()

it('deletes the timeline and closes the modal on successful delete', async () => {
const { getByText } = render(
<Provider store={store}>
<TimelineDetailsModal
timelineId="1"
onClose={mockOnClose}
showModal={true}
clickedEvent={{
title: 'Setup',
start: new Date('2022-05-01T09:00:00Z'),
end: new Date('2022-05-01T10:00:00Z'),
}}
/>
</Provider>
)

global.confirm = jest.fn().mockReturnValue(true)

fireEvent.click(getByText('Delete Timeline'))

await waitFor(() => {
expect(mockOnClose).toHaveBeenCalled()
})
})

it('does not delete the timeline if user cancels', async () => {
const { getByText } = render(
<Provider store={store}>
<TimelineDetailsModal
timelineId="1"
onClose={mockOnClose}
showModal={true}
clickedEvent={{
title: 'Setup',
start: new Date('2022-05-01T09:00:00Z'),
end: new Date('2022-05-01T10:00:00Z'),
}}
/>
</Provider>
)

global.confirm = jest.fn().mockReturnValue(false)

fireEvent.click(getByText('Delete Timeline'))
await waitFor(() => {
expect(mockOnClose).not.toHaveBeenCalled()
})
})
})
7 changes: 7 additions & 0 deletions __tests__/timeline/timeline.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ jest.mock('@/components/elements/Timeline/Calendar', () => {
}
})

jest.mock('@/components/elements/Timeline/TimelineDetailsModal', () => {
return {
__esModule: true,
default: jest.fn(() => <div>Mocked DemoApp</div>),
}
})

describe('EventTimeline', () => {
beforeEach(() => {
;(useGetTimelinesByEventQuery as jest.Mock).mockReturnValue({
Expand Down
41 changes: 14 additions & 27 deletions src/components/elements/Timeline/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import React from 'react'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin from '@fullcalendar/interaction'
import Modal from '@mui/material/Modal'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import { useGetTimelinesByEventQuery } from '@/redux/api/timelineApi'
import { EventApi } from '@fullcalendar/core/index.js'
import FullCalendar from '@fullcalendar/react'
import TimelineDetailsModal from './TimelineDetailsModal'

interface DemoAppProps {
eventId: string
Expand Down Expand Up @@ -51,14 +49,12 @@ const DemoApp: React.FC<DemoAppProps> = ({ eventId }) => {
p: 4,
}



if (isLoading) {
return (
<div className="flex flex-col justify-center items-center min-h-[90vh]">
<div data-testid="loader" className="loader"></div>
</div>
);
)
}

return (
Expand All @@ -77,27 +73,18 @@ const DemoApp: React.FC<DemoAppProps> = ({ eventId }) => {
eventColor="#14b8a6"
displayEventTime={false}
/>
<Modal
open={showModal}
onClose={handleCloseModal}
aria-labelledby="event-modal-title"
aria-describedby="event-modal-description"
>
<Box sx={style}>
<Typography id="modal-modal-title" variant="h6" component="h2">
Task Details
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Task title: {clickedEvent?.title}
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Start date: {clickedEvent?.start?.toLocaleTimeString()}
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
End date: {clickedEvent?.end?.toLocaleTimeString()}
</Typography>
</Box>
</Modal>
{clickedEvent && (
<TimelineDetailsModal
timelineId={clickedEvent.id}
onClose={handleCloseModal}
showModal={showModal}
clickedEvent={{
title: clickedEvent.title,
start: new Date(clickedEvent.startStr),
end: new Date(clickedEvent.endStr)
}}
/>
)}
</div>
</div>
)
Expand Down
86 changes: 86 additions & 0 deletions src/components/elements/Timeline/TimelineDetailsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import { useDeleteTimelineMutation } from '@/redux/api/timelineApi';
import Modal from '@mui/material/Modal';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';

interface TimelineDetailsModalProps {
timelineId: string;
onClose: () => void;
showModal: boolean;
clickedEvent: {
title: string;
start: Date;
end: Date;
};
}

const style = {
position: 'absolute' as 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};

const TimelineDetailsModal: React.FC<TimelineDetailsModalProps> = ({ timelineId, onClose, showModal, clickedEvent }) => {
const [deleteTimeline, { isLoading, isSuccess}] = useDeleteTimelineMutation();

const handleDelete = async () => {
if (window.confirm('Are you sure you want to delete this timeline?')) {
try {
await deleteTimeline({ id: timelineId });
onClose();
} catch (error) {
console.error('Failed to delete the timeline:', error);
alert('There was a problem deleting the timeline.');
}
}
};

React.useEffect(() => {
if (isSuccess) {
onClose();
}
}, [isSuccess, onClose]);


return (
<Modal
open={showModal}
onClose={onClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<Typography id="modal-modal-title" variant="h6" component="h2">
Task Details
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Task title: {clickedEvent?.title}
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Start date: {clickedEvent?.start.toLocaleTimeString()}
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
End date: {clickedEvent?.end.toLocaleTimeString()}
</Typography>
<div style={{ marginTop: 20 }}>
<Button variant="outlined" color="error" onClick={handleDelete} disabled={isLoading}>
Delete Timeline
</Button>
<Button variant="outlined" style={{ marginLeft: 10 }} onClick={onClose}>
Close
</Button>
</div>
</Box>
</Modal>
);
};

export default TimelineDetailsModal;
8 changes: 8 additions & 0 deletions src/redux/api/timelineApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,19 @@ export const timelineApi = baseApi.injectEndpoints({
}),
providesTags: ['Timeline'],
}),
deleteTimeline: builder.mutation<void, { id: string }>({
query: ({ id }) => ({
url: `/timelines/${id}/delete/`,
method: 'DELETE',
}),
invalidatesTags: (_, __, arg) => [{ type: 'Timeline', id: arg.id }],
}),
}),
})

export const {
useGetTimelinesByEventQuery,
useCreateTimelineMutation,
useModifyDetailTimelineMutation,
useDeleteTimelineMutation,
} = timelineApi

0 comments on commit 2bada46

Please sign in to comment.