From 492404084bd29bd41b2f5528e68cde8d836a143d Mon Sep 17 00:00:00 2001 From: charleswrayjr Date: Sat, 13 Sep 2025 10:45:34 -0500 Subject: [PATCH] Fixing base_url imports and making header sticky. --- src/App.js | 8 +- src/app/components/AppHeader.js | 2 +- src/app/services/media.js | 14 +- src/app/services/message_group_members.js | 10 +- src/app/services/message_groups.js | 10 +- src/app/services/messages.js | 14 +- src/app/services/posts.js | 2 +- src/app/views/Dashboard/Dashboard.jsx | 219 +++++++++++++++++----- src/styles/App.css | 28 +++ 9 files changed, 229 insertions(+), 78 deletions(-) diff --git a/src/App.js b/src/App.js index 19a34bc..b291e31 100755 --- a/src/App.js +++ b/src/App.js @@ -19,8 +19,12 @@ const App = () => { - - +
+ +
{/* Padding for sticky header */} + +
+
diff --git a/src/app/components/AppHeader.js b/src/app/components/AppHeader.js index 5288399..c33df0e 100644 --- a/src/app/components/AppHeader.js +++ b/src/app/components/AppHeader.js @@ -40,7 +40,7 @@ const AppHeader = () => { )), [navItems, navigate] ); return ( - + PHS Admin diff --git a/src/app/services/media.js b/src/app/services/media.js index 9057215..e945f55 100644 --- a/src/app/services/media.js +++ b/src/app/services/media.js @@ -4,7 +4,7 @@ import axios from 'axios'; -const BASE_URL = 'http://localhost:3601'; +const { base_url } = require('../../globals'); const getAuthHeaders = () => ({ headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }, @@ -12,21 +12,21 @@ const getAuthHeaders = () => ({ export const MediaService = { async getMedia(params = {}) { - return await axios.get(`${BASE_URL}/media`, { ...getAuthHeaders(), params }); + return await axios.get(`${base_url}/media`, { ...getAuthHeaders(), params }); }, async getMediaByFilePath(file_path) { - return await axios.get(`${BASE_URL}/media/file_path/${file_path}`, getAuthHeaders()); + return await axios.get(`${base_url}/media/file_path/${file_path}`, getAuthHeaders()); }, async getMediaById(id) { - return await axios.get(`${BASE_URL}/media/${id}`, getAuthHeaders()); + return await axios.get(`${base_url}/media/${id}`, getAuthHeaders()); }, async createMedia(data) { - return await axios.post(`${BASE_URL}/media/create`, data, getAuthHeaders()); + return await axios.post(`${base_url}/media/create`, data, getAuthHeaders()); }, async updateMedia(id, data) { - return await axios.put(`${BASE_URL}/media/${id}`, data, getAuthHeaders()); + return await axios.put(`${base_url}/media/${id}`, data, getAuthHeaders()); }, async softDeleteMedia(id, data) { - return await axios.put(`${BASE_URL}/media/${id}/soft_delete`, data, getAuthHeaders()); + return await axios.put(`${base_url}/media/${id}/soft_delete`, data, getAuthHeaders()); }, }; \ No newline at end of file diff --git a/src/app/services/message_group_members.js b/src/app/services/message_group_members.js index 0d745bf..2229b50 100644 --- a/src/app/services/message_group_members.js +++ b/src/app/services/message_group_members.js @@ -4,7 +4,7 @@ import axios from 'axios'; -const BASE_URL = 'http://localhost:3601'; +const { base_url } = require('../../globals'); const getAuthHeaders = () => ({ headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }, @@ -12,15 +12,15 @@ const getAuthHeaders = () => ({ export const MessageGroupMembersService = { async getMembersByGroupId(group_id, params = {}) { - return await axios.get(`${BASE_URL}/message_group_members/group/${group_id}`, { ...getAuthHeaders(), params }); + return await axios.get(`${base_url}/message_group_members/group/${group_id}`, { ...getAuthHeaders(), params }); }, async getMemberByIds(group_id, user_id) { - return await axios.get(`${BASE_URL}/message_group_members/ids/${group_id}/${user_id}`, getAuthHeaders()); + return await axios.get(`${base_url}/message_group_members/ids/${group_id}/${user_id}`, getAuthHeaders()); }, async addMember(data) { - return await axios.post(`${BASE_URL}/message_group_members/add`, data, getAuthHeaders()); + return await axios.post(`${base_url}/message_group_members/add`, data, getAuthHeaders()); }, async removeMember(data) { - return await axios.delete(`${BASE_URL}/message_group_members/remove`, { ...getAuthHeaders(), data }); + return await axios.delete(`${base_url}/message_group_members/remove`, { ...getAuthHeaders(), data }); }, }; \ No newline at end of file diff --git a/src/app/services/message_groups.js b/src/app/services/message_groups.js index 42ab639..490ee9c 100644 --- a/src/app/services/message_groups.js +++ b/src/app/services/message_groups.js @@ -4,7 +4,7 @@ import axios from 'axios'; -const BASE_URL = 'http://localhost:3601'; +const { base_url } = require('../../globals'); const getAuthHeaders = () => ({ headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }, @@ -12,15 +12,15 @@ const getAuthHeaders = () => ({ export const MessageGroupService = { async getMessageGroups(params = {}) { - return await axios.get(`${BASE_URL}/message_group`, { ...getAuthHeaders(), params }); + return await axios.get(`${base_url}/message_group`, { ...getAuthHeaders(), params }); }, async getMessageGroup(id) { - return await axios.get(`${BASE_URL}/message_group/${id}`, getAuthHeaders()); + return await axios.get(`${base_url}/message_group/${id}`, getAuthHeaders()); }, async createMessageGroup(data) { - return await axios.post(`${BASE_URL}/message_group/create`, data, getAuthHeaders()); + return await axios.post(`${base_url}/message_group/create`, data, getAuthHeaders()); }, async updateMessageGroup(id, data) { - return await axios.put(`${BASE_URL}/message_group/${id}`, data, getAuthHeaders()); + return await axios.put(`${base_url}/message_group/${id}`, data, getAuthHeaders()); }, }; \ No newline at end of file diff --git a/src/app/services/messages.js b/src/app/services/messages.js index decbe25..0c1f3a0 100644 --- a/src/app/services/messages.js +++ b/src/app/services/messages.js @@ -4,7 +4,7 @@ import axios from 'axios'; -const BASE_URL = 'http://localhost:3601'; +const { base_url } = require('../../globals'); const getAuthHeaders = () => ({ headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }, @@ -12,21 +12,21 @@ const getAuthHeaders = () => ({ export const MessageService = { async getMessages(params = {}) { - return await axios.get(`${BASE_URL}/message`, { ...getAuthHeaders(), params }); + return await axios.get(`${base_url}/message`, { ...getAuthHeaders(), params }); }, async getMessagesByGroupId(group_id, params = {}) { - return await axios.get(`${BASE_URL}/message/group/${group_id}`, { ...getAuthHeaders(), params }); + return await axios.get(`${base_url}/message/group/${group_id}`, { ...getAuthHeaders(), params }); }, async getMessagesByRecipientId(recipient_id, params = {}) { - return await axios.get(`${BASE_URL}/message/recipient/${recipient_id}`, { ...getAuthHeaders(), params }); + return await axios.get(`${base_url}/message/recipient/${recipient_id}`, { ...getAuthHeaders(), params }); }, async getMessage(id) { - return await axios.get(`${BASE_URL}/message/${id}`, getAuthHeaders()); + return await axios.get(`${base_url}/message/${id}`, getAuthHeaders()); }, async createMessage(data) { - return await axios.post(`${BASE_URL}/message/create`, data, getAuthHeaders()); + return await axios.post(`${base_url}/message/create`, data, getAuthHeaders()); }, async markMessageAsRead(id) { - return await axios.put(`${BASE_URL}/message/${id}/mark_as_read`, {}, getAuthHeaders()); + return await axios.put(`${base_url}/message/${id}/mark_as_read`, {}, getAuthHeaders()); }, }; \ No newline at end of file diff --git a/src/app/services/posts.js b/src/app/services/posts.js index 850959e..07d086c 100644 --- a/src/app/services/posts.js +++ b/src/app/services/posts.js @@ -4,7 +4,7 @@ import axios from 'axios'; -import { base_url } from '../../globals'; +const { base_url } = require('../../globals'); export const PostService = { diff --git a/src/app/views/Dashboard/Dashboard.jsx b/src/app/views/Dashboard/Dashboard.jsx index 436750b..3b28ef7 100755 --- a/src/app/views/Dashboard/Dashboard.jsx +++ b/src/app/views/Dashboard/Dashboard.jsx @@ -1,67 +1,186 @@ /** - * @file Dashboard view with navigation to main features + * @file Dashboard view with informative widgets */ -import React, { useContext, useMemo } from 'react'; -import { Container, Grid, Card, CardContent, Typography, Button } from '@mui/material'; +import React, { useContext, useEffect, useState } from 'react'; +import { Container, Grid, Card, CardContent, Typography, Box, Button } from '@mui/material'; +import { MaterialReactTable } from 'material-react-table'; import { useNavigate } from 'react-router-dom'; +import { useSnackbar } from 'notistack'; import { AuthContext } from '../../components/AuthContext'; +import { MessageService, MediaService, PostService, MessageGroupService } from '../../services'; +import { getFormattedDate, truncateContent } from '../../utils'; const Dashboard = () => { const navigate = useNavigate(); - const { user } = useContext(AuthContext) || {}; + const { enqueueSnackbar } = useSnackbar(); + const { user } = useContext(AuthContext); + const [recentMessages, setRecentMessages] = useState([]); + const [recentMedia, setRecentMedia] = useState([]); + const [recentPosts, setRecentPosts] = useState([]); + const [recentGroups, setRecentGroups] = useState([]); - console.log(user); + useEffect(() => { + const fetchData = async () => { + try { + // Fetch recent messages + const messages = await MessageService.getMessages({ limit: 5 }); + setRecentMessages(messages.data); - const features = useMemo( () => user ? [ - { title: 'Messages', path: '/messages', description: 'View and send messages', roles: ['User', 'Admin'] }, - { title: 'Message Groups', path: '/message-groups', description: 'Manage group chats', roles: ['User', 'Admin'] }, - { title: 'Media', path: '/media', description: 'Upload and view media', roles: ['User', 'Admin'] }, - { title: 'Posts', path: '/posts', description: 'Create and view posts', roles: ['User', 'Admin'] }, - { title: 'Docker', path: '/docker', description: 'Manage Docker containers', roles: ['Admin'] }, - { title: 'VPN', path: '/vpn', description: 'Manage OpenVPN Connections and Clients', roles: ['Admin'] }, - { title: 'GIT', path: '/git', description: 'Manage GIT repositories', roles: ['Admin'] }, - ].filter(feature => feature.roles.some( role => [...user.roles]?.map( r => r.name )?.includes( role ) ) ) : [], [user] ); + // Fetch recent media (filtered by visibility for non-Admin) + const mediaParams = user?.roles.includes('Admin') ? { limit: 5 } : { limit: 5, visibility: ['public', 'family'] }; + const media = await MediaService.getMedia(mediaParams); + setRecentMedia(media.data); - /** - * - * @type {unknown[]} - */ - const featureCards = useMemo( () => features.map((feature) => ( - ( - - - - - {feature.title} - - - {feature.description} - - - - - - ) - )), [features, navigate] ); + // Fetch recent posts (filtered by visibility for non-Admin) + const postsParams = user?.roles.includes('Admin') ? { limit: 5 } : { limit: 5, visibility: ['public', 'family'] }; + const posts = await PostService.getPosts(postsParams); + setRecentPosts(posts.data); + + // Fetch recent message groups + const groups = await MessageGroupService.getMessageGroups({ limit: 5 }); + setRecentGroups(groups.data); + } catch (error) { + enqueueSnackbar(`Error fetching dashboard data: ${error.message}`, { variant: 'error' }); + } + }; + fetchData(); + }, [enqueueSnackbar, user]); + + const messageColumns = [ + { accessorKey: 'sender_id', header: 'Sender ID', size: 100 }, + { accessorKey: 'content', header: 'Content', size: 200, Cell: ({ cell }) => truncateContent(cell.getValue(), 50) }, + { accessorKey: 'created_at', header: 'Sent At', size: 150, Cell: ({ cell }) => getFormattedDate(cell.getValue()) }, + ]; + + const mediaColumns = [ + { accessorKey: 'file_path', header: 'File Path', size: 200 }, + { accessorKey: 'file_type', header: 'Type', size: 100 }, + { accessorKey: 'visibility', header: 'Visibility', size: 100 }, + { accessorKey: 'created_at', header: 'Uploaded At', size: 150, Cell: ({ cell }) => getFormattedDate(cell.getValue()) }, + ]; + + const postColumns = [ + { accessorKey: 'title', header: 'Title', size: 200 }, + { accessorKey: 'post_type', header: 'Type', size: 100 }, + { accessorKey: 'visibility', header: 'Visibility', size: 100 }, + { accessorKey: 'created_at', header: 'Posted At', size: 150, Cell: ({ cell }) => getFormattedDate(cell.getValue()) }, + ]; + + const groupColumns = [ + { accessorKey: 'name', header: 'Group Name', size: 200 }, + { accessorKey: 'created_by_id', header: 'Created By', size: 100 }, + { accessorKey: 'created_at', header: 'Created At', size: 150, Cell: ({ cell }) => getFormattedDate(cell.getValue()) }, + ]; return ( -
- - - Welcome to PHS Admin{user ? `, ${user.first_name || 'User ' + user.id}` : ''} - - - {featureCards} + + + Welcome to PHS Admin{user ? `, ${user.first_name || 'User ' + user.id}` : ''} + + + + + + + Recent Messages + + + + + + + + + + + + + Recent Media + + + + + + + + + + + + + Recent Posts + + + + + + + - -
+ + + + + Recent Message Groups + + + + + + + + + + ); }; diff --git a/src/styles/App.css b/src/styles/App.css index cf0105d..33c4fb9 100755 --- a/src/styles/App.css +++ b/src/styles/App.css @@ -19,3 +19,31 @@ .App-link { color: #61dafb; } + +.container { + @apply max-w-7xl mx-auto p-4; +} + +.table-header { + @apply bg-gray-100 font-semibold text-gray-800; +} + +.table-row { + @apply border-b hover:bg-gray-50; +} + +.chat-container { + @apply max-w-3xl mx-auto p-4 bg-white shadow-md rounded-lg; +} + +.chat-message { + @apply p-2 my-2 rounded-lg; +} + +.chat-message-sent { + @apply bg-blue-100 ml-auto max-w-xs; +} + +.chat-message-received { + @apply bg-gray-100 mr-auto max-w-xs; +} -- 2.43.0