diff --git a/client/package.json b/client/package.json
index c929497..7267c75 100644
--- a/client/package.json
+++ b/client/package.json
@@ -19,6 +19,7 @@
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@hookform/resolvers": "^3.9.0",
+ "@react-email/components": "^0.0.33",
"@react-pdf/renderer": "^4.1.6",
"axios": "^1.7.4",
"firebase": "10.12.5",
diff --git a/client/src/assets/icons/CkEmail.svg b/client/src/assets/icons/CkEmail.svg
new file mode 100644
index 0000000..a744ae2
--- /dev/null
+++ b/client/src/assets/icons/CkEmail.svg
@@ -0,0 +1,13 @@
+
diff --git a/client/src/components/email/SendEmailButton.jsx b/client/src/components/email/SendEmailButton.jsx
new file mode 100644
index 0000000..7931dae
--- /dev/null
+++ b/client/src/components/email/SendEmailButton.jsx
@@ -0,0 +1,62 @@
+import React, { useState } from "react";
+
+import {
+ Button,
+ Flex,
+ Input,
+ FormControl,
+ FormErrorMessage
+} from "@chakra-ui/react";
+
+import { useBackendContext } from "../../contexts/hooks/useBackendContext";
+
+const SendEmailButton = () => {
+ const { backend } = useBackendContext();
+ const [email, setEmail] = useState("");
+ const [error, setError] = useState("");
+
+ const validateEmail = (email) => {
+ const regex = /\S+@\S+\.\S+/;
+ return regex.test(email);
+ };
+
+ const sendEmail = async () => {
+ if (!validateEmail(email)) {
+ setError("Please enter a valid email address.");
+ return;
+ }
+
+ const response = await backend.post("/email/send", {
+ to: email,
+ subject: "Invoice",
+ text: "This is a test email.",
+ html: "
{
{
{item.icon}
- {item.name}
+ {item.name}
+ {item.count !== null && item.count !== undefined && (
+
+ {item.count}
+
+ )}
))}
-
diff --git a/client/src/components/notifications/Counter.jsx b/client/src/components/notifications/Counter.jsx
index 1614d61..13af1bb 100644
--- a/client/src/components/notifications/Counter.jsx
+++ b/client/src/components/notifications/Counter.jsx
@@ -4,8 +4,6 @@ export const CounterComponent = ({ count }) => {
style={{
width: "75px",
height: "31px",
- borderRadius: "10px",
- border: "1px solid var(--medium-light-grey, #D2D2D2)",
background: "#FFF",
marginTop: "3px",
}}
diff --git a/client/src/components/notifications/FilterButton.jsx b/client/src/components/notifications/FilterButton.jsx
index e846d63..f98fba5 100644
--- a/client/src/components/notifications/FilterButton.jsx
+++ b/client/src/components/notifications/FilterButton.jsx
@@ -1,4 +1,5 @@
import { useEffect, useState } from "react";
+
import {
Button,
HStack,
@@ -16,43 +17,12 @@ 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]);
-
const handleFilterSelect = (type) => {
setType(type);
- setFilterType(prev => ({
+ setFilterType((prev) => ({
...prev,
type,
}));
@@ -68,16 +38,15 @@ export const FilterButton = ({ setFilterType, currentFilter }) => {
padding="8px 16px"
justifyContent="center"
alignItems="center"
- gap="4px"
flexShrink={0}
- borderRadius={15}
+ borderRadius={30}
border="1px solid var(--medium-light-grey, #D2D2D2)"
- background="var(--white, #FFF)"
+ background="#F0F1F4"
color="var(--medium-grey, #767778)"
fontFamily="Inter, sans-serif"
- fontSize="16px"
- fontStyle="normal"
- fontWeight={400}
+ fontSize="15px"
+ fontStyle="bold"
+ fontWeight={650}
lineHeight="normal"
>
Filters
@@ -88,30 +57,10 @@ export const FilterButton = ({ setFilterType, currentFilter }) => {
className={styles.modalContent}
boxShadow="0px 4px 6px -1px rgba(0, 0, 0, 0.1)"
border="1px solid #E2E2E2"
+ w={"auto"}
>
-
-
- Date Range
-
-
-
- setStartDate(e.target.value)}
- className={styles.dateInput}
- />
- to
- setEndDate(e.target.value)}
- className={styles.dateInput}
- />
-
-
Type
@@ -121,21 +70,27 @@ export const FilterButton = ({ setFilterType, currentFilter }) => {
>
All
+
);
-};
\ No newline at end of file
+};
diff --git a/client/src/components/notifications/FilterButton.module.css b/client/src/components/notifications/FilterButton.module.css
index 00eb305..1d77da9 100644
--- a/client/src/components/notifications/FilterButton.module.css
+++ b/client/src/components/notifications/FilterButton.module.css
@@ -9,7 +9,7 @@
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;
+ width: 100px;
}
.dateRangeHeader {
@@ -109,6 +109,7 @@
.filterButtonGroup {
display: flex;
+ flex-direction: column;
align-items: flex-start;
gap: 12px;
align-self: stretch;
diff --git a/client/src/components/notifications/InboxTab.jsx b/client/src/components/notifications/InboxTab.jsx
new file mode 100644
index 0000000..faa455b
--- /dev/null
+++ b/client/src/components/notifications/InboxTab.jsx
@@ -0,0 +1,33 @@
+import Ckemail from "../../assets/icons/CkEmail.svg";
+
+const EmailIcon = () => {
+ return (
+

+ );
+};
+
+export const InboxTab = () => {
+ return (
+
+
+ Primary Inbox
+
+ );
+};
diff --git a/client/src/components/notifications/Notifications.jsx b/client/src/components/notifications/Notifications.jsx
index feebf17..ae05a2f 100644
--- a/client/src/components/notifications/Notifications.jsx
+++ b/client/src/components/notifications/Notifications.jsx
@@ -1,12 +1,14 @@
import { useEffect, useState } from "react";
+import { formatDistanceToNow } from "date-fns";
+
import { useBackendContext } from "../../contexts/hooks/useBackendContext";
import Navbar from "../navbar/Navbar";
-import NotificationsComponents from "./NotificationsComponents";
import { CounterComponent } from "./Counter";
import { FilterButton } from "./FilterButton";
import styles from "./Notifications.module.css";
-import { formatDistanceToNow } from 'date-fns';
+import NotificationsComponents from "./NotificationsComponents";
+import { InboxTab } from "./InboxTab";
export const Notifications = () => {
const { backend } = useBackendContext();
@@ -23,25 +25,25 @@ export const Notifications = () => {
try {
const today = new Date();
let endpoints = [];
- let queryParams = "";
-
- // If we have dates, add them as query params regardless of filter type
- if (filterType.startDate && filterType.endDate) {
- queryParams = `?startDate=${filterType.startDate}&endDate=${filterType.endDate}`;
- }
// Only modify the endpoint if we're filtering by type AND it's not "all"
if (filterType.type === "all") {
- endpoints = [`/invoices/overdue${queryParams}`, `/invoices/neardue${queryParams}`];
+ endpoints = [
+ `/invoices/overdue`,
+ `/invoices/neardue`,
+ `/invoices/highpriority`,
+ ];
} else {
- endpoints = [`/invoices/${filterType.type}${queryParams}`];
+ endpoints = [`/invoices/${filterType.type}`];
}
const responses = await Promise.all(
- endpoints.map(endpoint => backend.get(endpoint))
+ endpoints.map((endpoint) => backend.get(endpoint))
);
- const notifsData = responses.flatMap(res => res.data);
+ const notifsData = responses.flatMap((res) => res.data);
+
+ console.log(notifsData);
// Fetch additional data for each invoice (total, paid, event name)
const enrichedInvoices = await Promise.all(
@@ -56,10 +58,12 @@ export const Notifications = () => {
const endDate = new Date(invoice.endDate);
const dueTime = formatDistanceToNow(endDate, { addSuffix: true });
let payStatus = "";
- if (endDate < today) {
+ if (endDate < today && invoice.isSent) {
payStatus = "overdue";
+ } else if (endDate < today && !invoice.isSent) {
+ payStatus = "highpriority";
} else {
- payStatus = "due in one week";
+ payStatus = "neardue";
}
return {
@@ -68,23 +72,26 @@ export const Notifications = () => {
total: totalRes.data.total,
paid: paidRes.data.paid,
payStatus,
- dueTime
+ dueTime,
};
} catch (err) {
- console.error(`Failed to fetch additional data for invoice ID: ${invoice.id}`, err);
+ console.error(
+ `Failed to fetch additional data for invoice ID: ${invoice.id}`,
+ err
+ );
return {
...invoice,
eventName: "Unknown Event",
total: 0,
paid: 0,
payStatus: "Unknown",
- dueTime: "Unknown"
+ dueTime: "Unknown",
};
}
})
);
- setNotifications(enrichedInvoices);
+ setNotifications(enrichedInvoices); // attaches additional info onto invoices
} catch (err) {
console.error("Failed to fetch invoices", err);
}
@@ -92,10 +99,16 @@ export const Notifications = () => {
fetchNotifs();
}, [filterType, backend]);
-
return (
-
-
+
+
{
Invoice Notifications
-
+
+
+
{
- return (
-
- {notifications.map((item, index) => (
-
-
-
- {
+ if (payStatus === "overdue") {
+ return (
+
+ Payment for {" "}
+
+ {eventName}
+ {" "}
+ is {payStatus}.
+
+ );
+ } else if (payStatus === "neardue") {
+ return (
+
+
+ {eventName}
+ {" "}
+ not sent to Payer(s).
+
+ );
+ } else {
+ return (
+
+ Missing an email for {" "}
+
+ {eventName}
+ {" "}
+ and is overdue.
+
+ );
+ }
+ };
+
+ const paymentRow = (eventName, payStatus, dueTime, index) => {
+ let notifType = "";
+ if (payStatus === "overdue") {
+ notifType = "Payment Past Due";
+ } else if (payStatus === "neardue") {
+ notifType = "Email Not Sent";
+ } else if (payStatus === "highpriority") {
+ notifType = "High Priority";
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
-
-
-
- {item.eventName} is {item.payStatus}
-
- {item.eventName} | Due: {format(new Date(item.endDate), "MMM d")} | Total: ${item.total} | Paid: ${item.paid}
-
-
-
- {item.dueTime}
-
- ))}
-
+ {notifType}
+
+ {paymentText(eventName, payStatus)}
+
{" "}
+
+
+
+ {dueTime}
+
+
+ );
+ };
+ return (
+
+ {notifications.map((item, index) =>
+ paymentRow(item.eventName, item.payStatus, item.dueTime, index)
+ )}
+
);
};
-export default NotificationsComponents;
\ No newline at end of file
+export default NotificationsComponents;
diff --git a/client/src/components/playground/Playground.jsx b/client/src/components/playground/Playground.jsx
index ea5c8d8..06aac9e 100644
--- a/client/src/components/playground/Playground.jsx
+++ b/client/src/components/playground/Playground.jsx
@@ -1,12 +1,13 @@
+import React from 'react';
+
import {
- Heading,
VStack,
} from "@chakra-ui/react";
-import { EventsTable } from "../EventsTable";
-import React from 'react';
-import PDFButton from "../PDFButton";
+
import Navbar from "../navbar/Navbar";
-import { AddClassModal } from '../AddClassModal';
+
+import { SendEmailButton } from "../email/SendEmailButton";
+
export const Playground = () => {
return (
@@ -15,10 +16,7 @@ export const Playground = () => {
spacing={8}
width={"100%"}
>
- Playground
-
-
-
+
);
diff --git a/server/.env.example b/server/.env.example
index 98178d3..88eae6b 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -8,3 +8,8 @@ DEV_DB_USERNAME=postgres
DEV_DB_PORT=5432
DEV_DB_NAME=postgres
DEV_DB_PASSWORD=DEV_DB_PASSWORD
+
+DEV_EMAIL_USERNAME=DEV_EMAIL_USERNAME
+DEV_EMAIL_PASSWORD=DEV_EMAIL_PASSWORD
+DEV_EMAIL_FIRSTNAME=FIRST_NAME
+DEV_EMAIL_LASTNAME=LAST_NAME
\ No newline at end of file
diff --git a/server/Test.pdf b/server/Test.pdf
new file mode 100644
index 0000000..3a01d8e
Binary files /dev/null and b/server/Test.pdf differ
diff --git a/server/common/transporter.ts b/server/common/transporter.ts
index 31518af..b987092 100644
--- a/server/common/transporter.ts
+++ b/server/common/transporter.ts
@@ -16,11 +16,11 @@ const pass =
const emailSender =
process.env.NODE_ENV === "development"
? `${process.env.DEV_EMAIL_FIRSTNAME} ${process.env.DEV_EMAIL_LASTNAME}`
- : `${process.env.PROD_EMAIL_FIRSTNAMS} ${process.env.DEV_EMAIL_LASTNAME}`;
+ : `${process.env.PROD_EMAIL_FIRSTNAME} ${process.env.DEV_EMAIL_LASTNAME}`;
// sender information
const transport = {
- host: "smtp.gmail.com", // e.g. smtp.gmail.com
+ service: "gmail",
auth: {
user,
pass,
diff --git a/server/package.json b/server/package.json
index e59779a..eda4b1f 100644
--- a/server/package.json
+++ b/server/package.json
@@ -25,7 +25,7 @@
"mongoose": "^8.2.0",
"mysql": "^2.18.1",
"node-schedule": "^2.1.1",
- "nodemailer": "^6.9.10",
+ "nodemailer": "^6.10.0",
"nodemon": "^2.0.14",
"pg-promise": "^11.5.4"
},
diff --git a/server/routes/email.js b/server/routes/email.js
new file mode 100644
index 0000000..9343a06
--- /dev/null
+++ b/server/routes/email.js
@@ -0,0 +1,35 @@
+import express, { Router } from "express";
+
+import { transporter, emailSender } from "../common/transporter";
+
+const emailRouter = Router();
+emailRouter.use(express.json());
+
+async function sendEmail(to, subject, text, html) {
+ const info = await transporter.sendMail({
+ from: emailSender,
+ to: to,
+ subject: subject,
+ text: text,
+ html: html,
+ attachments: [{
+ filename: 'Test.pdf',
+ path: 'Test.pdf',
+ contentType: 'application/pdf'
+ }],
+ })
+ return info;
+}
+
+emailRouter.post("/send", async (req, res) => {
+ const { to, subject, text, html } = req.body
+
+ try {
+ const info = await sendEmail(to, subject, text, html);
+ res.status(200).json(info);
+ } catch (error) {
+ res.status(500).send(error.message);
+ }
+})
+
+export { emailRouter };
\ No newline at end of file
diff --git a/server/routes/invoices.js b/server/routes/invoices.js
index 59645e2..6d6b7c5 100644
--- a/server/routes/invoices.js
+++ b/server/routes/invoices.js
@@ -35,28 +35,28 @@ invoicesRouter.get("/", async (req, res) => {
// Get all overdue invoices with optional date range filtering
invoicesRouter.get("/overdue", async (req, res) => {
try {
- const { startDate, endDate } = req.query;
-
+ // const { startDate, endDate } = req.query;
+
// Base query for overdue invoices
- let query = `
- SELECT * FROM invoices
- WHERE is_sent = false
- AND payment_status IN ('partial', 'none')
+ const query = `
+ SELECT * FROM invoices
+ WHERE is_sent = true
+ AND payment_status IN ('partial', 'none')
AND end_date < CURRENT_DATE`;
const params = [];
-
- // Add date range filtering if both dates are provided
- if (startDate && endDate) {
- query = `
- SELECT * FROM invoices
- WHERE is_sent = false
- AND payment_status IN ('partial', 'none')
- AND end_date < CURRENT_DATE
- AND start_date >= $1
- AND end_date <= $2`;
- params.push(startDate, endDate);
- }
+
+ // // Add date range filtering if both dates are provided
+ // if (startDate && endDate) {
+ // query = `
+ // SELECT * FROM invoices
+ // WHERE is_sent = false
+ // AND payment_status IN ('partial', 'none')
+ // AND end_date < CURRENT_DATE
+ // AND start_date >= $1
+ // AND end_date <= $2`;
+ // params.push(startDate, endDate);
+ // }
const overdueInvoices = await db.query(query, params);
res.status(200).json(keysToCamel(overdueInvoices));
@@ -65,6 +65,24 @@ invoicesRouter.get("/overdue", async (req, res) => {
}
});
+invoicesRouter.get("/highpriority", async (req, res) => {
+ try {
+ // const { startDate, endDate } = req.query;
+
+ // Base query for overdue invoices
+ const query = `
+ SELECT * FROM invoices
+ WHERE is_sent = false
+ AND payment_status IN ('partial', 'none')
+ AND end_date < CURRENT_DATE`;
+
+ const highPriorityInvoices = await db.query(query);
+ res.status(200).json(keysToCamel(highPriorityInvoices));
+ } catch (err) {
+ res.status(500).send(err.message);
+ }
+});
+
// Get all invoices due within the next week with optional date range filtering
invoicesRouter.get("/neardue", async (req, res) => {
try {
diff --git a/server/src/app.js b/server/src/app.js
index 7936ddb..13a828f 100644
--- a/server/src/app.js
+++ b/server/src/app.js
@@ -14,7 +14,8 @@ import { verifyToken } from "./middleware";
import { clientsRouter } from "../routes/clients";
import { invoicesRouter } from "../routes/invoices";
import { programsRouter } from "../routes/programs";
-import {invoicesAssignments} from "../routes/invoicesAssignments"
+import { invoicesAssignments } from "../routes/invoicesAssignments"
+import { emailRouter } from "../routes/email";
dotenv.config();
@@ -54,6 +55,7 @@ app.use("/invoices", invoicesRouter);
app.use("/assignments", assignmentsRouter)
app.use("/programs", programsRouter);
app.use("/invoicesAssignments", invoicesAssignments)
+app.use("/email", emailRouter)
app.listen(SERVER_PORT, () => {
console.info(`Server listening on ${SERVER_PORT}`);
});
diff --git a/yarn.lock b/yarn.lock
index d255f69..8ea0698 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -150,28 +150,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.24.7"
-"@babel/runtime@^7.0.0":
- version "7.25.0"
- resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz"
- integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
- dependencies:
- regenerator-runtime "^0.14.0"
-
-"@babel/runtime@^7.12.13":
- version "7.25.0"
- resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz"
- integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
- dependencies:
- regenerator-runtime "^0.14.0"
-
-"@babel/runtime@^7.12.5":
- version "7.25.0"
- resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz"
- integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
- dependencies:
- regenerator-runtime "^0.14.0"
-
-"@babel/runtime@^7.18.3":
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3":
version "7.25.0"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz"
integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
@@ -179,7 +158,7 @@
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.20.13":
- version "7.26.7"
+ version "7.26.9"
dependencies:
regenerator-runtime "^0.14.0"
@@ -1850,50 +1829,181 @@
resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
-"@react-pdf/fns@3.0.0":
- version "3.0.0"
+"@react-email/body@0.0.11":
+ version "0.0.11"
+ resolved "https://registry.npmjs.org/@react-email/body/-/body-0.0.11.tgz"
+ integrity sha512-ZSD2SxVSgUjHGrB0Wi+4tu3MEpB4fYSbezsFNEJk2xCWDBkFiOeEsjTmR5dvi+CxTK691hQTQlHv0XWuP7ENTg==
+
+"@react-email/button@0.0.19":
+ version "0.0.19"
+ resolved "https://registry.npmjs.org/@react-email/button/-/button-0.0.19.tgz"
+ integrity sha512-HYHrhyVGt7rdM/ls6FuuD6XE7fa7bjZTJqB2byn6/oGsfiEZaogY77OtoLL/mrQHjHjZiJadtAMSik9XLcm7+A==
+
+"@react-email/code-block@0.0.11":
+ version "0.0.11"
+ resolved "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.11.tgz"
+ integrity sha512-4D43p+LIMjDzm66gTDrZch0Flkip5je91mAT7iGs6+SbPyalHgIA+lFQoQwhz/VzHHLxuD0LV6gwmU/WUQ2WEg==
dependencies:
- "@babel/runtime" "^7.20.13"
+ prismjs "1.29.0"
-"@react-pdf/font@^3.0.1":
- version "3.0.1"
+"@react-email/code-inline@0.0.5":
+ version "0.0.5"
+ resolved "https://registry.npmjs.org/@react-email/code-inline/-/code-inline-0.0.5.tgz"
+ integrity sha512-MmAsOzdJpzsnY2cZoPHFPk6uDO/Ncpb4Kh1hAt9UZc1xOW3fIzpe1Pi9y9p6wwUmpaeeDalJxAxH6/fnTquinA==
+
+"@react-email/column@0.0.13":
+ version "0.0.13"
+ resolved "https://registry.npmjs.org/@react-email/column/-/column-0.0.13.tgz"
+ integrity sha512-Lqq17l7ShzJG/d3b1w/+lVO+gp2FM05ZUo/nW0rjxB8xBICXOVv6PqjDnn3FXKssvhO5qAV20lHM6S+spRhEwQ==
+
+"@react-email/components@^0.0.33":
+ version "0.0.33"
+ resolved "https://registry.npmjs.org/@react-email/components/-/components-0.0.33.tgz"
+ integrity sha512-/GKdT3YijT1iEWPAXF644jr12w5xVgzUr0zlbZGt2KOkGeFHNZUCL5UtRopmnjrH/Fayf8Gjv6q/4E2cZgDtdQ==
+ dependencies:
+ "@react-email/body" "0.0.11"
+ "@react-email/button" "0.0.19"
+ "@react-email/code-block" "0.0.11"
+ "@react-email/code-inline" "0.0.5"
+ "@react-email/column" "0.0.13"
+ "@react-email/container" "0.0.15"
+ "@react-email/font" "0.0.9"
+ "@react-email/head" "0.0.12"
+ "@react-email/heading" "0.0.15"
+ "@react-email/hr" "0.0.11"
+ "@react-email/html" "0.0.11"
+ "@react-email/img" "0.0.11"
+ "@react-email/link" "0.0.12"
+ "@react-email/markdown" "0.0.14"
+ "@react-email/preview" "0.0.12"
+ "@react-email/render" "1.0.5"
+ "@react-email/row" "0.0.12"
+ "@react-email/section" "0.0.16"
+ "@react-email/tailwind" "1.0.4"
+ "@react-email/text" "0.0.11"
+
+"@react-email/container@0.0.15":
+ version "0.0.15"
+ resolved "https://registry.npmjs.org/@react-email/container/-/container-0.0.15.tgz"
+ integrity sha512-Qo2IQo0ru2kZq47REmHW3iXjAQaKu4tpeq/M8m1zHIVwKduL2vYOBQWbC2oDnMtWPmkBjej6XxgtZByxM6cCFg==
+
+"@react-email/font@0.0.9":
+ version "0.0.9"
+ resolved "https://registry.npmjs.org/@react-email/font/-/font-0.0.9.tgz"
+ integrity sha512-4zjq23oT9APXkerqeslPH3OZWuh5X4crHK6nx82mVHV2SrLba8+8dPEnWbaACWTNjOCbcLIzaC9unk7Wq2MIXw==
+
+"@react-email/head@0.0.12":
+ version "0.0.12"
+ resolved "https://registry.npmjs.org/@react-email/head/-/head-0.0.12.tgz"
+ integrity sha512-X2Ii6dDFMF+D4niNwMAHbTkeCjlYYnMsd7edXOsi0JByxt9wNyZ9EnhFiBoQdqkE+SMDcu8TlNNttMrf5sJeMA==
+
+"@react-email/heading@0.0.15":
+ version "0.0.15"
+ resolved "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.15.tgz"
+ integrity sha512-xF2GqsvBrp/HbRHWEfOgSfRFX+Q8I5KBEIG5+Lv3Vb2R/NYr0s8A5JhHHGf2pWBMJdbP4B2WHgj/VUrhy8dkIg==
+
+"@react-email/hr@0.0.11":
+ version "0.0.11"
+ resolved "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.11.tgz"
+ integrity sha512-S1gZHVhwOsd1Iad5IFhpfICwNPMGPJidG/Uysy1AwmspyoAP5a4Iw3OWEpINFdgh9MHladbxcLKO2AJO+cA9Lw==
+
+"@react-email/html@0.0.11":
+ version "0.0.11"
+ resolved "https://registry.npmjs.org/@react-email/html/-/html-0.0.11.tgz"
+ integrity sha512-qJhbOQy5VW5qzU74AimjAR9FRFQfrMa7dn4gkEXKMB/S9xZN8e1yC1uA9C15jkXI/PzmJ0muDIWmFwatm5/+VA==
+
+"@react-email/img@0.0.11":
+ version "0.0.11"
+ resolved "https://registry.npmjs.org/@react-email/img/-/img-0.0.11.tgz"
+ integrity sha512-aGc8Y6U5C3igoMaqAJKsCpkbm1XjguQ09Acd+YcTKwjnC2+0w3yGUJkjWB2vTx4tN8dCqQCXO8FmdJpMfOA9EQ==
+
+"@react-email/link@0.0.12":
+ version "0.0.12"
+ resolved "https://registry.npmjs.org/@react-email/link/-/link-0.0.12.tgz"
+ integrity sha512-vF+xxQk2fGS1CN7UPQDbzvcBGfffr+GjTPNiWM38fhBfsLv6A/YUfaqxWlmL7zLzVmo0K2cvvV9wxlSyNba1aQ==
+
+"@react-email/markdown@0.0.14":
+ version "0.0.14"
+ resolved "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.14.tgz"
+ integrity sha512-5IsobCyPkb4XwnQO8uFfGcNOxnsg3311GRXhJ3uKv51P7Jxme4ycC/MITnwIZ10w2zx7HIyTiqVzTj4XbuIHbg==
+ dependencies:
+ md-to-react-email "5.0.5"
+
+"@react-email/preview@0.0.12":
+ version "0.0.12"
+ resolved "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.12.tgz"
+ integrity sha512-g/H5fa9PQPDK6WUEG7iTlC19sAktI23qyoiJtMLqQiXFCfWeQMhqjLGKeLSKkfzszqmfJCjZtpSiKtBoOdxp3Q==
+
+"@react-email/render@1.0.5":
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/@react-email/render/-/render-1.0.5.tgz"
+ integrity sha512-CA69HYXPk21HhtAXATIr+9JJwpDNmAFCvdMUjWmeoD1+KhJ9NAxusMRxKNeibdZdslmq3edaeOKGbdQ9qjK8LQ==
dependencies:
- "@babel/runtime" "^7.20.13"
- "@react-pdf/types" "^2.7.0"
+ html-to-text "9.0.5"
+ prettier "3.4.2"
+ react-promise-suspense "0.3.4"
+
+"@react-email/row@0.0.12":
+ version "0.0.12"
+ resolved "https://registry.npmjs.org/@react-email/row/-/row-0.0.12.tgz"
+ integrity sha512-HkCdnEjvK3o+n0y0tZKXYhIXUNPDx+2vq1dJTmqappVHXS5tXS6W5JOPZr5j+eoZ8gY3PShI2LWj5rWF7ZEtIQ==
+
+"@react-email/section@0.0.16":
+ version "0.0.16"
+ resolved "https://registry.npmjs.org/@react-email/section/-/section-0.0.16.tgz"
+ integrity sha512-FjqF9xQ8FoeUZYKSdt8sMIKvoT9XF8BrzhT3xiFKdEMwYNbsDflcjfErJe3jb7Wj/es/lKTbV5QR1dnLzGpL3w==
+
+"@react-email/tailwind@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-1.0.4.tgz"
+ integrity sha512-tJdcusncdqgvTUYZIuhNC6LYTfL9vNTSQpwWdTCQhQ1lsrNCEE4OKCSdzSV3S9F32pi0i0xQ+YPJHKIzGjdTSA==
+
+"@react-email/text@0.0.11":
+ version "0.0.11"
+ resolved "https://registry.npmjs.org/@react-email/text/-/text-0.0.11.tgz"
+ integrity sha512-a7nl/2KLpRHOYx75YbYZpWspUbX1DFY7JIZbOv5x0QU8SvwDbJt+Hm01vG34PffFyYvHEXrc6Qnip2RTjljNjg==
+
+"@react-pdf/fns@3.1.1":
+ version "3.1.1"
+
+"@react-pdf/font@^3.1.0":
+ version "3.1.0"
+ dependencies:
+ "@react-pdf/types" "^2.8.0"
fontkit "^2.0.2"
is-url "^1.2.4"
-"@react-pdf/image@^3.0.1":
- version "3.0.1"
+"@react-pdf/image@^3.0.2":
+ version "3.0.2"
dependencies:
- "@babel/runtime" "^7.20.13"
"@react-pdf/png-js" "^3.0.0"
- jay-peg "^1.1.0"
+ jay-peg "^1.1.1"
-"@react-pdf/layout@^4.2.0":
- version "4.2.0"
+"@react-pdf/layout@^4.2.3":
+ version "4.2.3"
dependencies:
"@babel/runtime" "^7.20.13"
- "@react-pdf/fns" "3.0.0"
- "@react-pdf/image" "^3.0.1"
- "@react-pdf/pdfkit" "^4.0.0"
- "@react-pdf/primitives" "^4.0.0"
- "@react-pdf/stylesheet" "^5.2.0"
- "@react-pdf/textkit" "^5.0.1"
- "@react-pdf/types" "^2.7.0"
+ "@react-pdf/fns" "3.1.1"
+ "@react-pdf/image" "^3.0.2"
+ "@react-pdf/pdfkit" "^4.0.2"
+ "@react-pdf/primitives" "^4.1.1"
+ "@react-pdf/stylesheet" "^6.0.0"
+ "@react-pdf/textkit" "^5.0.3"
+ "@react-pdf/types" "^2.8.0"
emoji-regex "^10.3.0"
queue "^6.0.1"
- yoga-layout "^3.1.0"
+ yoga-layout "^3.2.1"
-"@react-pdf/pdfkit@^4.0.0":
- version "4.0.0"
+"@react-pdf/pdfkit@^4.0.2":
+ version "4.0.2"
dependencies:
"@babel/runtime" "^7.20.13"
"@react-pdf/png-js" "^3.0.0"
browserify-zlib "^0.2.0"
crypto-js "^4.2.0"
fontkit "^2.0.2"
- jay-peg "^1.1.0"
+ jay-peg "^1.1.1"
+ linebreak "^1.1.0"
vite-compatible-readable-stream "^3.6.1"
"@react-pdf/png-js@^3.0.0":
@@ -1901,8 +2011,8 @@
dependencies:
browserify-zlib "^0.2.0"
-"@react-pdf/primitives@^4.0.0":
- version "4.0.0"
+"@react-pdf/primitives@^4.1.1":
+ version "4.1.1"
"@react-pdf/reconciler@^1.1.3":
version "1.1.3"
@@ -1910,14 +2020,14 @@
object-assign "^4.1.1"
scheduler "0.25.0-rc-603e6108-20241029"
-"@react-pdf/render@^4.0.2":
- version "4.0.2"
+"@react-pdf/render@^4.1.2":
+ version "4.1.2"
dependencies:
"@babel/runtime" "^7.20.13"
- "@react-pdf/fns" "3.0.0"
- "@react-pdf/primitives" "^4.0.0"
- "@react-pdf/textkit" "^5.0.1"
- "@react-pdf/types" "^2.7.0"
+ "@react-pdf/fns" "3.1.1"
+ "@react-pdf/primitives" "^4.1.1"
+ "@react-pdf/textkit" "^5.0.3"
+ "@react-pdf/types" "^2.8.0"
abs-svg-path "^0.1.1"
color-string "^1.9.1"
normalize-svg-path "^1.1.0"
@@ -1925,54 +2035,65 @@
svg-arc-to-cubic-bezier "^3.2.0"
"@react-pdf/renderer@^4.1.6":
- version "4.1.6"
+ version "4.2.2"
dependencies:
"@babel/runtime" "^7.20.13"
- "@react-pdf/font" "^3.0.1"
- "@react-pdf/layout" "^4.2.0"
- "@react-pdf/pdfkit" "^4.0.0"
- "@react-pdf/primitives" "^4.0.0"
+ "@react-pdf/fns" "3.1.1"
+ "@react-pdf/font" "^3.1.0"
+ "@react-pdf/layout" "^4.2.3"
+ "@react-pdf/pdfkit" "^4.0.2"
+ "@react-pdf/primitives" "^4.1.1"
"@react-pdf/reconciler" "^1.1.3"
- "@react-pdf/render" "^4.0.2"
- "@react-pdf/types" "^2.7.0"
+ "@react-pdf/render" "^4.1.2"
+ "@react-pdf/types" "^2.8.0"
events "^3.3.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
queue "^6.0.1"
-"@react-pdf/stylesheet@^5.2.0":
- version "5.2.0"
+"@react-pdf/stylesheet@^6.0.0":
+ version "6.0.0"
dependencies:
- "@babel/runtime" "^7.20.13"
- "@react-pdf/fns" "3.0.0"
- "@react-pdf/types" "^2.7.0"
+ "@react-pdf/fns" "3.1.1"
+ "@react-pdf/types" "^2.8.0"
color-string "^1.9.1"
hsl-to-hex "^1.0.0"
media-engine "^1.0.3"
postcss-value-parser "^4.1.0"
-"@react-pdf/textkit@^5.0.1":
- version "5.0.1"
+"@react-pdf/textkit@^5.0.3":
+ version "5.0.3"
dependencies:
- "@babel/runtime" "^7.20.13"
- "@react-pdf/fns" "3.0.0"
+ "@react-pdf/fns" "3.1.1"
bidi-js "^1.0.2"
hyphen "^1.6.4"
unicode-properties "^1.4.1"
-"@react-pdf/types@^2.7.0":
- version "2.7.0"
+"@react-pdf/types@^2.8.0":
+ version "2.8.0"
+ dependencies:
+ "@react-pdf/font" "^3.1.0"
+ "@react-pdf/primitives" "^4.1.1"
+ "@react-pdf/stylesheet" "^6.0.0"
-"@remix-run/router@1.19.1":
- version "1.19.1"
- resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz"
- integrity sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==
+"@remix-run/router@1.22.0":
+ version "1.22.0"
+ resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.22.0.tgz"
+ integrity sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw==
"@rollup/rollup-darwin-arm64@4.20.0":
version "4.20.0"
resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz"
integrity sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==
+"@selderee/plugin-htmlparser2@^0.11.0":
+ version "0.11.0"
+ resolved "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz"
+ integrity sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==
+ dependencies:
+ domhandler "^5.0.3"
+ selderee "^0.11.0"
+
"@swc/helpers@^0.5.12":
version "0.5.15"
dependencies:
@@ -2586,6 +2707,9 @@ base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.3.0:
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+base64-js@0.0.8:
+ version "0.0.8"
+
bidi-js@^1.0.2:
version "1.0.3"
dependencies:
@@ -2874,12 +2998,7 @@ content-type@~1.0.4, content-type@~1.0.5:
resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
-convert-source-map@^1.5.0:
- version "1.9.0"
- resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
- integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
-
-convert-source-map@^2.0.0:
+convert-source-map@^1.5.0, convert-source-map@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
@@ -3002,6 +3121,11 @@ deep-is@^0.1.3:
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+deepmerge@^4.3.1:
+ version "4.3.1"
+ resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz"
+ integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
+
define-data-property@^1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz"
@@ -3041,6 +3165,36 @@ dir-glob@^3.0.1:
dependencies:
path-type "^4.0.0"
+dom-serializer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz"
+ integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.2"
+ entities "^4.2.0"
+
+domelementtype@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz"
+ integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
+domhandler@^5.0.2, domhandler@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz"
+ integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+ dependencies:
+ domelementtype "^2.3.0"
+
+domutils@^3.0.1:
+ version "3.2.2"
+ resolved "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz"
+ integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==
+ dependencies:
+ dom-serializer "^2.0.0"
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+
dotenv@^10.0.0:
version "10.0.0"
resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz"
@@ -3101,6 +3255,11 @@ enquirer@^2.3.6, "enquirer@>= 2.3.0 < 3":
ansi-colors "^4.1.1"
strip-ansi "^6.0.1"
+entities@^4.2.0, entities@^4.4.0:
+ version "4.5.0"
+ resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz"
+ integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
+
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz"
@@ -3468,6 +3627,11 @@ farmhash-modern@^1.1.0:
resolved "https://registry.npmjs.org/farmhash-modern/-/farmhash-modern-1.1.0.tgz"
integrity sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==
+fast-deep-equal@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz"
+ integrity sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==
+
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
@@ -3961,6 +4125,27 @@ html-entities@^2.5.2:
resolved "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz"
integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==
+html-to-text@9.0.5:
+ version "9.0.5"
+ resolved "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz"
+ integrity sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==
+ dependencies:
+ "@selderee/plugin-htmlparser2" "^0.11.0"
+ deepmerge "^4.3.1"
+ dom-serializer "^2.0.0"
+ htmlparser2 "^8.0.2"
+ selderee "^0.11.0"
+
+htmlparser2@^8.0.2:
+ version "8.0.2"
+ resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz"
+ integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+ domutils "^3.0.1"
+ entities "^4.4.0"
+
http-errors@2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz"
@@ -4211,7 +4396,7 @@ isexe@^2.0.0:
resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-jay-peg@^1.1.0:
+jay-peg@^1.1.1:
version "1.1.1"
dependencies:
restructure "^3.0.0"
@@ -4380,6 +4565,11 @@ klaw-sync@^6.0.0:
dependencies:
graceful-fs "^4.1.11"
+leac@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz"
+ integrity sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==
+
levn@^0.4.1:
version "0.4.1"
resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz"
@@ -4393,6 +4583,12 @@ limiter@^1.1.5:
resolved "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz"
integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==
+linebreak@^1.1.0:
+ version "1.1.0"
+ dependencies:
+ base64-js "0.0.8"
+ unicode-trie "^2.0.0"
+
lines-and-columns@^1.1.6:
version "1.2.4"
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
@@ -4558,6 +4754,18 @@ luxon@^3.2.1:
resolved "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz"
integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==
+marked@7.0.4:
+ version "7.0.4"
+ resolved "https://registry.npmjs.org/marked/-/marked-7.0.4.tgz"
+ integrity sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==
+
+md-to-react-email@5.0.5:
+ version "5.0.5"
+ resolved "https://registry.npmjs.org/md-to-react-email/-/md-to-react-email-5.0.5.tgz"
+ integrity sha512-OvAXqwq57uOk+WZqFFNCMZz8yDp8BD3WazW1wAKHUrPbbdr89K9DWS6JXY09vd9xNdPNeurI8DU/X4flcfaD8A==
+ dependencies:
+ marked "7.0.4"
+
media-engine@^1.0.3:
version "1.0.3"
@@ -4761,11 +4969,6 @@ node-schedule@^2.1.1:
long-timeout "0.1.1"
sorted-array-functions "^1.3.0"
-nodemailer@^6.9.10:
- version "6.9.14"
- resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz"
- integrity sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==
-
nodemon@^2.0.14:
version "2.0.22"
resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz"
@@ -4799,7 +5002,7 @@ npm-run-path@^4.0.1:
dependencies:
path-key "^3.0.0"
-"npo-client-template@file:/Users/priskakndy/Downloads/ctc_lpa/lpa/client":
+"npo-client-template@file:/Users/astonchan/Desktop/Academics Folder/UC Irvine/Junior Year/Commit The Change/La Pena/client":
version "0.0.0"
resolved "file:client"
dependencies:
@@ -4808,20 +5011,22 @@ npm-run-path@^4.0.1:
"@emotion/react" "^11.13.0"
"@emotion/styled" "^11.13.0"
"@hookform/resolvers" "^3.9.0"
+ "@react-email/components" "^0.0.33"
"@react-pdf/renderer" "^4.1.6"
axios "^1.7.4"
firebase "10.12.5"
framer-motion "^11.3.27"
+ lucide-react "^0.474.0"
patch-package "^8.0.0"
react "^18.3.1"
react-cookie "^7.2.0"
react-dom "^18.3.1"
react-hook-form "^7.52.2"
react-icons "^5.3.0"
- react-router-dom "^6.26.1"
+ react-router-dom "^6.29.0"
zod "^3.23.8"
-"npo-server-template@file:/Users/priskakndy/Downloads/ctc_lpa/lpa/server":
+"npo-server-template@file:/Users/astonchan/Desktop/Academics Folder/UC Irvine/Junior Year/Commit The Change/La Pena/server":
version "1.0.0"
resolved "file:server"
dependencies:
@@ -4834,7 +5039,6 @@ npm-run-path@^4.0.1:
mongoose "^8.2.0"
mysql "^2.18.1"
node-schedule "^2.1.1"
- nodemailer "^6.9.10"
nodemon "^2.0.14"
pg-promise "^11.5.4"
@@ -4951,6 +5155,14 @@ parse-json@^5.0.0:
parse-svg-path@^0.1.2:
version "0.1.2"
+parseley@^0.12.0:
+ version "0.12.1"
+ resolved "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz"
+ integrity sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==
+ dependencies:
+ leac "^0.6.0"
+ peberminta "^0.9.0"
+
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz"
@@ -5007,6 +5219,11 @@ path-type@^4.0.0:
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+peberminta@^0.9.0:
+ version "0.9.0"
+ resolved "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz"
+ integrity sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==
+
pg-cloudflare@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz"
@@ -5144,6 +5361,16 @@ prettier@^3.3.3, "prettier@2 || 3", prettier@3.3.3:
resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz"
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
+prettier@3.4.2:
+ version "3.4.2"
+ resolved "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz"
+ integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==
+
+prismjs@1.29.0:
+ version "1.29.0"
+ resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz"
+ integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==
+
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
@@ -5264,7 +5491,7 @@ react-cookie@^7.2.0:
hoist-non-react-statics "^3.3.2"
universal-cookie "^7.0.0"
-react-dom@^18.0.0, react-dom@^18.3.1, react-dom@>=16.8, react-dom@>=18:
+"react-dom@^18.0 || ^19.0 || ^19.0.0-rc", react-dom@^18.0.0, react-dom@^18.3.1, react-dom@>=16.8, react-dom@>=18:
version "18.3.1"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
@@ -5304,6 +5531,13 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+react-promise-suspense@0.3.4:
+ version "0.3.4"
+ resolved "https://registry.npmjs.org/react-promise-suspense/-/react-promise-suspense-0.3.4.tgz"
+ integrity sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==
+ dependencies:
+ fast-deep-equal "^2.0.1"
+
react-refresh@^0.14.2:
version "0.14.2"
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz"
@@ -5328,20 +5562,20 @@ react-remove-scroll@^2.5.6:
use-callback-ref "^1.3.0"
use-sidecar "^1.1.2"
-react-router-dom@^6.26.1:
- version "6.26.1"
- resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.1.tgz"
- integrity sha512-veut7m41S1fLql4pLhxeSW3jlqs+4MtjRLj0xvuCEXsxusJCbs6I8yn9BxzzDX2XDgafrccY6hwjmd/bL54tFw==
+react-router-dom@^6.29.0:
+ version "6.29.0"
+ resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.29.0.tgz"
+ integrity sha512-pkEbJPATRJ2iotK+wUwHfy0xs2T59YPEN8BQxVCPeBZvK7kfPESRc/nyxzdcxR17hXgUPYx2whMwl+eo9cUdnQ==
dependencies:
- "@remix-run/router" "1.19.1"
- react-router "6.26.1"
+ "@remix-run/router" "1.22.0"
+ react-router "6.29.0"
-react-router@6.26.1:
- version "6.26.1"
- resolved "https://registry.npmjs.org/react-router/-/react-router-6.26.1.tgz"
- integrity sha512-kIwJveZNwp7teQRI5QmwWo39A5bXRyqpH0COKKmPnyD2vBvDwgFXSqDUYtt1h+FEyfnE8eXr7oe0MxRzVwCcvQ==
+react-router@6.29.0:
+ version "6.29.0"
+ resolved "https://registry.npmjs.org/react-router/-/react-router-6.29.0.tgz"
+ integrity sha512-DXZJoE0q+KyeVw75Ck6GkPxFak63C4fGqZGNijnWgzB/HzSP1ZfTlBj5COaGWwhrMQ/R8bXiq5Ooy4KG+ReyjQ==
dependencies:
- "@remix-run/router" "1.19.1"
+ "@remix-run/router" "1.22.0"
react-style-singleton@^2.2.1:
version "2.2.1"
@@ -5352,7 +5586,7 @@ react-style-singleton@^2.2.1:
invariant "^2.2.4"
tslib "^2.0.0"
-react@*, "react@^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", react@^18.0.0, react@^18.3.1, "react@>= 16.3.0", react@>=16.8, react@>=16.8.0, react@>=18:
+react@*, "react@^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18.0 || ^19.0", "react@^18.0 || ^19.0 || ^19.0.0-rc", react@^18.0.0, react@^18.3.1, "react@>= 16.3.0", react@>=16.8, react@>=16.8.0, react@>=18:
version "18.3.1"
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
@@ -5541,6 +5775,13 @@ scheduler@^0.23.2:
scheduler@0.25.0-rc-603e6108-20241029:
version "0.25.0-rc-603e6108-20241029"
+selderee@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz"
+ integrity sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==
+ dependencies:
+ parseley "^0.12.0"
+
semver-compare@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz"
@@ -6301,7 +6542,7 @@ yocto-queue@^0.1.0:
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-yoga-layout@^3.1.0:
+yoga-layout@^3.2.1:
version "3.2.1"
zod@^3.23.8: