295 lines
7.6 KiB
JavaScript
295 lines
7.6 KiB
JavaScript
import { useState, useCallback, useRef } from 'react';
|
|
|
|
import { tokenService } from '../../services/TokenService';
|
|
import {
|
|
sendMessageApi,
|
|
SendInstantMessageRequest,
|
|
} from '../../api/sendMessageApi';
|
|
import { scheduleApi } from '../../api/scheduleApi.js';
|
|
import { scheduleEventApi } from '../../api/scheduleEventApi.js';
|
|
|
|
const useSendMessageWizard = () => {
|
|
const [state, setState] = useState({
|
|
step: 'select',
|
|
selectedContacts: [],
|
|
scheduledTime: null,
|
|
message: '',
|
|
createdMessage: null,
|
|
isSubmitting: false,
|
|
isScheduled: false,
|
|
submissionError: null,
|
|
});
|
|
|
|
const abortControllerRef = useRef(null);
|
|
|
|
// Computed values
|
|
const canProceedToNextStep = useCallback(() => {
|
|
switch (state.step) {
|
|
case 'select':
|
|
return state.selectedContacts.length > 0;
|
|
case 'message':
|
|
return state.message.trim().length > 0;
|
|
case 'schedule':
|
|
console.log('Checking to see if schedule can go to the next step');
|
|
if (state.scheduledTime == null) {
|
|
return false;
|
|
}
|
|
console.log('Scheduled time is not null');
|
|
const result =
|
|
state.scheduledTime instanceof Date &&
|
|
isNaN(state.scheduledTime.getTime());
|
|
|
|
return !result;
|
|
case 'confirm':
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}, [
|
|
state.step,
|
|
state.selectedContacts.length,
|
|
state.message,
|
|
state.scheduledTime,
|
|
]);
|
|
|
|
const canGoBack = state.step !== 'select';
|
|
|
|
// Actions
|
|
const toggleContact = (contactId) => {
|
|
setState((prev) => ({
|
|
...prev,
|
|
selectedContacts: prev.selectedContacts.includes(contactId)
|
|
? prev.selectedContacts.filter((id) => id !== contactId)
|
|
: [...prev.selectedContacts, contactId],
|
|
}));
|
|
};
|
|
|
|
const toggleScheduled = (scheduled) => {
|
|
console.log('Yup');
|
|
setState((prev) => ({
|
|
...prev,
|
|
isScheduled: scheduled,
|
|
}));
|
|
};
|
|
|
|
const setMessage = (message) => {
|
|
setState((prev) => ({ ...prev, message }));
|
|
};
|
|
|
|
const setCreatedMessage = (message) => {
|
|
console.log('Setting created message');
|
|
setState((prev) => ({ ...prev, createdMessage: message }));
|
|
};
|
|
|
|
const setScheduledTime = (selectedTime) => {
|
|
console.log('Setting scheduled time');
|
|
setState((prev) => ({ ...prev, scheduledTime: selectedTime }));
|
|
};
|
|
|
|
const nextStep = () => {
|
|
if (!canProceedToNextStep()) return;
|
|
|
|
const stepOrder = ['select', 'message', 'schedule', 'confirm', 'result'];
|
|
const currentIndex = stepOrder.indexOf(state.step);
|
|
if (currentIndex < stepOrder.length - 1) {
|
|
if (state.step === 'message') {
|
|
if (state.isScheduled) {
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: stepOrder[currentIndex + 1],
|
|
submissionError: null,
|
|
}));
|
|
} else {
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: stepOrder[currentIndex + 2],
|
|
submissionError: null,
|
|
}));
|
|
}
|
|
} else {
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: stepOrder[currentIndex + 1],
|
|
submissionError: null,
|
|
}));
|
|
}
|
|
}
|
|
};
|
|
|
|
const prevStep = () => {
|
|
const stepOrder = ['select', 'message', 'schedule', 'confirm', 'result'];
|
|
const currentIndex = stepOrder.indexOf(state.step);
|
|
|
|
if (currentIndex > 0) {
|
|
if (state.step === 'confirm') {
|
|
if (state.isScheduled) {
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: stepOrder[currentIndex - 1],
|
|
submissionError: null,
|
|
}));
|
|
} else {
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: stepOrder[currentIndex - 2],
|
|
submissionError: null,
|
|
}));
|
|
}
|
|
} else {
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: stepOrder[currentIndex - 1],
|
|
submissionError: null,
|
|
}));
|
|
}
|
|
}
|
|
};
|
|
|
|
const submit = async () => {
|
|
if (state.isSubmitting) return;
|
|
|
|
abortControllerRef.current = new AbortController();
|
|
|
|
setState((prev) => ({
|
|
...prev,
|
|
isSubmitting: true,
|
|
submissionError: null,
|
|
}));
|
|
|
|
try {
|
|
if (state.scheduledTime != null) {
|
|
console.log('Going to schedule message');
|
|
|
|
const schMsgReq = {
|
|
scheduled: state.scheduledTime.toISOString(),
|
|
status: 'PENDING',
|
|
user_id: tokenService.getUserId(),
|
|
};
|
|
|
|
const token = tokenService.bearerToken();
|
|
const schMsgResponse = await scheduleApi.scheduleMessage(
|
|
schMsgReq,
|
|
token
|
|
);
|
|
|
|
if (schMsgResponse) {
|
|
console.log('Message scheduled');
|
|
|
|
const scheduledMessageId = schMsgResponse.data[0].id;
|
|
for (let contact of state.selectedContacts) {
|
|
let schMsgEvtReq = {
|
|
contact_id: contact,
|
|
message_id: state.createdMessage.id,
|
|
scheduled_message_id: scheduledMessageId,
|
|
};
|
|
|
|
const schMsgEvtResponse =
|
|
await scheduleEventApi.scheduleMessageEvent(schMsgEvtReq, token);
|
|
}
|
|
|
|
console.log('Updating message status');
|
|
const req = {
|
|
scheduled_message_id: scheduledMessageId,
|
|
status: 'READY',
|
|
};
|
|
console.log(req);
|
|
const response = await scheduleApi.prepareMessage(req, token);
|
|
if (response) {
|
|
console.log('Message scheduled');
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: 'result',
|
|
isSubmitting: false,
|
|
isScheduled: false,
|
|
scheduledTime: null,
|
|
}));
|
|
}
|
|
}
|
|
} else {
|
|
console.log('Sending message');
|
|
let reqBod = new SendInstantMessageRequest();
|
|
reqBod.user_id = tokenService.getUserId();
|
|
reqBod.message_id = state.createdMessage.id;
|
|
state.selectedContacts.forEach((selectedContact) => {
|
|
reqBod.contact_ids.push(selectedContact);
|
|
});
|
|
const response = await sendMessageApi.sendInstantMessage(
|
|
reqBod,
|
|
tokenService.bearerToken()
|
|
);
|
|
|
|
if (response) {
|
|
// Success - move to result step
|
|
setState((prev) => ({
|
|
...prev,
|
|
step: 'result',
|
|
isSubmitting: false,
|
|
isScheduled: false,
|
|
scheduledTime: null,
|
|
}));
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error.name === 'AbortError') {
|
|
console.log('Submission was aborted');
|
|
return;
|
|
}
|
|
|
|
setState((prev) => ({
|
|
...prev,
|
|
submissionError: error.message || 'Failed to send messages',
|
|
isSubmitting: false,
|
|
isScheduled: false,
|
|
scheduledTime: null,
|
|
}));
|
|
}
|
|
};
|
|
|
|
const reset = () => {
|
|
abortControllerRef.current?.abort();
|
|
setState({
|
|
step: 'select',
|
|
selectedContacts: [],
|
|
scheduledTime: null,
|
|
message: '',
|
|
createdMessage: null,
|
|
isSubmitting: false,
|
|
isScheduled: false,
|
|
submissionError: null,
|
|
});
|
|
};
|
|
|
|
// Cleanup
|
|
const cleanup = () => {
|
|
abortControllerRef.current?.abort();
|
|
};
|
|
|
|
return {
|
|
// Getters
|
|
currentStep: state.step,
|
|
selectedContacts: state.selectedContacts,
|
|
scheduledTime: state.scheduledTime,
|
|
message: state.message,
|
|
createdMessage: state.createdMessage,
|
|
isSubmitting: state.isSubmitting,
|
|
isScheduled: state.isScheduled,
|
|
submissionError: state.submissionError,
|
|
canProceedToNextStep: canProceedToNextStep(),
|
|
canGoBack,
|
|
|
|
// Actions
|
|
toggleContact,
|
|
toggleScheduled,
|
|
setMessage,
|
|
setCreatedMessage,
|
|
setScheduledTime,
|
|
nextStep,
|
|
prevStep,
|
|
submit,
|
|
reset,
|
|
cleanup,
|
|
};
|
|
};
|
|
|
|
export default useSendMessageWizard;
|