328 lines
12 KiB
TypeScript
328 lines
12 KiB
TypeScript
import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
|
|
import { toast } from 'react-toastify';
|
|
import colors from '../../utlity/colorsArr';
|
|
import api from '../../config/api';
|
|
|
|
export enum recipientType {
|
|
SIGNER = "Signer",
|
|
INPERSONSIGNER = "InPersonSigner",
|
|
CC = "CC"
|
|
}
|
|
|
|
export interface Recipient {
|
|
id?: string | null;
|
|
firstName: string;
|
|
lastName: string;
|
|
routingOrder: number;
|
|
email: string;
|
|
hostName: string;
|
|
hostEmail: string;
|
|
type: recipientType;
|
|
color?: string;
|
|
allowSenderToEdit: boolean;
|
|
allowSenderToDelete: boolean;
|
|
roleName: string
|
|
provideOwnTags?: boolean;
|
|
uuid?: string;
|
|
newOne?: boolean;
|
|
completed?: boolean;
|
|
}
|
|
|
|
export interface SelectedRecipientInt {
|
|
recipients: Recipient[],
|
|
signingOrder: boolean,
|
|
transactionTemplateToggle: TRANSACTION_TEMPLATE_TOGGLE
|
|
}
|
|
|
|
interface AddRecipientArgs {
|
|
recipientsData: Recipient[];
|
|
accountId: string;
|
|
transactionId: string;
|
|
transactionTemplateToggle: TRANSACTION_TEMPLATE_TOGGLE;
|
|
}
|
|
|
|
interface RemoveRecipientAsyncInterface {
|
|
recipientId: number | null;
|
|
accountId: string;
|
|
transactionId: string;
|
|
email: string;
|
|
transactionTemplateToggle: TRANSACTION_TEMPLATE_TOGGLE;
|
|
}
|
|
|
|
export enum TRANSACTION_TEMPLATE_TOGGLE {
|
|
TRANSACTIONS = "transactions",
|
|
TEMPLATES = "templates"
|
|
}
|
|
|
|
const initialState: SelectedRecipientInt = {
|
|
recipients: [],
|
|
signingOrder: false,
|
|
transactionTemplateToggle: TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS
|
|
};
|
|
|
|
// 1. Add Recipient Async
|
|
export const addRecipientAsync = createAsyncThunk<
|
|
Recipient[],
|
|
{ recipientsData: Recipient[]; accountId: string; transactionId: string }
|
|
>(
|
|
'selectedRecipients/addRecipientAsync',
|
|
async ({ recipientsData, accountId, transactionId }, { rejectWithValue, getState }) => {
|
|
try {
|
|
const state = getState() as { selectedRecipients: SelectedRecipientInt };
|
|
const toggle = state.selectedRecipients.transactionTemplateToggle;
|
|
|
|
const updateRecipientsData = recipientsData.filter(recipient => recipient.id != null);
|
|
const createRecipientsData = recipientsData.filter(recipient => recipient.id == null);
|
|
|
|
const basePath = `/api/v1/accounts/${accountId}/${toggle}/${transactionId}/recipients`;
|
|
|
|
const resUpdate = updateRecipientsData.length
|
|
? await api.put(basePath, updateRecipientsData)
|
|
: { data: [] };
|
|
|
|
const resCreate = createRecipientsData.length
|
|
? await api.post(basePath, createRecipientsData)
|
|
: { data: [] };
|
|
|
|
return [...resCreate.data, ...resUpdate.data] as Recipient[];
|
|
} catch (err: any) {
|
|
return rejectWithValue(err.response?.data || "Failed to add recipient");
|
|
}
|
|
}
|
|
);
|
|
|
|
// 2. Remove Recipient Async
|
|
export const removeRecipientAsync = createAsyncThunk<
|
|
string | number,
|
|
{ recipientId: number | null; accountId: string; transactionId: string; email: string }
|
|
>(
|
|
'selectedRecipients/removeRecipientAsync',
|
|
async ({ recipientId, accountId, transactionId, email }, { rejectWithValue, getState }) => {
|
|
try {
|
|
const state = getState() as { selectedRecipients: SelectedRecipientInt };
|
|
const toggle = state.selectedRecipients.transactionTemplateToggle;
|
|
|
|
const basePath = `/api/v1/accounts/${accountId}/${toggle}/${transactionId}/recipients`;
|
|
|
|
// return
|
|
if (recipientId) {
|
|
await api.delete(`${basePath}/${recipientId}`);
|
|
return recipientId;
|
|
}
|
|
|
|
return email;
|
|
} catch (err: any) {
|
|
return rejectWithValue("Failed to remove recipient");
|
|
}
|
|
}
|
|
);
|
|
|
|
// 3. Fetch Recipients Async
|
|
export const fetchRecipients = createAsyncThunk<
|
|
Recipient[],
|
|
{ accountId: string; transactionId: string }
|
|
>(
|
|
'selectedRecipients/fetchRecipients',
|
|
async ({ accountId, transactionId }, { rejectWithValue, getState }) => {
|
|
try {
|
|
const state = getState() as { selectedRecipients: SelectedRecipientInt };
|
|
const toggle = state.selectedRecipients.transactionTemplateToggle;
|
|
|
|
const basePath = `/api/v1/accounts/${accountId}/${toggle}/${transactionId}/recipients`;
|
|
const response = await api.get(basePath);
|
|
|
|
let data = response.data as Recipient[];
|
|
|
|
// data = data.filter((recipient, indx) => {
|
|
// return recipient.type != "CC";
|
|
// })
|
|
|
|
// if (data.length == 0 && window.location.pathname.includes('/review-and-tag')) {
|
|
// window.location.href = window.location.href.replace("review-and-tag", "setup-transaction") // ✅ navigate using window
|
|
// }
|
|
|
|
return data as Recipient[];
|
|
} catch (err: any) {
|
|
return rejectWithValue(err.response?.data || "Failed to fetch recipients");
|
|
}
|
|
}
|
|
);
|
|
|
|
const selectedRecipientsSlice = createSlice({
|
|
name: 'selectedRecipients',
|
|
initialState,
|
|
reducers: {
|
|
addRecipient: (state, action: PayloadAction<Recipient>) => {
|
|
if (action.payload.type == recipientType.INPERSONSIGNER) {
|
|
state.signingOrder = true;
|
|
state.recipients = [action.payload, ...state.recipients];
|
|
} else {
|
|
state.recipients.push(action.payload);
|
|
}
|
|
},
|
|
resetRecipients: (state) => {
|
|
state.recipients = [];
|
|
},
|
|
toggleToTemplates: (state) => {
|
|
state.transactionTemplateToggle = TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES;
|
|
},
|
|
setSelectedRecipients: (state, action: PayloadAction<Recipient[]>) => {
|
|
for (const [index, recipient] of action.payload.entries()) {
|
|
if ((recipient.type == recipientType.INPERSONSIGNER && index > 0)
|
|
&& action.payload[index - 1].type != recipientType.INPERSONSIGNER) {
|
|
return state;
|
|
}
|
|
}
|
|
|
|
state.recipients = action.payload;
|
|
},
|
|
setSigningOrder: (state, action: PayloadAction<boolean>) => {
|
|
for (const recipient of state.recipients) {
|
|
if (recipient.type == recipientType.INPERSONSIGNER) {
|
|
if (state.signingOrder) return state;
|
|
state.signingOrder = true;
|
|
return state;
|
|
}
|
|
}
|
|
|
|
state.signingOrder = action.payload;
|
|
},
|
|
removeSelectedRecipient: (state, action: PayloadAction<Recipient>) => {
|
|
state.recipients = state.recipients.filter((recipient) => recipient.uuid != action.payload.uuid);
|
|
},
|
|
removeAllRecipients: (state) => {
|
|
state.recipients = [];
|
|
},
|
|
addColorsToRecipient: (state) => {
|
|
for (const [index, recipient] of state.recipients.entries()) {
|
|
recipient.color = colors[index];
|
|
}
|
|
return state;
|
|
},
|
|
updateRecipientOrder: (state, action: PayloadAction<{ id: string; routingOrder: number }>) => {
|
|
const { id, routingOrder } = action.payload;
|
|
const recipient = state.recipients.find((r) => r.id == id || r.uuid == id);
|
|
if (recipient) {
|
|
recipient.routingOrder = routingOrder;
|
|
}
|
|
},
|
|
reorderAllRecipientAscOrder: (state) => {
|
|
state.recipients = state.recipients.sort((a, b) => a.routingOrder - b.routingOrder);
|
|
},
|
|
updateRecipientByIndxAndRo: (state, action: PayloadAction<{ indx1: number; ro1: number, indx2: number; ro2: number }>) => {
|
|
const indx1 = action.payload.indx1
|
|
const indx2 = action.payload.indx2
|
|
const ro1 = action.payload.ro1
|
|
const ro2 = action.payload.ro2
|
|
|
|
const temp = { ...state.recipients[indx1], routingOrder: ro1 };
|
|
state.recipients[indx1] = { ...state.recipients[indx2], routingOrder: ro2 };
|
|
state.recipients[indx2] = temp;
|
|
},
|
|
updateRecipientIds: (state, action: PayloadAction<Recipient[]>) => {
|
|
for (const recObj of state.recipients) {
|
|
for (const recObj2 of action.payload) {
|
|
recObj.id = recObj2.id;
|
|
}
|
|
}
|
|
},
|
|
updateRecipient(state, action: PayloadAction<Recipient>) {
|
|
const payloadUuid = String(action.payload.uuid);
|
|
|
|
// First try matching by id
|
|
let index = state.recipients.findIndex(
|
|
r => String(r.id) == payloadUuid
|
|
);
|
|
|
|
// If not found, try matching by uuid
|
|
if (index == -1) {
|
|
index = state.recipients.findIndex(
|
|
r => String(r.uuid) == payloadUuid
|
|
);
|
|
}
|
|
|
|
if (index != -1) {
|
|
// Merge existing recipient with new values
|
|
state.recipients[index] = {
|
|
...state.recipients[index],
|
|
...action.payload
|
|
};
|
|
} else {
|
|
console.warn('Recipient not found with uuid:', payloadUuid);
|
|
}
|
|
}
|
|
|
|
|
|
,
|
|
|
|
resetSelRecipient: () => initialState
|
|
},
|
|
extraReducers: (builder) => {
|
|
builder
|
|
.addCase(fetchRecipients.pending, () => { })
|
|
.addCase(fetchRecipients.fulfilled, (state, action: PayloadAction<Recipient[]>) => {
|
|
const assignedRecipients = action.payload.map((recipient, index) => ({
|
|
...recipient,
|
|
color: colors[index],
|
|
}));
|
|
state.recipients = assignedRecipients;
|
|
})
|
|
.addCase(fetchRecipients.rejected, (state, action) => {
|
|
console.error("Failed to fetch recipients:", action.payload);
|
|
// toast.error("Failed to fetch recipients", {
|
|
// position: "bottom-right",
|
|
// autoClose: 5000,
|
|
// theme: "light",
|
|
// });
|
|
})
|
|
.addCase(addRecipientAsync.pending, () => { })
|
|
.addCase(addRecipientAsync.fulfilled, (state, action: PayloadAction<Recipient[]>) => {
|
|
state.recipients = action.payload.map((recipient, index) => ({
|
|
...recipient,
|
|
color: colors[index % colors.length],
|
|
}));
|
|
})
|
|
.addCase(addRecipientAsync.rejected, (state, action) => {
|
|
console.error("Failed to add recipients:", action.payload);
|
|
// toast.error("Failed to add recipients", {
|
|
// position: "bottom-right",
|
|
// autoClose: 5000,
|
|
// theme: "light",
|
|
// });
|
|
})
|
|
.addCase(removeRecipientAsync.pending, () => { })
|
|
.addCase(removeRecipientAsync.fulfilled, (state, action: PayloadAction<string | number>) => {
|
|
state.recipients = state.recipients.filter(
|
|
(recipient) => recipient.id != action.payload && recipient.email != action.payload
|
|
);
|
|
})
|
|
.addCase(removeRecipientAsync.rejected, (state, action) => {
|
|
console.error("Failed to delete recipient:", action.payload);
|
|
// toast.error("Failed to delete recipient", {
|
|
// position: "bottom-right",
|
|
// autoClose: 5000,
|
|
// theme: "light",
|
|
// });
|
|
});
|
|
}
|
|
});
|
|
|
|
export const {
|
|
addRecipient,
|
|
setSelectedRecipients,
|
|
toggleToTemplates,
|
|
removeSelectedRecipient,
|
|
removeAllRecipients,
|
|
setSigningOrder,
|
|
addColorsToRecipient,
|
|
updateRecipientIds,
|
|
resetSelRecipient,
|
|
updateRecipientOrder,
|
|
updateRecipient,
|
|
resetRecipients,
|
|
reorderAllRecipientAscOrder,
|
|
updateRecipientByIndxAndRo
|
|
} = selectedRecipientsSlice.actions;
|
|
|
|
export default selectedRecipientsSlice.reducer;
|