Skip to content

Commit

Permalink
Merge pull request #47 from ctc-uci/35-create-endpoints-7
Browse files Browse the repository at this point in the history
35 create endpoints 7
  • Loading branch information
theNatePi authored Jan 27, 2025
2 parents 35dc0f0 + 9645279 commit 06c45da
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 10 deletions.
110 changes: 110 additions & 0 deletions client/src/components/EventsTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {
Table,
Thead,
Tbody,
Tr,
Th,
Td,
Menu,
MenuButton,
MenuList,
MenuItem,
Button,
} from '@chakra-ui/react';
import React, { useState, useEffect } from 'react';
import { useBackendContext } from "../contexts/hooks/useBackendContext";

export const EventsTable = () => {
const { backend } = useBackendContext();
const [ events, setEvents ] = useState([]);

const fetchEvents = async () => {
try {
const eventsResponse = await backend.get('/events');
const eventsData = eventsResponse.data;
const eventsWithAssignments = [];

for (const event of eventsData) {
const instructors = [];
const payees = [];

try {
// Attempt to fetch assignment information for each event
const assignmentsResponse = await backend.get('/assignments/event/' + event.id);
const assignmentsData = assignmentsResponse.data;

// Process assignment information if available
if (Array.isArray(assignmentsData) && assignmentsData.length > 0) {
for (const assignment of assignmentsData) {
if (assignment.role.toLowerCase() === 'instructor') {
instructors.push(assignment.clientName);
} else if (assignment.role.toLowerCase() === 'payee') {
payees.push(assignment.clientName);
}
}
}
} catch {
console.error('Failed to fetch assignments for event', event.id);
}

// Add event with assignments to list
eventsWithAssignments.push({
id: event.id,
name: event.name,
description: event.description,
instructors: instructors.join(', '),
payees: payees.join(', ')
});
}

setEvents(eventsWithAssignments);
} catch {
console.error('Failed to fetch events');
}
}

useEffect(() => {
// call the fetch event here to fetch all events
fetchEvents();
}, []);

Check warning on line 69 in client/src/components/EventsTable.jsx

View workflow job for this annotation

GitHub Actions / run-checks

React Hook useEffect has a missing dependency: 'fetchEvents'. Either include it or remove the dependency array

return (
<Table variant="striped" colorScheme="teal">
<Thead>
<Tr>
<Th>Class</Th>
<Th>Description</Th>
<Th>Instructor</Th>
<Th>Payee</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{events.map((event) => (
<Tr key={event.id}>
<Td>{event.name}</Td>
<Td>{event.description}</Td>
<Td>{event.instructors}</Td>
<Td>{event.payees}</Td>
<Td>
<Menu>
<MenuButton
as={Button}
size="sm"
variant="outline"
>
Actions
</MenuButton>
<MenuList>
<MenuItem onClick={() => {}}>Edit</MenuItem>
<MenuItem onClick={() => {}}>Delete</MenuItem>
</MenuList>
</Menu>
</Td>
</Tr>
))}
</Tbody>
</Table>
);

};
8 changes: 5 additions & 3 deletions client/src/components/playground/Playground.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
Heading,
VStack,
} from "@chakra-ui/react";
Heading,
VStack,
} from "@chakra-ui/react";
import { EventsTable } from "../EventsTable";
import React from 'react';
import PDFButton from "../PDFButton";

Expand All @@ -12,6 +13,7 @@ export const Playground = () => {
sx={{ width: 300, marginX: "auto" }}
>
<Heading>Playground</Heading>
<EventsTable />
<PDFButton/>
</VStack>
);
Expand Down
28 changes: 23 additions & 5 deletions server/routes/assignments.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
import express from "express";
import {db} from "../db/db-pgp";
import { Router } from "express";
import { keysToCamel } from "../common/utils";
import { db } from "../db/db-pgp";

const assignmentsRouter = express.Router();
export const assignmentsRouter = Router();
assignmentsRouter.use(express.json());

// Get assignments for a specific event
assignmentsRouter.get("/event/:event_id", async (req, res) => {
try {
const { event_id } = req.params;

const assignments = await db.query(
`SELECT a.id, a.event_id, a.client_id, a.role, c.name as client_name, e.name as event_name
FROM assignments a, clients c, events e
WHERE a.client_id = c.id AND a.event_id = e.id AND a.event_id = $1
ORDER BY a.id ASC`,
[event_id]
);

res.status(200).json(keysToCamel(assignments));
} catch (err) {
res.status(500).send(err.message);
}
});

assignmentsRouter.post("/", async (req, res) => {
try {
const { eventId, clientId, role } = req.body;
Expand Down Expand Up @@ -65,6 +85,4 @@ assignmentsRouter.delete("/:id", async (req, res) => {
});




export { assignmentsRouter };
export { assignmentsRouter };
67 changes: 65 additions & 2 deletions server/routes/clients.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,76 @@ import { db } from "../db/db-pgp"; // TODO: replace this db with

export const clientsRouter = Router();

// Get all comments
// Get all clients
clientsRouter.get("/", async (req, res) => {
try {
const users = await db.query(`SELECT * FROM clients ORDER BY id ASC`);

res.status(200).json(keysToCamel(users));
} catch (err) {
res.status(400).send(err.message);
res.status(500).send(err.message);
}
});

// Get client by id
clientsRouter.get("/:id", async (req, res) => {
try {
const { id } = req.params;
const user = await db.query(`SELECT * FROM clients WHERE id = $1`, [id]);

// Case when client not found
if (user.length === 0) {
return res.status(404).json(keysToCamel("Client not found"));
}

res.status(200).json(keysToCamel(user[0]));
} catch (err) {
res.status(500).send(err.message);
}
});

// Put client by id
clientsRouter.put("/:id", async (req, res) => {
try {
const { id } = req.params;
const { name, email } = req.body;

// Update just the name or just the email, without having to provide both fields
const updatedClient = await db.query(
`
UPDATE clients
SET
name = COALESCE($1, name),
email = COALESCE($2, email)
WHERE id = $3
RETURNING *
`,
[name, email, id]);

if (updatedClient.length === 0) {
return res.status(404).json(keysToCamel("Client not found"));
}

res.status(200).json(keysToCamel(updatedClient));
} catch (err) {
res.status(500).send(err.message);
}
});

// Delete client by id
clientsRouter.delete("/:id", async (req, res) => {
try {
const { id } = req.params;
const deletedClient = await db.query('DELETE FROM clients WHERE id = $1 RETURNING *', [id]);

if (deletedClient.length === 0) {
return res.status(404).json(keysToCamel({result: "error", message: "Client not found"}));
}

res.status(200).json(keysToCamel({result: "success", deletedClient: deletedClient[0]}));

} catch (err) {
res.status(500).send(err.message);
}
});

Expand All @@ -28,3 +90,4 @@ clientsRouter.post("/", async (req, res) => {
res.status(400).send(err.message);
}
});

1 change: 1 addition & 0 deletions server/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { bookingsRouter } from "../routes/bookings";
import { assignmentsRouter } from "../routes/assignments";
import { verifyToken } from "./middleware";
import { clientsRouter } from "../routes/clients";
import { assignmentsRouter } from "../routes/assignments";
import { invoicesRouter } from "../routes/invoices";

dotenv.config();
Expand Down

0 comments on commit 06c45da

Please sign in to comment.