From 76e1ff8a5cfc8cd1fcf1df0db3a72409a5e09b46 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 4 Jul 2026 19:20:55 -0400 Subject: [PATCH 1/9] Got the code working --- src/api/scheduleApi.js | 19 ++ src/components/ViewSentMessages.css | 99 +++++++ src/components/ViewSentMessages.jsx | 400 ++++++++++++---------------- 3 files changed, 295 insertions(+), 223 deletions(-) diff --git a/src/api/scheduleApi.js b/src/api/scheduleApi.js index dd6630e..4d4aac7 100644 --- a/src/api/scheduleApi.js +++ b/src/api/scheduleApi.js @@ -20,6 +20,25 @@ export const scheduleApi = { } }, + getScheduledMessage: async (userId, authBearerToken) => { + const response = await fetch( + `${API_BASE_URL}/api/v1/schedule/message?user_id=${userId}`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: authBearerToken, + }, + } + ); + + if (!response.ok) { + throw new Error('Error getting scheduled message'); + } else { + return response.json(); + } + }, + prepareMessage: async (reqBody, authBearerToken) => { console.log('Preparing Scheduled message'); diff --git a/src/components/ViewSentMessages.css b/src/components/ViewSentMessages.css index c17deca..8aacf71 100644 --- a/src/components/ViewSentMessages.css +++ b/src/components/ViewSentMessages.css @@ -355,3 +355,102 @@ .view-sent-message-list-container::-webkit-scrollbar-thumb:hover { background: #a1a1a1; } + +.view-sent-message-tabs { + display: flex; + margin-bottom: 20px; + border-bottom: 1px solid #e5e7eb; +} + +.tab-button { + padding: 10px 20px; + background: none; + border: none; + border-bottom: 3px solid transparent; + cursor: pointer; + font-weight: 500; + color: #6b7280; + transition: all 0.3s ease; +} + +.tab-button.active { + color: #3b82f6; + border-bottom-color: #3b82f6; +} + +.tab-button:hover { + color: #374151; + background-color: #f9fafb; +} + +.search-container { + margin-bottom: 20px; +} + +.search-input { + width: 100%; + padding: 10px 12px; + border: 1px solid #d1d5db; + border-radius: 6px; + font-size: 14px; +} + +.search-input:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; +} + +.section-header h3 { + margin: 0; + color: #111827; + font-size: 18px; + font-weight: 600; +} + +.last-updated { + font-size: 12px; + color: #6b7280; +} + +.no-messages { + text-align: center; + padding: 40px; + color: #6b7280; + font-style: italic; +} + +.status-badge { + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + font-weight: 500; + text-transform: uppercase; +} + +.status-processing { + background-color: #fef3c7; + color: #92400e; +} + +.status-sent { + background-color: #dcfce7; + color: #166534; +} + +.status-failed { + background-color: #fee2e2; + color: #991b1b; +} + +.status-default { + background-color: #f3f4f6; + color: #374151; +} diff --git a/src/components/ViewSentMessages.jsx b/src/components/ViewSentMessages.jsx index f1503bb..330183d 100644 --- a/src/components/ViewSentMessages.jsx +++ b/src/components/ViewSentMessages.jsx @@ -1,20 +1,21 @@ import { useState, useEffect, useCallback } from 'react'; - import { tokenService } from '../services/TokenService'; import { messageEventResponseApi } from '../api/messageEventResponseApi'; - +import { scheduleApi } from '../api/scheduleApi'; import './ViewSentMessages.css'; const ViewSentMessages = ({ isOpen, onClose, - title = 'View Sent Messages ', + title = 'View Sent Messages', }) => { const [sentMessages, setSentMessages] = useState([]); + const [scheduledMessages, setScheduledMessages] = useState([]); const [lastUpdated, setLastUpdated] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [searchTerm, setSearchTerm] = useState(''); + const [activeTab, setActiveTab] = useState('sent'); // Fetch the sent messages or Message Event Responses const fetchSentMessages = useCallback(async () => { @@ -33,7 +34,6 @@ const ViewSentMessages = ({ setLastUpdated(new Date()); setSentMessages(response.data); } else { - setLoading(false); throw new Error(response.message || 'Failed to load sent messages'); } } catch (err) { @@ -44,8 +44,32 @@ const ViewSentMessages = ({ } }, []); + const fetchScheduledMessages = useCallback(async () => { + try { + const userId = tokenService.getUserId(); + const response = await scheduleApi.getScheduledMessage( + userId, + tokenService.bearerToken() + ); + if (response) { + const scheduledMessages = response.data; + + setScheduledMessages(scheduledMessages); + } else { + throw new Error(response.message || 'Failed to get scheduled messages'); + } + } catch (err) { + console.error('Failed to load scheduled messages:', err); + setScheduledMessages([]); + } + }, []); + const handleRefresh = () => { - fetchSentMessages(); + if (activeTab === 'sent') { + fetchSentMessages(); + } else { + fetchScheduledMessages(); + } }; useEffect(() => { @@ -55,6 +79,13 @@ const ViewSentMessages = ({ } }, [isOpen, fetchSentMessages]); + // Fetch scheduled messages when tab is switched + useEffect(() => { + if (activeTab === 'scheduled' && isOpen) { + fetchScheduledMessages(); + } + }, [activeTab, isOpen, fetchScheduledMessages]); + const filteredSentMessages = sentMessages.filter((sentMessage) => { const searchLower = searchTerm.toLowerCase(); return ( @@ -66,6 +97,15 @@ const ViewSentMessages = ({ ); }); + // Filter scheduled messages + const filteredScheduledMessages = scheduledMessages.filter((message) => { + const searchLower = searchTerm.toLowerCase(); + return ( + (message.status && message.status.toLowerCase().includes(searchLower)) || + (message.id && message.id.toString().includes(searchTerm)) + ); + }); + const formatLastUpdated = () => { if (!lastUpdated) return 'Never'; return lastUpdated.toLocaleTimeString([], { @@ -74,6 +114,25 @@ const ViewSentMessages = ({ }); }; + // Format date for scheduled messages + const formatScheduledDate = (dateString) => { + return new Date(dateString).toLocaleString(); + }; + + // Get status badge styling + const getStatusBadgeClass = (status) => { + switch (status) { + case 'PROCESSING': + return 'status-processing'; + case 'SENT': + return 'status-sent'; + case 'FAILED': + return 'status-failed'; + default: + return 'status-default'; + } + }; + if (!isOpen) return null; return ( @@ -90,13 +149,40 @@ const ViewSentMessages = ({ + {/* Add tabs for navigation */} +
+ + +
+ + {/* Search input */} +
+ setSearchTerm(e.target.value)} + className="search-input" + /> +
+
{error && (
{error}
- - setSearchTerm(e.target.value)} - style={{ - flex: 1, - minWidth: '200px', - maxWidth: '300px', - padding: '8px 12px', - border: '1px solid #e5e7eb', - borderRadius: '6px', - fontSize: '14px', - }} - /> - -
- Updated: {formatLastUpdated()} - -
-
- - {/* Sent Messages List */} - {filteredSentMessages.length === 0 ? ( -
-
- X + {/* Sent Messages Tab Content */} + {activeTab === 'sent' && ( +
+
+

Sent Messages

+ + Last updated: {formatLastUpdated()} +
-

- {searchTerm - ? 'No matching sent messages found' - : 'No sent messages available'} -

-

- {searchTerm - ? 'Try a different search term' - : 'Create a contact and send a message to get started'} -

- {searchTerm && ( - + + {filteredSentMessages.length > 0 ? ( +
+ + + + + + + + + + {filteredSentMessages.map((message) => ( + + + + + + ))} + +
IDStatusSent Time
{message.id.substring(0, 8)}... + + {message.status} + + {message.sent || 'N/A'}
+
+ ) : ( +
No sent messages found.
)}
- ) : ( - <> -
-
- {filteredSentMessages.map((sentMessage, index) => ( -
-
-
- - {index + 1} - -
-

- {sentMessage.status} -

-
Sent: {sentMessage.sent}
-
-
- - Id: {sentMessage.id} - -
-
- ))} -
+ )} + + {/* Scheduled Messages Tab Content */} + {activeTab === 'scheduled' && ( +
+
+

Scheduled Messages

- + + {filteredScheduledMessages.length > 0 ? ( +
+ + + + + + + + + + + {filteredScheduledMessages.map((message) => ( + + + + + + + ))} + +
IDScheduled TimeCreated TimeStatus
{message.id.substring(0, 8)}... + {formatScheduledDate(message.scheduled)} + {formatScheduledDate(message.created)} + + {message.status} + +
+
+ ) : ( +
+ No scheduled messages found. +
+ )} +
)} )} -
- - -
-- 2.47.3 From 0267dc18ac0cffd59ba68c8cb8953cce92596442 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 4 Jul 2026 19:27:32 -0400 Subject: [PATCH 2/9] Remoing icon --- public/vite.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 public/vite.svg diff --git a/public/vite.svg b/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file -- 2.47.3 From 299fcf9dd19ca2379b3cbdcce3c88cbb3904edcd Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 4 Jul 2026 19:27:41 -0400 Subject: [PATCH 3/9] Adding placeholder for public --- public/.empty | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/.empty diff --git a/public/.empty b/public/.empty new file mode 100644 index 0000000..e69de29 -- 2.47.3 From 3c552717a679a5436d02cc376cd8ecfacbdd23e2 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 4 Jul 2026 19:27:49 -0400 Subject: [PATCH 4/9] Updating readme --- README.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 4f4e202..a36e621 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,6 @@ -# React + Vite +# textsender +Frontend web app used to send messages -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. # Getting started -- 2.47.3 From dd81decb5955644d8af65066d33ab8c937c28490 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 4 Jul 2026 19:27:58 -0400 Subject: [PATCH 5/9] Updating title --- index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.html b/index.html index 0c589ec..0d3cc0b 100644 --- a/index.html +++ b/index.html @@ -2,9 +2,8 @@ - - Vite + React + textsender
-- 2.47.3 From 708d463a4f9edd74c1e2cd8c3c8e3e24e5db54c7 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 4 Jul 2026 19:30:19 -0400 Subject: [PATCH 6/9] Updating name --- src/components/Dashboard.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx index 1a44675..43fdf0f 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Dashboard.jsx @@ -53,7 +53,7 @@ const Dashboard = () => { {/* Navbar */}