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:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "textsender",
|
"name": "textsender",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "textsender",
|
"name": "textsender",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.2.7",
|
"react": "^19.2.7",
|
||||||
"react-dom": "^19.2.7",
|
"react-dom": "^19.2.7",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "textsender",
|
"name": "textsender",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { API_BASE_URL } from '../constants/api';
|
||||||
|
|
||||||
|
export const scheduleApi = {
|
||||||
|
scheduleMessage: async (reqBody, authBearerToken) => {
|
||||||
|
console.log('Scheduling message');
|
||||||
|
|
||||||
|
const response = await fetch(`${API_BASE_URL}/api/v1/schedule/message`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: authBearerToken,
|
||||||
|
},
|
||||||
|
body: JSON.stringify(reqBody),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Error scheduling message');
|
||||||
|
} else {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
prepareMessage: async (reqBody, authBearerToken) => {
|
||||||
|
console.log('Preparing Scheduled message');
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/schedule/message/status/update`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: authBearerToken,
|
||||||
|
},
|
||||||
|
body: JSON.stringify(reqBody),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Error updating status of scheduled message');
|
||||||
|
} else {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { API_BASE_URL } from '../constants/api';
|
||||||
|
|
||||||
|
export const scheduleEventApi = {
|
||||||
|
scheduleMessageEvent: async (reqBody, authBearerToken) => {
|
||||||
|
console.log('Scheduling message Event');
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/schedule/message/event`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: authBearerToken,
|
||||||
|
},
|
||||||
|
body: JSON.stringify(reqBody),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Error scheduling message event');
|
||||||
|
} else {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -5,6 +5,7 @@ function ConfirmationStep({
|
|||||||
selectedContacts,
|
selectedContacts,
|
||||||
createdMessage,
|
createdMessage,
|
||||||
message,
|
message,
|
||||||
|
scheduledTime,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
}) {
|
}) {
|
||||||
// In a real app, you might fetch full contact details here
|
// In a real app, you might fetch full contact details here
|
||||||
@@ -88,6 +89,12 @@ function ConfirmationStep({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Scheduled time Section */}
|
||||||
|
<div>
|
||||||
|
Scheduled time:{' '}
|
||||||
|
{scheduledTime ? scheduledTime.toISOString() : 'No schedule date'}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Summary Section */}
|
{/* Summary Section */}
|
||||||
<div className={styles.confirmationSection}>
|
<div className={styles.confirmationSection}>
|
||||||
<div className={styles.sectionHeader}>
|
<div className={styles.sectionHeader}>
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
function FutureTimeForm({ scheduledTime, setScheduledTime }) {
|
||||||
|
const [selectedTime, setSelectedTime] = useState(new Date());
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
const [success, setSuccess] = useState('');
|
||||||
|
|
||||||
|
const handleTimeChange = (e) => {
|
||||||
|
setSelectedTime(e.target.value);
|
||||||
|
setScheduledTime(new Date(e.target.value));
|
||||||
|
setError('');
|
||||||
|
setSuccess('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateAndSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!selectedTime) {
|
||||||
|
setError('Please select a date and time.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const inputDate = new Date(selectedTime);
|
||||||
|
|
||||||
|
// Calculate the minimum allowed time (Now + 10 minutes)
|
||||||
|
const minAllowedTime = new Date(now.getTime() + 10 * 60000);
|
||||||
|
|
||||||
|
if (inputDate < minAllowedTime) {
|
||||||
|
setError('The time must be at least 10 minutes in the future.');
|
||||||
|
setSuccess('');
|
||||||
|
setScheduledTime(null);
|
||||||
|
} else {
|
||||||
|
setError('');
|
||||||
|
setSuccess('Time validated successfully!');
|
||||||
|
setScheduledTime(inputDate);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{ maxWidth: '400px', margin: '2rem auto', fontFamily: 'Arial' }}
|
||||||
|
>
|
||||||
|
<h2>Schedule Event</h2>
|
||||||
|
<form onSubmit={validateAndSubmit}>
|
||||||
|
<div style={{ marginBottom: '1rem' }}>
|
||||||
|
<label
|
||||||
|
htmlFor="future-time"
|
||||||
|
style={{ display: 'block', marginBottom: '0.5rem' }}
|
||||||
|
>
|
||||||
|
Select Date and Time:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="datetime-local"
|
||||||
|
id="future-time"
|
||||||
|
value={selectedTime}
|
||||||
|
onChange={handleTimeChange}
|
||||||
|
style={{
|
||||||
|
padding: '8px',
|
||||||
|
width: '100%',
|
||||||
|
borderColor: error ? 'red' : '#ccc',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && <p style={{ color: 'red', fontSize: '0.9rem' }}>{error}</p>}
|
||||||
|
{success && (
|
||||||
|
<p style={{ color: 'green', fontSize: '0.9rem' }}>{success}</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
style={{
|
||||||
|
padding: '10px 20px',
|
||||||
|
backgroundColor: '#007BFF',
|
||||||
|
color: 'white',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '4px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FutureTimeForm;
|
||||||
@@ -3,9 +3,15 @@ import styles from './SendMessageWizard.module.css';
|
|||||||
import { tokenService } from '../../services/TokenService';
|
import { tokenService } from '../../services/TokenService';
|
||||||
import { messageApi, CreateMessageRequest } from '../../api/messageApi';
|
import { messageApi, CreateMessageRequest } from '../../api/messageApi';
|
||||||
|
|
||||||
function MessageForm({ message, onMessageChange, onMessageCreated }) {
|
function MessageForm({
|
||||||
|
message,
|
||||||
|
onMessageChange,
|
||||||
|
onMessageCreated,
|
||||||
|
onToggleScheduled,
|
||||||
|
}) {
|
||||||
const [characterCount, setCharacterCount] = useState(message.length);
|
const [characterCount, setCharacterCount] = useState(message.length);
|
||||||
const [isCreatingMessage, setIsCreatingMessage] = useState(false);
|
const [isCreatingMessage, setIsCreatingMessage] = useState(false);
|
||||||
|
const [isScheduledChecked, setIsScheduledChecked] = useState(false);
|
||||||
const [createdMessage, setCreatedMessage] = useState(null);
|
const [createdMessage, setCreatedMessage] = useState(null);
|
||||||
|
|
||||||
const handleMessageChange = (e) => {
|
const handleMessageChange = (e) => {
|
||||||
@@ -14,6 +20,11 @@ function MessageForm({ message, onMessageChange, onMessageCreated }) {
|
|||||||
setCharacterCount(newMessage.length);
|
setCharacterCount(newMessage.length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleIsScheduledCheckbox = (event) => {
|
||||||
|
setIsScheduledChecked(event.target.checked);
|
||||||
|
onToggleScheduled(event.target.checked);
|
||||||
|
};
|
||||||
|
|
||||||
const createMessage = async () => {
|
const createMessage = async () => {
|
||||||
if (!message.trim()) {
|
if (!message.trim()) {
|
||||||
return;
|
return;
|
||||||
@@ -38,10 +49,8 @@ function MessageForm({ message, onMessageChange, onMessageCreated }) {
|
|||||||
const createdMessage = response.data[0];
|
const createdMessage = response.data[0];
|
||||||
setCreatedMessage(createdMessage);
|
setCreatedMessage(createdMessage);
|
||||||
if (onMessageCreated) {
|
if (onMessageCreated) {
|
||||||
console.log('Setting createdMessage');
|
|
||||||
onMessageCreated(createdMessage);
|
onMessageCreated(createdMessage);
|
||||||
}
|
}
|
||||||
console.log('Created message: ', createdMessage);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@@ -97,6 +106,17 @@ function MessageForm({ message, onMessageChange, onMessageCreated }) {
|
|||||||
<li>Check spelling and grammar</li>
|
<li>Check spelling and grammar</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isScheduledChecked}
|
||||||
|
onChange={handleIsScheduledCheckbox}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
Schedule Message
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ContactSelection from './ContactSelection';
|
import ContactSelection from './ContactSelection';
|
||||||
|
import FutureTimeForm from './FutureTimeForm';
|
||||||
import MessageForm from './MessageForm';
|
import MessageForm from './MessageForm';
|
||||||
import ConfirmationStep from './ConfirmationStep';
|
import ConfirmationStep from './ConfirmationStep';
|
||||||
import StepNavigation from './StepNavigation';
|
import StepNavigation from './StepNavigation';
|
||||||
@@ -26,6 +27,14 @@ function SendMessageWizardModal({ isOpen, onClose, onComplete }) {
|
|||||||
message={wizard.message}
|
message={wizard.message}
|
||||||
onMessageChange={wizard.setMessage}
|
onMessageChange={wizard.setMessage}
|
||||||
onMessageCreated={wizard.setCreatedMessage}
|
onMessageCreated={wizard.setCreatedMessage}
|
||||||
|
onToggleScheduled={wizard.toggleScheduled}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'schedule':
|
||||||
|
return (
|
||||||
|
<FutureTimeForm
|
||||||
|
scheduledTime={wizard.scheduledTime}
|
||||||
|
setScheduledTime={wizard.setScheduledTime}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'confirm':
|
case 'confirm':
|
||||||
@@ -34,6 +43,7 @@ function SendMessageWizardModal({ isOpen, onClose, onComplete }) {
|
|||||||
selectedContacts={wizard.selectedContacts}
|
selectedContacts={wizard.selectedContacts}
|
||||||
createdMessage={wizard.createdMessage}
|
createdMessage={wizard.createdMessage}
|
||||||
message={wizard.message}
|
message={wizard.message}
|
||||||
|
scheduledTime={wizard.scheduledTime}
|
||||||
isSubmitting={wizard.isSubmitting}
|
isSubmitting={wizard.isSubmitting}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -74,6 +84,7 @@ function SendMessageWizardModal({ isOpen, onClose, onComplete }) {
|
|||||||
const stepTitles = {
|
const stepTitles = {
|
||||||
select: 'Select Contacts',
|
select: 'Select Contacts',
|
||||||
message: 'Compose Message',
|
message: 'Compose Message',
|
||||||
|
schedule: 'Schedule message',
|
||||||
confirm: 'Review & Send',
|
confirm: 'Review & Send',
|
||||||
result: 'Result',
|
result: 'Result',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,25 @@ function StepNavigation({
|
|||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
case 'schedule':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={onBack}
|
||||||
|
disabled={!canGoBack}
|
||||||
|
className={`${styles.navButton} ${styles.backButton}`}
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={onNext}
|
||||||
|
disabled={!canProceed}
|
||||||
|
className={`${styles.navButton} ${styles.nextButton}`}
|
||||||
|
>
|
||||||
|
{currentStep === 'schedule' ? 'Next' : 'Review'}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
case 'confirm':
|
case 'confirm':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -5,14 +5,18 @@ import {
|
|||||||
sendMessageApi,
|
sendMessageApi,
|
||||||
SendInstantMessageRequest,
|
SendInstantMessageRequest,
|
||||||
} from '../../api/sendMessageApi';
|
} from '../../api/sendMessageApi';
|
||||||
|
import { scheduleApi } from '../../api/scheduleApi.js';
|
||||||
|
import { scheduleEventApi } from '../../api/scheduleEventApi.js';
|
||||||
|
|
||||||
const useSendMessageWizard = () => {
|
const useSendMessageWizard = () => {
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
step: 'select',
|
step: 'select',
|
||||||
selectedContacts: [],
|
selectedContacts: [],
|
||||||
|
scheduledTime: null,
|
||||||
message: '',
|
message: '',
|
||||||
createdMessage: null,
|
createdMessage: null,
|
||||||
isSubmitting: false,
|
isSubmitting: false,
|
||||||
|
isScheduled: false,
|
||||||
submissionError: null,
|
submissionError: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -25,12 +29,28 @@ const useSendMessageWizard = () => {
|
|||||||
return state.selectedContacts.length > 0;
|
return state.selectedContacts.length > 0;
|
||||||
case 'message':
|
case 'message':
|
||||||
return state.message.trim().length > 0;
|
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':
|
case 'confirm':
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}, [state.step, state.selectedContacts.length, state.message]);
|
}, [
|
||||||
|
state.step,
|
||||||
|
state.selectedContacts.length,
|
||||||
|
state.message,
|
||||||
|
state.scheduledTime,
|
||||||
|
]);
|
||||||
|
|
||||||
const canGoBack = state.step !== 'select';
|
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) => {
|
const setMessage = (message) => {
|
||||||
setState((prev) => ({ ...prev, message }));
|
setState((prev) => ({ ...prev, message }));
|
||||||
};
|
};
|
||||||
@@ -53,29 +81,67 @@ const useSendMessageWizard = () => {
|
|||||||
setState((prev) => ({ ...prev, createdMessage: message }));
|
setState((prev) => ({ ...prev, createdMessage: message }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setScheduledTime = (selectedTime) => {
|
||||||
|
console.log('Setting scheduled time');
|
||||||
|
setState((prev) => ({ ...prev, scheduledTime: selectedTime }));
|
||||||
|
};
|
||||||
|
|
||||||
const nextStep = () => {
|
const nextStep = () => {
|
||||||
if (!canProceedToNextStep()) return;
|
if (!canProceedToNextStep()) return;
|
||||||
|
|
||||||
const stepOrder = ['select', 'message', 'confirm', 'result'];
|
const stepOrder = ['select', 'message', 'schedule', 'confirm', 'result'];
|
||||||
const currentIndex = stepOrder.indexOf(state.step);
|
const currentIndex = stepOrder.indexOf(state.step);
|
||||||
if (currentIndex < stepOrder.length - 1) {
|
if (currentIndex < stepOrder.length - 1) {
|
||||||
setState((prev) => ({
|
if (state.step === 'message') {
|
||||||
...prev,
|
if (state.isScheduled) {
|
||||||
step: stepOrder[currentIndex + 1],
|
setState((prev) => ({
|
||||||
submissionError: null,
|
...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 prevStep = () => {
|
||||||
const stepOrder = ['select', 'message', 'confirm', 'result'];
|
const stepOrder = ['select', 'message', 'schedule', 'confirm', 'result'];
|
||||||
const currentIndex = stepOrder.indexOf(state.step);
|
const currentIndex = stepOrder.indexOf(state.step);
|
||||||
|
|
||||||
if (currentIndex > 0) {
|
if (currentIndex > 0) {
|
||||||
setState((prev) => ({
|
if (state.step === 'confirm') {
|
||||||
...prev,
|
if (state.isScheduled) {
|
||||||
step: stepOrder[currentIndex - 1],
|
setState((prev) => ({
|
||||||
submissionError: null,
|
...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 {
|
try {
|
||||||
console.log('Sending message');
|
if (state.scheduledTime != null) {
|
||||||
let reqBod = new SendInstantMessageRequest();
|
console.log('Going to schedule message');
|
||||||
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) {
|
const schMsgReq = {
|
||||||
// Success - move to result step
|
scheduled: state.scheduledTime.toISOString(),
|
||||||
setState((prev) => ({
|
status: 'PENDING',
|
||||||
...prev,
|
user_id: tokenService.getUserId(),
|
||||||
step: 'result',
|
};
|
||||||
isSubmitting: false,
|
|
||||||
}));
|
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) {
|
} catch (error) {
|
||||||
if (error.name === 'AbortError') {
|
if (error.name === 'AbortError') {
|
||||||
@@ -121,6 +239,8 @@ const useSendMessageWizard = () => {
|
|||||||
...prev,
|
...prev,
|
||||||
submissionError: error.message || 'Failed to send messages',
|
submissionError: error.message || 'Failed to send messages',
|
||||||
isSubmitting: false,
|
isSubmitting: false,
|
||||||
|
isScheduled: false,
|
||||||
|
scheduledTime: null,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -130,9 +250,11 @@ const useSendMessageWizard = () => {
|
|||||||
setState({
|
setState({
|
||||||
step: 'select',
|
step: 'select',
|
||||||
selectedContacts: [],
|
selectedContacts: [],
|
||||||
|
scheduledTime: null,
|
||||||
message: '',
|
message: '',
|
||||||
createdMessage: null,
|
createdMessage: null,
|
||||||
isSubmitting: false,
|
isSubmitting: false,
|
||||||
|
isScheduled: false,
|
||||||
submissionError: null,
|
submissionError: null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -146,17 +268,21 @@ const useSendMessageWizard = () => {
|
|||||||
// Getters
|
// Getters
|
||||||
currentStep: state.step,
|
currentStep: state.step,
|
||||||
selectedContacts: state.selectedContacts,
|
selectedContacts: state.selectedContacts,
|
||||||
|
scheduledTime: state.scheduledTime,
|
||||||
message: state.message,
|
message: state.message,
|
||||||
createdMessage: state.createdMessage,
|
createdMessage: state.createdMessage,
|
||||||
isSubmitting: state.isSubmitting,
|
isSubmitting: state.isSubmitting,
|
||||||
|
isScheduled: state.isScheduled,
|
||||||
submissionError: state.submissionError,
|
submissionError: state.submissionError,
|
||||||
canProceedToNextStep: canProceedToNextStep(),
|
canProceedToNextStep: canProceedToNextStep(),
|
||||||
canGoBack,
|
canGoBack,
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
toggleContact,
|
toggleContact,
|
||||||
|
toggleScheduled,
|
||||||
setMessage,
|
setMessage,
|
||||||
setCreatedMessage,
|
setCreatedMessage,
|
||||||
|
setScheduledTime,
|
||||||
nextStep,
|
nextStep,
|
||||||
prevStep,
|
prevStep,
|
||||||
submit,
|
submit,
|
||||||
|
|||||||
Reference in New Issue
Block a user