Skip to content

Commit

Permalink
Merge pull request #78 from ctc-uci/71-settings-page-skeleton-and-tot…
Browse files Browse the repository at this point in the history
…al-endpoint

Created total endpoint and settings skeleton
  • Loading branch information
jessieh9 authored Feb 23, 2025
2 parents a636495 + 9cc3264 commit e743dd9
Show file tree
Hide file tree
Showing 3 changed files with 436 additions and 94 deletions.
5 changes: 5 additions & 0 deletions client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { AuthProvider } from "./contexts/AuthContext";
import { BackendProvider } from "./contexts/BackendContext";
import { RoleProvider } from "./contexts/RoleContext";
import { Home } from "./components/home/Home";
import { Settings } from "./components/settings/Settings";

const App = () => {
return (
Expand Down Expand Up @@ -96,6 +97,10 @@ const App = () => {
path="/programs/:id"
element={<ProtectedRoute element={<Program />} />}
/>
<Route
path="/settings"
element={<ProtectedRoute element={<Settings />} />}
/>
<Route
path="*"
element={<ProtectedRoute element={<CatchAll />} />}
Expand Down
246 changes: 246 additions & 0 deletions client/src/components/settings/Settings.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
import { useEffect, useState } from "react";

import {
Button,
Heading,
Input,
Popover,
PopoverBody,
PopoverContent,
PopoverFooter,
PopoverHeader,
PopoverTrigger,
Stack,
Table,
TableContainer,
Tbody,
Td,
Text,
Th,
Thead,
Tr,
} from "@chakra-ui/react";

import { useBackendContext } from "../../contexts/hooks/useBackendContext";
import Navbar from "../navbar/Navbar";

export const Settings = () => {
const [users, setUsers] = useState([]);
const [rooms, setRooms] = useState([]);
const [selectedRoom, setSelectedRoom] = useState(null);
const [newRate, setNewRate] = useState("");
const { backend } = useBackendContext();

useEffect(() => {
const fetchUserData = async () => {
try {
const response = await backend.get("/users");
const pendingUsers = response.data.filter(
(user) => user.editPerms === false
);
setUsers(pendingUsers);
console.log(pendingUsers);
} catch (error) {
console.log("Error fetching users:", error);
}
};

const fetchRoomsData = async () => {
try {
const response = await backend.get("/rooms");
setRooms(response.data);
console.log(response.data);
} catch (error) {
console.log("Error fetching rooms: ", error);
}
};
fetchUserData();
fetchRoomsData();
}, [backend]);

// Approve users function: set edit_perms = True and update the rendering of the table
const handleApprove = async (user) => {
try {
await backend.put(`/users/${user.id}`, {
email: user.email,
firstName: user.first_name,
lastName: user.last_name,
editPerms: true,
});
// Remove approved user from the list
setUsers(users.filter((u) => u.id !== user.id));
} catch (error) {
console.log("Error approving user:", error);
}
};

// Remove a user and delete from DB and Firebase
const handleRemove = async (user) => {
try {
// await backend.delete(`/users/${user.id}`);
await backend.delete(`/users/${user.firebaseUid}`);
setUsers(users.filter((u) => u.id !== user.id));
} catch (error) {
console.log("Error removing user:", error);
}
};

// Open the edit panel for a room
const handleEditRoom = (room) => {
setSelectedRoom(room);
setNewRate(room.rate);
};

// Save the updated room rate
const handleSaveRate = async () => {
try {
await backend.put(`/rooms/${selectedRoom.id}`, {
...selectedRoom,
rate: newRate,
});
setRooms(
rooms.map((room) =>
room.id === selectedRoom.id ? { ...room, rate: newRate } : room
)
);
setSelectedRoom(null);
setNewRate("");
} catch (error) {
console.log("Error updating room rate:", error);
}
};

// Cancel editing
const handleCancelEdit = () => {
setSelectedRoom(null);
setNewRate("");
};

return (
<Navbar>
<Stack m="20">
<Heading size="lg">Approve Users</Heading>
<TableContainer mb="40px">
<Table variant="striped">
<Thead>
<Tr>
<Th>Name</Th>
<Th>Created</Th>
<Th>Approve</Th>
<Th>Deny</Th>
<Th>Make Admin</Th>
</Tr>
</Thead>
<Tbody>
{users.map((user) => (
<Tr key={user.id}>
<Td>{`${user.firstName} ${user.lastName}`}</Td>
<Td>January 20, 2025</Td>
<Td>
<Button
onClick={() => handleApprove(user)}
colorScheme="green"
>
Approve
</Button>
</Td>
<Td>
<Button
onClick={() => handleRemove(user)}
colorScheme="red"
>
Deny
</Button>
</Td>
<Td>
<Button
colorScheme="blackAlpha"
variant="outline"
>
Admin
</Button>
</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</Stack>

<Stack m="20">
<Heading size="lg">Edit Room Rate</Heading>
<TableContainer mb="40px">
<Table variant="striped">
<Thead>
<Tr>
<Th>Room</Th>
<Th>Rate</Th>
<Th>Edit</Th>
</Tr>
</Thead>
<Tbody>
{rooms.map((room) => (
<Tr key={room.id}>
<Td>{room.name}</Td>
<Td>{room.rate}</Td>
<Td>
<Popover>
{({ onClose }) => (
<>
<PopoverTrigger>
<Button onClick={() => handleEditRoom(room)}>
Edit
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverHeader>Edit Room Rate</PopoverHeader>
<PopoverBody>
<Stack>
<Text as="b">Room:</Text>
<Text>{room.name}</Text>
<Input
mt="2"
type="number"
value={newRate}
onChange={(e) => setNewRate(e.target.value)}
/>
</Stack>
</PopoverBody>
<PopoverFooter
display="flex"
justifyContent="flex-end"
>
<Button
colorScheme="green"
mr="3"
onClick={() => {
handleSaveRate();
onClose();
}}
>
Save
</Button>
<Button
colorScheme="red"
onClick={() => {
handleCancelEdit();
onClose();
}}
>
Cancel
</Button>
</PopoverFooter>
</PopoverContent>
</>
)}
</Popover>
</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</Stack>
</Navbar>
);
};
Loading

0 comments on commit e743dd9

Please sign in to comment.