152 lines
4.9 KiB
TypeScript

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<JobOffer>('job/setNewJobOffer');
export const acceptJobSync = createAction('job/acceptJobSync');
export const rejectJobSync = createAction('job/rejectJobSync');
export const advanceJobStatus = createAction<JobStatus>('job/advanceJobStatus');
export const completeJob = createAction('job/completeJob');
export const clearJob = createAction('job/clearJob');
export const setJobHistory = createAction<Job[]>('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;
});
});