tsk-7: Schedule message (#8)

Closes #7

Reviewed-on: phoenix/textsender#8
This commit was merged in pull request #8.
This commit is contained in:
2026-06-30 12:13:52 -04:00
parent 833a044ff6
commit f2bdb60d55
10 changed files with 378 additions and 37 deletions
@@ -5,14 +5,18 @@ 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,
});
@@ -25,12 +29,28 @@ const useSendMessageWizard = () => {
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.step,
state.selectedContacts.length,
state.message,
state.scheduledTime,
]);
const canGoBack = state.step !== 'select';
@@ -44,6 +64,14 @@ const useSendMessageWizard = () => {
}));
};
const toggleScheduled = (scheduled) => {
console.log('Yup');
setState((prev) => ({
...prev,
isScheduled: scheduled,
}));
};
const setMessage = (message) => {
setState((prev) => ({ ...prev, message }));
};
@@ -53,29 +81,67 @@ const useSendMessageWizard = () => {
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', 'confirm', 'result'];
const stepOrder = ['select', 'message', 'schedule', 'confirm', 'result'];
const currentIndex = stepOrder.indexOf(state.step);
if (currentIndex < stepOrder.length - 1) {
setState((prev) => ({
...prev,
step: stepOrder[currentIndex + 1],
submissionError: null,
}));
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', 'confirm', 'result'];
const stepOrder = ['select', 'message', 'schedule', 'confirm', 'result'];
const currentIndex = stepOrder.indexOf(state.step);
if (currentIndex > 0) {
setState((prev) => ({
...prev,
step: stepOrder[currentIndex - 1],
submissionError: null,
}));
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,
}));
}
}
};
@@ -91,25 +157,77 @@ const useSendMessageWizard = () => {
}));
try {
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 (state.scheduledTime != null) {
console.log('Going to schedule message');
if (response) {
// Success - move to result step
setState((prev) => ({
...prev,
step: 'result',
isSubmitting: false,
}));
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') {
@@ -121,6 +239,8 @@ const useSendMessageWizard = () => {
...prev,
submissionError: error.message || 'Failed to send messages',
isSubmitting: false,
isScheduled: false,
scheduledTime: null,
}));
}
};
@@ -130,9 +250,11 @@ const useSendMessageWizard = () => {
setState({
step: 'select',
selectedContacts: [],
scheduledTime: null,
message: '',
createdMessage: null,
isSubmitting: false,
isScheduled: false,
submissionError: null,
});
};
@@ -146,17 +268,21 @@ const useSendMessageWizard = () => {
// 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,