From 6b43b5da012cb90eb437e5e309367c3571bbbde6 Mon Sep 17 00:00:00 2001 From: intisarosman1 <77607212+intisarosman1@users.noreply.github.com> Date: Tue, 12 Mar 2024 02:10:51 -0700 Subject: [PATCH] belindas-closet-nextjs_4_256_buttons-functionality (#261) * Added functionality to delete button * Added functionality to delete and archive buttons Resolves #256 As a developer, I added functionality to the delete and archive buttons along with confirmation dialogues. When products are deleted or archived from the frontend, they are hidden. They are marked as isHidden (deleted) or isSold (archived) in the database. I wanted to make the page reroute back to the category page, but the components complicates it and my attempts to incorporate router.back() caused errors. * Routes back to category page after successful deletion * Created pop up success/error messages --- app/auth/sign-in/page.tsx | 2 +- app/category-page/[categoryId]/page.tsx | 12 +- .../[productId]/ProductDetailDisplay.tsx | 38 ++++- .../products/[productId]/page.tsx | 2 + components/ConfirmArchiveDialog.tsx | 101 +++++++++++++ components/ConfirmDeleteDialog.tsx | 115 +++++++++++++++ package-lock.json | 137 ++++++++---------- 7 files changed, 330 insertions(+), 77 deletions(-) create mode 100644 components/ConfirmArchiveDialog.tsx create mode 100644 components/ConfirmDeleteDialog.tsx diff --git a/app/auth/sign-in/page.tsx b/app/auth/sign-in/page.tsx index 8ad6331b..0384e5f7 100644 --- a/app/auth/sign-in/page.tsx +++ b/app/auth/sign-in/page.tsx @@ -49,7 +49,7 @@ const Signin = () => { setError("Invalid email or password"); } else { const { token } = await res.json(); - localStorage.setItem('token', token); + localStorage.setItem("token", token); const userRole = JSON.parse(atob(token.split(".")[1])).role; // decode token to get user role // Redirect to user page if (userRole === "admin") { diff --git a/app/category-page/[categoryId]/page.tsx b/app/category-page/[categoryId]/page.tsx index d6dc82a0..f3d853d5 100644 --- a/app/category-page/[categoryId]/page.tsx +++ b/app/category-page/[categoryId]/page.tsx @@ -15,6 +15,8 @@ interface Product { productSizePantsWaist: string; productSizePantsInseam: string; productDescription: string; + isHidden: Boolean; + isSold: Boolean; } async function fetchData( @@ -36,6 +38,7 @@ async function fetchData( throw new Error(res.statusText); } else { const data = await res.json(); + const filteredData = data.filter((product: Product) => !product.isHidden); setProducts(data); console.log(data); } @@ -46,11 +49,16 @@ async function fetchData( const ViewProduct = ({ categoryId }: { categoryId: string }) => { const [products, setProducts] = useState([]); + const [filteredProducts, setFilteredProducts] = useState([]); useEffect(() => { fetchData(categoryId, setProducts); // Pass categoryId to fetchData }, [categoryId]); + useEffect(() => { + setFilteredProducts(products.filter(product => !product.isHidden && !product.isSold)); + }, [products]); + return ( { justifyContent={"center"} align={"center"} > - Found {products.length} products in {categoryId} + Found {filteredProducts.length} products in {categoryId} - {products.map((product, index) => ( + {filteredProducts.map((product, index) => ( { + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + + const handleDeleteButtonClick = () => { + setOpenDeleteDialog(true); + }; + + const handleCloseDeleteDialog = () => { + setOpenDeleteDialog(false); + }; + + const [openArchiveDialog, setOpenArchiveDialog] = useState(false); + + const handleArchiveButtonClick = () => { + setOpenArchiveDialog(true); + }; + + const handleCloseArchiveDialog = () => { + setOpenArchiveDialog(false); + }; + return ( { variant="contained" color="error" startIcon={} + onClick={handleDeleteButtonClick} > Delete @@ -125,11 +150,22 @@ const ProductDetailDisplay = ({ product }: { product: Product }) => { variant="contained" color="warning" startIcon={} + onClick={handleArchiveButtonClick} > Archive + + diff --git a/app/category-page/[categoryId]/products/[productId]/page.tsx b/app/category-page/[categoryId]/products/[productId]/page.tsx index ed89dafb..cab885d7 100644 --- a/app/category-page/[categoryId]/products/[productId]/page.tsx +++ b/app/category-page/[categoryId]/products/[productId]/page.tsx @@ -17,6 +17,8 @@ interface Product { productSizePantsInseam: string[]; productDescription: string; productImage: string; + isHidden: boolean; + isSold: boolean; } const ProductDetail = ({ diff --git a/components/ConfirmArchiveDialog.tsx b/components/ConfirmArchiveDialog.tsx new file mode 100644 index 00000000..5a12165d --- /dev/null +++ b/components/ConfirmArchiveDialog.tsx @@ -0,0 +1,101 @@ +import Box from "@mui/material/Box"; +import Button from "@mui/material/Button"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogActions from "@mui/material/DialogActions"; +import Dialog from "@mui/material/Dialog"; +import React, { useState } from "react"; +import { Product } from "@/app/category-page/[categoryId]/products/[productId]/ProductDetailDisplay"; +import Snackbar from "@mui/material/Snackbar"; + +/** + * Props for the ConfirmArchiveDialog component. + */ +interface ConfirmArchiveDialogProps { + open: boolean; + onClose: () => void; + product: Product; +} +/** + * Renders a confirmation dialog for archiving products. + * + * @param props - The component props. + * @returns The rendered ConfirmArchiveDialog component. + */ +export default function ConfirmArchiveDialog({ + open, + onClose, + product, +}: ConfirmArchiveDialogProps) { + const [snackBarMessage, setSnackBarMessage] = useState(""); + + /** + * Handles the click event when the user confirms "No" to archiving product. + * @returns {void} + */ + const handleNo = () => { + onClose(); + }; + /** + * Handles the click event when the user confirms "Yes" to archiving product. + * @returns {void} + */ + const handleYes = async () => { + // TODO: Confirm Yes to archive product + const token = localStorage.getItem('token'); + console.log('Token:', token); + try { + const response = await fetch(`http://localhost:3000/api/products/archive/${product._id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + }, + body: JSON.stringify({isSold: Boolean}), + }); + if (response.ok) { + onClose(); + setSnackBarMessage("Product archived successfully!"); + setTimeout(() => { + window.history.back(); + }, 2000); + } else { + const errorMessage = await response.json(); + setSnackBarMessage(errorMessage.message); + console.error('Failed to archive product', response.statusText); + } + } catch (error) { + setSnackBarMessage("Error archiving product"); + console.error('Error archiving product:', error); + } + }; + + return ( + + + Are you sure you want to archive this product? + + + + + + setSnackBarMessage("")} + anchorOrigin={{ vertical: "bottom", horizontal: "center" }} + message={snackBarMessage} + /> + + ); +} diff --git a/components/ConfirmDeleteDialog.tsx b/components/ConfirmDeleteDialog.tsx new file mode 100644 index 00000000..8c7037a7 --- /dev/null +++ b/components/ConfirmDeleteDialog.tsx @@ -0,0 +1,115 @@ +import Box from "@mui/material/Box"; +import Button from "@mui/material/Button"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogActions from "@mui/material/DialogActions"; +import Dialog from "@mui/material/Dialog"; +import React, { useState } from "react"; +import { Product } from "@/app/category-page/[categoryId]/products/[productId]/ProductDetailDisplay"; +import Snackbar, { SnackbarOrigin } from "@mui/material/Snackbar"; + +interface State extends SnackbarOrigin { + open: boolean; + } + +interface DeleteSuccessResponse { + status: "delete_success"; + message: string; + token?: string; + } + +interface DeleteErrorResponse { + status: "delete_error"; + message: string; + } + +/** + * Props for the ConfirmDeleteDialog component. + */ +interface ConfirmDeleteDialogProps { + open: boolean; + onClose: () => void; + product: Product; +} +/** + * Renders a confirmation dialog for deleting products. + * + * @param props - The component props. + * @returns The rendered ConfirmDeleteDialog component. + */ +export default function ConfirmDeleteDialog({ + open, + onClose, + product, +}: ConfirmDeleteDialogProps) { + const [snackBarMessage, setSnackBarMessage] = useState(""); + /** + * Handles the click event when the user confirms "No" to deleting product. + * @returns {void} + */ + const handleNo = () => { + onClose(); + }; + /** + * Handles the click event when the user confirms "Yes" to deleting product. + * @returns {void} + */ + const handleYes = async () => { + // TODO: Confirm Yes to delete product + const token = localStorage.getItem('token'); + console.log('Token:', token); + try { + const response = await fetch(`http://localhost:3000/api/products/remove/${product._id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + }, + body: JSON.stringify({isHidden: Boolean}), + }); + if (response.ok) { + onClose(); + setSnackBarMessage("Product deleted successfully!"); + setTimeout(() => { + window.history.back(); + }, 2000); + } else { + const errorMessage = await response.json(); + setSnackBarMessage(errorMessage.message); + console.error('Failed to delete product', response.statusText); + } + } catch (error) { + setSnackBarMessage("Error deleting product"); + console.error('Error deleting product:', error); + } + }; + + return ( + + + Are you sure you want to delete this product? + + + + + + setSnackBarMessage("")} + anchorOrigin={{ vertical: "bottom", horizontal: "center" }} + message={snackBarMessage} + /> + + ); +} diff --git a/package-lock.json b/package-lock.json index 27004db7..819459cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1680,9 +1680,9 @@ } }, "node_modules/@next/env": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.9.tgz", - "integrity": "sha512-vuDRK05BOKfmoBYLNi2cujG2jrYbEod/ubSSyqgmEx9n/W3eZaJQdRNhTfumO+qmq/QTzLurW487n/PM/fHOkw==" + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz", + "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.4.9", @@ -1693,9 +1693,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.9.tgz", - "integrity": "sha512-TVzGHpZoVBk3iDsTOQA/R6MGmFp0+17SWXMEWd6zG30AfuELmSSMe2SdPqxwXU0gbpWkJL1KgfLzy5ReN0crqQ==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", + "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", "cpu": [ "arm64" ], @@ -1708,9 +1708,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.9.tgz", - "integrity": "sha512-aSfF1fhv28N2e7vrDZ6zOQ+IIthocfaxuMWGReB5GDriF0caTqtHttAvzOMgJgXQtQx6XhyaJMozLTSEXeNN+A==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", + "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", "cpu": [ "x64" ], @@ -1723,9 +1723,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.9.tgz", - "integrity": "sha512-JhKoX5ECzYoTVyIy/7KykeO4Z2lVKq7HGQqvAH+Ip9UFn1MOJkOnkPRB7v4nmzqAoY+Je05Aj5wNABR1N18DMg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", + "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", "cpu": [ "arm64" ], @@ -1738,9 +1738,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.9.tgz", - "integrity": "sha512-OOn6zZBIVkm/4j5gkPdGn4yqQt+gmXaLaSjRSO434WplV8vo2YaBNbSHaTM9wJpZTHVDYyjzuIYVEzy9/5RVZw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", + "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", "cpu": [ "arm64" ], @@ -1753,9 +1753,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.9.tgz", - "integrity": "sha512-iA+fJXFPpW0SwGmx/pivVU+2t4zQHNOOAr5T378PfxPHY6JtjV6/0s1vlAJUdIHeVpX98CLp9k5VuKgxiRHUpg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", + "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", "cpu": [ "x64" ], @@ -1768,9 +1768,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.9.tgz", - "integrity": "sha512-rlNf2WUtMM+GAQrZ9gMNdSapkVi3koSW3a+dmBVp42lfugWVvnyzca/xJlN48/7AGx8qu62WyO0ya1ikgOxh6A==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", + "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", "cpu": [ "x64" ], @@ -1783,9 +1783,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.9.tgz", - "integrity": "sha512-5T9ybSugXP77nw03vlgKZxD99AFTHaX8eT1ayKYYnGO9nmYhJjRPxcjU5FyYI+TdkQgEpIcH7p/guPLPR0EbKA==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", + "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", "cpu": [ "arm64" ], @@ -1798,9 +1798,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.9.tgz", - "integrity": "sha512-ojZTCt1lP2ucgpoiFgrFj07uq4CZsq4crVXpLGgQfoFq00jPKRPgesuGPaz8lg1yLfvafkU3Jd1i8snKwYR3LA==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", + "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", "cpu": [ "ia32" ], @@ -1813,9 +1813,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.9.tgz", - "integrity": "sha512-QbT03FXRNdpuL+e9pLnu+XajZdm/TtIXVYY4lA9t+9l0fLZbHXDYEKitAqxrOj37o3Vx5ufxiRAniaIebYDCgw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", + "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", "cpu": [ "x64" ], @@ -1933,9 +1933,9 @@ } }, "node_modules/@swc/helpers": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", - "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", + "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", "dependencies": { "tslib": "^2.4.0" } @@ -4665,9 +4665,9 @@ } }, "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" }, "node_modules/is-array-buffer": { "version": "3.0.2", @@ -5647,9 +5647,9 @@ } }, "node_modules/jose": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", - "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", + "version": "4.15.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz", + "integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -6137,39 +6137,37 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/next": { - "version": "13.4.9", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.9.tgz", - "integrity": "sha512-vtefFm/BWIi/eWOqf1GsmKG3cjKw1k3LjuefKRcL3iiLl3zWzFdPG3as6xtxrGO6gwTzzaO1ktL4oiHt/uvTjA==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz", + "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==", "dependencies": { - "@next/env": "13.4.9", - "@swc/helpers": "0.5.1", + "@next/env": "13.5.6", + "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", + "postcss": "8.4.31", "styled-jsx": "5.1.1", - "watchpack": "2.4.0", - "zod": "3.21.4" + "watchpack": "2.4.0" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=16.8.0" + "node": ">=16.14.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.9", - "@next/swc-darwin-x64": "13.4.9", - "@next/swc-linux-arm64-gnu": "13.4.9", - "@next/swc-linux-arm64-musl": "13.4.9", - "@next/swc-linux-x64-gnu": "13.4.9", - "@next/swc-linux-x64-musl": "13.4.9", - "@next/swc-win32-arm64-msvc": "13.4.9", - "@next/swc-win32-ia32-msvc": "13.4.9", - "@next/swc-win32-x64-msvc": "13.4.9" + "@next/swc-darwin-arm64": "13.5.6", + "@next/swc-darwin-x64": "13.5.6", + "@next/swc-linux-arm64-gnu": "13.5.6", + "@next/swc-linux-arm64-musl": "13.5.6", + "@next/swc-linux-x64-gnu": "13.5.6", + "@next/swc-linux-x64-musl": "13.5.6", + "@next/swc-win32-arm64-msvc": "13.5.6", + "@next/swc-win32-ia32-msvc": "13.5.6", + "@next/swc-win32-x64-msvc": "13.5.6" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "fibers": ">= 3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -6178,9 +6176,6 @@ "@opentelemetry/api": { "optional": true }, - "fibers": { - "optional": true - }, "sass": { "optional": true } @@ -6214,9 +6209,9 @@ } }, "node_modules/next/node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -6225,10 +6220,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -8365,14 +8364,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } }