152 lines
4.9 KiB
TypeScript
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;
|
|
});
|
|
});
|