import { createReducer, createAction } from '@reduxjs/toolkit'; import { Job, JobOffer } from '@app-types/index'; import { JobStatus } from '@utils/constants'; import { acceptJobThunk, rejectJobThunk, confirmPickupThunk, confirmDeliveryThunk } from './thunk'; export interface JobState { activeJob: Job | null; jobStatus: JobStatus; newJobOffer: JobOffer | null; jobHistory: Job[]; loading: boolean; error: string | null; } const initialState: JobState = { activeJob: null, jobStatus: JobStatus.Idle, newJobOffer: null, jobHistory: [], loading: false, error: null, }; export const setNewJobOffer = createAction('job/setNewJobOffer'); export const acceptJobSync = createAction('job/acceptJobSync'); export const rejectJobSync = createAction('job/rejectJobSync'); export const advanceJobStatus = createAction('job/advanceJobStatus'); export const completeJob = createAction('job/completeJob'); export const clearJob = createAction('job/clearJob'); export const setJobHistory = createAction('job/setJobHistory'); export const jobReducer = createReducer(initialState, (builder) => { builder // Sync Actions .addCase(setNewJobOffer, (state, action) => { state.newJobOffer = action.payload; state.jobStatus = JobStatus.NewRequest; }) .addCase(acceptJobSync, (state) => { if (state.newJobOffer) { state.activeJob = { ...state.newJobOffer, orderId: `#ORD${Date.now().toString().slice(-6)}`, status: JobStatus.Accepted, acceptedAt: new Date().toISOString(), collectAmount: state.newJobOffer.paymentType === 'cod' ? state.newJobOffer.amount : 0, }; state.jobStatus = JobStatus.Accepted; state.newJobOffer = null; } }) .addCase(rejectJobSync, (state) => { state.newJobOffer = null; state.jobStatus = JobStatus.Idle; }) .addCase(advanceJobStatus, (state, action) => { state.jobStatus = action.payload; if (state.activeJob) { state.activeJob.status = action.payload; if (action.payload === JobStatus.PickedUp) { state.activeJob.pickedUpAt = new Date().toISOString(); } } }) .addCase(completeJob, (state) => { if (state.activeJob) { const completedJob: Job = { ...state.activeJob, status: JobStatus.Delivered, deliveredAt: new Date().toISOString(), }; state.jobHistory = [completedJob, ...state.jobHistory]; } state.activeJob = null; state.jobStatus = JobStatus.Idle; }) .addCase(clearJob, (state) => { state.activeJob = null; state.newJobOffer = null; state.jobStatus = JobStatus.Idle; }) .addCase(setJobHistory, (state, action) => { state.jobHistory = action.payload; }) // Async Thunks .addCase(acceptJobThunk.pending, (state) => { state.loading = true; state.error = null; }) .addCase(acceptJobThunk.fulfilled, (state, action) => { state.loading = false; state.activeJob = action.payload; state.jobStatus = JobStatus.Accepted; state.newJobOffer = null; }) .addCase(acceptJobThunk.rejected, (state, action) => { state.loading = false; state.error = action.payload as string; }) .addCase(rejectJobThunk.pending, (state) => { state.loading = true; state.error = null; }) .addCase(rejectJobThunk.fulfilled, (state) => { state.loading = false; state.newJobOffer = null; state.jobStatus = JobStatus.Idle; }) .addCase(rejectJobThunk.rejected, (state, action) => { state.loading = false; state.error = action.payload as string; }) .addCase(confirmPickupThunk.pending, (state) => { state.loading = true; state.error = null; }) .addCase(confirmPickupThunk.fulfilled, (state) => { state.loading = false; state.jobStatus = JobStatus.PickedUp; if (state.activeJob) { state.activeJob.status = JobStatus.PickedUp; state.activeJob.pickedUpAt = new Date().toISOString(); } }) .addCase(confirmPickupThunk.rejected, (state, action) => { state.loading = false; state.error = action.payload as string; }) .addCase(confirmDeliveryThunk.pending, (state) => { state.loading = true; state.error = null; }) .addCase(confirmDeliveryThunk.fulfilled, (state) => { state.loading = false; // Complete Job logic can be triggered here or separately if (state.activeJob) { const completedJob: Job = { ...state.activeJob, status: JobStatus.Delivered, deliveredAt: new Date().toISOString(), }; state.jobHistory = [completedJob, ...state.jobHistory]; } state.activeJob = null; state.jobStatus = JobStatus.Idle; }) .addCase(confirmDeliveryThunk.rejected, (state, action) => { state.loading = false; state.error = action.payload as string; }); });