Files
schedtxt/src/components/SendMessageWizard/useSendMessageWizard.js
T
phoenixandphoenix 34644d1cd2 tsk-6: Send Message (#22)
Closes #6

Reviewed-on: phoenix/textsender#22
Co-authored-by: phoenix <kundeng00@pm.me>
Co-committed-by: phoenix <kundeng00@pm.me>
2026-01-04 00:21:22 +00:00

169 lines
4.1 KiB
JavaScript

import { useState, useCallback, useRef } from 'react';
import { tokenService } from '../../services/TokenService';
import {
sendMessageApi,
SendInstantMessageRequest,
} from '../../api/sendMessageApi';
const useSendMessageWizard = () => {
const [state, setState] = useState({
step: 'select',
selectedContacts: [],
message: '',
createdMessage: null,
isSubmitting: 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 'confirm':
return true;
default:
return false;
}
}, [state.step, state.selectedContacts.length, state.message]);
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 setMessage = (message) => {
setState((prev) => ({ ...prev, message }));
};
const setCreatedMessage = (message) => {
console.log('Setting created message');
setState((prev) => ({ ...prev, createdMessage: message }));
};
const nextStep = () => {
if (!canProceedToNextStep()) return;
const stepOrder = ['select', 'message', 'confirm', 'result'];
const currentIndex = stepOrder.indexOf(state.step);
if (currentIndex < stepOrder.length - 1) {
setState((prev) => ({
...prev,
step: stepOrder[currentIndex + 1],
submissionError: null,
}));
}
};
const prevStep = () => {
const stepOrder = ['select', 'message', 'confirm', 'result'];
const currentIndex = stepOrder.indexOf(state.step);
if (currentIndex > 0) {
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 {
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,
}));
}
} catch (error) {
if (error.name === 'AbortError') {
console.log('Submission was aborted');
return;
}
setState((prev) => ({
...prev,
submissionError: error.message || 'Failed to send messages',
isSubmitting: false,
}));
}
};
const reset = () => {
abortControllerRef.current?.abort();
setState({
step: 'select',
selectedContacts: [],
message: '',
createdMessage: null,
isSubmitting: false,
submissionError: null,
});
};
// Cleanup
const cleanup = () => {
abortControllerRef.current?.abort();
};
return {
// Getters
currentStep: state.step,
selectedContacts: state.selectedContacts,
message: state.message,
createdMessage: state.createdMessage,
isSubmitting: state.isSubmitting,
submissionError: state.submissionError,
canProceedToNextStep: canProceedToNextStep(),
canGoBack,
// Actions
toggleContact,
setMessage,
setCreatedMessage,
nextStep,
prevStep,
submit,
reset,
cleanup,
};
};
export default useSendMessageWizard;