Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useState } from 'react'; // Importing React and useState hook
import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom'; // Importing necessary components from react-router-dom

// Importing Components
import Header from './components/Header'; // Header component
import Login from './components/Login'; // Login component
import HelpInfo from './components/HelpInfo'; // HelpInfo component
import Contact from './components/Contact'; // Contact component
import Dashboard from './components/Dashboard'; // Dashboard component
import Registration from './components/Registration'; // Registration component
import ForgotPassword from './components/ForgotPassword'; // ForgotPassword component
import GlucoseLogs from './components/GlucoseLogs'; // GlucoseLogs component
import Profile from './components/Profile'; // Profile component
import Appointment from './components/Appointment'; // Appointment component
import Notifications from './components/Notifications'; // Notifications component
import MedicalForms from './components/MedicalForms'; // MedicalForms component
import Products from './components/products'; // Products component

// Main functional component AimPlusMedicalSupplies
export default function AimPlusMedicalSupplies() {
const [isLoggedIn, setIsLoggedIn] = useState(false); // State to track user's login status
const [username, setUsername] = useState(''); // State to store the username

return (
<Router>
<div>
{/* Header component */}
<Header isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} />

<Routes>
{/* Route for the home page, redirects to dashboard if logged in, otherwise shows login component */}
<Route path="/" element={isLoggedIn ? <Navigate to='/dashboard'/> : <Login setIsLoggedIn={setIsLoggedIn} setUsername={setUsername}/>} />

{/* Route for dashboard and its child routes */}
<Route path="/dashboard/*" element={isLoggedIn ? <Dashboard username={username}/> : <Navigate to="/" />} >
{/* Child routes of dashboard */}
<Route path="profile" element={<Profile />} />
<Route path="glucose-logs" element={<GlucoseLogs />} />
<Route path="appointments" element={<Appointment />} />
<Route path="notifications" element={<Notifications />} />
<Route path="medical-forms" element={<MedicalForms />} />
<Route path="products" element={<Products />} />
</Route>

{/* Route for help page */}
<Route path="/help" element={<HelpInfo />} />

{/* Route for forgot password page */}
<Route path="/forgot-password" element={<ForgotPassword />} />

{/* Route for registration page */}
<Route path="/registration" element={<Registration />} />

{/* Route for contact page */}
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</Router>
)
}
237 changes: 237 additions & 0 deletions Appointment.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { Button, CssBaseline, TextField, Container, Box, Typography, Paper, Grid } from '@mui/material';
import { ArrowBack as ArrowBackIcon } from '@mui/icons-material';
import jsPDF from 'jspdf';
import 'jspdf-autotable';

export default function Appointment() {
const navigate = useNavigate();
const [dateTime, setDateTime] = useState('');
const [doctorName, setDoctorName] = useState('');
const [notes, setNotes] = useState('');
const [appointments, setAppointments] = useState([]);
const token = localStorage.getItem('jwtToken');

useEffect(() => { fetchAppointments(); }, []);

const formatDateTime = (dateTimeString) => {
const date = new Date(dateTimeString);
return date.toISOString().slice(0, 16);
};

const fetchAppointments = async () => {
try {
const response = await fetch('http://127.0.0.1:5000/dashboard/appointments', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
}
});
if (response.ok) {
const responseData = await response.json();
setAppointments(responseData.appointments);
}
} catch (error) {
console.error('Error fetching appointments:', error);
}
};

const recordAppointment = async () => {
const appointment = { date: dateTime, doctor_name: doctorName, notes: notes };
try {
const response = await fetch('http://127.0.0.1:5000/dashboard/appointments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(appointment),
});
if (response.ok) {
console.log('Appointment recorded successfully');
fetchAppointments();
}
} catch (error) {
console.error('Error recording appointment:', error);
}
};

