-
Notifications
You must be signed in to change notification settings - Fork 2
Project Milestone 3
In the frontend, every time we make a POST request with Axiom, we ensure the frontend doesn't crash if the response isn't successful.
axios
.post('http://localhost:8000/triage/triage-tickets', data)
.then(response => {
setMessage(response.data.message);
const { symptoms } = response.data;
// Redirect to homepage using navigate
navigate('/patientWaiting'); // Replace '/' with the homepage URL if needed
})
.catch(error => {
console.error(error);
setMessage(error.response?.data?.detail || 'Error registering. Please try again.');
});- Does the component request correctly for valid requests?
- Does the component handle exceptions for invalid requests?
- In Enter Virtual Triage, submit a ticket as normal. Request works as normal.
- In
EnterVirtualTriage.js, in the address field of the axiom post request inhandleEnter(), and change tohttp://localbadhost:8000/triage/triage-tickets. Submit a ticket as normal. Request is denied, error message "Error registering. Please try again." is issued.
login and enter tell the user gracefully it didn't work
https://react-bootstrap.netlify.app/docs/forms/form-control/
In our database hosting service, MongoDB Compass, we maintain replica sets of the data. The database cluster has a primary node and two secondary nodes. The primary node fields read and write calls from our API, and the secondary nodes remain ready to switchover in the event of a failure. The nodes communicate via heartbeat to maintain connectivity.
- Are the nodes synchronized?
- Are the nodes consistent?
- Are the nodes maintaining communication?
- Do the nodes failover successfully?
- Do the nodes failover consistently and quickly enough?
- Issue
r.status()in the mongosh terminal to check if the each member is working properly. Each member should have a health value of1. One member should havestateStr: PRIMARY, and the other two should havestateStr: SECONDARY. - In the terminal, issue
db.ShutdownServer(). This shuts down the primary node. Issuer.status()to confirm. - Attempt to register from mr_ed web app. The API call to the database works despite the primary node being down.
- Restart mongoDB service with
sudo systemctl start mongodin the terminal to restore default system state.
CORS
For your project, identify and plan at least five design patterns in your design and system. It should be a pattern that you implement. On your Wiki, create a section, "Design Patterns," where you describe each design pattern in general and how they manifest in your design and system. Implement the code for these five design patterns in your project.
LIAM PUT COPILOT HERE:
The Decorator pattern allows behavior to be added to individual objects, dynamically, without affecting the behavior of other objects from the same class. In your project, this pattern is evident in the use of decorators in FastAPI.
-
Route Decorators: The
@router.get,@router.post,@router.put, and@router.deletedecorators intriage_routes.pyadd routing behavior to the functions they decorate.
@router.get("/tickets", response_model=List[VTTicket])
async def get_all_tickets():
return await get_tickets()-
Middleware Decorators: The
@app.middlewaredecorator can be used to add middleware to the FastAPI application.
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)The Observer pattern is used to allow an object to notify other objects about changes in its state. In your project, this pattern is evident in the use of React's useEffect hook, which allows components to react to changes in state or props.
-
useEffect Hook: The
useEffecthook inNurseWaiting.jsobserves changes in the component's state and performs side effects like data fetching.
useEffect(() => {
const fetchTickets = async () => {
try {
const response = await fetch('/api/triage-tickets');
const data = await response.json();
setTickets(data);
} catch (error) {
console.error('Error fetching tickets:', error);
} finally {
setLoading(false);
}
};
fetchTickets();
}, []);The Factory pattern is used to create objects without specifying the exact class of object that will be created. In your project, this pattern is evident in the creation of VTTicket instances from the data fetched from the database.
-
Creating VTTicket Instances: The
VTTicketmodel's constructor acts as a factory method to create instances of the model from the data returned by the database.
async def get_tickets() -> List[VTTicket]:
try:
tickets = list(tickets_collection.find({}, {'_id': 0})) # Exclude the MongoDB _id field
return [VTTicket(**ticket) for ticket in tickets]
except Exception as e:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))The MVC pattern separates an application into three main components: Model, View, and Controller. This separation helps in organizing the code and promoting reusability and maintainability.
-
Model: The
VTTicketmodel inVirtualTriage.pydefines the structure of the data.
class VTTicket(BaseModel):
ticketID: int
userID: str
ED: str
consent: bool
timestamp: str
generalSymptoms: GeneralSymptoms
respiratorySymptoms: RespiratorySymptoms
gastrointestinalSymptoms: GastrointestinalSymptoms
neurologicalSymptoms: NeurologicalSymptoms
musculoskeletalSymptoms: MusculoskeletalSymptoms
cardiovascularSymptoms: CardiovascularSymptoms
skinSymptoms: SkinSymptoms
psychologicalSymptoms: PsychologicalSymptoms
substanceHabits: SubstanceHabits
allergies: List[str]
medications: List[str]
durationOfSymptoms: str
listAllergies: List[str]
pastMedicalConditions: List[str]-
View: The
NurseWaiting.jsReact component is responsible for rendering the user interface.
const NurseWaiting = () => {
const [tickets, setTickets] = useState([]);
const [loading, setLoading] = useState(true);
const [selectedTicket, setSelectedTicket] = useState(null);
useEffect(() => {
const fetchTickets = async () => {
try {
const response = await fetch('/api/triage-tickets');
const data = await response.json();
setTickets(data);
} catch (error) {
console.error('Error fetching tickets:', error);
} finally {
setLoading(false);
}
};
fetchTickets();
}, []);
if (loading) {
return <div>Loading...</div>;
}
if (selectedTicket) {
return (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: '20px' }}>
<h1>Ticket Details</h1>
<div style={{
border: '1px solid #ccc',
padding: '20px',
borderRadius: '5px',
backgroundColor: '#f9f9f9',
width: '80%',
textAlign: 'center',
transition: 'transform 0.2s, background-color 0.2s',
}}>
<strong>User ID:</strong> {selectedTicket.userID || 'N/A'}
<div><strong>Timestamp:</strong> {selectedTicket.timestamp}</div>
<div><strong>Allergies:</strong> {selectedTicket.listAllergies?.join(', ') || 'None'}</div>
<div><strong>Duration:</strong> {selectedTicket.durationOfSymptoms || 'N/A'}</div>
<h3>Symptoms:</h3>
<div>
{Object.entries(selectedTicket).map(([key, value]) => {
if (typeof value === 'object' && value !== null) {
return (
<div key={key}>
<strong>{key}:</strong>
<ul>
{Object.entries(value).map(([symptom, hasSymptom]) => (
<li key={symptom}>{symptom}: {hasSymptom ? 'Yes' : 'No'}</li>
))}
</ul>
</div>
);
}
return null;
})}
</div>
<button onClick={() => setSelectedTicket(null)} style={{ marginTop: '20px' }}>Back</button>
</div>
</div>
);
}
return (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: '20px' }}>
<h1 style={{ marginBottom: '20px' }}>Incoming Triage Tickets</h1>
<div style={{ width: '80%', display: 'flex', flexDirection: 'column', gap: '10px' }}>
{tickets.map(ticket => (
<div key={ticket.ticketID} style={{
border: '1px solid #ccc',
padding: '10px',
borderRadius: '5px',
backgroundColor: '#f9f9f9',
transition: 'transform 0.2s',
cursor: 'pointer'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'scale(1.05)';
e.currentTarget.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'scale(1)';
e.currentTarget.style.boxShadow = 'none';
}}
onClick={() => setSelectedTicket(ticket)}
>
<strong>User ID:</strong> {ticket.userID}
<div><strong>Timestamp:</strong> {ticket.timestamp}</div>
<div><strong>Allergies:</strong> {ticket.listAllergies?.join(', ') || 'None'}</div>
<div><strong>Duration:</strong> {ticket.durationOfSymptoms || 'N/A'}</div>
</div>
))}
</div>
</div>
);
};
export default NurseWaiting;-
Controller: The FastAPI routes in
triage_routes.pyhandle the HTTP requests and interact with the data models.
from fastapi import APIRouter, Depends
from models.VirtualTriage import VTTicket
from services.triage_service import get_tickets, create_ticket, update_ticket, delete_ticket
from typing import List
router = APIRouter()
@router.get("/tickets", response_model=List[VTTicket])
async def get_all_tickets():
return await get_tickets()
@router.post("/tickets", response_model=VTTicket)
async def create_new_ticket(ticket: VTTicket):
return await create_ticket(ticket)
@router.put("/tickets/{ticket_id}", response_model=VTTicket)
async def update_existing_ticket(ticket_id: int, ticket: VTTicket):
return await update_ticket(ticket_id, ticket)
@router.delete("/tickets/{ticket_id}", response_model=dict)
async def delete_existing_ticket(ticket_id: int):
return await delete_ticket(ticket_id)ERICH PUT STATE PATTERN HERE:
Update all the previous UML Diagrams and the System Description according to feasibility and changed requirements. This should be in detail as to why they were changed and not feasible.
Summarize the contributions made by each team member. (Point out the sections/parts each group member was "most responsible" for.)