Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Notifications Page #63

Merged
merged 9 commits into from
Feb 9, 2025
Merged
5 changes: 5 additions & 0 deletions client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { CatchAll } from "./components/CatchAll";
import { Dashboard } from "./components/dashboard/Dashboard";
import { Playground } from "./components/playground/Playground";
import { Notifications } from "./components/notifications/Notifications";
import { Login } from "./components/login/Login";
import { ProtectedRoute } from "./components/ProtectedRoute";
import { Signup } from "./components/signup/Signup";
Expand All @@ -17,8 +18,8 @@
import { BackendProvider } from "./contexts/BackendContext";
import { RoleProvider } from "./contexts/RoleContext";
import { ForgotPassword } from "./components/login/ForgotPassword";
import { PDFViewer } from "@react-pdf/renderer";

Check warning on line 21 in client/src/App.jsx

View workflow job for this annotation

GitHub Actions / run-checks

'PDFViewer' is defined but never used. Allowed unused vars must match /^_/u
import PDFButton from "./components/PDFButton";

Check warning on line 22 in client/src/App.jsx

View workflow job for this annotation

GitHub Actions / run-checks

'PDFButton' is defined but never used. Allowed unused vars must match /^_/u

const App = () => {
return (
Expand All @@ -40,6 +41,10 @@
path="/playground"
element={<Playground />}
/>
<Route
path="/notifications"
element={<ProtectedRoute element={<Notifications />} />}
/>
<Route
path="/dashboard"
element={<ProtectedRoute element={<Dashboard />} />}
Expand Down
14 changes: 14 additions & 0 deletions client/src/components/notifications/CalendarIcon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const CalendarIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M15.8333 15.8333H4.16667V6.66668H15.8333M13.3333 0.833344V2.50001H6.66667V0.833344H5V2.50001H4.16667C3.24167 2.50001 2.5 3.24168 2.5 4.16668V15.8333C2.5 16.2754 2.67559 16.6993 2.98816 17.0119C3.30072 17.3244 3.72464 17.5 4.16667 17.5H15.8333C16.2754 17.5 16.6993 17.3244 17.0118 17.0119C17.3244 16.6993 17.5 16.2754 17.5 15.8333V4.16668C17.5 3.72465 17.3244 3.30073 17.0118 2.98817C16.6993 2.6756 16.2754 2.50001 15.8333 2.50001H15V0.833344M14.1667 10H10V14.1667H14.1667V10Z"
fill="#767778"
/>
</svg>
);
29 changes: 29 additions & 0 deletions client/src/components/notifications/Counter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const CounterComponent = ({ count }) => {
return (
<div
style={{
width: "75px",
height: "31px",
borderRadius: "10px",
border: "1px solid var(--medium-light-grey, #D2D2D2)",
background: "#FFF",
marginTop: "3px",
}}
>
<p
style={{
color: "var(--medium-grey, #767778",
fontFamily: "Inter, sans-serif",
fontSize: "20px",
fontStyle: "normal",
fontWeight: 400,
lineHeight: "normal",
textAlign: "center",
marginTop: "3px",
}}
>
{count}
</p>
</div>
);
};
141 changes: 141 additions & 0 deletions client/src/components/notifications/FilterButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { useEffect, useState } from "react";
import {
Button,
HStack,
Popover,
PopoverBody,
PopoverCloseButton,
PopoverContent,
PopoverTrigger,
Text,
useToast,
} from "@chakra-ui/react";

import { CalendarIcon } from "./CalendarIcon";
import styles from "./FilterButton.module.css";
import { FilterIcon } from "./FilterIcon";

export const FilterButton = ({ setFilterType, currentFilter }) => {
const [startDate, setStartDate] = useState("");
const [endDate, setEndDate] = useState("");
const toast = useToast();
const [type, setType] = useState("all");

// Watch for changes in both dates
useEffect(() => {
console.log(startDate, endDate);
if (startDate.substring(0,1) === "2" && endDate.substring(0,1) === "2") { // checking if the date is filled out completely
const start = new Date(startDate);
const end = new Date(endDate);

console.log(start, end);
if (start > end) {
toast({
title: "Invalid Date Range",
description: "Start date must be before end date",
status: "error",
duration: 3000,
isClosable: true,
});
return;
}

// Update filter with new dates
setFilterType(prev => ({
...prev,
type: type,
startDate: startDate, // The date input already returns YYYY-MM-DD format
endDate: endDate
}));
}
}, [startDate, endDate, type, toast]);

Check warning on line 51 in client/src/components/notifications/FilterButton.jsx

View workflow job for this annotation

GitHub Actions / run-checks

React Hook useEffect has a missing dependency: 'setFilterType'. Either include it or remove the dependency array. If 'setFilterType' changes too often, find the parent component that defines it and wrap that definition in useCallback

const handleFilterSelect = (type) => {
setType(type);
setFilterType(prev => ({
...prev,
type,
}));
};

return (
<Popover placement="bottom-end">
<PopoverTrigger>
<Button
leftIcon={<FilterIcon />}
display="inline-flex"
height="54.795px"
padding="8px 16px"
justifyContent="center"
alignItems="center"
gap="4px"
flexShrink={0}
borderRadius={15}
border="1px solid var(--medium-light-grey, #D2D2D2)"
background="var(--white, #FFF)"
color="var(--medium-grey, #767778)"
fontFamily="Inter, sans-serif"
fontSize="16px"
fontStyle="normal"
fontWeight={400}
lineHeight="normal"
>
Filters
</Button>
</PopoverTrigger>

<PopoverContent
className={styles.modalContent}
boxShadow="0px 4px 6px -1px rgba(0, 0, 0, 0.1)"
border="1px solid #E2E2E2"
>
<PopoverCloseButton />
<PopoverBody className={styles.modalBody}>
<HStack spacing={2} className={styles.dateRangeHeader}>
<CalendarIcon />
<Text>Date Range</Text>
</HStack>

<div className={styles.dateInputContainer}>
<input
type="date"
value={startDate}
onChange={(e) => setStartDate(e.target.value)}
className={styles.dateInput}
/>
<Text className={styles.toText}>to</Text>
<input
type="date"
value={endDate}
onChange={(e) => setEndDate(e.target.value)}
className={styles.dateInput}
/>
</div>

<Text className={styles.typeHeader}>Type</Text>

<div className={styles.filterButtonGroup}>
<Button
onClick={() => handleFilterSelect("all")}
className={`${styles.filterButton} ${currentFilter.type === "all" ? styles.active : ""}`}
>
All
</Button>
<Button
onClick={() => handleFilterSelect("overdue")}
className={`${styles.filterButton} ${currentFilter.type === "overdue" ? styles.active : ""}`}
>
Overdue
</Button>
<Button
onClick={() => handleFilterSelect("neardue")}
className={`${styles.filterButton} ${currentFilter.type === "neardue" ? styles.active : ""}`}
>
Near Due
</Button>
</div>
</PopoverBody>
</PopoverContent>
</Popover>
);
};
149 changes: 149 additions & 0 deletions client/src/components/notifications/FilterButton.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/* FilterButton.module.css */
.modalContent {
display: inline-flex;
padding: 16px;
flex-direction: column;
align-items: flex-start;
gap: 16px;
border-radius: 15px;
border: 1px solid var(--medium-light-grey, #D2D2D2);
background: var(--white, #FFF);
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
width: 200px;
}

.dateRangeHeader {
color: var(--medium-grey, #767778);
font-family: "Inter", sans-serif;
font-size: 18px;
font-style: normal;
font-weight: 600;
line-height: normal;
margin-bottom: 16px;

}

.modalBody {
padding: 0;
}

.dateInputContainer {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
width: 280px;
}

.dateInput {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 5px;
border: 1px solid var(--medium-light-grey, #d2d2d2);
background-color: #F6F6F6;
padding: 8px;
font-family: "Inter", sans-serif;
font-size: 13px;
color: #767778;
width: 110px;
cursor: pointer;
overflow: hidden;
}

/* Make the calendar icon transparent but keep it clickable */
.dateInput::-webkit-calendar-picker-indicator {
opacity: 0;
position: absolute;
width: 100%;
height: 100%;
cursor: pointer;
margin: 0;
padding: 0;
visibility: hidden;
}


/* Remove default styling */
.dateInput::-webkit-datetime-edit {
padding: 0;
}

.dateInput::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}

.dateInput::-webkit-datetime-edit-text,
.dateInput::-webkit-datetime-edit-month-field,
.dateInput::-webkit-datetime-edit-day-field,
.dateInput::-webkit-datetime-edit-year-field {
color: #767778;
}

/* When no date is selected (placeholder state) */
.dateInput:invalid {
color: #767778;
}


.dateInput::placeholder{
color: var(--medium-grey, #767778);
font-family: "Inter", sans-serif;
font-size: 13px;
font-style: normal;
font-weight: 500;
line-height: 20px; /* 125% */
}

.toText {
color: var(--medium-grey, #767778);
font-family: "Inter", sans-serif;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: normal;
}

.typeHeader {
color: var(--medium-grey, #767778);
font-family: "Inter", sans-serif;
font-size: 18px;
font-style: normal;
font-weight: 600;
line-height: normal;
margin-bottom: 16px;
}

.filterButtonGroup {
display: flex;
align-items: flex-start;
gap: 12px;
align-self: stretch;
}

.filterButton {
border: 1px solid #d2d2d2 !important;
border-radius: 15px !important;
padding: 0px 15px !important;
background: white !important;
color: #767778 !important;
transition: all 0.2s !important;
color: var(--medium-grey, #767778);
font-family: "Inter", sans-serif;
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: normal;
}

.filterButton:hover {
background: #f5f5f5 !important;
}

.filterButton.active {
color: var(--indigo, #4E4AE7) !important;
border-radius: 30px !important;
border: 1px solid var(--indigo, #4E4AE7) !important;
background: var(--light-indigo, #EDEDFD) !important;
}
18 changes: 18 additions & 0 deletions client/src/components/notifications/FilterIcon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const FilterIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="21"
viewBox="0 0 20 21"
fill="none"
style={{ marginRight: '8px' }} // Add some spacing between icon and text
>
<path
d="M5.00016 10.3973C4.55814 10.3973 4.13421 10.2217 3.82165 9.9091C3.50909 9.59654 3.3335 9.17262 3.3335 8.73059C3.3335 8.28856 3.50909 7.86464 3.82165 7.55208C4.13421 7.23952 4.55814 7.06392 5.00016 7.06392M5.00016 10.3973C5.44219 10.3973 5.86611 10.2217 6.17867 9.9091C6.49123 9.59654 6.66683 9.17262 6.66683 8.73059C6.66683 8.28856 6.49123 7.86464 6.17867 7.55208C5.86611 7.23952 5.44219 7.06392 5.00016 7.06392M5.00016 10.3973V17.0639M5.00016 7.06392V3.73059M10.0002 15.3973C9.55814 15.3973 9.13421 15.2217 8.82165 14.9091C8.50909 14.5965 8.3335 14.1726 8.3335 13.7306C8.3335 13.2886 8.50909 12.8646 8.82165 12.5521C9.13421 12.2395 9.55814 12.0639 10.0002 12.0639M10.0002 15.3973C10.4422 15.3973 10.8661 15.2217 11.1787 14.9091C11.4912 14.5965 11.6668 14.1726 11.6668 13.7306C11.6668 13.2886 11.4912 12.8646 11.1787 12.5521C10.8661 12.2395 10.4422 12.0639 10.0002 12.0639M10.0002 15.3973V17.0639M10.0002 12.0639V3.73059M15.0002 7.89726C14.5581 7.89726 14.1342 7.72166 13.8217 7.4091C13.5091 7.09654 13.3335 6.67262 13.3335 6.23059C13.3335 5.78856 13.5091 5.36464 13.8217 5.05208C14.1342 4.73952 14.5581 4.56392 15.0002 4.56392M15.0002 7.89726C15.4422 7.89726 15.8661 7.72166 16.1787 7.4091C16.4912 7.09654 16.6668 6.67262 16.6668 6.23059C16.6668 5.78856 16.4912 5.36464 16.1787 5.05208C15.8661 4.73952 15.4422 4.56392 15.0002 4.56392M15.0002 7.89726V17.0639M15.0002 4.56392V3.73059"
stroke="currentColor" // This will inherit the button's text color
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
); /** simplified syntax */
Loading
Loading