diff --git a/src/app/services/tasksApi.ts b/src/app/services/tasksApi.ts index 5cd678f48..4cab3fce2 100644 --- a/src/app/services/tasksApi.ts +++ b/src/app/services/tasksApi.ts @@ -3,6 +3,8 @@ import task, { TasksResponseType, GetAllTaskParamType, ExtensionRequestsResponse, + ExtensionRequestCreatePayload, + ExtensionRequestCreateResponse, } from '@/interfaces/task.type'; import { api } from './api'; import { MINE_TASKS_URL, TASKS_URL } from '@/constants/url'; @@ -114,6 +116,21 @@ export const tasksApi = api.injectEndpoints({ }), providesTags: ['Extension_Requests'], }), + createExtensionRequest: builder.mutation< + ExtensionRequestCreateResponse, + ExtensionRequestCreatePayload & { dev?: boolean } + >({ + query: (payload) => ({ + url: '/extension-requests', + method: 'POST', + params: { dev: payload.dev ?? true }, + body: (() => { + const { dev, ...requestPayload } = payload; + return requestPayload; + })(), + }), + invalidatesTags: ['Extension_Requests'], + }), }), overrideExisting: true, }); @@ -125,4 +142,5 @@ export const { useUpdateTaskMutation, useUpdateSelfTaskMutation, useGetSelfExtensionRequestsQuery, + useCreateExtensionRequestMutation, } = tasksApi; diff --git a/src/components/ExtensionRequest/ExtensionRequestForm.tsx b/src/components/ExtensionRequest/ExtensionRequestForm.tsx new file mode 100644 index 000000000..c41d941ce --- /dev/null +++ b/src/components/ExtensionRequest/ExtensionRequestForm.tsx @@ -0,0 +1,216 @@ +import React, { useState, useEffect } from 'react'; +import styles from './Form.module.scss'; +import { useCreateExtensionRequestMutation } from '@/app/services/tasksApi'; +import { toast, ToastTypes } from '@/helperFunctions/toast'; +import { + EXTENSION_REQUEST_SUCCESS_MESSAGE, + EXTENSION_REQUEST_ERROR_MESSAGE, +} from '@/constants/constants'; + +interface ExtensionRequestFormProps { + isOpen: boolean; + onClose: () => void; + taskId: string; + assignee: string; + oldEndsOn: number | null; +} + +interface FormData { + reason: string; + newEndsOn: number; + title: string; +} + +const { SUCCESS, ERROR } = ToastTypes; + +const formatDateForInput = (timestamp: number) => + new Date(timestamp).toISOString().slice(0, 16); + +const getOldEndsOnDate = (oldEndsOn: number | null) => + oldEndsOn + ? new Date(oldEndsOn).toLocaleDateString('en-US', { + month: 'numeric', + day: 'numeric', + year: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + hour12: true, + }) + : 'Not available'; + +export function ExtensionRequestForm({ + isOpen, + onClose, + taskId, + assignee, + oldEndsOn, +}: ExtensionRequestFormProps) { + const [formData, setFormData] = useState({ + reason: '', + newEndsOn: new Date().getTime(), + title: '', + }); + + const [etaError, setEtaError] = useState(false); + const [createExtensionRequest, { isLoading }] = + useCreateExtensionRequestMutation(); + + useEffect(() => { + if (isOpen) { + const defaultNewEndsOn = oldEndsOn + ? oldEndsOn + 3 * 24 * 60 * 60 * 1000 + : new Date().getTime(); + setFormData((prev) => ({ ...prev, newEndsOn: defaultNewEndsOn })); + setEtaError(false); + } + }, [isOpen, oldEndsOn]); + + const handleChange = ( + e: React.ChangeEvent + ) => { + const { name, value } = e.target; + + if (name === 'newEndsOn') { + const timestamp = new Date(value).getTime(); + setFormData((prev) => ({ ...prev, [name]: timestamp })); + + if (oldEndsOn && timestamp <= oldEndsOn) { + setEtaError(true); + } else { + setEtaError(false); + } + } else { + setFormData((prev) => ({ ...prev, [name]: value })); + } + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + const submissionOldEndsOn = oldEndsOn || new Date().getTime(); + + try { + await createExtensionRequest({ + assignee: assignee, + newEndsOn: Math.floor(formData.newEndsOn / 1000), + oldEndsOn: submissionOldEndsOn, + reason: formData.reason, + status: 'PENDING', + taskId, + title: formData.title, + dev: true, + }).unwrap(); + + toast(SUCCESS, EXTENSION_REQUEST_SUCCESS_MESSAGE); + onClose(); + } catch (error: any) { + toast( + ERROR, + error?.data?.message ?? EXTENSION_REQUEST_ERROR_MESSAGE + ); + } + }; + + if (!isOpen) return null; + + const oldEndsOnDate = getOldEndsOnDate(oldEndsOn); + + return ( +
+
+

+ Extension Request Form +

+
+
+ +