const deleteAppointment = async (appointmentID) => {
try {
const response = await fetch(`http://127.0.0.1:5000/dashboard/appointments?appointment_id=${appointmentID}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (response.ok) {
console.log('Appointment deleted successfully');
fetchAppointments();
}
} catch (error) {
console.error('Error deleting appointment:', error);
}
};

const exportToPDF = () => {
const doc = new jsPDF();
const tableColumn = ["Date & Time", "Doctor Name", "Notes"];
let sortedAppointments = [...appointments];
sortedAppointments.sort((a, b) => new Date(a.date) - new Date(b.date));
const tableRows = [];

sortedAppointments.forEach(appointment => {
const formattedDateTime = new Date(appointment.date).toLocaleString();
const appointmentData = [
formattedDateTime,
appointment.doctor_name,
appointment.notes
];
tableRows.push(appointmentData);
});

const currentDate = new Date();
const formattedDate = currentDate.toLocaleDateString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '_');
const fileName = `appointments_${formattedDate}.pdf`;

const title = `Your Appointments\nGenerated: ${currentDate.toLocaleString()}`;
doc.text(title, 14, 20);

doc.autoTable({
head: [tableColumn],
body: tableRows,
startY: 35,
theme: 'grid',
styles: {
overflow: 'linebreak',
cellWidth: 'wrap',
cellPadding: 2,
},
columnStyles: {
0: { cellWidth: 'auto' },
1: { cellWidth: 'auto' },
2: { cellWidth: 'auto' },
},
margin: { top: 20 },
tableWidth: 'auto',
tableHeight: 'auto',
});

doc.save(fileName);
};

return (
<Container component="main" maxWidth="md">
<CssBaseline />
<Button
variant="contained"
color="primary"
startIcon={<ArrowBackIcon />}
onClick={() => navigate('/')}
sx={{ mb: 2 }}
>
Go Back
</Button>
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<Paper elevation={6} sx={{ padding: 2 }}>
<Typography component="h1" variant="h5" gutterBottom>
Appointment Scheduler
</Typography>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="dateTime"
label="Date & Time"
type="datetime-local"
InputLabelProps={{ shrink: true }}
value={dateTime}
onChange={(e) => setDateTime(e.target.value)}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
required
name="doctorName"
label="Doctor Name"
type="text"
value={doctorName}
onChange={(e) => setDoctorName(e.target.value)}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
multiline
rows={4}
name="notes"
label="Appointment Notes"
type="text"
value={notes}
onChange={(e) => setNotes(e.target.value)}
/>
<Button
type="button"
fullWidth
variant="contained"
onClick={recordAppointment}
sx={{ mt: 3 }}
>
Schedule Appointment
</Button>
</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper elevation={6} sx={{ padding: 2 }}>
<Button
variant="contained"
color="primary"
onClick={exportToPDF}
sx={{ mb: 2}}
>
Export to PDF
</Button>
<Typography variant="h6" gutterBottom>
Scheduled Appointments:
</Typography>
{appointments
.sort((a, b) => new Date(a.date) - new Date(b.date))
.map((appointment) =>

{
const appointmentDate = new Date(appointment.date);
const formattedDate = appointmentDate.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' });
const formattedTime = appointmentDate.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });

return (
<Paper key={appointment.id} elevation={3} sx={{ padding: 2, marginBottom: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: '1px solid #ccc', paddingBottom: 1 }}>
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>
{formattedDate} at {formattedTime}
</Typography>
<Button variant="outlined" color="error" onClick={() => deleteAppointment(appointment.id)}>
Delete
</Button>
</Box>
<Box sx={{ marginTop: 1 }}>
<Typography variant="body1" sx={{ textAlign: 'right', paddingBottom: 1 }}>
Dr. {appointment.doctor_name}
</Typography>
<Typography variant="body2" sx={{ fontSize: 16 }}>
{appointment.notes}
</Typography>
</Box>
</Paper>
);
})}
</Paper>
</Grid>
</Grid>
</Container>
);
}
47 changes: 47 additions & 0 deletions ClickableBox.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from "react"; // Importing necessary modules from React
import { Link } from "react-router-dom"; // Importing Link component from react-router-dom
import { Box, Typography } from "@mui/material"; // Importing Box and Typography components from Material-UI

// Functional component ClickableBox
const ClickableBox = ({ title, path, icon: Icon }) => {
return (
// Link component to navigate to the specified path when clicked
<Link to={path} style={{ textDecoration: 'none' }}>
{/* Box component representing the clickable box */}
<Box
sx={{
width: '300px',
height: '200px',
backgroundColor: '#ff3856',
borderRadius: '4px',
boxShadow: '0 0 10px rgba(0, 0, 0, 0.3)',
cursor: 'pointer',
transition: 'transform 0.3s',
'&:hover': {
transform: 'translateY(-5px)',
},
}}
>
{/* Box component to center content vertically and horizontally */}
<Box sx={{
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
justifyContent: 'center',
height: '100%',
padding: '20px',
}}
>
{/* Rendering icon if provided */}
{Icon && <Icon sx={{ color: 'white', fontSize: 40 }} />}
{/* Rendering title */}
<Typography variant="h5" component="div" color="white" fontWeight={'bold'} style={{ textShadow: '2px 2px 4px rgba(0, 0, 0, 0.1)' }}>
{title}
</Typography>
</Box>
</Box>
</Link>
);
};

export default ClickableBox; // Exporting the component as the default export
45 changes: 45 additions & 0 deletions Communication.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useState } from 'react';
import { Box, TextField, Button, Typography } from '@mui/material';

export default function CommunicationPage() {
const [message, setMessage] = useState('');
const [messages, setMessages] = useState([]);

// Function to handle sending a message
const sendMessage = () => {
if (message.trim() !== '') {
// Add the new message to the list of messages
setMessages([...messages, message]);
// Clear the message input field
setMessage('');
}
};

return (
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mt: 4 }}>
<Typography variant="h4" gutterBottom>
Communication Tools
</Typography>
{/* Render the list of messages */}
<Box sx={{ maxWidth: 400, overflowY: 'auto', mb: 2 }}>
{messages.map((msg, index) => (
<Typography key={index} variant="body1" gutterBottom>
{msg}
</Typography>
))}
</Box>
{/* Input field for typing a new message */}
<TextField
label="Type your message"
variant="outlined"
value={message}
onChange={(e) => setMessage(e.target.value)}
sx={{ width: '100%', mb: 2 }}
/>
{/* Button to send the message */}
<Button variant="contained" onClick={sendMessage}>
Send
</Button>
</Box>
);
}
Loading