From 83a7d693adb50fc3f475d718c62fadb250f702a9 Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Wed, 17 Apr 2024 14:03:39 -0700 Subject: [PATCH 01/43] new branch --- src/app/orderConfirmationPickUp/page.tsx | 26 ++++++++++++----------- src/app/orderConfirmationPickUp/styles.ts | 16 +++++++------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 871a0e1e..7cde8b21 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -9,41 +9,44 @@ import { getOrderById, } from '@/api/supabase/queries/order_queries'; import { + Body2Bold, + Body2, + Heading3Bold, Body1, Body1Bold, - Body2Light, - Heading3Bold, Heading4Bold, + Body2Light, } from '@/styles/fonts'; +import { fetchCartItemsWithQuantity } from '../../api/supabase/queries/cart_queries'; import { useSearchParams } from 'next/navigation'; -import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; - import BackButton from '../../components/BackButton/BackButton'; import NavBar from '../../components/NavBarFolder/NavBar'; import { - TextDiv, - TextDiv1, - BackButtonDiv, FavoriteDiv, + ColDiv, OutterFavoriteDiv, + TextDiv1, + OutterBox, + Label, LabelBox, - LabelBox1, ScrollDiv, ShippingDetailsDiv, ImageDiv, BottomColumnDiv, - Wrapper, + LabelBox1, LeftColumnDiv, RightColumnDiv, DetailsHeader, PageDiv, CenterDiv, + BackButtonDiv, + TextDiv, } from './styles'; import { Product, User, Pickup } from '../../schema/schema'; - +import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; export default function OrderConfirmationPickUp() { const [Cart, setCart] = useState([]); const [user, setUser] = useState(); @@ -95,10 +98,9 @@ export default function OrderConfirmationPickUp() { Your order has been submitted - - Order No. {orderIDFromSearch} + Order No. {user?.cart_id} {Cart.map(cartItem => ( diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index d142d103..32b850c6 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -26,9 +26,8 @@ export const OutterFavoriteDiv = styled.div` max-height: 100%; margin-top: 20px; margin-right: 60px; - margin-left: 60px; - padding-right: 20px; - padding-left: 10px; + margin-left: 40px; + padding-right: 15px; padding-top: 10px; `; @@ -232,7 +231,6 @@ export const RightColumnDiv = styled.div` display: flex; flex-flow: column; align-items: start; - margin-left: 10px; width: 100%; `; @@ -241,7 +239,7 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; - margin-left: 80px; + margin-left: 60px; margin-bottom: 40px; `; @@ -261,6 +259,7 @@ export const BottomColumnDiv = styled.div` justify-content: space-around; width: 100%; margin-left: 20px; + margin-right: 20px; margin-bottom: 30px; gap: 30px; `; @@ -268,7 +267,7 @@ export const BottomColumnDiv = styled.div` export const TextDiv = styled.div` display: flex; flex-direction: row; - margin-left: 60px; + margin-left: 40px; margin-top: 20px; margin-bottom: 20px; `; @@ -287,6 +286,7 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; + margin-bottom: 40px; `; export const ShippingDetailsDiv = styled.div` @@ -296,7 +296,7 @@ export const ShippingDetailsDiv = styled.div` border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 467px; + width: 475px; height: auto; max-height: 100%; padding: 36px 34px; @@ -322,4 +322,4 @@ export const CenterDiv = styled.div` justify-content: center; width: 100%; padding: 20px; -`; +`; \ No newline at end of file From 1d57cf491da09db10ccf9bf18d2ef54a46a9494b Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Wed, 17 Apr 2024 14:20:29 -0700 Subject: [PATCH 02/43] fixes --- src/app/[productId]/Buttons.tsx | 11 +++++---- src/app/[productId]/page.tsx | 20 ++++++++--------- src/app/[productId]/styles.ts | 26 +++++++++------------- src/app/globals.css | 6 ++++- src/app/login/styles.ts | 8 +++++-- src/app/storefront/productButtons.tsx | 1 - src/components/InputFieldsFolder/styles.ts | 6 ++--- 7 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/app/[productId]/Buttons.tsx b/src/app/[productId]/Buttons.tsx index 80bea55a..35783e34 100644 --- a/src/app/[productId]/Buttons.tsx +++ b/src/app/[productId]/Buttons.tsx @@ -1,5 +1,7 @@ import React, { useState } from 'react'; import { toast } from 'react-toastify'; +import { Plus, Minus } from 'react-feather'; +import { Body1Bold } from '@/styles/fonts'; import { ButtonsWrapper, AddToCartButton, @@ -9,6 +11,7 @@ import { import { addToCart } from '../../api/supabase/queries/cart_queries'; + export default function Buttons(props: { productNumber: number }) { const [quantity, setQuantity] = useState(1); const { productNumber } = props; @@ -26,18 +29,18 @@ export default function Buttons(props: { productNumber: number }) { // used hyphen instead of dash for display const changeCart = () => { addToCart(productNumber, quantity); - toast(`you have added ${quantity} items to the cart!`); + toast(`You have added ${quantity} items to the cart!`); }; return ( - – + - {quantity} + {quantity} - + + diff --git a/src/app/[productId]/page.tsx b/src/app/[productId]/page.tsx index f93bd3d3..02d35983 100644 --- a/src/app/[productId]/page.tsx +++ b/src/app/[productId]/page.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; -import { Body1, Heading1, Body2Light } from '@/styles/fonts'; +import { Body1, Heading1, Body2Light, Body2Bold } from '@/styles/fonts'; import { fetchProductByID } from '../../api/supabase/queries/product_queries'; import BackButton from '../../components/BackButton/BackButton'; import 'react-toastify/dist/ReactToastify.css'; @@ -13,6 +13,7 @@ import { DescriptionContainer, ToastPopUP, Fullscreen, + LeftColumnDiv } from './styles'; import NavBar from '../../components/NavBarFolder/NavBar'; @@ -53,11 +54,10 @@ export default function ItemDisplay({ limit={1} hideProgressBar /> -
- -
+ + + {Item?.name} - {Item?.category} + Category: {Item?.category} - - Product ID: {Item?.id} - - + Product Details: + + + {Item?.description} - {Item?.description} diff --git a/src/app/[productId]/styles.ts b/src/app/[productId]/styles.ts index e96cbb27..3a68f588 100644 --- a/src/app/[productId]/styles.ts +++ b/src/app/[productId]/styles.ts @@ -2,42 +2,37 @@ import styled from 'styled-components'; import { ToastContainer } from 'react-toastify'; import COLORS from '../../styles/colors'; -export const BackButton = styled.button` + +export const LeftColumnDiv = styled.div` display: flex; - padding-top: 230px; - padding-left: 30px; - width: 100px; - height: 40px; - background-color: transparent; - border-color: transparent; - font-size: 15px; + flex-direction: column; + gap: 25px; `; export const DescriptionContainer = styled.div` display: flex; - margin-left: 50px; - margin-right: 50px; + margin-top: 50px; width: 1440px; height: 400px; + justify-content: space-around; + align-self: center; + justify-self: center; `; export const ImageContainer = styled.div` - margin: 50px; width: 500px; height: 500px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; - margin-left: 200px; background-color: ${COLORS.lightGrey}; `; export const TextContainer = styled.div` - margin-left: 70px; width: 440px; height: 350px; - margin-top: 50px; + margin-top: 41px; `; export const ButtonsWrapper = styled.div` @@ -46,7 +41,7 @@ export const ButtonsWrapper = styled.div` align-items: center; width: 450px; height: 50px; - margin-top: 20px; + margin-top: 40px; `; export const QuantityButton = styled.div` @@ -94,4 +89,5 @@ export const ToastPopUP = styled(ToastContainer)` export const Fullscreen = styled.div` width: 100%; height: 100%; + display: grid; `; diff --git a/src/app/globals.css b/src/app/globals.css index 4d40d22d..c241f2ec 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -84,7 +84,11 @@ body { max-width: 100vw; min-height: 100vh; } - +button{ + &:hover { + cursor: pointer; + } +} body { background: white; color: black; diff --git a/src/app/login/styles.ts b/src/app/login/styles.ts index 41968785..d94d373f 100644 --- a/src/app/login/styles.ts +++ b/src/app/login/styles.ts @@ -3,11 +3,14 @@ import styled from 'styled-components'; import COLORS from '../../styles/colors'; export const LoginBox = styled.div` + display: flex; width: 500px; height: 420px; - border: 1px solid ${COLORS.neutralGrey}; justify-self: center; align-self: center; + background-color: ${COLORS.white}; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.10); + border-radius: 10px; `; export const LoginContent = styled.div` @@ -15,7 +18,6 @@ export const LoginContent = styled.div` flex-direction: column; align-self: center; justify-self: center; - margin-top: 30px; text-color: ${COLORS.black}; `; @@ -78,8 +80,10 @@ export const Fullscreen = styled.div` width: 100%; height: 100vh; display: grid; + background-color: ${COLORS.lightGrey}; `; export const InputField = styled.div` position: relative; + background-color: ${COLORS.lightGrey}; `; diff --git a/src/app/storefront/productButtons.tsx b/src/app/storefront/productButtons.tsx index 076e25a4..23b99371 100644 --- a/src/app/storefront/productButtons.tsx +++ b/src/app/storefront/productButtons.tsx @@ -68,7 +68,6 @@ export default function ProductButtons(props: { // Applying the filter to the categories of the product if (category !== 'All') { - console.log(category); const products = await filterUserProducts(category); if (products !== null) { setFiltredProducts(products); diff --git a/src/components/InputFieldsFolder/styles.ts b/src/components/InputFieldsFolder/styles.ts index aad7eb73..73520526 100644 --- a/src/components/InputFieldsFolder/styles.ts +++ b/src/components/InputFieldsFolder/styles.ts @@ -4,7 +4,7 @@ import COLORS from '../../styles/colors'; export const Input1 = styled.input<{ $pickColor?: boolean }>` color: ${props => (props.$pickColor ? '#203354' : COLORS.black)}; - background: ${props => (props.$pickColor ? '#ADD8E6' : COLORS.white)}; + background: ${props => (props.$pickColor ? '#ADD8E6' : COLORS.lightGrey)}; stroke-width: 1px; width: 420px; height: 40px; @@ -31,8 +31,8 @@ export const Input = styled.input<{ stroke-width: 1px; color: ${COLORS.black}; border: 1.5px solid - ${props => (props.$wrongLogin ? COLORS.darkRed : COLORS.black)}; - background: ${props => (props.$pickColor ? COLORS.lightRed : COLORS.white)}; + ${props => (props.$wrongLogin ? COLORS.darkRed : COLORS.neutralGrey)}; + background: ${props => (props.$pickColor ? COLORS.lightRed : COLORS.lightGrey)}; width: 420px; height: 40px; padding-left: 10px; From 9f61fe8200f845a490afa4a08e9c05ef535724f4 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Wed, 17 Apr 2024 21:07:56 -0700 Subject: [PATCH 03/43] product page finished; favorites hover button finished; login partially done --- src/api/supabase/queries/user_queries.ts | 1 + src/app/[productId]/page.tsx | 37 +++++++++-- src/app/[productId]/styles.ts | 49 ++++++++++++++- src/app/favorites/individualItem.tsx | 78 ++++++++++++++++++++++++ src/app/favorites/page.tsx | 47 +++----------- src/app/favorites/styles.ts | 23 +++++++ src/app/profileScreen/individualItem.tsx | 64 +++++++++++++++++++ src/app/profileScreen/page.tsx | 36 +++-------- src/app/profileScreen/styles.ts | 17 ++++++ 9 files changed, 279 insertions(+), 73 deletions(-) create mode 100644 src/app/favorites/individualItem.tsx create mode 100644 src/app/profileScreen/individualItem.tsx diff --git a/src/api/supabase/queries/user_queries.ts b/src/api/supabase/queries/user_queries.ts index 6b374796..cba6d587 100644 --- a/src/api/supabase/queries/user_queries.ts +++ b/src/api/supabase/queries/user_queries.ts @@ -105,6 +105,7 @@ export async function arrayOfFavorites(): Promise { return arrayOfProducts; } + /** * fetchUserAddress: Get's a user's address based on their UUID * @param uuid: String containing the uuid of the user diff --git a/src/app/[productId]/page.tsx b/src/app/[productId]/page.tsx index 02d35983..b657c863 100644 --- a/src/app/[productId]/page.tsx +++ b/src/app/[productId]/page.tsx @@ -2,8 +2,8 @@ import { useEffect, useState } from 'react'; import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; -import { Body1, Heading1, Body2Light, Body2Bold } from '@/styles/fonts'; -import { fetchProductByID } from '../../api/supabase/queries/product_queries'; +import { Body1, Heading1, Body2Light, Body2Bold, Body3 } from '@/styles/fonts'; +import { fetchProductByID, fetchUserProducts } from '../../api/supabase/queries/product_queries'; import BackButton from '../../components/BackButton/BackButton'; import 'react-toastify/dist/ReactToastify.css'; @@ -13,9 +13,13 @@ import { DescriptionContainer, ToastPopUP, Fullscreen, - LeftColumnDiv + LeftColumnDiv, + FavoritePopup, + HeartContainer, + HeartIcon, + TopRightContainer } from './styles'; - +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; import { Product } from '../../schema/schema'; import Buttons from './Buttons'; @@ -26,6 +30,10 @@ export default function ItemDisplay({ params: { productId: number }; }) { const [Item, setItem] = useState(); + const [IsFavorite, setIsFavorite] = useState( + false + ); + const [FilteredProducts, setFilteredProducts] = useState([]); useEffect(() => { async function fetchProducts() { @@ -34,8 +42,12 @@ export default function ItemDisplay({ response.category = await convertButtonNumberToCategory( response.category, ); + const data = (await fetchUserProducts()) as Product[]; + + setIsFavorite(!!data.find(item => item.id === params.productId)) if (response) { setItem(response); + setFilteredProducts(data); } } catch (error) { // console.error(error); @@ -45,6 +57,11 @@ export default function ItemDisplay({ fetchProducts(); }, [params.productId]); + async function handleFavorite() { + await addOrRemoveProductFromFavorite(await fetchProductByID(params.productId), !IsFavorite); + setIsFavorite(!IsFavorite); + } + return ( @@ -67,8 +84,18 @@ export default function ItemDisplay({ + {Item?.name} - + handleFavorite()}> + + + {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} + + + + + + Category: {Item?.category} diff --git a/src/app/[productId]/styles.ts b/src/app/[productId]/styles.ts index 3a68f588..285c5f76 100644 --- a/src/app/[productId]/styles.ts +++ b/src/app/[productId]/styles.ts @@ -1,8 +1,9 @@ import styled from 'styled-components'; import { ToastContainer } from 'react-toastify'; +import { Body3 } from '@/styles/fonts'; +import { Heart } from 'react-feather'; import COLORS from '../../styles/colors'; - export const LeftColumnDiv = styled.div` display: flex; flex-direction: column; @@ -19,6 +20,12 @@ export const DescriptionContainer = styled.div` justify-self: center; `; +export const TopRightContainer = styled.div` + display: flex; + justify-content: space-between; + width: 440px; +`; + export const ImageContainer = styled.div` width: 500px; height: 500px; @@ -66,6 +73,7 @@ export const PlusMinusButton = styled.button` font-size: 20px; color: ${COLORS.navy}; `; + export const AddToCartButton = styled.button` width: 265px; height: 50px; @@ -80,6 +88,45 @@ export const AddToCartButton = styled.button` border-color: transparent; `; +export const HeartIcon = styled(Heart)<{ $favorited: boolean }>` + width: 30px; + height: 30px; + color: ${props => (props.$favorited ? COLORS.marineBlue : COLORS.black)}; + fill: ${props => (props.$favorited ? COLORS.marineBlue : 'none')}; + position: relative; +`; + +export const HeartContainer = styled.button` + right: 16px; + top: 16px; + background-color: transparent; + border: none; + cursor: pointer; +`; + +export const FavoritePopup = styled.div` + position: absolute; + visibility: hidden; + width: 150px; + border-radius: 8px; + padding: 8px; + // Find better way to refactor this, it shouldn't need a calc + transform: translate(calc(-50% + 15px), -40px); + z-index: 1; + + color: ${COLORS.black}; + background: ${COLORS.lightPeriwinkle}; + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + + ${Body3} { + display: inline; + } + + ${HeartContainer}:hover & { + visibility: visible; + } +`; + export const ToastPopUP = styled(ToastContainer)` position: fixed; z-index: 100; diff --git a/src/app/favorites/individualItem.tsx b/src/app/favorites/individualItem.tsx new file mode 100644 index 00000000..7b68d6ad --- /dev/null +++ b/src/app/favorites/individualItem.tsx @@ -0,0 +1,78 @@ +import React, { useEffect, useState } from 'react'; + +import { useRouter } from 'next/navigation'; + +import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; + +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { + HeartIcon, + Hover, + FavoriteDiv, + ProductNameDiv, + ViewItem, + TransparentButton, +} from './styles'; + +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; + +import { Product } from '../../schema/schema'; + +export default function IndividualItem(props: { + favorite: Product; + setFavorites: (category: Product[]) => void; + Favorites: Product[]; +}) { + const { favorite, Favorites, setFavorites } = props; + const router = useRouter(); + const [hovering, setHovering] = useState(false); + + useEffect(() => { + async function changeCategory() { + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); + } + } + + changeCategory(); + }, []); + + async function clickFunctions(props2: { fav: Product }) { + const { fav } = props2; + addOrRemoveProductFromFavorite(fav, false); + setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); + } + + return ( + + {favorite.name} + + + {favorite.name} + Category: {favorite.category} + router.push(`/${favorite.id}`)}> + View Item + + + + clickFunctions({ fav: favorite })} + onMouseEnter={() => setHovering(true)} + onMouseLeave={() => setHovering(false)} + > + + Remove from favorites + + + + + ); +} \ No newline at end of file diff --git a/src/app/favorites/page.tsx b/src/app/favorites/page.tsx index 8c16242d..96af5abc 100644 --- a/src/app/favorites/page.tsx +++ b/src/app/favorites/page.tsx @@ -1,34 +1,26 @@ 'use client'; import { useState, useEffect } from 'react'; -import { useRouter } from 'next/navigation'; -import { Body1Bold, Body2, Heading1 } from '@/styles/fonts'; +import { Heading1 } from '@/styles/fonts'; import BackButton from '../../components/BackButton/BackButton'; import { arrayOfFavorites, - addOrRemoveProductFromFavorite, } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; import { - FavoriteDiv, OutterFavoriteDiv, OutterBox, - ProductNameDiv, - HeartIcon, - TransparentButton, - ViewItem, Fullscreen, - ImageLinkWrapper, } from './styles'; +import IndividualItem from './individualItem'; import { Product } from '../../schema/schema'; export default function FavoritesPage() { const [Favorites, setFavorites] = useState([]); - const router = useRouter(); async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; @@ -38,12 +30,6 @@ export default function FavoritesPage() { fetchProducts(); }, []); - async function clickFunctions(props: { fav: Product }) { - const { fav } = props; - addOrRemoveProductFromFavorite(fav, false); - setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); - } - return ( @@ -52,29 +38,12 @@ export default function FavoritesPage() { Favorites {Favorites.map(favorite => ( - - - {favorite.name} - - - - {favorite.name} - Category: {favorite.category} - router.push(`/${favorite.id}`)}> - View Item - - - - clickFunctions({ fav: favorite })} - > - - - + ))} diff --git a/src/app/favorites/styles.ts b/src/app/favorites/styles.ts index b2fb6851..b764502f 100644 --- a/src/app/favorites/styles.ts +++ b/src/app/favorites/styles.ts @@ -43,6 +43,11 @@ export const BackDiv = styled.button` export const OutterBox = styled.div` width: 800px; height: 100%; + margin-top: 40px; + display: flex; + flex-direction: column; + gap: 20px; + margin-bottom: 20px; `; export const Backtext = styled.p` @@ -55,6 +60,7 @@ export const HeartIcon = styled(Heart)` height: 30px; fill: #333286; margin-right: 25px; + margin-bottom: 40px; `; export const TransparentButton = styled.button` @@ -63,6 +69,23 @@ export const TransparentButton = styled.button` cursor: pointer; `; + +export const Hover = styled.div<{ $ishovering?: boolean }>` + visibility: ${props => (props.$ishovering ? 'visible' : 'hidden')}; + transform: translate(-10px, 0px); + margin-bottom: 7px; + color: black; + border: none; + width: 156px; + height: 26px; + border-radius: 8px; + background: var(--Light-Periwinkle, #f4f7ff); + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + padding-top: 6px; + position: relative; + text-align: center; +`; + export const NavBarMovedUP = styled(NavBar)` position: relative; `; diff --git a/src/app/profileScreen/individualItem.tsx b/src/app/profileScreen/individualItem.tsx new file mode 100644 index 00000000..eb2d7627 --- /dev/null +++ b/src/app/profileScreen/individualItem.tsx @@ -0,0 +1,64 @@ +import React, { useEffect, useState } from 'react'; + +import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; + +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { HeartIcon, Hover, FavoriteDiv, ProductNameDiv } from './styles'; + +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; + +import { Product } from '../../schema/schema'; +import { TransparentButton } from '../favorites/styles'; + +export default function IndividualItem(props: { + favorite: Product; + setFavorites: (category: Product[]) => void; + Favorites: Product[]; +}) { + const { favorite, Favorites, setFavorites } = props; + const [hovering, setHovering] = useState(false); + + useEffect(() => { + async function changeCategory() { + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); + } + } + + changeCategory(); + }, []); + + async function clickFunctions(props2: { fav: Product }) { + const { fav } = props2; + addOrRemoveProductFromFavorite(fav, false); + setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); + } + + return ( + + {favorite.name} + + {favorite.name} + Category: {favorite.category} + + clickFunctions({ fav: favorite })} + onMouseEnter={() => setHovering(true)} + onMouseLeave={() => setHovering(false)} + > + + Remove from favorites + + + + + ); +} \ No newline at end of file diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 2e101da1..8dca6cd1 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -42,9 +42,6 @@ import { TextSpacing, OrderHistory, FavoritesContainer, - ProductNameDiv, - FavoriteDiv, - HeartIcon, BackButtonDiv, BlankSpace, HeaderDiv, @@ -56,18 +53,14 @@ import { } from './styles'; import { signOut } from '../../api/supabase/auth/auth'; import 'react-toastify/dist/ReactToastify.css'; -import { TransparentButton } from '../favorites/styles'; +import IndividualItem from './individualItem'; + function FavoriteSection(props: { Favorites: Product[]; setFavorites: (category: Product[]) => void; }) { const { Favorites, setFavorites } = props; - async function clickFunctions(props2: { fav: Product }) { - const { fav } = props2; - addOrRemoveProductFromFavorite(fav, false); - setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); - } if (Favorites.length > 0) { return (
@@ -77,25 +70,12 @@ function FavoriteSection(props: { {Favorites.slice(0, 2).map(favorite => ( - - {favorite.name} - -

- {favorite.name} -
- Product ID: {favorite.id} -

-
- clickFunctions({ fav: favorite })} - > - - -
+ ))}
diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 884f01b1..5bdb9465 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -109,6 +109,23 @@ export const HeartIcon = styled(Heart)` width: 25px; height: 25px; fill: #333286; + margin-bottom: 40px; +`; + +export const Hover = styled.div<{ $ishovering?: boolean }>` + visibility: ${props => (props.$ishovering ? 'visible' : 'hidden')}; + transform: translate(0px, -1px); + margin-bottom: 7px; + color: black; + border: none; + width: 156px; + height: 26px; + border-radius: 8px; + background: var(--Light-Periwinkle, #f4f7ff); + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + padding-top: 6px; + position: relative; + text-align: center; `; export const BackButtonDiv = styled.div` From 20ce153cccd8734534c7a8b535f2c41154e22f41 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Wed, 17 Apr 2024 21:10:10 -0700 Subject: [PATCH 04/43] eslint and prettier --- src/api/supabase/queries/user_queries.ts | 1 - src/app/[productId]/Buttons.tsx | 5 +- src/app/[productId]/page.tsx | 62 +++++++++++----------- src/app/favorites/individualItem.tsx | 22 ++++---- src/app/favorites/page.tsx | 20 +++---- src/app/favorites/styles.ts | 1 - src/app/globals.css | 2 +- src/app/login/styles.ts | 2 +- src/app/profileScreen/individualItem.tsx | 36 ++++++------- src/app/profileScreen/page.tsx | 12 ++--- src/components/InputFieldsFolder/styles.ts | 3 +- 11 files changed, 79 insertions(+), 87 deletions(-) diff --git a/src/api/supabase/queries/user_queries.ts b/src/api/supabase/queries/user_queries.ts index cba6d587..6b374796 100644 --- a/src/api/supabase/queries/user_queries.ts +++ b/src/api/supabase/queries/user_queries.ts @@ -105,7 +105,6 @@ export async function arrayOfFavorites(): Promise { return arrayOfProducts; } - /** * fetchUserAddress: Get's a user's address based on their UUID * @param uuid: String containing the uuid of the user diff --git a/src/app/[productId]/Buttons.tsx b/src/app/[productId]/Buttons.tsx index 35783e34..a24fb075 100644 --- a/src/app/[productId]/Buttons.tsx +++ b/src/app/[productId]/Buttons.tsx @@ -11,7 +11,6 @@ import { import { addToCart } from '../../api/supabase/queries/cart_queries'; - export default function Buttons(props: { productNumber: number }) { const [quantity, setQuantity] = useState(1); const { productNumber } = props; @@ -36,11 +35,11 @@ export default function Buttons(props: { productNumber: number }) { - + {quantity} - + diff --git a/src/app/[productId]/page.tsx b/src/app/[productId]/page.tsx index b657c863..4f5aa2e0 100644 --- a/src/app/[productId]/page.tsx +++ b/src/app/[productId]/page.tsx @@ -3,7 +3,10 @@ import { useEffect, useState } from 'react'; import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; import { Body1, Heading1, Body2Light, Body2Bold, Body3 } from '@/styles/fonts'; -import { fetchProductByID, fetchUserProducts } from '../../api/supabase/queries/product_queries'; +import { + fetchProductByID, + fetchUserProducts, +} from '../../api/supabase/queries/product_queries'; import BackButton from '../../components/BackButton/BackButton'; import 'react-toastify/dist/ReactToastify.css'; @@ -17,7 +20,7 @@ import { FavoritePopup, HeartContainer, HeartIcon, - TopRightContainer + TopRightContainer, } from './styles'; import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; @@ -30,9 +33,7 @@ export default function ItemDisplay({ params: { productId: number }; }) { const [Item, setItem] = useState(); - const [IsFavorite, setIsFavorite] = useState( - false - ); + const [IsFavorite, setIsFavorite] = useState(false); const [FilteredProducts, setFilteredProducts] = useState([]); useEffect(() => { @@ -44,7 +45,7 @@ export default function ItemDisplay({ ); const data = (await fetchUserProducts()) as Product[]; - setIsFavorite(!!data.find(item => item.id === params.productId)) + setIsFavorite(!!data.find(item => item.id === params.productId)); if (response) { setItem(response); setFilteredProducts(data); @@ -58,7 +59,10 @@ export default function ItemDisplay({ }, [params.productId]); async function handleFavorite() { - await addOrRemoveProductFromFavorite(await fetchProductByID(params.productId), !IsFavorite); + await addOrRemoveProductFromFavorite( + await fetchProductByID(params.productId), + !IsFavorite, + ); setIsFavorite(!IsFavorite); } @@ -74,34 +78,32 @@ export default function ItemDisplay({ - - - {Item?.name} - + + + {Item?.name} + - - {Item?.name} - handleFavorite()}> - - - {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} - - - - - - + + {Item?.name} + handleFavorite()}> + + + {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} + + + + + + Category: {Item?.category} - - Product Details: - + Product Details: {Item?.description} diff --git a/src/app/favorites/individualItem.tsx b/src/app/favorites/individualItem.tsx index 7b68d6ad..7b9eea0c 100644 --- a/src/app/favorites/individualItem.tsx +++ b/src/app/favorites/individualItem.tsx @@ -26,20 +26,20 @@ export default function IndividualItem(props: { const { favorite, Favorites, setFavorites } = props; const router = useRouter(); const [hovering, setHovering] = useState(false); - + useEffect(() => { async function changeCategory() { - try { - favorite.category = await convertButtonNumberToCategory( - favorite.category, - ); - } catch (error) { - // console.error(error); - } + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); } + } - changeCategory(); - }, []); + changeCategory(); + }, [favorite]); async function clickFunctions(props2: { fav: Product }) { const { fav } = props2; @@ -75,4 +75,4 @@ export default function IndividualItem(props: { ); -} \ No newline at end of file +} diff --git a/src/app/favorites/page.tsx b/src/app/favorites/page.tsx index 96af5abc..6c00e83a 100644 --- a/src/app/favorites/page.tsx +++ b/src/app/favorites/page.tsx @@ -4,17 +4,11 @@ import { useState, useEffect } from 'react'; import { Heading1 } from '@/styles/fonts'; import BackButton from '../../components/BackButton/BackButton'; -import { - arrayOfFavorites, -} from '../../api/supabase/queries/user_queries'; +import { arrayOfFavorites } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; -import { - OutterFavoriteDiv, - OutterBox, - Fullscreen, -} from './styles'; +import { OutterFavoriteDiv, OutterBox, Fullscreen } from './styles'; import IndividualItem from './individualItem'; import { Product } from '../../schema/schema'; @@ -39,11 +33,11 @@ export default function FavoritesPage() { {Favorites.map(favorite => ( + key={favorite.id} + favorite={favorite} + setFavorites={setFavorites} + Favorites={Favorites} + /> ))} diff --git a/src/app/favorites/styles.ts b/src/app/favorites/styles.ts index b764502f..479119e8 100644 --- a/src/app/favorites/styles.ts +++ b/src/app/favorites/styles.ts @@ -69,7 +69,6 @@ export const TransparentButton = styled.button` cursor: pointer; `; - export const Hover = styled.div<{ $ishovering?: boolean }>` visibility: ${props => (props.$ishovering ? 'visible' : 'hidden')}; transform: translate(-10px, 0px); diff --git a/src/app/globals.css b/src/app/globals.css index c241f2ec..5b0dbd13 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -84,7 +84,7 @@ body { max-width: 100vw; min-height: 100vh; } -button{ +button { &:hover { cursor: pointer; } diff --git a/src/app/login/styles.ts b/src/app/login/styles.ts index d94d373f..03fb0708 100644 --- a/src/app/login/styles.ts +++ b/src/app/login/styles.ts @@ -9,7 +9,7 @@ export const LoginBox = styled.div` justify-self: center; align-self: center; background-color: ${COLORS.white}; - box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.10); + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); border-radius: 10px; `; diff --git a/src/app/profileScreen/individualItem.tsx b/src/app/profileScreen/individualItem.tsx index eb2d7627..f7de722e 100644 --- a/src/app/profileScreen/individualItem.tsx +++ b/src/app/profileScreen/individualItem.tsx @@ -17,20 +17,20 @@ export default function IndividualItem(props: { }) { const { favorite, Favorites, setFavorites } = props; const [hovering, setHovering] = useState(false); - + useEffect(() => { async function changeCategory() { - try { - favorite.category = await convertButtonNumberToCategory( - favorite.category, - ); - } catch (error) { - // console.error(error); - } + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); } + } - changeCategory(); - }, []); + changeCategory(); + }, [favorite]); async function clickFunctions(props2: { fav: Product }) { const { fav } = props2; @@ -40,12 +40,12 @@ export default function IndividualItem(props: { return ( - {favorite.name} - + {favorite.name} + {favorite.name} Category: {favorite.category} @@ -59,6 +59,6 @@ export default function IndividualItem(props: { - + ); -} \ No newline at end of file +} diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 8dca6cd1..4d63bb8f 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -13,7 +13,6 @@ import { Body2, } from '@/styles/fonts'; import { - addOrRemoveProductFromFavorite, arrayOfFavorites, fetchUser, fetchCurrentUserAddress, @@ -55,7 +54,6 @@ import { signOut } from '../../api/supabase/auth/auth'; import 'react-toastify/dist/ReactToastify.css'; import IndividualItem from './individualItem'; - function FavoriteSection(props: { Favorites: Product[]; setFavorites: (category: Product[]) => void; @@ -71,11 +69,11 @@ function FavoriteSection(props: { {Favorites.slice(0, 2).map(favorite => ( + key={favorite.id} + favorite={favorite} + setFavorites={setFavorites} + Favorites={Favorites} + /> ))} diff --git a/src/components/InputFieldsFolder/styles.ts b/src/components/InputFieldsFolder/styles.ts index 73520526..2fa8ed20 100644 --- a/src/components/InputFieldsFolder/styles.ts +++ b/src/components/InputFieldsFolder/styles.ts @@ -32,7 +32,8 @@ export const Input = styled.input<{ color: ${COLORS.black}; border: 1.5px solid ${props => (props.$wrongLogin ? COLORS.darkRed : COLORS.neutralGrey)}; - background: ${props => (props.$pickColor ? COLORS.lightRed : COLORS.lightGrey)}; + background: ${props => + props.$pickColor ? COLORS.lightRed : COLORS.lightGrey}; width: 420px; height: 40px; padding-left: 10px; From 3add398b5ac281677719a58e5ca2eeb4fc8d3c17 Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Thu, 18 Apr 2024 15:50:09 -0700 Subject: [PATCH 05/43] temp --- src/app/orderConfirmationPickUp/page.tsx | 7 +++- src/app/orderConfirmationPickUp/styles.ts | 47 +++++++++++++++-------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 7cde8b21..0a448c5c 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -17,8 +17,9 @@ import { Heading4Bold, Body2Light, } from '@/styles/fonts'; -import { fetchCartItemsWithQuantity } from '../../api/supabase/queries/cart_queries'; import { useSearchParams } from 'next/navigation'; + + import BackButton from '../../components/BackButton/BackButton'; import NavBar from '../../components/NavBarFolder/NavBar'; @@ -39,6 +40,7 @@ import { LeftColumnDiv, RightColumnDiv, DetailsHeader, + Wrapper2, PageDiv, CenterDiv, BackButtonDiv, @@ -47,6 +49,7 @@ import { import { Product, User, Pickup } from '../../schema/schema'; import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; + export default function OrderConfirmationPickUp() { const [Cart, setCart] = useState([]); const [user, setUser] = useState(); @@ -76,7 +79,6 @@ export default function OrderConfirmationPickUp() { function organizePickupTime() { const startTime = pickupTime?.start_time.toLocaleString(); - const endTime = pickupTime?.end_time.toLocaleString(); const date = startTime == null ? ['0', '0', '0'] @@ -138,6 +140,7 @@ export default function OrderConfirmationPickUp() { + diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index 32b850c6..255792de 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -9,10 +9,10 @@ export const FavoriteDiv = styled.div` flex-direction: row; align-items: center; justify-content: space-between; - width: 100%; + width: 750px; margin-bottom: 50px; margin-top: 30px; - margin-right: 20px; + margin-right: 10px; `; export const OutterFavoriteDiv = styled.div` @@ -22,18 +22,19 @@ export const OutterFavoriteDiv = styled.div` border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 800px; max-height: 100%; + max-width: 750px; margin-top: 20px; - margin-right: 60px; - margin-left: 40px; - padding-right: 15px; - padding-top: 10px; + margin-right: 10px; + margin-left: 20px; + padding-right: 7px; + padding-top: 7px; `; export const ScrollDiv = styled.div` overflow: scroll; - width: 100%; + overflow-x: hidden; + max-width: 100%; `; export const ImageDiv = styled.div` @@ -225,13 +226,13 @@ export const LeftColumnDiv = styled.div` flex-flow: column; justify-content: space-evenly; align-items: space-evenly; - width: 100%; + width: 800px; `; export const RightColumnDiv = styled.div` display: flex; flex-flow: column; - align-items: start; - width: 100%; + align-items: left; + width: 475px; `; export const BackButtonDiv = styled.div` @@ -239,8 +240,9 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; - margin-left: 60px; + margin-left: 40px; margin-bottom: 40px; + margin-top: 20px; `; export const WhiteBackgroundDiv = styled.div` @@ -252,6 +254,14 @@ export const WhiteBackgroundDiv = styled.div` box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); `; + +export const Wrapper2 = styled.div` + display: flex; + flex-direction: col; + align-items: space-evenly; + justify-content: space-around; +`; + export const BottomColumnDiv = styled.div` display: flex; flex-direction: row; @@ -261,15 +271,15 @@ export const BottomColumnDiv = styled.div` margin-left: 20px; margin-right: 20px; margin-bottom: 30px; - gap: 30px; + gap: 10px; `; export const TextDiv = styled.div` display: flex; flex-direction: row; - margin-left: 40px; - margin-top: 20px; - margin-bottom: 20px; + margin-left: 20px; + margin-top: 10px; + margin-bottom: 10px; `; export const TextDiv1 = styled.div` @@ -286,10 +296,12 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; + position: relative; margin-bottom: 40px; `; export const ShippingDetailsDiv = styled.div` + display: flex; flex-direction: column; align-items: flex-start; @@ -302,7 +314,7 @@ export const ShippingDetailsDiv = styled.div` padding: 36px 34px; gap: 33px; max-height: 100%; - margin-top: 93px; + margin-top: 75px; margin-bottom: 30px; margin-right: 40px; `; @@ -320,6 +332,7 @@ export const CenterDiv = styled.div` display: flex; align-items: center; justify-content: center; + position: relative; width: 100%; padding: 20px; `; \ No newline at end of file From f595b6407f7c85b92d0a36fbb5e6302904f70c60 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 11:20:09 -0700 Subject: [PATCH 06/43] order details page done --- src/app/pickup/page.tsx | 26 ++++++++++++++++++-------- src/app/pickup/styles.ts | 9 +++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 097b878e..4e336ece 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -1,6 +1,9 @@ 'use client'; // import { GlobalStyle } from "@/styles/components"; + +import 'react-toastify/dist/ReactToastify.css'; +import { toast } from 'react-toastify'; import { ArrowLeft } from 'react-feather'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import querystring from 'querystring'; @@ -11,7 +14,7 @@ import { } from '@/api/supabase/queries/cart_queries'; import { useState, useEffect } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; -import { Heading4Bold } from '@/styles/fonts'; +import { Body1, Heading4Bold } from '@/styles/fonts'; import { fetchNRecentPickupTimes } from '@/api/supabase/queries/pickup_queries'; import { updateCartPickupId, @@ -36,8 +39,10 @@ import { PickupContent, PickupContainer, PickupTimeButton, + ToastPopUP, } from './styles'; + function DateInfoComponent(date: { date: unknown }) { const date1 = new Date(date.date as string); const daysOfWeek = [ @@ -100,6 +105,12 @@ export default function PickUp() { return (
+ router.push('/cart')}> @@ -116,10 +127,11 @@ export default function PickUp() { Phone Number {Profile?.phone_numbers} -
+
Time Slot
- +
Pick Up times: 10:00 AM - 12:00 PM
+
Location: 3170 23rd Street, San Francisco, CA 94110
{Time.map(time => ( ))}
-
Pick Up times: 10:00 AM - 12:00 PM
-
Location: 3170 23rd Street, San Francisco, CA 94110
@@ -157,12 +167,12 @@ export default function PickUp() { await updateOrderStatus(orderID, OrderStatus.Submitted); await createOrder(); const newestOrder = await fetchCartIdFromUser(); - console.log(newestOrder); await updateOrderStatus(newestOrder, OrderStatus.inProgress); const queryString = querystring.stringify({ orderID }); router.push(`/orderConfirmationPickUp?${queryString}`); - } else { - // TODO handle the case where they didn't select a time! + } + if (selectedPickupIndex === 0){ + toast(`You must select a pick-up date!`); } }} > diff --git a/src/app/pickup/styles.ts b/src/app/pickup/styles.ts index 35365312..257579c3 100644 --- a/src/app/pickup/styles.ts +++ b/src/app/pickup/styles.ts @@ -1,11 +1,13 @@ import styled from 'styled-components'; +import { ToastContainer } from 'react-toastify'; import COLORS from '../../styles/colors'; import NavBar from '../../components/NavBarFolder/NavBar'; import Footer from '../../components/FooterFolder/Footer'; + export const PickupContainer = styled.div` width: 730px; height: 400px; @@ -263,3 +265,10 @@ export const HeaderShiftLeft = styled.h2` export const PShiftLeft = styled.p` margin-left: 15px; `; + +export const ToastPopUP = styled(ToastContainer)` + position: fixed; + z-index: 100; + transform: translatey(90px); + background-color: ${COLORS.lightRed}; +`; \ No newline at end of file From a34ef2d70f43e4bf7cb10a766ee0fec7e6c94987 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 11:30:25 -0700 Subject: [PATCH 07/43] changes made --- src/app/pickup/page.tsx | 20 ++++++++++++++----- src/app/pickup/styles.ts | 3 +-- .../OrderSummaryFolder/OrderSummary.tsx | 6 +++--- src/components/OrderSummaryFolder/styles.ts | 8 +++++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 4e336ece..33e43490 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -42,7 +42,6 @@ import { ToastPopUP, } from './styles'; - function DateInfoComponent(date: { date: unknown }) { const date1 = new Date(date.date as string); const daysOfWeek = [ @@ -127,11 +126,22 @@ export default function PickUp() { Phone Number {Profile?.phone_numbers} -
+
Time Slot
-
Pick Up times: 10:00 AM - 12:00 PM
-
Location: 3170 23rd Street, San Francisco, CA 94110
+
+ {' '} + Pick Up times: 10:00 AM - 12:00 PM{' '} +
+
+ Location: 3170 23rd Street, San Francisco, CA 94110 +
{Time.map(time => ( Order Summary - Product Name - Qty. + PRODUCT NAME + QTY {cart.map(cartItem => ( diff --git a/src/components/OrderSummaryFolder/styles.ts b/src/components/OrderSummaryFolder/styles.ts index e90a18ef..16fd4a3f 100644 --- a/src/components/OrderSummaryFolder/styles.ts +++ b/src/components/OrderSummaryFolder/styles.ts @@ -1,3 +1,4 @@ +import COLORS from '@/styles/colors'; import styled from 'styled-components'; export const OrderSummaryDiv = styled.div` @@ -37,6 +38,10 @@ export const WhiteBackgroundDiv = styled.div` width: 350px; padding: 20px; box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); + display: flex; + justify-content: center; + align-items: flex-start; + flex-direction: column; `; export const HeaderShiftRight = styled.h2` @@ -57,7 +62,8 @@ export const OrderSummaryHeaderDiv = styled.div` justify-content: space-between; align-items: center; flex-direction: row; - margin-bottom: 10px; + margin-bottom: 15px; + color: ${COLORS.marineBlue}; `; export const ItemNameDiv = styled.div` From 745b2a1949b2cac8983436c63f34a99414748bd5 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 12:32:56 -0700 Subject: [PATCH 08/43] order details page done --- src/api/supabase/queries/cart_queries.ts | 1 - src/api/supabase/queries/delivery_queries.ts | 15 ++++++ src/api/supabase/queries/order_queries.ts | 2 - src/api/supabase/queries/product_queries.ts | 2 - src/api/supabase/queries/user_queries.ts | 12 ++--- src/app/orderConfirmationDelivery/page.tsx | 50 ++++++++++++++++++-- src/app/orderConfirmationDelivery/styles.ts | 14 ++++-- src/app/orderConfirmationPickUp/page.tsx | 6 +-- src/app/pickup/page.tsx | 2 +- 9 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 src/api/supabase/queries/delivery_queries.ts diff --git a/src/api/supabase/queries/cart_queries.ts b/src/api/supabase/queries/cart_queries.ts index 2f1bee77..c8062040 100644 --- a/src/api/supabase/queries/cart_queries.ts +++ b/src/api/supabase/queries/cart_queries.ts @@ -206,7 +206,6 @@ export async function fetchCartItemsWithQuantity(): Promise< }); const fetchedProducts = await Promise.all(productPromises); - console.log(fetchedProducts); return fetchedProducts; } diff --git a/src/api/supabase/queries/delivery_queries.ts b/src/api/supabase/queries/delivery_queries.ts new file mode 100644 index 00000000..baa88631 --- /dev/null +++ b/src/api/supabase/queries/delivery_queries.ts @@ -0,0 +1,15 @@ +import supabase from '../createClient'; + +export type DeliveryTimes = { + delivery_group: number; + delivery_time: number; +}; + +export async function fetchDeliveryTimes(): Promise { + const { data, error } = await supabase.from('delivery_times').select('*'); + + if (error) { + throw new Error(`Error fetching delivery times: ${error.message}`); + } + return data; +} diff --git a/src/api/supabase/queries/order_queries.ts b/src/api/supabase/queries/order_queries.ts index f3e44c69..e011398d 100644 --- a/src/api/supabase/queries/order_queries.ts +++ b/src/api/supabase/queries/order_queries.ts @@ -38,12 +38,10 @@ export async function createOrder() { .insert({ user_id: user.id }) .select('*') .single(); - console.log(order); if (error) { throw new Error(`Error creating order: ${error.message}`); } - console.log(order.id); await supabase .from('profiles') .update({ cart_id: order.id }) diff --git a/src/api/supabase/queries/product_queries.ts b/src/api/supabase/queries/product_queries.ts index 6112c195..85ec9fbb 100644 --- a/src/api/supabase/queries/product_queries.ts +++ b/src/api/supabase/queries/product_queries.ts @@ -88,7 +88,6 @@ export async function filterProduct(productType: string): Promise { export async function convertCategoryToNumber( productType: string, ): Promise { - console.log(productType); const { data: buttonVal, error } = await supabase .from('storefront_buttons') .select('*') @@ -104,7 +103,6 @@ export async function convertCategoryToNumber( export async function fetchUnprescribedCategory( productType: string, ): Promise { - console.log(productType); const productTypeConverted = await convertCategoryToNumber(productType); const { data: products, error } = await supabase diff --git a/src/api/supabase/queries/user_queries.ts b/src/api/supabase/queries/user_queries.ts index 6b374796..96cd6def 100644 --- a/src/api/supabase/queries/user_queries.ts +++ b/src/api/supabase/queries/user_queries.ts @@ -1,8 +1,6 @@ -import { Lekton } from 'next/font/google'; import supabase from '../createClient'; import { User, Product } from '../../../schema/schema'; import { fetchProductByID } from './product_queries'; -import { convertButtonNumberToCategory } from './button_queries'; /** * fetchUser is a function that fetches the user data from the database and returns the user object. @@ -48,12 +46,12 @@ export async function fetchUserByUUID(uuid: string) { .single(); if (error) { - console.error('Error fetching user data:', error); + throw new Error(`Error fetching user data: ${error.message}`); } return user; } catch (error) { - console.error('Error:', error); + throw new Error(`Error`); throw error; } } @@ -118,13 +116,12 @@ export async function fetchUserAddress(uuid: string) { .single(); if (error) { - console.error('Error fetching user data:', error); + throw new Error(`Error fetching user data: ${error.message}`); } return user; } catch (error) { - console.error('Error:', error); - throw error; + throw new Error(`Error:`); } } @@ -141,7 +138,6 @@ export async function fetchCurrentUserAddress() { .eq('user_id', user.id) .limit(1) .single(); - console.log(address); if (error) { console.error('Error fetching user data:', error); diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx index 2d2f902d..3a538d50 100644 --- a/src/app/orderConfirmationDelivery/page.tsx +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -6,8 +6,18 @@ import { fetchCurrentUserAddress, } from '@/api/supabase/queries/user_queries'; -import { Body1, Body2Light, Heading3Bold, Heading4Bold } from '@/styles/fonts'; +import { + Body1, + Body2, + Body2Light, + Heading3Bold, + Heading4Bold, +} from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; +import { + DeliveryTimes, + fetchDeliveryTimes, +} from '@/api/supabase/queries/delivery_queries'; import BackButton from '../../components/BackButton/BackButton'; import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; @@ -26,6 +36,7 @@ import { DetailsHeader, PageDiv, CenterDiv, + Quantity, } from './styles'; import { Product, User, Address } from '../../schema/schema'; @@ -37,12 +48,12 @@ export default function OrderConfirmationDelivery() { const [userAddress, setUserAddress] = useState
(); const searchParams = useSearchParams(); const orderIDFromSearch = searchParams.get('orderID'); + const [delivTimes, setDelivTimes] = useState([]); useEffect(() => { async function fetchProducts() { const cartItems = (await fetchCartItemsWithQuantityByID( orderIDFromSearch, )) as Product[]; - console.log(cartItems); setCart(cartItems); } @@ -52,11 +63,39 @@ export default function OrderConfirmationDelivery() { const address = await fetchCurrentUserAddress(); setUserAddress(address); } + async function fetchDelivTimes() { + const deliv = await fetchDeliveryTimes(); + setDelivTimes(deliv); + } fetchProducts(); setUserDetails(); + fetchDelivTimes(); }, []); + function organizeDelivTime() { + const userGrp = user?.delivery_group == null ? 1 : user?.delivery_group; + const Time = delivTimes[userGrp]?.delivery_time.toLocaleString(); + const date = + Time == null ? ['0', '0', '0'] : Time?.substring(0, 10).split('-'); + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const dateStr = `${months[parseInt(date[1], 10)]} ${date[2]}, ${date[0]}`; + return `${dateStr}`; + } + return (
@@ -84,6 +123,11 @@ export default function OrderConfirmationDelivery() { {cartItem.name} Category: {cartItem.category} + + + Quantity: {cartItem.quantity} + + ))} @@ -93,7 +137,7 @@ export default function OrderConfirmationDelivery() { Delivery Information Estimated Date - {user?.delivery_group} + {organizeDelivTime()} Location {userAddress?.street}, {userAddress?.city},{' '} diff --git a/src/app/orderConfirmationDelivery/styles.ts b/src/app/orderConfirmationDelivery/styles.ts index e72f1ef1..618a5919 100644 --- a/src/app/orderConfirmationDelivery/styles.ts +++ b/src/app/orderConfirmationDelivery/styles.ts @@ -8,11 +8,17 @@ export const FavoriteDiv = styled.div` display: flex; flex-direction: row; align-items: flex-start; - justify-content: flex-start; + justify-content: space-between; width: 100%; margin-bottom: 50px; margin-top: 30px; - gap: 120px; +`; + +export const Quantity = styled.div` + display: flex; + align-self: center; + justify-content: flex-start; + margin-right: 40px; `; export const OrderDetailsDiv = styled.div` @@ -216,16 +222,18 @@ export const OrderTotalDiv = styled.div` `; export const LeftColumnDiv = styled.div` + margin-top: 30px; display: flex; flex-flow: column; justify-content: space-evenly; align-items: space-evenly; + gap: 20px; `; export const RightColumnDiv = styled.div` display: flex; flex-flow: column; margin-left: 20px; - margin-top: 127px; + margin-top: 123px; `; export const WhiteBackgroundDiv = styled.div` diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 871a0e1e..671c018a 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -4,10 +4,7 @@ import { useState, useEffect } from 'react'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; -import { - fetchCurrentOrdersByUser, - getOrderById, -} from '@/api/supabase/queries/order_queries'; +import { getOrderById } from '@/api/supabase/queries/order_queries'; import { Body1, Body1Bold, @@ -73,7 +70,6 @@ export default function OrderConfirmationPickUp() { function organizePickupTime() { const startTime = pickupTime?.start_time.toLocaleString(); - const endTime = pickupTime?.end_time.toLocaleString(); const date = startTime == null ? ['0', '0', '0'] diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 33e43490..6ea5a83a 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -13,7 +13,7 @@ import { totalNumberOfItemsInCart, } from '@/api/supabase/queries/cart_queries'; import { useState, useEffect } from 'react'; -import { useRouter, useSearchParams } from 'next/navigation'; +import { useRouter } from 'next/navigation'; import { Body1, Heading4Bold } from '@/styles/fonts'; import { fetchNRecentPickupTimes } from '@/api/supabase/queries/pickup_queries'; import { From dfd7df1cca03afa739ca33bdc737770819924672 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Wed, 17 Apr 2024 14:20:29 -0700 Subject: [PATCH 09/43] fixes --- src/app/[productId]/Buttons.tsx | 8 ++++--- src/app/[productId]/page.tsx | 20 ++++++++--------- src/app/[productId]/styles.ts | 26 +++++++++------------- src/app/globals.css | 6 ++++- src/app/login/styles.ts | 8 +++++-- src/app/storefront/productButtons.tsx | 1 - src/components/InputFieldsFolder/styles.ts | 6 ++--- 7 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/app/[productId]/Buttons.tsx b/src/app/[productId]/Buttons.tsx index 3cfe8355..9cc8d802 100644 --- a/src/app/[productId]/Buttons.tsx +++ b/src/app/[productId]/Buttons.tsx @@ -1,5 +1,7 @@ import React, { useState } from 'react'; import { toast } from 'react-toastify'; +import { Plus, Minus } from 'react-feather'; +import { Body1Bold } from '@/styles/fonts'; import { ButtonsWrapper, AddToCartButton, @@ -37,11 +39,11 @@ export default function Buttons(props: { productNumber: number }) { - – + - {quantity} + {quantity} - + + diff --git a/src/app/[productId]/page.tsx b/src/app/[productId]/page.tsx index 3a45652a..d892f214 100644 --- a/src/app/[productId]/page.tsx +++ b/src/app/[productId]/page.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; -import { Body1, Heading1, Body2Light } from '@/styles/fonts'; +import { Body1, Heading1, Body2Light, Body2Bold } from '@/styles/fonts'; import { fetchProductByID } from '../../api/supabase/queries/product_queries'; import BackButton from '../../components/BackButton/BackButton'; import 'react-toastify/dist/ReactToastify.css'; @@ -13,6 +13,7 @@ import { DescriptionContainer, ToastPopUP, Fullscreen, + LeftColumnDiv } from './styles'; import NavBar from '../../components/NavBarFolder/NavBar'; @@ -53,11 +54,10 @@ export default function ItemDisplay({ limit={1} hideProgressBar /> -
- -
+ + + {Item?.name} - {Item?.category} + Category: {Item?.category} - - Product ID: {Item?.id} - - + Product Details: + + + {Item?.description} - {Item?.description} diff --git a/src/app/[productId]/styles.ts b/src/app/[productId]/styles.ts index e96cbb27..3a68f588 100644 --- a/src/app/[productId]/styles.ts +++ b/src/app/[productId]/styles.ts @@ -2,42 +2,37 @@ import styled from 'styled-components'; import { ToastContainer } from 'react-toastify'; import COLORS from '../../styles/colors'; -export const BackButton = styled.button` + +export const LeftColumnDiv = styled.div` display: flex; - padding-top: 230px; - padding-left: 30px; - width: 100px; - height: 40px; - background-color: transparent; - border-color: transparent; - font-size: 15px; + flex-direction: column; + gap: 25px; `; export const DescriptionContainer = styled.div` display: flex; - margin-left: 50px; - margin-right: 50px; + margin-top: 50px; width: 1440px; height: 400px; + justify-content: space-around; + align-self: center; + justify-self: center; `; export const ImageContainer = styled.div` - margin: 50px; width: 500px; height: 500px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; - margin-left: 200px; background-color: ${COLORS.lightGrey}; `; export const TextContainer = styled.div` - margin-left: 70px; width: 440px; height: 350px; - margin-top: 50px; + margin-top: 41px; `; export const ButtonsWrapper = styled.div` @@ -46,7 +41,7 @@ export const ButtonsWrapper = styled.div` align-items: center; width: 450px; height: 50px; - margin-top: 20px; + margin-top: 40px; `; export const QuantityButton = styled.div` @@ -94,4 +89,5 @@ export const ToastPopUP = styled(ToastContainer)` export const Fullscreen = styled.div` width: 100%; height: 100%; + display: grid; `; diff --git a/src/app/globals.css b/src/app/globals.css index 4d40d22d..c241f2ec 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -84,7 +84,11 @@ body { max-width: 100vw; min-height: 100vh; } - +button{ + &:hover { + cursor: pointer; + } +} body { background: white; color: black; diff --git a/src/app/login/styles.ts b/src/app/login/styles.ts index 41968785..d94d373f 100644 --- a/src/app/login/styles.ts +++ b/src/app/login/styles.ts @@ -3,11 +3,14 @@ import styled from 'styled-components'; import COLORS from '../../styles/colors'; export const LoginBox = styled.div` + display: flex; width: 500px; height: 420px; - border: 1px solid ${COLORS.neutralGrey}; justify-self: center; align-self: center; + background-color: ${COLORS.white}; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.10); + border-radius: 10px; `; export const LoginContent = styled.div` @@ -15,7 +18,6 @@ export const LoginContent = styled.div` flex-direction: column; align-self: center; justify-self: center; - margin-top: 30px; text-color: ${COLORS.black}; `; @@ -78,8 +80,10 @@ export const Fullscreen = styled.div` width: 100%; height: 100vh; display: grid; + background-color: ${COLORS.lightGrey}; `; export const InputField = styled.div` position: relative; + background-color: ${COLORS.lightGrey}; `; diff --git a/src/app/storefront/productButtons.tsx b/src/app/storefront/productButtons.tsx index 076e25a4..23b99371 100644 --- a/src/app/storefront/productButtons.tsx +++ b/src/app/storefront/productButtons.tsx @@ -68,7 +68,6 @@ export default function ProductButtons(props: { // Applying the filter to the categories of the product if (category !== 'All') { - console.log(category); const products = await filterUserProducts(category); if (products !== null) { setFiltredProducts(products); diff --git a/src/components/InputFieldsFolder/styles.ts b/src/components/InputFieldsFolder/styles.ts index aad7eb73..73520526 100644 --- a/src/components/InputFieldsFolder/styles.ts +++ b/src/components/InputFieldsFolder/styles.ts @@ -4,7 +4,7 @@ import COLORS from '../../styles/colors'; export const Input1 = styled.input<{ $pickColor?: boolean }>` color: ${props => (props.$pickColor ? '#203354' : COLORS.black)}; - background: ${props => (props.$pickColor ? '#ADD8E6' : COLORS.white)}; + background: ${props => (props.$pickColor ? '#ADD8E6' : COLORS.lightGrey)}; stroke-width: 1px; width: 420px; height: 40px; @@ -31,8 +31,8 @@ export const Input = styled.input<{ stroke-width: 1px; color: ${COLORS.black}; border: 1.5px solid - ${props => (props.$wrongLogin ? COLORS.darkRed : COLORS.black)}; - background: ${props => (props.$pickColor ? COLORS.lightRed : COLORS.white)}; + ${props => (props.$wrongLogin ? COLORS.darkRed : COLORS.neutralGrey)}; + background: ${props => (props.$pickColor ? COLORS.lightRed : COLORS.lightGrey)}; width: 420px; height: 40px; padding-left: 10px; From 37910e22e12143b088fad58210797440a689cc53 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Wed, 17 Apr 2024 21:07:56 -0700 Subject: [PATCH 10/43] product page finished; favorites hover button finished; login partially done --- src/api/supabase/queries/user_queries.ts | 1 + src/app/[productId]/page.tsx | 37 +++++++++-- src/app/[productId]/styles.ts | 49 ++++++++++++++- src/app/favorites/individualItem.tsx | 78 ++++++++++++++++++++++++ src/app/favorites/page.tsx | 47 +++----------- src/app/favorites/styles.ts | 25 +++++++- src/app/profileScreen/individualItem.tsx | 64 +++++++++++++++++++ src/app/profileScreen/page.tsx | 36 +++-------- src/app/profileScreen/styles.ts | 17 ++++++ 9 files changed, 278 insertions(+), 76 deletions(-) create mode 100644 src/app/favorites/individualItem.tsx create mode 100644 src/app/profileScreen/individualItem.tsx diff --git a/src/api/supabase/queries/user_queries.ts b/src/api/supabase/queries/user_queries.ts index 4b70bbcb..b186ec0e 100644 --- a/src/api/supabase/queries/user_queries.ts +++ b/src/api/supabase/queries/user_queries.ts @@ -112,6 +112,7 @@ export async function arrayOfFavorites(): Promise { return arrayOfProducts; } + /** * fetchUserAddress: Get's a user's address based on their UUID * @param uuid: String containing the uuid of the user diff --git a/src/app/[productId]/page.tsx b/src/app/[productId]/page.tsx index d892f214..74314a16 100644 --- a/src/app/[productId]/page.tsx +++ b/src/app/[productId]/page.tsx @@ -2,8 +2,8 @@ import { useEffect, useState } from 'react'; import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; -import { Body1, Heading1, Body2Light, Body2Bold } from '@/styles/fonts'; -import { fetchProductByID } from '../../api/supabase/queries/product_queries'; +import { Body1, Heading1, Body2Light, Body2Bold, Body3 } from '@/styles/fonts'; +import { fetchProductByID, fetchUserProducts } from '../../api/supabase/queries/product_queries'; import BackButton from '../../components/BackButton/BackButton'; import 'react-toastify/dist/ReactToastify.css'; @@ -13,9 +13,13 @@ import { DescriptionContainer, ToastPopUP, Fullscreen, - LeftColumnDiv + LeftColumnDiv, + FavoritePopup, + HeartContainer, + HeartIcon, + TopRightContainer } from './styles'; - +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; import { Product } from '../../schema/schema'; import Buttons from './Buttons'; @@ -26,6 +30,10 @@ export default function ItemDisplay({ params: { productId: number }; }) { const [Item, setItem] = useState(); + const [IsFavorite, setIsFavorite] = useState( + false + ); + const [FilteredProducts, setFilteredProducts] = useState([]); useEffect(() => { async function fetchProducts() { @@ -34,8 +42,12 @@ export default function ItemDisplay({ response.category = await convertButtonNumberToCategory( response.category, ); + const data = (await fetchUserProducts()) as Product[]; + + setIsFavorite(!!data.find(item => item.id === params.productId)) if (response) { setItem(response); + setFilteredProducts(data); } } catch (error) { // console.error(error); @@ -45,6 +57,11 @@ export default function ItemDisplay({ fetchProducts(); }, [params.productId]); + async function handleFavorite() { + await addOrRemoveProductFromFavorite(await fetchProductByID(params.productId), !IsFavorite); + setIsFavorite(!IsFavorite); + } + return ( @@ -67,8 +84,18 @@ export default function ItemDisplay({ + {Item?.name} - + handleFavorite()}> + + + {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} + + + + + + Category: {Item?.category} diff --git a/src/app/[productId]/styles.ts b/src/app/[productId]/styles.ts index 3a68f588..285c5f76 100644 --- a/src/app/[productId]/styles.ts +++ b/src/app/[productId]/styles.ts @@ -1,8 +1,9 @@ import styled from 'styled-components'; import { ToastContainer } from 'react-toastify'; +import { Body3 } from '@/styles/fonts'; +import { Heart } from 'react-feather'; import COLORS from '../../styles/colors'; - export const LeftColumnDiv = styled.div` display: flex; flex-direction: column; @@ -19,6 +20,12 @@ export const DescriptionContainer = styled.div` justify-self: center; `; +export const TopRightContainer = styled.div` + display: flex; + justify-content: space-between; + width: 440px; +`; + export const ImageContainer = styled.div` width: 500px; height: 500px; @@ -66,6 +73,7 @@ export const PlusMinusButton = styled.button` font-size: 20px; color: ${COLORS.navy}; `; + export const AddToCartButton = styled.button` width: 265px; height: 50px; @@ -80,6 +88,45 @@ export const AddToCartButton = styled.button` border-color: transparent; `; +export const HeartIcon = styled(Heart)<{ $favorited: boolean }>` + width: 30px; + height: 30px; + color: ${props => (props.$favorited ? COLORS.marineBlue : COLORS.black)}; + fill: ${props => (props.$favorited ? COLORS.marineBlue : 'none')}; + position: relative; +`; + +export const HeartContainer = styled.button` + right: 16px; + top: 16px; + background-color: transparent; + border: none; + cursor: pointer; +`; + +export const FavoritePopup = styled.div` + position: absolute; + visibility: hidden; + width: 150px; + border-radius: 8px; + padding: 8px; + // Find better way to refactor this, it shouldn't need a calc + transform: translate(calc(-50% + 15px), -40px); + z-index: 1; + + color: ${COLORS.black}; + background: ${COLORS.lightPeriwinkle}; + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + + ${Body3} { + display: inline; + } + + ${HeartContainer}:hover & { + visibility: visible; + } +`; + export const ToastPopUP = styled(ToastContainer)` position: fixed; z-index: 100; diff --git a/src/app/favorites/individualItem.tsx b/src/app/favorites/individualItem.tsx new file mode 100644 index 00000000..7b68d6ad --- /dev/null +++ b/src/app/favorites/individualItem.tsx @@ -0,0 +1,78 @@ +import React, { useEffect, useState } from 'react'; + +import { useRouter } from 'next/navigation'; + +import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; + +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { + HeartIcon, + Hover, + FavoriteDiv, + ProductNameDiv, + ViewItem, + TransparentButton, +} from './styles'; + +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; + +import { Product } from '../../schema/schema'; + +export default function IndividualItem(props: { + favorite: Product; + setFavorites: (category: Product[]) => void; + Favorites: Product[]; +}) { + const { favorite, Favorites, setFavorites } = props; + const router = useRouter(); + const [hovering, setHovering] = useState(false); + + useEffect(() => { + async function changeCategory() { + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); + } + } + + changeCategory(); + }, []); + + async function clickFunctions(props2: { fav: Product }) { + const { fav } = props2; + addOrRemoveProductFromFavorite(fav, false); + setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); + } + + return ( + + {favorite.name} + + + {favorite.name} + Category: {favorite.category} + router.push(`/${favorite.id}`)}> + View Item + + + + clickFunctions({ fav: favorite })} + onMouseEnter={() => setHovering(true)} + onMouseLeave={() => setHovering(false)} + > + + Remove from favorites + + + + + ); +} \ No newline at end of file diff --git a/src/app/favorites/page.tsx b/src/app/favorites/page.tsx index 8c16242d..96af5abc 100644 --- a/src/app/favorites/page.tsx +++ b/src/app/favorites/page.tsx @@ -1,34 +1,26 @@ 'use client'; import { useState, useEffect } from 'react'; -import { useRouter } from 'next/navigation'; -import { Body1Bold, Body2, Heading1 } from '@/styles/fonts'; +import { Heading1 } from '@/styles/fonts'; import BackButton from '../../components/BackButton/BackButton'; import { arrayOfFavorites, - addOrRemoveProductFromFavorite, } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; import { - FavoriteDiv, OutterFavoriteDiv, OutterBox, - ProductNameDiv, - HeartIcon, - TransparentButton, - ViewItem, Fullscreen, - ImageLinkWrapper, } from './styles'; +import IndividualItem from './individualItem'; import { Product } from '../../schema/schema'; export default function FavoritesPage() { const [Favorites, setFavorites] = useState([]); - const router = useRouter(); async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; @@ -38,12 +30,6 @@ export default function FavoritesPage() { fetchProducts(); }, []); - async function clickFunctions(props: { fav: Product }) { - const { fav } = props; - addOrRemoveProductFromFavorite(fav, false); - setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); - } - return ( @@ -52,29 +38,12 @@ export default function FavoritesPage() { Favorites {Favorites.map(favorite => ( - - - {favorite.name} - - - - {favorite.name} - Category: {favorite.category} - router.push(`/${favorite.id}`)}> - View Item - - - - clickFunctions({ fav: favorite })} - > - - - + ))} diff --git a/src/app/favorites/styles.ts b/src/app/favorites/styles.ts index acd1f56c..479119e8 100644 --- a/src/app/favorites/styles.ts +++ b/src/app/favorites/styles.ts @@ -43,9 +43,11 @@ export const BackDiv = styled.button` export const OutterBox = styled.div` width: 800px; height: 100%; - - margin-top: 50px; - margin-bottom: 50px; + margin-top: 40px; + display: flex; + flex-direction: column; + gap: 20px; + margin-bottom: 20px; `; export const Backtext = styled.p` @@ -58,6 +60,7 @@ export const HeartIcon = styled(Heart)` height: 30px; fill: #333286; margin-right: 25px; + margin-bottom: 40px; `; export const TransparentButton = styled.button` @@ -66,6 +69,22 @@ export const TransparentButton = styled.button` cursor: pointer; `; +export const Hover = styled.div<{ $ishovering?: boolean }>` + visibility: ${props => (props.$ishovering ? 'visible' : 'hidden')}; + transform: translate(-10px, 0px); + margin-bottom: 7px; + color: black; + border: none; + width: 156px; + height: 26px; + border-radius: 8px; + background: var(--Light-Periwinkle, #f4f7ff); + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + padding-top: 6px; + position: relative; + text-align: center; +`; + export const NavBarMovedUP = styled(NavBar)` position: relative; `; diff --git a/src/app/profileScreen/individualItem.tsx b/src/app/profileScreen/individualItem.tsx new file mode 100644 index 00000000..eb2d7627 --- /dev/null +++ b/src/app/profileScreen/individualItem.tsx @@ -0,0 +1,64 @@ +import React, { useEffect, useState } from 'react'; + +import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; + +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { HeartIcon, Hover, FavoriteDiv, ProductNameDiv } from './styles'; + +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; + +import { Product } from '../../schema/schema'; +import { TransparentButton } from '../favorites/styles'; + +export default function IndividualItem(props: { + favorite: Product; + setFavorites: (category: Product[]) => void; + Favorites: Product[]; +}) { + const { favorite, Favorites, setFavorites } = props; + const [hovering, setHovering] = useState(false); + + useEffect(() => { + async function changeCategory() { + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); + } + } + + changeCategory(); + }, []); + + async function clickFunctions(props2: { fav: Product }) { + const { fav } = props2; + addOrRemoveProductFromFavorite(fav, false); + setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); + } + + return ( + + {favorite.name} + + {favorite.name} + Category: {favorite.category} + + clickFunctions({ fav: favorite })} + onMouseEnter={() => setHovering(true)} + onMouseLeave={() => setHovering(false)} + > + + Remove from favorites + + + + + ); +} \ No newline at end of file diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 0b98511a..105a1fa9 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -42,9 +42,6 @@ import { TextSpacing, OrderHistory, FavoritesContainer, - ProductNameDiv, - FavoriteDiv, - HeartIcon, BackButtonDiv, BlankSpace, HeaderDiv, @@ -56,18 +53,14 @@ import { } from './styles'; import { signOut } from '../../api/supabase/auth/auth'; import 'react-toastify/dist/ReactToastify.css'; -import { TransparentButton } from '../favorites/styles'; +import IndividualItem from './individualItem'; + function FavoriteSection(props: { Favorites: Product[]; setFavorites: (category: Product[]) => void; }) { const { Favorites, setFavorites } = props; - async function clickFunctions(props2: { fav: Product }) { - const { fav } = props2; - addOrRemoveProductFromFavorite(fav, false); - setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); - } if (Favorites.length > 0) { return (
@@ -77,25 +70,12 @@ function FavoriteSection(props: { {Favorites.slice(0, 2).map(favorite => ( - - {favorite.name} - -

- {favorite.name} -
- Product ID: {favorite.id} -

-
- clickFunctions({ fav: favorite })} - > - - -
+ ))}
diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 1ee1f70b..1ae59176 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -109,6 +109,23 @@ export const HeartIcon = styled(Heart)` width: 25px; height: 25px; fill: #333286; + margin-bottom: 40px; +`; + +export const Hover = styled.div<{ $ishovering?: boolean }>` + visibility: ${props => (props.$ishovering ? 'visible' : 'hidden')}; + transform: translate(0px, -1px); + margin-bottom: 7px; + color: black; + border: none; + width: 156px; + height: 26px; + border-radius: 8px; + background: var(--Light-Periwinkle, #f4f7ff); + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + padding-top: 6px; + position: relative; + text-align: center; `; export const BackButtonDiv = styled.div` From c7fa3e0ecd314f4a673c7218ed297cf16663137d Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Wed, 17 Apr 2024 21:10:10 -0700 Subject: [PATCH 11/43] eslint and prettier --- src/api/supabase/queries/user_queries.ts | 1 - src/app/[productId]/page.tsx | 62 +++++++++++----------- src/app/favorites/individualItem.tsx | 22 ++++---- src/app/favorites/page.tsx | 20 +++---- src/app/globals.css | 2 +- src/app/login/styles.ts | 2 +- src/app/profileScreen/individualItem.tsx | 36 ++++++------- src/app/profileScreen/page.tsx | 12 ++--- src/components/InputFieldsFolder/styles.ts | 3 +- 9 files changed, 77 insertions(+), 83 deletions(-) diff --git a/src/api/supabase/queries/user_queries.ts b/src/api/supabase/queries/user_queries.ts index b186ec0e..4b70bbcb 100644 --- a/src/api/supabase/queries/user_queries.ts +++ b/src/api/supabase/queries/user_queries.ts @@ -112,7 +112,6 @@ export async function arrayOfFavorites(): Promise { return arrayOfProducts; } - /** * fetchUserAddress: Get's a user's address based on their UUID * @param uuid: String containing the uuid of the user diff --git a/src/app/[productId]/page.tsx b/src/app/[productId]/page.tsx index 74314a16..55cd995a 100644 --- a/src/app/[productId]/page.tsx +++ b/src/app/[productId]/page.tsx @@ -3,7 +3,10 @@ import { useEffect, useState } from 'react'; import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; import { Body1, Heading1, Body2Light, Body2Bold, Body3 } from '@/styles/fonts'; -import { fetchProductByID, fetchUserProducts } from '../../api/supabase/queries/product_queries'; +import { + fetchProductByID, + fetchUserProducts, +} from '../../api/supabase/queries/product_queries'; import BackButton from '../../components/BackButton/BackButton'; import 'react-toastify/dist/ReactToastify.css'; @@ -17,7 +20,7 @@ import { FavoritePopup, HeartContainer, HeartIcon, - TopRightContainer + TopRightContainer, } from './styles'; import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; @@ -30,9 +33,7 @@ export default function ItemDisplay({ params: { productId: number }; }) { const [Item, setItem] = useState(); - const [IsFavorite, setIsFavorite] = useState( - false - ); + const [IsFavorite, setIsFavorite] = useState(false); const [FilteredProducts, setFilteredProducts] = useState([]); useEffect(() => { @@ -44,7 +45,7 @@ export default function ItemDisplay({ ); const data = (await fetchUserProducts()) as Product[]; - setIsFavorite(!!data.find(item => item.id === params.productId)) + setIsFavorite(!!data.find(item => item.id === params.productId)); if (response) { setItem(response); setFilteredProducts(data); @@ -58,7 +59,10 @@ export default function ItemDisplay({ }, [params.productId]); async function handleFavorite() { - await addOrRemoveProductFromFavorite(await fetchProductByID(params.productId), !IsFavorite); + await addOrRemoveProductFromFavorite( + await fetchProductByID(params.productId), + !IsFavorite, + ); setIsFavorite(!IsFavorite); } @@ -74,34 +78,32 @@ export default function ItemDisplay({ - - - {Item?.name} - + + + {Item?.name} + - - {Item?.name} - handleFavorite()}> - - - {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} - - - - - - + + {Item?.name} + handleFavorite()}> + + + {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} + + + + + + Category: {Item?.category} - - Product Details: - + Product Details: {Item?.description} diff --git a/src/app/favorites/individualItem.tsx b/src/app/favorites/individualItem.tsx index 7b68d6ad..7b9eea0c 100644 --- a/src/app/favorites/individualItem.tsx +++ b/src/app/favorites/individualItem.tsx @@ -26,20 +26,20 @@ export default function IndividualItem(props: { const { favorite, Favorites, setFavorites } = props; const router = useRouter(); const [hovering, setHovering] = useState(false); - + useEffect(() => { async function changeCategory() { - try { - favorite.category = await convertButtonNumberToCategory( - favorite.category, - ); - } catch (error) { - // console.error(error); - } + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); } + } - changeCategory(); - }, []); + changeCategory(); + }, [favorite]); async function clickFunctions(props2: { fav: Product }) { const { fav } = props2; @@ -75,4 +75,4 @@ export default function IndividualItem(props: { ); -} \ No newline at end of file +} diff --git a/src/app/favorites/page.tsx b/src/app/favorites/page.tsx index 96af5abc..6c00e83a 100644 --- a/src/app/favorites/page.tsx +++ b/src/app/favorites/page.tsx @@ -4,17 +4,11 @@ import { useState, useEffect } from 'react'; import { Heading1 } from '@/styles/fonts'; import BackButton from '../../components/BackButton/BackButton'; -import { - arrayOfFavorites, -} from '../../api/supabase/queries/user_queries'; +import { arrayOfFavorites } from '../../api/supabase/queries/user_queries'; import NavBar from '../../components/NavBarFolder/NavBar'; -import { - OutterFavoriteDiv, - OutterBox, - Fullscreen, -} from './styles'; +import { OutterFavoriteDiv, OutterBox, Fullscreen } from './styles'; import IndividualItem from './individualItem'; import { Product } from '../../schema/schema'; @@ -39,11 +33,11 @@ export default function FavoritesPage() { {Favorites.map(favorite => ( + key={favorite.id} + favorite={favorite} + setFavorites={setFavorites} + Favorites={Favorites} + /> ))} diff --git a/src/app/globals.css b/src/app/globals.css index c241f2ec..5b0dbd13 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -84,7 +84,7 @@ body { max-width: 100vw; min-height: 100vh; } -button{ +button { &:hover { cursor: pointer; } diff --git a/src/app/login/styles.ts b/src/app/login/styles.ts index d94d373f..03fb0708 100644 --- a/src/app/login/styles.ts +++ b/src/app/login/styles.ts @@ -9,7 +9,7 @@ export const LoginBox = styled.div` justify-self: center; align-self: center; background-color: ${COLORS.white}; - box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.10); + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); border-radius: 10px; `; diff --git a/src/app/profileScreen/individualItem.tsx b/src/app/profileScreen/individualItem.tsx index eb2d7627..f7de722e 100644 --- a/src/app/profileScreen/individualItem.tsx +++ b/src/app/profileScreen/individualItem.tsx @@ -17,20 +17,20 @@ export default function IndividualItem(props: { }) { const { favorite, Favorites, setFavorites } = props; const [hovering, setHovering] = useState(false); - + useEffect(() => { async function changeCategory() { - try { - favorite.category = await convertButtonNumberToCategory( - favorite.category, - ); - } catch (error) { - // console.error(error); - } + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); } + } - changeCategory(); - }, []); + changeCategory(); + }, [favorite]); async function clickFunctions(props2: { fav: Product }) { const { fav } = props2; @@ -40,12 +40,12 @@ export default function IndividualItem(props: { return ( - {favorite.name} - + {favorite.name} + {favorite.name} Category: {favorite.category} @@ -59,6 +59,6 @@ export default function IndividualItem(props: { - + ); -} \ No newline at end of file +} diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 105a1fa9..49c95de6 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -13,7 +13,6 @@ import { Body2, } from '@/styles/fonts'; import { - addOrRemoveProductFromFavorite, arrayOfFavorites, fetchUser, fetchCurrentUserAddress, @@ -55,7 +54,6 @@ import { signOut } from '../../api/supabase/auth/auth'; import 'react-toastify/dist/ReactToastify.css'; import IndividualItem from './individualItem'; - function FavoriteSection(props: { Favorites: Product[]; setFavorites: (category: Product[]) => void; @@ -71,11 +69,11 @@ function FavoriteSection(props: { {Favorites.slice(0, 2).map(favorite => ( + key={favorite.id} + favorite={favorite} + setFavorites={setFavorites} + Favorites={Favorites} + /> ))}
diff --git a/src/components/InputFieldsFolder/styles.ts b/src/components/InputFieldsFolder/styles.ts index 73520526..2fa8ed20 100644 --- a/src/components/InputFieldsFolder/styles.ts +++ b/src/components/InputFieldsFolder/styles.ts @@ -32,7 +32,8 @@ export const Input = styled.input<{ color: ${COLORS.black}; border: 1.5px solid ${props => (props.$wrongLogin ? COLORS.darkRed : COLORS.neutralGrey)}; - background: ${props => (props.$pickColor ? COLORS.lightRed : COLORS.lightGrey)}; + background: ${props => + props.$pickColor ? COLORS.lightRed : COLORS.lightGrey}; width: 420px; height: 40px; padding-left: 10px; From 9b32140dd9c7d5b58851357fa25cf54411d3462d Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 11:20:09 -0700 Subject: [PATCH 12/43] order details page done --- src/app/pickup/page.tsx | 26 ++++++++++++++++++-------- src/app/pickup/styles.ts | 9 +++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 097b878e..4e336ece 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -1,6 +1,9 @@ 'use client'; // import { GlobalStyle } from "@/styles/components"; + +import 'react-toastify/dist/ReactToastify.css'; +import { toast } from 'react-toastify'; import { ArrowLeft } from 'react-feather'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import querystring from 'querystring'; @@ -11,7 +14,7 @@ import { } from '@/api/supabase/queries/cart_queries'; import { useState, useEffect } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; -import { Heading4Bold } from '@/styles/fonts'; +import { Body1, Heading4Bold } from '@/styles/fonts'; import { fetchNRecentPickupTimes } from '@/api/supabase/queries/pickup_queries'; import { updateCartPickupId, @@ -36,8 +39,10 @@ import { PickupContent, PickupContainer, PickupTimeButton, + ToastPopUP, } from './styles'; + function DateInfoComponent(date: { date: unknown }) { const date1 = new Date(date.date as string); const daysOfWeek = [ @@ -100,6 +105,12 @@ export default function PickUp() { return (
+ router.push('/cart')}> @@ -116,10 +127,11 @@ export default function PickUp() { Phone Number {Profile?.phone_numbers} -
+
Time Slot
- +
Pick Up times: 10:00 AM - 12:00 PM
+
Location: 3170 23rd Street, San Francisco, CA 94110
{Time.map(time => ( ))}
-
Pick Up times: 10:00 AM - 12:00 PM
-
Location: 3170 23rd Street, San Francisco, CA 94110
@@ -157,12 +167,12 @@ export default function PickUp() { await updateOrderStatus(orderID, OrderStatus.Submitted); await createOrder(); const newestOrder = await fetchCartIdFromUser(); - console.log(newestOrder); await updateOrderStatus(newestOrder, OrderStatus.inProgress); const queryString = querystring.stringify({ orderID }); router.push(`/orderConfirmationPickUp?${queryString}`); - } else { - // TODO handle the case where they didn't select a time! + } + if (selectedPickupIndex === 0){ + toast(`You must select a pick-up date!`); } }} > diff --git a/src/app/pickup/styles.ts b/src/app/pickup/styles.ts index 35365312..257579c3 100644 --- a/src/app/pickup/styles.ts +++ b/src/app/pickup/styles.ts @@ -1,11 +1,13 @@ import styled from 'styled-components'; +import { ToastContainer } from 'react-toastify'; import COLORS from '../../styles/colors'; import NavBar from '../../components/NavBarFolder/NavBar'; import Footer from '../../components/FooterFolder/Footer'; + export const PickupContainer = styled.div` width: 730px; height: 400px; @@ -263,3 +265,10 @@ export const HeaderShiftLeft = styled.h2` export const PShiftLeft = styled.p` margin-left: 15px; `; + +export const ToastPopUP = styled(ToastContainer)` + position: fixed; + z-index: 100; + transform: translatey(90px); + background-color: ${COLORS.lightRed}; +`; \ No newline at end of file From 816eb75bde6bbde7991911605601a25f606bd797 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 11:30:25 -0700 Subject: [PATCH 13/43] changes made --- src/app/pickup/page.tsx | 20 ++++++++++++++----- src/app/pickup/styles.ts | 3 +-- .../OrderSummaryFolder/OrderSummary.tsx | 6 +++--- src/components/OrderSummaryFolder/styles.ts | 8 +++++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 4e336ece..33e43490 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -42,7 +42,6 @@ import { ToastPopUP, } from './styles'; - function DateInfoComponent(date: { date: unknown }) { const date1 = new Date(date.date as string); const daysOfWeek = [ @@ -127,11 +126,22 @@ export default function PickUp() { Phone Number {Profile?.phone_numbers} -
+
Time Slot
-
Pick Up times: 10:00 AM - 12:00 PM
-
Location: 3170 23rd Street, San Francisco, CA 94110
+
+ {' '} + Pick Up times: 10:00 AM - 12:00 PM{' '} +
+
+ Location: 3170 23rd Street, San Francisco, CA 94110 +
{Time.map(time => ( Order Summary - Product Name - Qty. + PRODUCT NAME + QTY {cart.map(cartItem => ( diff --git a/src/components/OrderSummaryFolder/styles.ts b/src/components/OrderSummaryFolder/styles.ts index e90a18ef..16fd4a3f 100644 --- a/src/components/OrderSummaryFolder/styles.ts +++ b/src/components/OrderSummaryFolder/styles.ts @@ -1,3 +1,4 @@ +import COLORS from '@/styles/colors'; import styled from 'styled-components'; export const OrderSummaryDiv = styled.div` @@ -37,6 +38,10 @@ export const WhiteBackgroundDiv = styled.div` width: 350px; padding: 20px; box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); + display: flex; + justify-content: center; + align-items: flex-start; + flex-direction: column; `; export const HeaderShiftRight = styled.h2` @@ -57,7 +62,8 @@ export const OrderSummaryHeaderDiv = styled.div` justify-content: space-between; align-items: center; flex-direction: row; - margin-bottom: 10px; + margin-bottom: 15px; + color: ${COLORS.marineBlue}; `; export const ItemNameDiv = styled.div` From 27560191d56fa2139f1f961e28ae3822b344aea6 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 12:32:56 -0700 Subject: [PATCH 14/43] order details page done --- src/api/supabase/queries/cart_queries.ts | 1 - src/api/supabase/queries/delivery_queries.ts | 15 ++++++ src/api/supabase/queries/order_queries.ts | 2 - src/api/supabase/queries/product_queries.ts | 2 - src/api/supabase/queries/user_queries.ts | 12 ++--- src/app/orderConfirmationDelivery/page.tsx | 50 ++++++++++++++++++-- src/app/orderConfirmationDelivery/styles.ts | 14 ++++-- src/app/orderConfirmationPickUp/page.tsx | 6 +-- src/app/pickup/page.tsx | 2 +- 9 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 src/api/supabase/queries/delivery_queries.ts diff --git a/src/api/supabase/queries/cart_queries.ts b/src/api/supabase/queries/cart_queries.ts index 2f1bee77..c8062040 100644 --- a/src/api/supabase/queries/cart_queries.ts +++ b/src/api/supabase/queries/cart_queries.ts @@ -206,7 +206,6 @@ export async function fetchCartItemsWithQuantity(): Promise< }); const fetchedProducts = await Promise.all(productPromises); - console.log(fetchedProducts); return fetchedProducts; } diff --git a/src/api/supabase/queries/delivery_queries.ts b/src/api/supabase/queries/delivery_queries.ts new file mode 100644 index 00000000..baa88631 --- /dev/null +++ b/src/api/supabase/queries/delivery_queries.ts @@ -0,0 +1,15 @@ +import supabase from '../createClient'; + +export type DeliveryTimes = { + delivery_group: number; + delivery_time: number; +}; + +export async function fetchDeliveryTimes(): Promise { + const { data, error } = await supabase.from('delivery_times').select('*'); + + if (error) { + throw new Error(`Error fetching delivery times: ${error.message}`); + } + return data; +} diff --git a/src/api/supabase/queries/order_queries.ts b/src/api/supabase/queries/order_queries.ts index f3e44c69..e011398d 100644 --- a/src/api/supabase/queries/order_queries.ts +++ b/src/api/supabase/queries/order_queries.ts @@ -38,12 +38,10 @@ export async function createOrder() { .insert({ user_id: user.id }) .select('*') .single(); - console.log(order); if (error) { throw new Error(`Error creating order: ${error.message}`); } - console.log(order.id); await supabase .from('profiles') .update({ cart_id: order.id }) diff --git a/src/api/supabase/queries/product_queries.ts b/src/api/supabase/queries/product_queries.ts index 6112c195..85ec9fbb 100644 --- a/src/api/supabase/queries/product_queries.ts +++ b/src/api/supabase/queries/product_queries.ts @@ -88,7 +88,6 @@ export async function filterProduct(productType: string): Promise { export async function convertCategoryToNumber( productType: string, ): Promise { - console.log(productType); const { data: buttonVal, error } = await supabase .from('storefront_buttons') .select('*') @@ -104,7 +103,6 @@ export async function convertCategoryToNumber( export async function fetchUnprescribedCategory( productType: string, ): Promise { - console.log(productType); const productTypeConverted = await convertCategoryToNumber(productType); const { data: products, error } = await supabase diff --git a/src/api/supabase/queries/user_queries.ts b/src/api/supabase/queries/user_queries.ts index 4b70bbcb..6a6c75a8 100644 --- a/src/api/supabase/queries/user_queries.ts +++ b/src/api/supabase/queries/user_queries.ts @@ -1,8 +1,6 @@ -import { Lekton } from 'next/font/google'; import supabase from '../createClient'; import { User, Product } from '../../../schema/schema'; import { fetchProductByID } from './product_queries'; -import { convertButtonNumberToCategory } from './button_queries'; /** * fetchUser is a function that fetches the user data from the database and returns the user object. @@ -55,12 +53,12 @@ export async function fetchUserByUUID(uuid: string) { .single(); if (error) { - console.error('Error fetching user data:', error); + throw new Error(`Error fetching user data: ${error.message}`); } return user; } catch (error) { - console.error('Error:', error); + throw new Error(`Error`); throw error; } } @@ -125,13 +123,12 @@ export async function fetchUserAddress(uuid: string) { .single(); if (error) { - console.error('Error fetching user data:', error); + throw new Error(`Error fetching user data: ${error.message}`); } return user; } catch (error) { - console.error('Error:', error); - throw error; + throw new Error(`Error:`); } } @@ -148,7 +145,6 @@ export async function fetchCurrentUserAddress() { .eq('user_id', user.id) .limit(1) .single(); - console.log(address); if (error) { console.error('Error fetching user data:', error); diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx index c82042cb..bacfca1d 100644 --- a/src/app/orderConfirmationDelivery/page.tsx +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -6,8 +6,18 @@ import { fetchCurrentUserAddress, } from '@/api/supabase/queries/user_queries'; -import { Body1, Body2Light, Heading3Bold, Heading4Bold } from '@/styles/fonts'; +import { + Body1, + Body2, + Body2Light, + Heading3Bold, + Heading4Bold, +} from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; +import { + DeliveryTimes, + fetchDeliveryTimes, +} from '@/api/supabase/queries/delivery_queries'; import BackButton from '../../components/BackButton/BackButton'; import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; @@ -26,6 +36,7 @@ import { DetailsHeader, PageDiv, CenterDiv, + Quantity, } from './styles'; import { Product, User, Address } from '../../schema/schema'; @@ -38,12 +49,12 @@ export default function OrderConfirmationDelivery() { const [userAddress, setUserAddress] = useState
(); const searchParams = useSearchParams(); const orderIDFromSearch = searchParams.get('orderID'); + const [delivTimes, setDelivTimes] = useState([]); useEffect(() => { async function fetchProducts() { const cartItems = (await fetchCartItemsWithQuantityByID( orderIDFromSearch, )) as Product[]; - console.log(cartItems); setCart(cartItems); } @@ -53,11 +64,39 @@ export default function OrderConfirmationDelivery() { const address = await fetchCurrentUserAddress(); setUserAddress(address); } + async function fetchDelivTimes() { + const deliv = await fetchDeliveryTimes(); + setDelivTimes(deliv); + } fetchProducts(); setUserDetails(); + fetchDelivTimes(); }, []); + function organizeDelivTime() { + const userGrp = user?.delivery_group == null ? 1 : user?.delivery_group; + const Time = delivTimes[userGrp]?.delivery_time.toLocaleString(); + const date = + Time == null ? ['0', '0', '0'] : Time?.substring(0, 10).split('-'); + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const dateStr = `${months[parseInt(date[1], 10)]} ${date[2]}, ${date[0]}`; + return `${dateStr}`; + } + return (
@@ -105,6 +144,11 @@ export default function OrderConfirmationDelivery() {
+ + + Quantity: {cartItem.quantity} + + ))} @@ -114,7 +158,7 @@ export default function OrderConfirmationDelivery() { Delivery Information Estimated Date - {user?.delivery_group} + {organizeDelivTime()} Location {userAddress?.street}, {userAddress?.city},{' '} diff --git a/src/app/orderConfirmationDelivery/styles.ts b/src/app/orderConfirmationDelivery/styles.ts index e72f1ef1..618a5919 100644 --- a/src/app/orderConfirmationDelivery/styles.ts +++ b/src/app/orderConfirmationDelivery/styles.ts @@ -8,11 +8,17 @@ export const FavoriteDiv = styled.div` display: flex; flex-direction: row; align-items: flex-start; - justify-content: flex-start; + justify-content: space-between; width: 100%; margin-bottom: 50px; margin-top: 30px; - gap: 120px; +`; + +export const Quantity = styled.div` + display: flex; + align-self: center; + justify-content: flex-start; + margin-right: 40px; `; export const OrderDetailsDiv = styled.div` @@ -216,16 +222,18 @@ export const OrderTotalDiv = styled.div` `; export const LeftColumnDiv = styled.div` + margin-top: 30px; display: flex; flex-flow: column; justify-content: space-evenly; align-items: space-evenly; + gap: 20px; `; export const RightColumnDiv = styled.div` display: flex; flex-flow: column; margin-left: 20px; - margin-top: 127px; + margin-top: 123px; `; export const WhiteBackgroundDiv = styled.div` diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index c9b612ce..9a93cb72 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -4,10 +4,7 @@ import { useState, useEffect } from 'react'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; -import { - fetchCurrentOrdersByUser, - getOrderById, -} from '@/api/supabase/queries/order_queries'; +import { getOrderById } from '@/api/supabase/queries/order_queries'; import { Body1, Body1Bold, @@ -73,7 +70,6 @@ export default function OrderConfirmationPickUp() { function organizePickupTime() { const startTime = pickupTime?.start_time.toLocaleString(); - const endTime = pickupTime?.end_time.toLocaleString(); const date = startTime == null ? ['0', '0', '0'] diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 33e43490..6ea5a83a 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -13,7 +13,7 @@ import { totalNumberOfItemsInCart, } from '@/api/supabase/queries/cart_queries'; import { useState, useEffect } from 'react'; -import { useRouter, useSearchParams } from 'next/navigation'; +import { useRouter } from 'next/navigation'; import { Body1, Heading4Bold } from '@/styles/fonts'; import { fetchNRecentPickupTimes } from '@/api/supabase/queries/pickup_queries'; import { From cf03702349e1f60b725cd22d3dabdfbf7a9c4a0a Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Sun, 21 Apr 2024 14:02:17 -0700 Subject: [PATCH 15/43] preRebase --- src/api/supabase/queries/product_queries.ts | 2 +- src/app/orderConfirmationDelivery/page.tsx | 4 +++- src/app/pickup/page.tsx | 1 + src/app/pickup/styles.ts | 2 +- src/app/profileScreen/individualItem.tsx | 24 ++++++++++----------- src/app/profileScreen/page.tsx | 8 +++++++ 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/api/supabase/queries/product_queries.ts b/src/api/supabase/queries/product_queries.ts index 85ec9fbb..67396986 100644 --- a/src/api/supabase/queries/product_queries.ts +++ b/src/api/supabase/queries/product_queries.ts @@ -64,7 +64,7 @@ export async function fetchProductByID(productId: number): Promise { if (error) { throw new Error(`Error fetching product: ${error.message}`); } - + return product; } diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx index bacfca1d..1652742e 100644 --- a/src/app/orderConfirmationDelivery/page.tsx +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -93,7 +93,9 @@ export default function OrderConfirmationDelivery() { 'November', 'December', ]; - const dateStr = `${months[parseInt(date[1], 10)]} ${date[2]}, ${date[0]}`; + const dateStr = `${months[parseInt(date[1], 10) - 1]} ${date[2]}, ${ + date[0] + }`; return `${dateStr}`; } diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 6ea5a83a..bd8d8ea3 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -183,6 +183,7 @@ export default function PickUp() { } if (selectedPickupIndex === 0) { toast(`You must select a pick-up date!`); + toast.clearWaitingQueue(); } }} > diff --git a/src/app/pickup/styles.ts b/src/app/pickup/styles.ts index 78adbb49..3c984c57 100644 --- a/src/app/pickup/styles.ts +++ b/src/app/pickup/styles.ts @@ -269,5 +269,5 @@ export const ToastPopUP = styled(ToastContainer)` position: fixed; z-index: 100; transform: translatey(90px); - background-color: ${COLORS.lightRed}; + `; diff --git a/src/app/profileScreen/individualItem.tsx b/src/app/profileScreen/individualItem.tsx index f7de722e..457c23d4 100644 --- a/src/app/profileScreen/individualItem.tsx +++ b/src/app/profileScreen/individualItem.tsx @@ -18,19 +18,19 @@ export default function IndividualItem(props: { const { favorite, Favorites, setFavorites } = props; const [hovering, setHovering] = useState(false); - useEffect(() => { - async function changeCategory() { - try { - favorite.category = await convertButtonNumberToCategory( - favorite.category, - ); - } catch (error) { - // console.error(error); - } - } + // useEffect(() => { + // // async function changeCategory() { + // // try { + // // favorite.category = await convertButtonNumberToCategory( + // // favorite.category, + // // ); + // // } catch (error) { + // // // console.error(error); + // // } + // // } - changeCategory(); - }, [favorite]); + // // changeCategory(); + // }, []); async function clickFunctions(props2: { fav: Product }) { const { fav } = props2; diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 49c95de6..42f5a064 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -12,6 +12,7 @@ import { Body2Bold, Body2, } from '@/styles/fonts'; +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; import { arrayOfFavorites, fetchUser, @@ -363,6 +364,13 @@ export default function Profile() { async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; + data.forEach( + async product => + (product.category = await convertButtonNumberToCategory( + product.category, + )), + ); + console.log(data); setFavorites(data); } From 21ff7aa07ed9449aa10d6685119ee27b5b69e166 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 14:10:21 -0700 Subject: [PATCH 16/43] a --- src/app/login/page.tsx | 13 ++++++++++++- src/app/pickup/styles.ts | 1 - src/components/LoginFormFolder/LoginForm.tsx | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 93fcea70..aeff396f 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -1,6 +1,7 @@ 'use client'; import { useState } from 'react'; + import Image from 'next/image'; import supabase from '@/api/supabase/createClient'; import { Body1, Heading1 } from '@/styles/fonts'; @@ -39,6 +40,16 @@ export default function App() { window.location.href = '/storefront'; } }; + + async function applyFilter( + e: React.KeyboardEvent, + ) { + const keypressed = e.code; + if (keypressed === 'Enter') { + handleLogin(); + } + } + return ( @@ -78,7 +89,7 @@ export default function App() { )} {errorMessage && {errorMessage}} - diff --git a/src/app/pickup/styles.ts b/src/app/pickup/styles.ts index 78adbb49..af517b07 100644 --- a/src/app/pickup/styles.ts +++ b/src/app/pickup/styles.ts @@ -269,5 +269,4 @@ export const ToastPopUP = styled(ToastContainer)` position: fixed; z-index: 100; transform: translatey(90px); - background-color: ${COLORS.lightRed}; `; diff --git a/src/components/LoginFormFolder/LoginForm.tsx b/src/components/LoginFormFolder/LoginForm.tsx index 6604f84f..684399e6 100644 --- a/src/components/LoginFormFolder/LoginForm.tsx +++ b/src/components/LoginFormFolder/LoginForm.tsx @@ -8,7 +8,7 @@ export default function LoginForm(props: { isError: boolean; showPassword: boolean; }) { - const { isError, changeUserName, changePassword, showPassword } = props; + const { isError, changeUserName, changePassword, showPassword} = props; return (
Date: Sun, 21 Apr 2024 14:26:39 -0700 Subject: [PATCH 17/43] profile page --- .eslintrc.js | 14 + .github/pull_request_template.md | 28 + .github/workflows/lint.yml | 56 + .gitignore | 36 + .nvmrc | 1 + .prettierignore | 11 + .prettierrc.js | 5 + .vscode/extensions.json | 13 + .vscode/settings.json | 8 + README.md | 54 + holder.zip | Bin 0 -> 48762 bytes next.config.js | 11 + package-lock.json | 6771 +++++++++++++++++ package.json | 49 + public/check.svg | 4 + public/images/Arrow_Left_MD.png | Bin 0 -> 267 bytes public/images/Cart.png | Bin 0 -> 1142 bytes public/images/PAWS.png | Bin 0 -> 84860 bytes public/images/Profile.png | Bin 0 -> 1154 bytes public/images/ShantiLogo.png | Bin 0 -> 4473 bytes public/images/profile (1).svg | 1 + public/images/profile blue version-2.svg | 1 + public/next.svg | 1 + public/ready.svg | 11 + public/right_arrow.svg | 4 + public/vercel.svg | 1 + public/x.svg | 6 + src/api/supabase/auth/auth.tsx | 28 + src/api/supabase/createClient.tsx | 20 + src/api/supabase/queries/button_queries.ts | 32 + src/api/supabase/queries/cart_queries.ts | 263 + src/api/supabase/queries/delivery_queries.ts | 15 + src/api/supabase/queries/order_queries.ts | 272 + src/api/supabase/queries/pickup_queries.ts | 69 + src/api/supabase/queries/product_queries.ts | 144 + src/api/supabase/queries/tests/order_test.ts | 7 + src/api/supabase/queries/tests/pickup_test.ts | 7 + .../supabase/queries/tests/product_test.ts | 25 + src/api/supabase/queries/tests/user_test.ts | 7 + src/api/supabase/queries/user_queries.ts | 157 + src/app/[productId]/Buttons.tsx | 53 + src/app/[productId]/page.tsx | 114 + src/app/[productId]/styles.ts | 140 + src/app/cart/Buttons.tsx | 74 + src/app/cart/cartItem.tsx | 69 + src/app/cart/page.tsx | 91 + src/app/cart/styles.tsx | 383 + src/app/delivery/itemRows.tsx | 62 + src/app/delivery/page.tsx | 100 + src/app/delivery/styles.ts | 157 + src/app/favicon.ico | Bin 0 -> 25931 bytes src/app/favorites/individualItem.tsx | 78 + src/app/favorites/page.tsx | 46 + src/app/favorites/styles.ts | 132 + src/app/globals.css | 106 + src/app/layout.tsx | 23 + src/app/login/page.tsx | 99 + src/app/login/styles.ts | 89 + src/app/orderConfirmationDelivery/page.tsx | 176 + src/app/orderConfirmationDelivery/styles.ts | 247 + src/app/orderConfirmationPickUp/page.tsx | 158 + src/app/orderConfirmationPickUp/styles.ts | 325 + src/app/orderHistory/page.tsx | 51 + src/app/orderHistory/styles.ts | 54 + src/app/orderPage/page.tsx | 115 + src/app/orderPage/styles.ts | 141 + src/app/page.module.css | 229 + src/app/page.tsx | 88 + src/app/pickup/page.tsx | 196 + src/app/pickup/styles.ts | 272 + src/app/profileScreen/individualItem.tsx | 64 + src/app/profileScreen/page.tsx | 430 ++ src/app/profileScreen/styles.ts | 185 + src/app/profileScreen/stylesOld.ts | 128 + src/app/storefront/IndividualItem.tsx | 53 + src/app/storefront/StoreFrontNavBar.tsx | 161 + src/app/storefront/buttonValues.tsx | 24 + src/app/storefront/page.tsx | 51 + src/app/storefront/productButtons.tsx | 96 + src/app/storefront/storefrontItems.tsx | 34 + src/app/storefront/styles.ts | 254 + src/app/types/types.txt | 0 src/app/util/util.txt | 0 src/components/BackButton/BackButton.tsx | 12 + src/components/BackButton/styles.ts | 22 + src/components/FooterFolder/Footer.tsx | 127 + src/components/FooterFolder/Location.tsx | 17 + src/components/FooterFolder/styles.ts | 159 + .../InputFieldsFolder/InputFields.tsx | 56 + src/components/InputFieldsFolder/styles.ts | 56 + src/components/LoginFormFolder/LoginForm.tsx | 34 + src/components/NavBarFolder/NavBar.tsx | 62 + src/components/NavBarFolder/styles.ts | 74 + src/components/OrderHistory/ImageCarousel.tsx | 21 + .../OrderHistory/OrderHistoryBox.tsx | 61 + .../OrderHistory/OrderHistoryText.tsx | 166 + src/components/OrderHistory/styles.ts | 218 + .../OrderSummaryFolder/OrderSummary.tsx | 48 + src/components/OrderSummaryFolder/styles.ts | 77 + src/components/PickUpFolder/PickupButton.tsx | 22 + src/components/PickUpFolder/PickupForm.tsx | 16 + src/components/PickUpFolder/PickupInputs.tsx | 35 + .../ViewAllButton/ViewAllButton.tsx | 16 + src/components/ViewAllButton/styles.ts | 15 + src/components/components.txt | 0 src/schema/schema.ts | 90 + src/styles/colors.ts | 19 + src/styles/components.tsx | 139 + src/styles/fonts.tsx | 160 + tsconfig.json | 41 + 110 files changed, 15243 insertions(+) create mode 100644 .eslintrc.js create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/lint.yml create mode 100644 .gitignore create mode 100644 .nvmrc create mode 100644 .prettierignore create mode 100644 .prettierrc.js create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 holder.zip create mode 100644 next.config.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/check.svg create mode 100644 public/images/Arrow_Left_MD.png create mode 100644 public/images/Cart.png create mode 100644 public/images/PAWS.png create mode 100644 public/images/Profile.png create mode 100644 public/images/ShantiLogo.png create mode 100644 public/images/profile (1).svg create mode 100644 public/images/profile blue version-2.svg create mode 100644 public/next.svg create mode 100644 public/ready.svg create mode 100644 public/right_arrow.svg create mode 100644 public/vercel.svg create mode 100644 public/x.svg create mode 100644 src/api/supabase/auth/auth.tsx create mode 100644 src/api/supabase/createClient.tsx create mode 100644 src/api/supabase/queries/button_queries.ts create mode 100644 src/api/supabase/queries/cart_queries.ts create mode 100644 src/api/supabase/queries/delivery_queries.ts create mode 100644 src/api/supabase/queries/order_queries.ts create mode 100644 src/api/supabase/queries/pickup_queries.ts create mode 100644 src/api/supabase/queries/product_queries.ts create mode 100644 src/api/supabase/queries/tests/order_test.ts create mode 100644 src/api/supabase/queries/tests/pickup_test.ts create mode 100644 src/api/supabase/queries/tests/product_test.ts create mode 100644 src/api/supabase/queries/tests/user_test.ts create mode 100644 src/api/supabase/queries/user_queries.ts create mode 100644 src/app/[productId]/Buttons.tsx create mode 100644 src/app/[productId]/page.tsx create mode 100644 src/app/[productId]/styles.ts create mode 100644 src/app/cart/Buttons.tsx create mode 100644 src/app/cart/cartItem.tsx create mode 100644 src/app/cart/page.tsx create mode 100644 src/app/cart/styles.tsx create mode 100644 src/app/delivery/itemRows.tsx create mode 100644 src/app/delivery/page.tsx create mode 100644 src/app/delivery/styles.ts create mode 100644 src/app/favicon.ico create mode 100644 src/app/favorites/individualItem.tsx create mode 100644 src/app/favorites/page.tsx create mode 100644 src/app/favorites/styles.ts create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/login/page.tsx create mode 100644 src/app/login/styles.ts create mode 100644 src/app/orderConfirmationDelivery/page.tsx create mode 100644 src/app/orderConfirmationDelivery/styles.ts create mode 100644 src/app/orderConfirmationPickUp/page.tsx create mode 100644 src/app/orderConfirmationPickUp/styles.ts create mode 100644 src/app/orderHistory/page.tsx create mode 100644 src/app/orderHistory/styles.ts create mode 100644 src/app/orderPage/page.tsx create mode 100644 src/app/orderPage/styles.ts create mode 100644 src/app/page.module.css create mode 100644 src/app/page.tsx create mode 100644 src/app/pickup/page.tsx create mode 100644 src/app/pickup/styles.ts create mode 100644 src/app/profileScreen/individualItem.tsx create mode 100644 src/app/profileScreen/page.tsx create mode 100644 src/app/profileScreen/styles.ts create mode 100644 src/app/profileScreen/stylesOld.ts create mode 100644 src/app/storefront/IndividualItem.tsx create mode 100644 src/app/storefront/StoreFrontNavBar.tsx create mode 100644 src/app/storefront/buttonValues.tsx create mode 100644 src/app/storefront/page.tsx create mode 100644 src/app/storefront/productButtons.tsx create mode 100644 src/app/storefront/storefrontItems.tsx create mode 100644 src/app/storefront/styles.ts create mode 100644 src/app/types/types.txt create mode 100644 src/app/util/util.txt create mode 100644 src/components/BackButton/BackButton.tsx create mode 100644 src/components/BackButton/styles.ts create mode 100644 src/components/FooterFolder/Footer.tsx create mode 100644 src/components/FooterFolder/Location.tsx create mode 100644 src/components/FooterFolder/styles.ts create mode 100644 src/components/InputFieldsFolder/InputFields.tsx create mode 100644 src/components/InputFieldsFolder/styles.ts create mode 100644 src/components/LoginFormFolder/LoginForm.tsx create mode 100644 src/components/NavBarFolder/NavBar.tsx create mode 100644 src/components/NavBarFolder/styles.ts create mode 100644 src/components/OrderHistory/ImageCarousel.tsx create mode 100644 src/components/OrderHistory/OrderHistoryBox.tsx create mode 100644 src/components/OrderHistory/OrderHistoryText.tsx create mode 100644 src/components/OrderHistory/styles.ts create mode 100644 src/components/OrderSummaryFolder/OrderSummary.tsx create mode 100644 src/components/OrderSummaryFolder/styles.ts create mode 100644 src/components/PickUpFolder/PickupButton.tsx create mode 100644 src/components/PickUpFolder/PickupForm.tsx create mode 100644 src/components/PickUpFolder/PickupInputs.tsx create mode 100644 src/components/ViewAllButton/ViewAllButton.tsx create mode 100644 src/components/ViewAllButton/styles.ts create mode 100644 src/components/components.txt create mode 100644 src/schema/schema.ts create mode 100644 src/styles/colors.ts create mode 100644 src/styles/components.tsx create mode 100644 src/styles/fonts.tsx create mode 100644 tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..0d9341d7 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,14 @@ +module.exports = { + extends: ["@calblueprint/eslint-config-react"], + rules: { + // Add any custom rules here + // Disable the rule that requires React to be in scope -- we don't need this with React 18 + 'react/react-in-jsx-scope': 'off', + 'react/jsx-uses-react': 'off', + }, + settings: { + 'import/resolver': { + typescript: {} + } + } +}; \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..1de99dc5 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,28 @@ +[//]: # "These comments are meant for your reference. They are invisible and don't need to be deleted!" + +## What's new in this PR +### Description +[//]: # "Required - Describe what's new in this PR in a few lines. A description and bullet points for specifics will suffice." + +### Screenshots +[//]: # "Required for frontend changes, otherwise optional but strongly recommended. Add screenshots of expected behavior - GIFs if you're feeling fancy!" + +## How to review +[//]: # "Required - Describe the order in which to review files and what to expect when testing locally. Is there anything specifically you want feedback on? Should this be reviewed commit by commit, or all at once? What are some user flows to test? What are some edge cases to look out for?" + +## Next steps +[//]: # "Optional - What's NOT in this PR, doesn't work yet, and/or still needs to be done. Note any temporary fixes in this PR that should be cleaned up later." + +## Relevant Links + +### Online sources +[//]: # "Optional - copy links to any tutorials or documentation that was useful to you when working on this PR" + +### Related PRs +[//]: # "Optional - related PRs you're waiting on/ PRs that will conflict, etc; if this is a refactor, feel free to add PRs that previously modified this code" + + + + +[//]: # "This tags the project leader as a default. Feel free to change, or add on anyone who you should be in on the conversation." +🛍 CC: @EthanAuyeung \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..186e163e --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,56 @@ +--- +name: Lint + +############################# +# Start the job on push # +############################# +on: + push: + branches-ignore: [main] + pull_request: + branches: [main] + +############### +# Set the Job # +############### +jobs: + build: + # Name the Job + name: Run ESLint, Prettier, and TypeScript compiler + # Set the agent to run on + runs-on: ubuntu-latest + + ################## + # Load all steps # + ################## + steps: + ########################## + # Checkout the code base # + ########################## + - name: Checkout Code + uses: actions/checkout@v3 + with: + # Full git history is needed to get a proper + # list of changed files within `super-linter` + fetch-depth: 0 + + ################################ + # Install packages # + ################################ + - name: Install packages + run: npm ci + ################################ + # Lint codebase # + ################################ + - name: Run ESLint + run: npx eslint . + ################################ + # Check Prettier on codebase # + ################################ + - name: Run Prettier + run: npx prettier --check . + ################################ + # Check for TypeScript errors # + ################################ + - name: Run TypeScript compiler (tsc) + run: npx tsc --noEmit \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..45c1abce --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..25bf17fc --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +18 \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..a3757027 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +.github/ +.vscode/ +README.md +package-lock.json +.eslintrc.js +.next/ +.prettierrc.js +next-env.d.ts +next.config.js +package.json +tsconfig.json \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..324e2c0d --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,5 @@ +const blueprintPrettier = require("@calblueprint/prettier-config"); + +module.exports = { + ...blueprintPrettier, +}; \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..0c7c4d38 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "eamodio.gitlens" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [] + } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..2e70ce1e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "typescript.tsdk": "node_modules\\typescript\\lib", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "editor.formatOnSave": true, + "files.autoSave": "onFocusChange" + } \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..f1acdea1 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Shanti Project + +This project is designed and developed by a team of UC Berkeley students through one of [Cal Blueprint](https://calblueprint.org/)'s project teams during the 2022-23 academic year. + +Learn more about [Shanti Project](https://www.shanti.org/) and [Cal Blueprint](https://calblueprint.org/). + +--- +## Getting Started + +Check your installation of npm and node: + +```sh +node -v +npm -v +``` +We strongly recommend using a Node version manager like [nvm](https://github.com/nvm-sh/nvm) (for Mac) or [nvm-windows](https://github.com/coreybutler/nvm-windows) (for Windows) to install Node.js and npm. See [Downloading and installing Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). +### Installation + +1. Clone the repo & install dependencies + 1. Clone this repo + * using SSH (recommended) + ```sh + git clone git@github.com:calblueprint/shanti-project.git + ``` + * using HTTPS + ```sh + git clone https://github.com/calblueprint/shanti-project.git + ``` + 2. Enter the cloned directory + ```sh + cd shanti-project + ``` + 3. Install project dependencies. This command installs all packages from [`package.json`](package.json). + ```sh + npm install + ``` +2. Set up secrets: + TBD + +**Helpful resources** + +* [GitHub: Cloning a Repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository#cloning-a-repository) +* [GitHub: Generating SSH keys](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) +### Development Environment + +- **[VSCode](https://code.visualstudio.com/) (recommended)** + 1. Open the `shanti-project` project in VSCode. + 2. Install recommended workspace VSCode extensions. You should see a pop-up on the bottom right to "install the recommended extensions for this repository". +### Running the app +1. In the project directory, run: + ```shell + npm run dev + ``` +2. Open up [http://localhost:3000](http://localhost:3000) in your browser to see the results. diff --git a/holder.zip b/holder.zip new file mode 100644 index 0000000000000000000000000000000000000000..f73e7a51dab44fcbcef02776374442c3af33e72d GIT binary patch literal 48762 zcmbTd1CVV^wk=$Cow9Yxwr$(CZQHIoW!tuGo2P8su6Mrf_rLDjw=d$~u`^@sh?Qey ztQ}+I%sEHONdkjF0sQs3$+K1c+r|IwKmf1-932d4m6ad?fDKcWjsI%SZqNXLAdi3m z03gVJ?vwj}qv?$U{=;a9|2taW&hGCB-pQ86f3<&u@D~!q-<~gk%lX7f1OOmu3;=-i zPY5RZF6M@|HZ*^_|86=Lnvh(H>+igbw1!yq#*$LR_;FPvXPDZShltZBooZZ^~SpOQAf|+n`xe(S_~oUci+#SUfp>2+3q>_ zUdNrsT-T1M0J#9*@W>!Hy4Z3%AieMaegpK?!hox=DbzZXtvVpR=HfSiqt2x;0PMB? zKwi{gtMuc%en_=Y?5QqvV=!y<<0L?PWIs&Mq~6F}=(`7^4I@LvaRzLd%A!0)1yD_> zp_`?a8LU#-cp)`OW*DuG`!4j8Gcqz35)u+lRcmxU@koe?=d!Z0MAx3_tXQKeRaI1y zx7OAq@S=Bj_1lw^m(5_qte4HKIbAMZLO*Z!M@HUY)eV2&-`vdN@%ntESbKYOYYPY% zaJ|DCCN8K}X*}{X0twBqS-0vtz0-#a;`Dr9`wfa?O97!HkP4S*QG*pTNMWTCrAEWVqZ^M$c@|?y z(8cz8fjI(1ZG(fOKV$2!N}$UU)8Pkd0}ri=q-OocBfSuzF%yanst^*t`vd!l^%PE-VQCdCew8ct5-0 z>gG+OqN2XW-$?|_%*ZM};oWUn>eg)Iv^)uZvRAdXvQ>O#knH>J_6I*)U0ub#xjH*% zO|n@TGy+brjH+S7#o}_m&8m{fZ{w@HZHq;OhtHj#oqg?Monn!YkR;qrUHBr!^vq#f za_RK=d=6|FAU@KKY>V#Cs9|&ClG1O9#AEovM`8Jn?2q2Eh2OHoPrgI~xTAd-R}Q!JTpu*);f$cOhCS`#^JwCD|LWz;q^b7lfaD&f()sxW?cqNpG0+ zOM8HHjx|9P1nyX4)0m!vH~9(lELS=|l|_pm`v>R=jkvpytjS>&Wr zQ*P|2aosadFF0dkgNiKshiXENHQB}OY7r%hQ7HvuTCtgT=zOCRTv-O4*kgb<&l+ci zccHPjhPO_bdxv5S_uwEGnWlINc#$Ow@U)^12kutM_ogarDqO~dJ(*#I_om6mw3T*F zTv@|zV+SX%&;jOI9kEd*3+S|IFo55KjWgRd+8rWzn3(C)ZsOqkGutJf7^M{z3*O$| zB^{R|n!NlsO*Ojse9I@@i;selkd2JD%r)BtFKa6^2tPf+bjQDjl%Djump=(fx{p3P z;`pAJc$dD&JC5f``d2!Axe@R5-e%w?zd_nXf!RI%59;jwy6&;gdymc6dzFrQtopSu578EvHdE}a>LXOW zQ5B^Ua6mdg>dU;BwVd(MYBCl24YUhZTCffX{<0u;CK!Ce#?$};x|iF-OE{Yo=?cyV z#xS>{c^+)hv@f2f?qTB^g!Ak`k3Zq;QG#`^b>N1Z8jP*FAP2RP;oz!CKtjvZci{E& zS^e{7>1;O~N>&I(CsX;G`&uhJs1QN+Cadd5&}Q&M5nC*YW1% zdJhjCZgbhw(-cFjchv$P-Wi5ld*zwUDhndHI{!AiOraXY%mT!tT`C~Mc+9HEP9&0@ zeVI~e@M;}zbiHbBm`UKACGzIZ61uZZvfNyFjGn%qr13yS2EV(b0b9Jd7Hb=HmSyTN zoab3;Ny=&U8lgP#gne&`s!lKRB|}dbhfv&mV_qRSwVazo6D{E_ksbvk?8}evlh)OE zDba3o11kApIKgM8hfeX>&m^A+?G{-eoWID5i)9OeW|wxNu!R+!$@u`qu`}9dO)I&^ zfY4w>MdosU2ua`R>AqE<(42%B+3gtbXOG=sbZ{WGIEZ1r+j&9`mkn_@rbj~lma@8b zmx%xoan(VHVWM$Va?b2Qw>V&(CTum}w0S2lu^UlNy&I-*bSEp<%g)7=?gtWoLyRtL z>dBj$6C@Mnt#^v(N{udEVM%q zt^fsjQ++gNlh_IRN!>Jr4Nk@BOn>|N{_LE%XtuDpopFRVhq@UC8O>6wzM#2W&jc?xIRm#BPNe zS+`+s_DLC~QYW_e-9Z5690kpuzClo+(_#3h%~~q~7t=ZeDHL(9<$Ri~#IfuBvfI3N zC$O>Cw?Nq3E4q`5(cSWNyw%rXp5)?Tpu23h((}jHkE{fZtw$1uvUV1q%SxYUhpqL@ zsSlx;QbG>v-x~pm#*kL$vn(F&)$P2GMw+P-|m#wsIA)-HP@afiKFYvvl_%&P$b z`KJR=sE{hzmS&cebPU^~+?1l*`z2Ntwk?X2u=Z+Qk?jPwW}y0!AjqFDS>$#7qb4I2 zX-{)3GxWxw#y!v9`K2O6c~^q!(?yoF8?f!!^%M5$uOz;u8@%jE2CrZAc^7?=yK9LH zk{pc_h7y-^^5E5<5vLZS#^{-IBg5N(uv|=4$Ose|oAIU)D29m@^hupK=f?)w)`VAQ zYBC#L^EKzxc>HQ05)*Er-KV$n`$4L9sJzl8A0xco=g82qiCLQ#0X^YACK0pKBGKGp z#$I%)2;^;uNeC4V>J|9{gqHfBOSJN`R4HLupbBz51%mHdgTR;9n%4Lw734bJG=k<& zGNKj>X_&(}by^8hc|}RQSQ{BFkGleL2|V+Q3@thOyv`}l1GoZ^NPr*NaD6>6RyDSZxT->v|Os}hyHbGc%rt=rgaAqK?*+?B}x zYHH{%{JB`hPd{tx$MvM8LJ{?CeB-rMkHfF*6VX;WdOz;q>R+i!Gfts$dGUpzq^LCo zGtQ9D)6A1-R4{7~kVMt9wv)yr>g_0i8aJasujodySSU}`4M=-BZx9z6Tr;NU1_g76u0mqbmiQPwCn6$ic+7>NRCgd0cKMrE<<{;8)h zT^F`A0wgbps8m{k$yAf>S*{acVB@}<7iLgc3%>}?s#)ika#YvmAhRRk%V9Jh$}7yg zjVsnK`5-w}1@v1%_vUWqUX5n0tUoEaS?OzbQu{96c%(|8?IKW-`>7k)IF6Zu zJ>{O&?wGc}bQ`>-MO$PBK+sv@M-qDZ2MgYc^s!Y#%g$LXw+OIzX+@L7^xR6{P;GHR zA(!A(dmBj>Kau=c{eXG7UL>YR4bj|%k0_2Y@J6XW5v!Gp*bsw)W|n4nyOR_XgHxV$UDKh`$7k|$0qBWYWO18 zRl}co#vydrQO$Y=4_;m-$y3c^&6C0lKOc$jk?_dJdmll?nQ-lQN|9>G*yo{ZsJ-?!JIoq+h{M_|8?4WIvt))Clk4jwC;A^TKb3JSCT>B9sIi@B4 zE4WCDX4!HAW}=iRJh@u6I&xjvp3-Tz-4Y72@h}a1?VAif-PCQUoB6g#=H>dD70cBs z2}DrMA}Ie6xJc`I3Rt^FaPtM%F2(w=msXLij&!*5dV!0^_C|9k+Y|6(jJ}y^>49w~ z0EP9J?O>u)m+NW?Cwe355!?^l$pb5Crz=5l0IUSzzCsaOb4@JbEi>y;Ycq_T)(BDe zH(YhlC5rlzcUM7MX3QAsuwB$9QgwEuilOrf!zc^9G`17c&{xwTJwaX7x7SUuv`q1> zkI#+38mFn;p?ZBuTTRv!$Wr8>X^*sB+2@5v<AtLA3i3R!|u zd!Cz4;0cAUa|pc1mV)G&YloB|NAi(Fqc<%pT?xfnJ((er>gnwUIqT z3fO3$kSZ@9n+>iItgh!rHXhw%h9iLSeq-@nKICJIBpQ*l^Ir-zU|1Ac1)tg+%gr;_b{o9lknA z+m%Hfb>d20Z5WN!p+(ROG;2?hOzl-|88c-O5>E6(;5?Src1NXXl8j1C-|9aW9}MJGLy*S=_+X4=lV3s+Wi&f93ox}1ylJ*iK3{3*Ai-5 zOPD_)4yx(7jO)5JFWLU$-jvZx9-HT{^FnI2#yN`3!nrSvk^(b&I`d5~iv!Y{6IJ8( zhKx*0G2!IeO@69#8&=`wdH+=#7X9J2#qNWeU*RO!j9BxdB~CM*T%HHi<)?b(U9+pl zS>M)ClpW=oG&AezrZa6R__`)-9J^4xJT9m4FP+S{{eAC)&#G$6ZKC6D-ce=h;xeNz zy(V}ivPe~Nt5J*p|9gp^|P5&<=1k;Gc$3(2Wzy7lFewd{<`W)VeiraH0uJ6 z3y)4&`aw{;Tm~ml>5@5(*7ywIc?)s68LAZ>Fl7d(o=lgQs)TkcliAV_Y5(yzjjF-L zihSd1QxXl3H^R(C5@9OO`RM`QO6S3yM#{-hi8~$4K?`%LIs6E##DPf{-13%1UM?wa zH=0t=mxQ6uR!QN&hlQHF$*oI~Z)P;+xyj-&^;6c^&7WYbw+*?2yZLv}j2Dwg#i6+x zOC*{XTpr8JC?0;ok-*bXPp*C4Uv&DDmoL7AFW#ro_B2q*N4#<)v^nbdg=;@#xqn;T zbBym*9tH&k4KN3^#6$IsY4dCrW67Tj^Ep@FBuG=3xUp(QxXNcRHLs7Bd+S|q0y{aR zt-JT#ZhcKN5~K|^@grGt_5!K4Cq4-RiQAHzR?w)n`^r9ky~tBBy3bq$*$-U7>&1C~ zQKzQUtZ8gKleg_>H@jx66{g`dl{~?ZNnzu@l+e*~Di8)|*tptdYfOx2zc+D{HB8v3m*ZNiUqi^bVQxf-BhmGcxN7qA014TZ3`P@pdU zfL;FfJ4M&>rR)?ZrEKe5vWFzQofT#SbHWar$2>pnu&=)SSZqdh6xty{3Q6D8eK#id zsgX9Wgr9XXTT02%BC&GKGdE|Dhr((2y&t*px{gXfn>i|*bV9Wl1HeKTCN^y%J?Vj% zG`m2^f946-+wmh+y@&Qj5TBb<`5X8a8w)e}#R&Xn7*D!*lnE>bzZmEOMAfnCjqa6P z$lq*(lGpY3sHfp$PRx6I%9;U>XiG%({Qi#^V$xNskvF&)7iJ+?oO7ab&LsT96(JE| zXloXeMSuE^-Gacuh1rhyGXd1!bCFStfDRcB23#b#w7QcV6=a$hkOcu8 zCvTjd7g58RFsSBA#Op5Q5png+BaT4b+}+vos_Q3_tdhuh>u>FsghvAaJe` zBHJb05N}4aNDldjQDE~pb#%9$aTv-j7Vb5$aBA~P~KXB}PZ0`!irvJorQFxhi4ZZ*JQKC9Oe4!Cy2NFj!>DzuvP-*HUr4cqHru?M`s*uUj(`96y(|T3|0ou#^>I^)j01_awT@RY=o*nNW|1O z#$DJ$OBjiWVT|vU-IB$h)9|C<`k1xk8~^lCK9wP9ouqGP#qY8d0f(SN>RH8qR@JR% z+S|@JyGk~>LogB9SaNu!IiQW7LB6e;m6hn#!LjbDxDLh|wN*tzvCIv0z6HApTo0JW zvmqXihg^|~P7I0Q^!6Hmryo6Oq17|{HCx7R)7xkI>?1@Ax-kMV zn3d_%ugcxZwq(4Kxs6sV7nfP7{u4(;{n}?=1*zVxZO%n7wM`pnE3u(v#n(Gl$}MYyCBc|_ z1bzI3Tq$$tCiDqFR#MsR?NS&C=jVh%T6$lX?k8rXZya3@a9!_DOj_y2{UEY)(ZwR^A%{Q<%giG~lfkscCt@Je6Id#{WW)4@Ou(fT-0*tT7D6A`GobJnhoos!t|ub4P>J9Bdwt+_k$TZ@tQa%*@8K73 z8}xnjFLr<~X}3=StGh6jHCVCg$l$m!s5?|_@+j9`?Bt!ycS}(KpzElv5x3M-dweB7 zmKmF&ht%plX=XULQ&uH}Uvj zj_PMD-<=}DKO-7@)Uh54o=3I3-YUNCA#*HrDm?+lEP_Cj$S7Mqpe`RiI;^Yln8mqqP= z9=PjG(?SR=W0sk44xUXFWXq@~ReTed^MV3PI{yHa3TIDB`luqD%dr7fZs)akGjZTd zZ&98a+j>5i`Xa#>1qy?#$e1j&EqU-x7v3!wFJXbjMx_sW|G>WYovw4!Bg=QWo|uw) zY#91bDgnfG0m9yg3B-cHwx6mXP4)vs5Ch4By{OVyQU6(TJ1^mA$J}k_PZT`pW*Nz>5I-cYtj6P zd_=)rNY=Zz&wUmsf=nK@x*)J}eS4oZA9@Uj_tBCyhqGrkt#HB!>v`DX(Wq=|HWVJy zz@?tonA}W-KBeC0R#<*Er;Gwfum&xVca8)sw^VEV-aui+Cf7=Y(k$CJf>c<^CLvm< z1>xd~)CV644yW|Udo0+NskNhV%A_WCcSekaRpapFRQD{cg`@Gt#G)Y`*qflBKL(En z%dzg)#uF_}3flE>h&?!@Alw2FT?nKuDuWJMp<=FH*d6HaKuxuu(bTkTK~$tY?N63k zqN3n4EFa(vC`_t4|V&xkoBZ z$6xo3>ndE92kCB0&V`APUBJdxVoc*;UxcF&{PZS1@m;#7}KDnVA$j*VZ0AjJvn z>OU)5PM@+Nb1_YbvloImnhXV?(J=ES)G8h0Yqv1CEW zF3QzmjoL1zPn=w)Jm?p7huHmxUr?27@E(u3I5Ys8%5yP&-IW;_#aqe z=DSbRh5_N|l+JVjc3nnGICcsJyGJfSy^YUNcBI)T`p+-Oi)_`uFRT;XP%z8bfVli6 zkH7a3jX#Yn2)2$d>Ac}j!4<=Umf@qk2YSP=(alHClV8qvG!}Uu<8^?t5dVav--VSz z#9e{HhDhdt3_1r%-ZZaDu^Z?|8yF#POYz)HEDNb*6+fRD?*f5P|3oM2aK~cSTi#$P zGY+<2;6Ywo{@X$?3hjV&Ji(^Kgk4w+oHg(+rJ=)LgtgSjJU`t#(Fm64krZTx$@ujH zIqsg^W(~f}H0VkW1N+_)&D2Z$=|_(md_#W~G#i0f95)G9FWQ@BS~~iP z`a$=`v`b92ZBCX)P^?UC+xG+^RA>P6bP8MbjQ*(7Oi2A8OgHnYN>A|BWfrTihU60g z5bZ{it|e1t+<7^^SDP40a)9SvycpNtT8)se-7Rj`@I$1xSr>;xQl zlVm@s$D>$x?XNE9ZrQdze?h-$$XKeSyOSTv$e2%67`&&@ujfbh#beU4@B>1FT%qm; zFvf)601Ev)=MbT~{C&pR*r|{bP$?{^AsD}T#52fhFKQ4kf^ozG2+x62{IXL)HY*%{ zge`47+zX1&R*#G&<$^>o|JD~TEOuFoCfbK4+QUMMAL`OfTLfIkjzZ!&l#fGZxC#)D z{s9ccsgHNduus13Fo^rSyLe9E+#&1Liguea+ozGoJ)8KH8Gk&>uW{ajBDxX)#FWa2 zkZaWCpLMU>`ynrA?hN3KWhm6cl2Kc&E*Hp~6=D|WXLnCx(6IVk`U?J$_0AXx{g%fU zHC2bGx04RLexzbN>U+TS!A$5{AeK|%T<4QbYjp+W0q^{B)F)1=GeailZ6jS?$?naw zj%4P2-Pj^DDu=ks20A=h$C$8r{Lez#81(E zXzS$-Toa31uj7cy9Sw?F9)uB4;fZi8hA$ltLd4GMVDvs{Zhhwne|#ySn7>KPfoLrM zbu7N7VQmyJ-~LKp#h3lt&OV1*nrV9C=Fk$Tm6N=Y$sdIR-a2W>SiyjSwo1X8a2!is{3*6j^GXEs7Bs{RQ8|}lA zI+Js@oc}s$$Ph!aVZbIiI}xk7Wo>}PIuw`O3umTwQG^)|C%u;UwQWo+vx>{_P2l=k z%jQz%l$`ki4R0sNMGyyH{2Jb-RN@S^hyp<>C3uBi(~IhQ`A1?5$4?^N>hMad_Q2f_ z=lSY#d*+DJ^ni;6@D#4+{2C=coCU%H1y@XW_h|6KTz$NsG1Sv^GS}Kk0_;*17C82S zhZGlD)ey+~$8=y{q-EFhS?LHR@*@j%Xn?%hJ9=9trYTVIYr(yHKHsKZPnznGu3B8S z(*TwR(ML#xVdPgvZ@1~y+Nej8p?uvNy9RD1*d`4bP|b-@h{x35{v1SW|*rkEEDG+=Kh`CzV;mjNT%tp_tzq9-etlUte3e(0P3I1X?gSY$T0}ziz z`Kq>Zd@{2VyLUAhU|?r;0mxrL_~5+6H^7GhD~~toB^ZTb@ay(wX(MD&nm>8=_jl~1 z*Ol}aI!}3G3cwr0j%L^|;A;7+XR)Vn>uLt%2}uW>S}{G}6(gA#pH3cvt5mEAeRWn{ z=dO_Sl$j~oi9GK7Xuy6=H3Nzt^FXbNGZf`Skat%RfCqZka$GFYE`IBLdC2v;7a}zH z5mW%C_My=<+%7};5`~55LzxhMsAtYYjSQAS5w;NT2k%4t!{Kz6W{l=T>jt5&3aq5(LTbsx4L+7&1dQXo!XWMCGdM3ed$lfv`-moz28}J`arhoN8{rD#zl9Rig zvE$$UO#h=J>R)lt{u9pM&}f|8oc=pc(?2H0>iZupR{v~}a&)qFFg9_pwQ>6U?A!+} zjsI%@rQ7N+Fu4pKj~-wE0C;GCKXd!L+v_jC)<1zcI=NdJJJL8g{%wkXA$tC2)GQUt z*fkFL&*>WUvMK<`g&PX%X1Jz`bx+muatX~-iDx7dmtJi{(HM7>+wJRBcbXvTDj_ij zjMy3M91P7$L~E)-7h3l7K0tzjvO`}_Ge@YW_;P+S9JC&exD^_se zUcI82+*DCIl&Cf-{dZWl(T$5FnUWtTFe56KM{?v7(o%#!!so=#2*Vy!B2N4p;0r9q z%G%9wWZ^e8A65;=qp*S!=@(25_G^haP*luN1gKmx+fFH@h=75xEI5L^5F(3+w_6c3 z^Kgl-`x@M^W%papMTP_jI^od`2v6e~x-LP+ehj-w-!eq9UxILt`hN1Sz^y}>q~OC0 zD>}J^5W6nq68nCO2N`&w_1_FP+>kZNT3R-h$EUwPw}884>rJ=(_zaE5VC&9dE`I*_ zh46O8?ewA8gZTq5_mc{Oq>sr)Fl?q}p$9C7x1~c=Hi<=yf<7_a8MB|rO@6}MAzuDA z8y2b$vwS`XQ%O23aQ(2~2D~10Tr>Ag1WIx z)=Gh(bOS!w5zz2sC@X@O6wIFL-AzqvwyUP`FH5s{rm#-+WX*?R;eqdMd5XO-wq301 zgYM;isBkX-={ozeX+nyEX}de1Fx@O0X-mgwuc`>`9j-40QoN#%nD~kSTJVO2D~)9{ z{V53_1=~8+#|y2CHofVa7o>S@CCaiGR_EqSlymG&zKzQZ6}9u z5z=zT4akl<1lSRz?TC)ED%L;>`VE0p-(i-Mhlt&y{# zlYq06lda8P;^6i-b@7cs|CgZ+fpbA@r@o-3=E;_30z zhtBQI>K3b=7*^C3OWuM+xa4Z1Qjx2yykz+b{EY#04trT?%I;OnO|V4Ha%gZG!lL|o z7D<>j%TZBGGXGSDV)3E>&;n+NnMNzc7S*1Rf(3367OUPxv~f7i92#_Wax%c)GKFqKO{0<#mG2j@iMi9jtJ$6~k0ZA_IaWe2Ws41I3LDSp zCWa{0J@&QFkiSfp{UF24?QsoT_ZhdcDV2BG@hjzCpF*#%LQmM8(p6#k%S2X}Us*6g zk~cs-EuwDdx~SCo$Np!^3=MlrCazTeZlkAl>&VtHS7-@0rPqWvBl zZ;EN#qPiHw9KAZZTUpAgZf^nTYl&eq5o$rl>)10nMPP2upJGz2AFM4&kXq>;E@GBA zSalhFQb$%k!e+v>#rvJ2KQHpu%@fSfpk3=o4MMN+cZ36i57fLJEYV_k0c1{FG38bE}jDAAUU@qqxstFIcYb74j zI`qbZ&z+Qfnm!HUaDD1thnFO_56?<9Xtzv0+c$96-v+;32@ zN4S3_fGRePZ@jq61aVKNz|B=Sl3KKSgd@!B&DBZ?! z@Ed}oRY?vOOJbM!5fo@q^%ON%>5UM#*V;PJ<`n*F>x}!i25G8A25$IKzXMS%q(wzY zYIwN|$%kNY3d<+;3p{2?oUqyBHP{@=MvFP#jM+31HiHw-LbaG+^`|D=JQva3hsnjK`}5HzxNGi~#<=jh18 zFR+O~uMA9N>y{#;7Wr%w42Tku+F_OG#?or7M$p^{26ns@dH@n!nC^Vigg^@(e1Xmt*=fx`k>UOkd=OJ&_vO{hfkFuI&(-tbGX z$Go@7q7BOxfo7c#SgQpxaLrJM$ft~k%D5Hn2AsuoUy22j@~}mp&DT6BMQOFA4}PEx zu`*Cz%wHH+>QmzT?NZJ(60K$BKbe?Il=4EdP@EyL`g_&db;qDO1K5*TW2qkc-MEJo z8}{uN9N&E!=rLxYjL6mydXk znK)BnyQ28=vI8^`9nrrB12QftR;>grqW1G2ZpBCU3x1{T-U8+j(nZ7?;4R|JESOHd zi8JpaStSn1K*Urssi%%NR@T+n&$PDJHnMjl;LJWysj6rc#~6F0Q!^eVp8pKOY4qtS z(1cSql46u#(DPNV9x)|?5F`L6-D-mN7QD_SgaS`NRS=Pa&rK8v*{Zg;Vj&?$)#6g` zfIi3KIj`WQEOfLaMAsmbU#So3bt47UMx>lba8rdG{E@YRn{Di|QmNG)&7Bb$pv<2e ziz4#Nb*>oL|DG`Z7WPyfAp5q}s(mLo?b5}FDYQ3z%EPMJz*B=ZgB6qR2SGHmc4KlA zr>ALQf;@8}k`=Zis@SCn`Sj>fB+~=q<9Cg7JkfG0OFS$2%?IMgRKzd7 zIR|+4IKu(qUhUU1+pezlr4~hyS8*lC1E83JaD$MB&ri%V^u%WPE9C)6F1brA5JGs1 zdDqH-J?>r`VAhMf*4j~oOnL@z&5MX9h_>7pZgd52=rHp}JQ_Ev$8^UU;2Yc7fA}nN1X!=RgYKO=)#OYH#L**yO5#F4BP=aO}ep+zUE~ zu{1PXM~@*q9O(v8HCRw6tZ@xI9QyKw7u@b}O(^z1S2%9k4qp_DPKI~6$-=4llndRw zGr9D>bZLMFli1=IA1k`n+dh-tOeOF#xTaNnT`wuka#*Fx_ee`iE|)=yt$`LU*M4yq zPtd)CO1ZlFB1wV%K)^s@t$lkr74+5_lFM}?AGPJg?g z1B=sgKMUsj-{clx|4GoDoy@KNf2I~t{uSmgtp9yt;a|^gA^sEGpOaU%4(3k(U)JM) zJjL}F76#a+e#ala3jbNMF#j#qe_FBrElDM9*Xdxok5$b|R{2n?LbWwGd+V##{j6cv zE|rjhEf?zKM(&8%rQu(CVjZkrmwt=}=JVX`E8Z&*Ml$%frRh$Y7^sRFuZDZeN$~iN z4Aw>vOI)pL;R_vE2k0p%0aLZLCKd4?*0STm%;?iL>jh0hZh~)P(6!di9~1SN3C#h| zpaU1}xFu)}=uqg((N@yL*e+6E9pJJ`3>zC&k97u9nN)Qg#xH7yCt8MOW8O-V;Nf>Lj=*rfXy9t3<|(MXQU)+=6Qr#V z(1Nzn@X0T&7}=?O1$|;J!i`gWbzvCElcj~hToVMRI$F1Z$u|_kSf#ebC~WZGo8G#W z-qMrEnS>A<6F}EU}Day24 zu8(=UvIAPdms`>qlUxtZnlffE7vx~%sAMu!*FB@>n@w3ORWtP zG*f1C$tdsLs-(J}lgtY3EJ1qcyl+%`2GFzL(9NPw>7L(!S>vLa5XD(Zn7e`?Nkjz+ z-l!OSTt8G%>hot%36dvjojC39kG;>1Jv!Z5KqV_N)anST9VwcduB*; zCa{7k^W`Dsmb(%EX!7ty?p#`-DN+Pjd_do#ZJ${7othXC&qEWQovF837v%=uf8^}` zm0ASiaIZ4CJW_7Lv$D zT)q7MGqTTb{nPSglq?2I(+SZGF|Q)EEM!wvL#nJiDr5kGr>Q4SoB7B}Jsq53ikT_U zeI5431z=~w4%9MpClRd2L}GejR&!9RArcX`@Ygu7?oPR|QJ)ggL4RPt@djEF{?`Vq z%{qQ(NwCt%MLZgMfUyDkU4JId9T$?*AwSXTJR3bBWSfEi5yK_o4;~u2iPgZ@;EVE<4G} zg#MPcWvNeP0j@!a#J^l)t#e_vgt64oT0VadBKU+oaA#pas0QFQqcGmmMjY= zFKPM_&up&)tzyndkTel;I%B_PJ4;;gra}~Hc_yfq#Shn=WIGuW?GTMry|^tuxKeY9 z6r44Rh^W->}7LPPcC^=fg5idCaGdhldGV@P*_)Lh-KB_}I zCI)On*|;zgt)I85j=DDh)p1FYQySC0j8b(GivmY(a0+FJ6wN333d?Ex=u$U{anWlm z#aV^pl($IJE$TRlv-*Th+$+wq)4HsUhs}eX?y;@#uKFX%1y9`}YM;lOBv|v+#xTHB{GeQ+R&j+itNe=6T{aCUZAUv~`YEY98N7*L^ z&*n>y+Rd9!XGq`XOS-bJzQtCXW8ZO?9dt@mGqx_)Bc|XyJf1E)C9xpg(5G2Mw70y2 z&--x60D$6u zMXUeKiWaQAZnMt<@BOSQl|uzsohIFEb}j}KzbXB!-vJr_kOvVEkSv0#udXCM9q=2#7AFXhAiB$~d@{6J^piTfcBS-Oo zM9|rfI70M~i}{DPShx5vne0%V|v zfwQ*T@Np_<9-!Cpxn}iO zVSRiLZsi`i3d2kWAFFu2+&Rm<>DjK1%OQjHKJFs0bl^@cDaW+kPzG=0$TMb+-gw0Z zp9V@DPNrpu&kpp%M>~HVRil534N>k~Yl$kvW>g@_+l1voSLfTxwEE==@rBArMU|Fq zL~CSret1KOAnTlFL=ct?2(Isbe`aO)@w*Th&6o4#@0o=L5a(GO?@byHWRj?KG0|Jg z8;~;znS>%iWZLU=(#s@?WDgM}u~(1f=-t||HHikuypZdLkMGB)Q9}WnHWA-k3Q}ps zxbNv03gx<{VmJ{wj*%dz294prT z%kGSKd)WyI)2&qbvP7(T2SQXs-xZGpU)S^6>}GDZIFw$oSrLjtZyKrI%(^LmW^uM) z&LHmbt3{C+4BF({xFwKo^!SpSmP%wXVSrJy@S{YMMD|$vG_cC!-*Z`7h*{B7zUX`k(?H{^!zpKKN1tg&rt14U&DbsK_wmdE3 zqIS&@5I4jL`RC(!Mt(g1z>60X-!ehV0I=u6oZin!i!HF0b_@K{#usv5Q8`G@%Qr|d zg+Gy%YBOrv%O8`YDOcP)A^pze7>cBv7A{aLU|4J-GJWY?q%;%>RO+;%Q?0z(`FTQD zHbkA5$Z8ydOH|R6dj!kFpo7~dhB$J(e}87(w5G6p7~isHi;iU*BjwP99`sCQcRdC@ zJB0Jy&wy;3^W+VG5TMJhJOYyy9z}->V)?ns9dL8?utJ;4nyAf?_yZMM;r?tbhb3Qw z$$(ongi4Tm!Z_#xES}ih`3FmIS<14Tx$ubfAyGxxo~cPf5;3?s_9CIZ9Jbh(f`q*V z*`NX>r0E23xRn8W8HK$9y3l#Fi_H!@gg6En$t9?B{+`omm@=l!mM3W)QDROzZWrGP z{3NI`2{G_x#d*pIn~y1|1f)D@uVuJD0uQ|&w8BvB<&6yRGDCj;rU)yUlVIZ2HA`4# zqFN0p&O*!36c_^}yg4ugfan;@rM)j4vX47Sa9rca6E`#9W$n+SU-5;foF+~|^K8`} z(TwIj?&5t1Ga`+9u)p|;?^4Rt?|t!&xEma$jzN8DL7Q=)5h#f*HXmXI7cvT(*8{sz zdquUho9+gzu6$imGw8tYeqWIWcf~r6h`5~jEFRFr9?qh3Zlc#+vrYVfp=&_earL7% z9qDByzKfWU=%j&N<~f<&RNP3PeP6uB%j^Zzt^+D`L&K`W11I;uKGJWDU*U(J)^5*e zmGt-qj@vUL-<*oy20VhplY*2krRhOXbMPzXB?q?ZqqGLbDNl%Ud4FPfYPS(uN$~ji zjxk`ZP9htUhVs_*ehc%l9L+O0A)AIzH7lq5;Ey(|MJ)LUBjdc!bUxWHS)yew$jlur zHF+AuL_n`BMcFt2r)ROU#!io!u2ld0)F$kamXg`#d0HP-U^~EW$1V22D4Us^-hC;) zJyWzIrcAx4HF`*7go3H8%OGvG!kIM;6!&|9v)=)z1J7g4jBRK4oMVSmmgHebgovie zQ0)JZ_Ri6Lt=-yiY&AxcG`7vgw%yovW7}-l*tU(vNrT2oW7~Xx-TT>lck7(zd|$^{ zqsc#WWZn1lHRrVm7-8g`e9OWkQCxT0+bb1?Zn$)6bS5(@eML;rp~k5YBuhY{2|FXO zmBP>=XVRk*>|3$?E~}b=S`zXTSd)}ORp9a}oG1ll zjm$jljkEtlA%gl-R-^eJKu_FI`~OgSAR*Ke$N)+YDnONw`!CY|UThTn9Uv@Mp0HVZ zhuU#lxlUhv+-(*|dbnjC%+e~gIAb|hXA$~QW;F~LSmsFOc@2^^6oX5JwHO&=b>j5V z706h^Trz@&gFenYCHB${h2-l!7?j1h%|um{I{~bCWQMpN1R#MJ$G>olLL#CKF7G1N8_hfpVj^(NvJ3S6A>-zdE zXd?2*LPa2X##!#^#nZ%$cW@QGGZ-G0ijQ!lQ$^GgQ&3H0L$(eHdLq{_!cqk^=<(vg z181g7bXeN_-o2R*-=$c3-E-sw$ie9A*nf z;(`Gi%|O5APWg~Zc}*AhI$lcQ3`tYQweqRSK<1r>-wFs6K0il=Pyjk3N_=0x&kK&4 zX6t@7;dK?>-~&%#PY%tJ%liB39tbcxSwYooyYrK3y(*2*#$puo2K>HHIAB@H}y~uvDkvuvpKLrT9 zwGSO~@Cag_2qdMsA^^)#v!FhR*D^yhM-Y6?_MWE;wfsEpf*}1Rji;51snwv=$$)w@ zN~l}Xavj&xpgRB|pT#15zQf+WUd~_>!ZKj9_u}5CxMt;06X-Kf?bJyynzW!ZR*VHj zXBv*)N9yaza*R~8MwE;Co0IUbtHR{w+Idk+sakUClc)S53KSk=8?YtWH^}dNX04Z`9<;50`6WuKc8BwZnEq3bVfUxf4Z?(_nepK63KDP9X`QE4Y2MGaQu8phFU-i^0ZoPmZm9`*y&!==f7nS0*E*Kg1P=`H=Rf8>2Xnk@@MdId7 z{p{oZR;&HP)Iy|^_K&Fr&xy*WEfNI7oc+PBxJ6p7u^O;Nqj{NqK??tYBoukguM+kq ze&^n6RH83(jDZ60F4{$JGaVfBg{?3RNlbcZSI3Oo6cjY?zVsuK*OloK%-52Tco{63 zxS*}nnx(dOeX;=xe^ExIuBB>xvMe^5e85ee8kOk=uU+^qGtxGGbZpm%8*|9gjjx>k zNn=XX9P_@?IF(6o2Kr^abI`uLi`S8kH(+x0i zLaQTE#)y6J!$7(QPm2FKDT!6PSuj_r@rAs>FT{-I+L4O@mqWeADfu#_qpz5c>+of~ zj#H}D&t^BT^YhX4=$r=Mj8!Dn+vORI$U-LZuj=?WilPw9?3r)m&&xiXDh3$7D~9ixmiS=>U0c=FN01KHU7h! zNPkEUBwN=+8LWOVQ2v)=v9d0h5AKWt2VqHKvQyl<`rdSCA~sL_V8b4uZS9tH*LD*4 zkL~ae*Qe&LSLVcT8ZLwKo|oE}tRI}YMOh9Shue7RYK=^l%~&zO-D)rF^m}L-K29Be zdU6}k|Jq4)w^LX9KMhnO{^W;k%?vD@{=*RWFJ;&t_Wh%-a}KdRQwQ+HnE{?Z)pfrL z`jct@i$KY8@-K9h@?zrBlGI}q@?unDlC(pk6Nd0@&lIgWMyBSh9JmoaT*`5@p&gqO{=*N5Z z49}+e={4YncAKh(+70yW8toZ`<_V|Y9K{f(I(vB$ zb?0e&-LC8VF$Pk`vW!WWZw@XJn;z_sj1HYOHV=d5N7e)!OO2b#^)h?VoF*BJ3QJ;@l1{x7hw2 zc6j%b()G@_)=sE(0`++~Q1&h{sRvX@p|8ruv5ap$Hh`3J3EzoxG`%y}LE@}=PMFBIhLD*h zzb5C_e{@g?U7}qF|9yUY$HMG^V@fF`;Sj2l|NT7NSp(>LxGnf?Qx^&J38}(p+@z*d zN=~j8HWY0hB=4X$(HjR!B3g93QS|{29rBHDg1ZfPJs6A_$dMV<96`D{@0-uBKs9@_h9P&-uav(NV@pLjy%NMg>uzl9OHl8-2o50W9)RASZdmS#!qT z-2yDvUDd}f4<=Gu0VGLu3CPuuf?V1veG++iP0eMoJrgMkN-v6pP#e@T*v(t!X+E9= zf|NAk0<0sB>!dvr>bf#pzDCbqXF2@Z$-`Q9-f5)7$t8m!`ue{P_AAPG*z4l+pYOxB zpjpZs_Y5Y~3@Mo@Y3SN5>NUgUt+&BP#l2Inm@X3Oox^lkuGu2mAzVly4q;aCm7pm? zY3!S#Y)Bx6juY94MScxx5=rl_3YC){Fw2|k5uIm7AAzt07s5AZp`X)gZHK|;5Kb?Rm8tNlz12ile%9U}%w~5YiD%jL#-}BP2jHsh=*iLR zFz;nNhAqI?atyeXFAQXnCa~s!Jo415Q9tcpqwg1-T$WkjG>qMt6TR9^eVADACa_xh z{+fMUNT0wwQsH7Xhyi($-o}2mNd~e8ekBrTa))pp2AB3^>D1VJ^f8SPWN+UrkQpg% zucNju6>@%0>A(mUESb8gRs1vPcR#UX+fkE;3fAeuRy#E`6-f>O6 zYNzAIZ?Cnc?Ux^}X;pRRqT5FAm1xMNDFt5)oA9iE9WVH!;?daEp-BW7rzrptB>yjr z^KYT!A8a#FWyNMg1j&21@)NI~Bq|HS&2^bJk%2Wm!Qv;TFD3n2@GbmXiV}pgZE1psci&_eo&d?WN!2fb_o#$y zZ%Po7q_{_xvr4KdyfBk4q}#SglPI#6)|F`6e4=>w(+3T(Sw9mZ>TM_%5mK!F|bW#37fq1O-#m#6} zvaNdj#7IFwwmJK4bf1e>nZyO%7H|oELJQAx$`^3i9pg0JTo1DMlq8B9c=sUjspPO+&+uBD@2OD!E zC(~TBX$2XAZMU?r0rwCQp?r94w@N9nWn0GeGZ(zH_!~Q|5I-xc78jpyZ4k@JT_EWq8B!&Wt2XJlQx<_r_nf1ld9bBwUyRLA*jPUYAx0 zB7uuZuveJWXJ_amP&8F7dW;P}_p}VT@Iu#+pT>gXC8T!%HS| z&|D7sqWqik0c;HN>^WuY45pY!-nTHUd0Kp(q+n&{ zIcuJ?6>IKH3g%1!5v`303-s-{V7Fe!bmABg*xlvp{2-=dcuF7WgoEho8-KF)m+wIKsS6KlopXnkJd;JaG4 zN*2Lg=Y(B@Q!D2EzPp=13;q{|E#U<$^MLcfE8aB|x7m-_NXD-G=n_>vK;^l3_Tj1> z@=V<7BDa;A4TjA}A)NlPqr~bHStzQNPtFkUS@9NB&oXhk7kBWHoMQ(pu-j4}POlCc zMByDEx>Dg)Vmh@0jNmJyc;)TAFf?J>9o=-LSwU`lb?Z<^5bhT)5$^WLm}7K*-3k5Ybu`Of|d7AV-fUboH+^ z*?*nrK>x|d0{W=NW|l^Z2KGiq*8hiAYQf=)=L?{f`T@|i__<5b0w?R#G4kDCtw}#P6=B*eKDeq)}SzUV_54K2}XMxU6yAc{(p+C%~t{0uA-z;nA^q zs?~ETVCFATixzP+MI^yO6y%9aNw5(tJcTk0$j^%#yNmsZ;=~m*Ww>xpCf?`Z2uob@ ziwiaxy178L4>0M67V4i zlT`OiaR~Psozjhl`TYeebh8N<_b+-Fh*n6R%&F|1x++C+I2C-~ zB5W`-8kk(gRU`yCJhn<>_=Z)J0xoKhz-A`EE+u+V6f4vZGR*56sw8nC$T+?zVecV^ zzv#5=_>TK8i_1afNn?>#yfv5blc_vnBy$@lkwHb3#k(rg&4rDO@aK@K>$t4!k) zrgd0okt!N!*T+3xy)WXaRS6v7_At_`@+kI)wMH zX8N}T=pSq6ZtGuaXR0QhBcS3$y+)StY<@OWwfJ|^h+Obt(p)`nr((9sgx9_C^XF3( zkL0@ON69YE&qJfI!()_T>cdY&h@6Us*x7-5am?Rhn`YBH`iO0oqG;eLQ)Cc&CLW7v zxC}9qGr8clP<;Mr1)^sW_5RM{c-z^PPpl*68rO zx5if;F>KX%)d0{@Af}0nS+$Cwuc+Y0Tn`9xOh(4fM6L|R78NOR9+)ped!)z|5}5af zKxi8<_kDMDj**z)N?n+}_G?=Acf!o-%?JJ(E@9L;J*~dr4!LQ^wfnUGMGB6J&QWj3 z^>Aq8o|p%%re+?b5{!mBGxLd>=14ipqdZ^F9vv=`lRP<-w-H~-DgMhmhRGiKJMEeR;VDlT5_xo02~_f7I{1q< z7h)30oTB*!i1|tyIwh7DGVMqVdnIYM$k+TOt+gt zxQEoCsoHB|75$ttoAd}dPJ-pgRyv$vS?B(xRv^bYrSnSCn_GZ`~#2 zG5pC%fF#ADRAyNe*k9S;I~Ae+z&BovDL;rZ`+)ZoqS2Su5cp?dup!q}+WZg@8}dS` z2YVst9KD+O{SlT*aMx?$MenlnxG!VZEsO>tXqgcG@&XYFs$zy8T-3#|ZG0=GKp?8( zHe+1XFtXmxF~@~QlWv|*9GHal#~JH%78*h3{GfHMY?rAOIS)ravK(D_PN&xjS zj=A**#IV0{koFG=IRlF_RWHg@CY64Zyh*tdFlj`n{E!IP5rP6Y8Lcqes4xSzbf$#P z63c8)O>%~JE@Xb*QkGO$hciX4%BN^CY50^n{vd_51f&StvCp9N-Ie9!>$n&-+G+1Q z@tRoaI<5X;JJcylGe$eIoY@VCOc%}QNT2k&IF3g4a_=Q}mFBPtRmdnw6Lb-w7ec=^ z!#8Gp9IUXM$@qB67QEP{SsZjl1RMo8$Q<*Z-~e6YJ)$~;nRJ7Qhqq&Pqrw_fV|-y9 zxE5Qo%RqB9)sq?f2Q%K^bV2F&XF8X;_|0{J?_-%AufxVm?kH_D{bf#-LxAsLLbOmW z;uMs|n2xFZa_N?}p4B&`6q@T}J&h_1g&7-GJ|Ap7k7ksRxFsjn4<5+M8dpSJskvD* zagDJRtw)GNDh8=8?asLy(p{}LnHZhN8XGYzo3ZSv5L}=7KDam4U%gb#;i^RtWT{T# z=M~(Y>D$=xeIhZ1tczH^@vD+CR^dvmUK+%v`@q0IraOIEPUFheUpM&$OT)c z>HUsAW1_Z5H_H?kdoQT!M?2e5>^E^1p80N8bSxOvQhTTwDA);WT5&ablZgRgF|h`!{hOkJVJsT8x#qXffogIt5XD>12tJ3GHa zRsKBH=T!cXp_`uy9hnc&NI{;`K+3;cvhdCJ+so7Xars+o-vnP&^A4RaS*=|7t4}}8 zL;Z+_9RcBFLV#F^0*Hl}KgGgdJkdWPp#R{C5@P`?fb>Yhw;uhp#J)anC8*>gaI?&d-yk!=1^Pw4{|Oyt~<+I9rlWesdlo2+d%MT*^uZ`rm=_i z{>>*kJIR@3jT!J2)DFd?x#-HmoLw1cVI<#{+K#GYSqLV?luv;!ZBV%=r8 znJ2m#vmFhimLmvs3`~~$frD|-i`VW_@EJ0&mcQHV$g!tNlccw$VlFS;u9uiGfrC+R z?u%rkRB8#5)3@@_a+Nc8F~@WfMlsRB>hl_h0ve%Q_ICam30hge6x}E98;J zqEe`fLHIr(F~~8*BcMxrVC3u9^co*2Pr*e!0fmLbO$na)gY>JUJ}`x;(c3eC`6tM& z2shfI#!;y_ez{KFK-@}4H$reH$9&di98%|>Dtj_Q?4_rJGCTIz8AQW-HAZ5*N4gZ- zmtr}TF_%dxct;i9LWNe~taHuvzOVfRG5cM0miyq9H$%x9-I*@3NGBL!ZE)Eae*Gb9`i7u;y0+K17vz;>-k0NQ{eo?@J25a-0crZl^2ewtH?OykJf%gB5ZhM+qk^L|D0 zO_G0uX_z(`gJk#1wCj!e89{iK6l&-&_2k&x41eJ%jr8pKB8)Je%e&byR4KEKP|FsX ztMbml!t&d@y0#M~!|9o{j&2^Jz?@;f)en72NSZi-*9)mo{J_{}>)=hPb+wIJISgO# zJ4qAb-US_XLCL6}3P9V(RI!Z$^?u8ztTVS>!A@pnljUOZox59-P6^JoYG7@VABAWm zBy}eyQOq9=G0F1!60Ipna9oF#jq5$x3R-d8eG~DvG1m<^?1&gC_81wD+eSvZP5RB; zNAD|+Kq zGzw$fThusVCt?r7_nd~9N?FMwwJvQF61p$0==JpLjdbfT)X3#0_}lcVN8^pMkNSg>)efU&dgk}v1d|#(G=IhY*u^&M|MKw%MRFkCN6v8Z$F zl9iuXC?7E)bZFwG5#uc+0S_9BC$=$Hl*d{m|)CUH#OeBIo&*m z4YGWSGe|prSxA4>;UmU1X!zlK%hp2n3V+mGn!ETOp9^7llhhd5DUX2n4(#sB%29;- zv(tXwb`Vc`=RHF&1QxCO=S8c?@V1U$$r*laJp7eU=4VXN@K2i~|I+07!}a_SHHrMV zs0;v6jR4QjnBwoE{^WlCMdbf4D3yeTtd_dINC5z&_63tq2NzG*?UZbT`~su?(a+ZY zgm)YT2wda9{ zU4i6b@-2Qf5V+A5VLi;{WI-Ru(Y*cPi67*Yi!dAHVr_JVuskI^S*`0u5!Td+bCr7p zx_I?KmFsTgD|P|kqh3r)8)^*;VV_FJkk5vT5F;j7Vcxqqmi8U`wD0bf`PFe#_6m++ zkuJ84LiHE1gS%A}Kyelou0kp!!X=%_)PuXKpv_a9owAU6P@+Y2ZUm8zOEl=0k96yH zQz#c5h859#`-hAA6JBwZvaKXJxf_*3R=0wzt{^z|VaMJpp8EM_^y#LCQ|3di2FDdC zy^V<-dF+^;WuEB}?mS$h=zKxr#d=Tb=X#Md=Ubzu0^S#x8 zED^gqDIX)OU=)PD#J-IPr{=WEv#aHmN`6_>L{|A`((|y`RJ-87TR<4Ey{Pn7B5t|i z?x#VWANt3#wbB3!xYJBP&+BI&_!ScW)NDk$^h5D9b zcIj;(!NBA6aF0bXxuP#&0=~JeaE1X5FQ5<`={jp#npNG%T}-xMSV??1ZHrr3@IU-R$zYcG=DV1ASX7i^4UbSzxv z|ImCO=qVqk=qM|6oTWKGkRtGY{!J3?>12?ZTYR(0(gTsfKkHF1M)(G<=I$)!tECLJ`#MTT%;n55K0LqsTE zOnIe?@q574ZCLFhB3k=xlk(9er}3mvTB>w0;fr0dSod;7>-~(6L;c|7ECF9lDkw|k z537@%H}KRA&&A>?G6 zknO$cC+7Z<@*B;&o}t(6mMEUXORa1ZMz)C|(II^n;w!@2*pG{BM5mfCkR;YerPEEI zaTG|hzNRn%rywe)y$=JaZ03!hXZv^*sDp;~q+}g)21TyQv6_Q}h2{s$BJ|oZ_q}WE zbw(8BF4wdYILvQ>48`09iUW_)<#dMvwYyf!SCwBZY4&S*4DZN7&!?v>V`QbQ_;k7{ zL^Wk7P@D^w49IBMT0Xsh!}1wHId{&BdsWr!+jF-v57GymEsxbUmB3onP?=a#GIC$I z%U%5u)NiEfV=|ms^qOI&wArcxFgLP|5oQ+dL+Oewkhj02l)r|EzcPgVOkHMaV`BE7 zp7ei34n{=cGpYdSNrMB%dw(9Z`Bl#Ey^H^e7c5eF1mJ#=+8(J~$z#yTajBfK1x4tf zHR|}nfQATEr#B?@rDH+F`|ZP?+*M_l;+}wnFyGQ9*D^_J5ErvXsWm2ciJLkKRFpu& zGgnZ^jqA{ekn~T09M#y5pJ_OTXdpYlDNYtBK-15G!)eh(Eo?GN4^e zA`)n-DmK*o9DsZQ4$@Dz-NUyYpu&5Stez8=7`aY+GjwbimlVqoLhj6)vNFTh1D7d4 z5&-Vz9>SUNV5nn2WyOwZj){?S9r~?{T1`~MBAABu~(N29BSClCzi`YlWB+>$g&{t+Mv&6wk13?z=>R`(= zEF-Zq$c_2BleHsH7N@Y)4Yq%rz~qn>f0g$YJ&K_<9^hpxcWso76NR>&OlyZbSF z&>?M|3h+OVD;|OK<}<@b)&Qbb=f|e zn@CZA4|=NIEwEZaIUTN?lBty6j%FlRQeK3&B)8QSygZs$=L@{I7GF?mTr1N$N)}lW z%#$wE{*i2Luq%&oIodD*C4c;a`~RJe4#7L=dQ66P4^+*)kHw$2~Wbi+UDj zqFFfpWmkGf{7wmKQb`fS@u-`x9R>?E+hx=NLc3gzvb#A&jBt$IDRooVmIL7mX0R;p z+UjQ*O?4}kfn$xCEu`JTrTG!dRK=ZZ0vfxD*p$UT7oU@UhNj^-e>X&*YShSUb$XeF zptVY+eI;Wjb(TgkBf-pUNRR1hen&aOgr@mOC{mMAXvTm724%wz+Ef`pFBUk2CP8}_ z$qB!!NkZdRe}RI68EAFiowBMlN9ocst+8)2irMyL&YE|s*myrbw7pc#QyviLNy0Re z7(i##tj39*5;xF8ry@tIqWh`cLbj6tKpGm7vwdxe^6!`A=)5AN}-8oiUD2>g9EqlwrEmXHX zwp3(nxNq1Cx#Yms-PM|AB+q~~MI@@`yTgl)zu^#{_LZ8>;%b@cz_-Vyd`&fKFo1BS znxH&r$JPZYTqNVRZ&n;sD~f2)j&vBiQ45BGSa!HIkn-FytG$+*-#~t84;I%Z%-L4z%P8dc@J9s(r025Q)sdFru{u?(((v z*Lg70@jHS>vu88EmVKE+Y?u-|cCV5Pm>fi#5tO7Rf4uosH@MWPWH7cf*hU0GvhO>A zFiPN(O(zr3(A~xNcd3SIk)ZC(Qr?B&7dKRMSJ>~9Wi|szw-&t)Y$MkCqBeF6QWK3Z}+H<%rCCBAonvjhSs;&4rzga5bP6~f9 zI?rvhEZ_&$;3^uX5SIm_6&HI?P}x{C=d-#;6?d{Dn`lT&X*11~5}N zp?U{}{B_mE7xV}mff{5CI(vB9)i_5we!Xd$Cd7Nt%p|C8S~z4oX@277G91?}#1}j- z8thOAu5x`4rYqG#tY_}jdi?-q?$D*tJRhQ*i)#jnA)mI2!b)>QoH80dQ6(65Kukfs z6Mi{seqAz|zyz_+GjKdGs;-9=Omwfd)>wc*FcjToy4UOdNiWV`*%3i2f9Z-M;vT$* z#Z-7A?-IhEhQ@Q7dU;XIQ`DHyrQgiJNg2j`EZO+7-gGG?K;5=H<|bn_K{Y)a^OL$D z<f=Q|V49%sZYa97781tB0d+*Lp_f?4?vSlPR2QtO1sFsP688i~;V#n?le7pL( z&_45M2K>-2QDKZ#hSgHQN{ynt26kB%Ng`x^F5a>*C38|6WWY1#%(a^}_5JbLhw&+` znZ^f!SE~$TZ$1u~!sf9m*GNl-JsCSP(W|jvwtbAqx=+2rdj#sdByb@;r! zi>kItgjoXMpw#|;P{sf{*FSjKnkGLOiU0keGNSkq{C+fLdHRpkX89Bh6gE~3l6h_{R&l49rGDzcb{L$qCN0~z!;^g015_FJdn*Zh&rz{bkf#@guT z*Zh}Aov&gQy~vLA($U$2-vE*akD<2La3xKnycAz@QnI|C_gE)$*sDjJLFDlKIitvSB=*Q7jF&a0}*GzJ#3hiYOU+C;V#|0=c4nq?@&Lg2X&w z5q-<;#)e<>v-?$J!2t{nU{O6qZJYtKG;*DRMIORSRjHe_)5PoX{^qc!66+;af;RD5 z9G2^|L^ixR;m28F7jIuV!Xbp??}$(R`@IT7k?)usn_bA@jFO&f^@H$q=2>pC1{{0z z;xo9q3LU5=K1Aj_`=)i;^lD-z@gDKYOBI25MCB6bMUzx%nHzsXWlE^_i~A}JPj9}t zZrRM}qEt%YZ&2)b`E!2%bJFsmf>!bnMwLp(OU;xcWcn1ED6pPGdTLy z4}Z-nA~t6rX8!!y&c@J?SMVFz3*oj5u589^?sC!)?O+f(X-^kbdb*!}am{2t5X%P3 zW-HcLwLPf3k($i}<24GtTi%S~K4w9I5|$m&!#POpG!7JI4X4q}NM}Y;ueYdH<-_ z9cWJz5=u?Ym}zj3cr2Or*5HbPL805S>Pnd<$kpa6B~aN*L0ttDp-N`-3?DeSuBaU3 z)sOFZYhf)V&Q5B*ea|ssUNnHLe)lys+t{kV`@uXG8&b?kVeWLnpfHbn!0u@CPCBkS zva&aB+B)ltqLv#x@FN9MQTdn#b7)7DCIybH|LpyY2HiN@sV<$}Zhv zCxOgfohA>jgs}ZeVFvU1Ohtyzor+%Bkl>s3(nWEPr*dcf66{yr+sok-kS=Wyr2;tb zZ4!$%4N)nV#Y5Ul2p&{+DBqUINREp+=`gX_-95O%LQZkEJ&`qv5N7j!OKdL1a&3Jg zf!}c`P>_)|b#E3;mU@*;^Z*SI8=^qpJA25h)3kq(kB8)o>2>iC#L4Ke-mi!aL^HJU zhl@L*gFraVdD;7@qm^y?Kurgc4SW9Se8dxh4kl8kUBvUzX0KPkMozZtvLe{HXt!0` z#ujQ)iTCa#ApisBnaOH-`Pp9Ic5U3LiG*b>yig~VN!#Yz>e5fkrGKqEf7|f*!@U2? z$ngWIDqVsPp#fy|gn*pnH+S)qAQ?Sp0X_TQ2ipFn^XI839S$fx0m}|>*;NPu>@*2@ zb2oamJYY#yW-ZCI*`|rrH0F{O%&UkIukIuZ)fov#;+N;lr)JDV!xCnGRzr*dN~OpZ z#2pIcTI&aHq%BVwG2R9HJr4#qkc={trdh0aEYedPbIWgt0vb9Calfo`=$QMUR&R9B zewOo=Yz)X>7>2Jc-b@61h$srUx;SzotM_EPk zaAihFB31MJh+FlgFn0xN4AwCl(*L1VrI_4yB+)TjyP`zm%V>7%yija*V~_cILq{C> z(DY_$;d|ZT1HX6WBxKo!l_aLR^%`c(H)gPvQ|R^Mo4#)}{rFqz2kgMzO4a@D1YEbm zpak#Hrroo-s(C8@og*HrBUd;NscDW6D1Av6ZR{V;=+mIme@7B zNOCf|ny%VNOf!!L2`yfjQt|!F7Z9{Ye}`e)4&7JzratJv$joC}kG(lU>y}z+?AtLb z)J(ufXCrzpS%tr|Bhu=V6=Xbv{yAK=Y6vf(0fO-=KnH)@ApA-Hq<-{KL~QK;AQ}9Z zh*cl=J6cMf=A)G8iCklmC#IYz{0NMW7eZp7$wVq1cy|l(J(dq+#gWZrXLNH|CpjX< zJaC}0kv|K@WTD2RL;xi!wrgWEBc!D8-WSeQ zJ~W^_6FvJU{X9hZbqE3fZz?G=)nrB&P;oq3WpPW@--$m}CT+FrDTD`cwp3OJ@hH_g z(bbyC34*NH9g_-ti1V$226k4^zR{lPLkxOE^)Yw&yoL~;IGFY!GEjx2v{8T@UO+-% zr+BYU?A)?m$Q*MsHj9XC<9;L0ZSFb(Cmn7%i%jOc&rsl!o$#fU=iBWBO(y#Nhh>`V zSEf5lON?7tOqNc$_7SAd_DhXrfQA+8`V(b@WKyoC@gh5 zCPygt4Ma3Olo}P>P9~Ww2Z<$82ED~SYY^8A?PipIk%nSd*`r(!W7O890GH-czq`Ri zKQC2+zi0Nx=>sJzH31|r5jDtJC<(+aC{;{&K^Wk#2Ba(rA1G#P-iW`5n4x_gmokan z60Cc2^EF9hY{{f4n}~1te5#}_c^I)}{rx?325hdJdFN%vumeaP?E92}D&cDoE|UOT zgHNB{vcgPt(dNpgNjaEte1%e_56`XAG;+_Xrg_?F3eQX*)5bz9=XRU@}t1X?i10TQMzW{IK+1y%GnY2w4m!@Gyc+ESb?WNMyVJ6lp1`^ z#2UB916Sr-%2Sj-4B>|()*w7==mlh^s(>5%jd}J@hG6guYuTS%@ju*;cJz+~6;boy#9T{x=MazXDx9 z0Fi0w`^QeeQ9l8U;kRkUKV;E~TiZH0ikKN$8vaod{6OW50MB2law~;jH~j#_HSP1j zes?-c&2Ti>x>RB1OGfkj_4`Ub)L3!p4fIcIqT(-dVXIePZiRT`_H~iWyX6<_#E@67 zB{VU8dpfCWp-}2HoMOxk>vPK@-1A!@4dKmegX51NTkR2p)2}^gXHrI%=MjAeJflu^ z7IjA;^s;dct(xQbJtpLtNe}A}#%Lm-efnM8VF%11p znKw9w`)k+(qHp~rP^Ej6fn>hAu|79HxR+_a#$Dy>9U=|Cz)6U@=s$7O=N2>P$lPiI=c^g_q*#k}#E5X2LZ=`m<8EHCkBkI;@L`*U zhZp^9SZbXFx1A&SKFT^nF=enia{swJ##y$te86c;F(E7}8=DBpp)Fkfv=E&v5iY!V zz|{eV=tKLqA*~PN2dQbxg01&Itni<;4eEFN6Y!ZpC1@bfe}QHHUBVxru^F9%ldYb< zo`ccDo%9&@D!I|O{l_&qya*QO7op`XjC+n2-=b6N5$U1s&6Ms*QAtRz{3DA>O-aUruCPJiLmGymwk`K~o!B7O4Y7gY6EZTaD|0cZL9 zzuzM2pAOW{$;jU9zh-lN1oQ|ULQ*7B0Y0e_;pc77pYG^4k-sdKe)!LCfcyGILl=f? zjFte;UtH9Rsuf^O0qJGDl3h7I?p^8;Q<d*GL6V}QrWE$(+cY59V>m^3+G?#{N4lif-YIYRn zXB(0=P%V2<*MP!EOj19Lf=@6nI^|e5f@(K0b~l5teipQjlbaKsU?-MRjG4sjNYl=aIzaMZ zjo@w$lN?5_0#mYlX%8BR{ktK{w=Ful7*Pzu&r``+Ckq9=secu7j|5Lzc!ClJIn+fwq{~ib^Z;qU zvw3gpFO^7+o`(*G$5af>9#}yni^Uj(K2~mGpLLJmB^t_`|pJOtcAk*MPd@6m#n__%Dob{wz|hHmTxUKXm{d1QM79`Vv?9{ z*0Il3`k*zbe}68H9UWX(M|9m=n@TBx3?0@F3#-^ zs(yxl=FAXkoJz|SP$YQs;Une~%Ukb7ar*|F^*bKRV0PJoW$z{bQN~W5KrE0Iso;D$ z%ILuJ;QUD@!v!8s^SqW6u;ONZ)pYn+Oq4w1Ch5X7;-!EVoQe2y2L)DP7nYVX*A=!V zjuDf$q6VU)-3De%Mapt7cWpb)1t9oY6DityK~AKaxn~UsBaHR4^JU-}L-{7vBgHo| zQ{*4iI#fdPXpeG656wc0DQj~nl&hTEQR-^xGfcr(kp?~`XyItCw4ijHQ-ZF~sNA8q zeyC${XLW30m(eNpP-gF0Aw@Lhq!v^p&(yL(uGM58CBPeeQNg|uKkTu-&)x9?`Ew4~ z5MW9r2S`e!01n^}BFuj<{$Gh4{%ZX{s&h4Q=f7HiyZjGljkOiJvbxv1rnV)s^N11jx|@4=eM!FVf0>`TOK} zREmUJA{vl{fg4F?X$Q@AtV}@&}~^Q%SN_bADL<9s^YKwZUQ5&X}xy zSLOuUP|B!nLNg>o4ucF2Ja2_LUAQLMN7w&uP=Wue9jhVeDS{k_>pC`=uq$H0BL6gk ztab`rFPe#p+q6T*_XDJ^VsEwTZ0CJ--#KrF@=C!?*FFyhnMIwFdioshdTFxuEdPQ* zXtheME960Q#BFMjEe!r(XuO+g==YLFRpYL!Hv6xlH`RPL>BTIqFLmD5aL)Iit@j4e zoJQ{d2jYo8w#okC&H$|5j{o_Z*^i6*@%+V2|Dg;&dirD3$&Fn9ueIxrr}BOOMx;ZMoydB3mwy6*eB$8!x}GB5&@K?-sdSvg4j-U*h0e^nJb1pfAWI{;t%bqOD_ zi_MLII~>>jdFwq@{zvSl-%and=+)X=XOME#hTrJeOwWOqA9wZoFB!41@5$54o?p=K zW$SW7TrWxd0Tv}>3vwv^wnRX`ynLhewSO;p zd7XXnmZeLA=V3OxjYQzAuJgrc=F0w$>{Tbi>BC;Uv=cC^+4X@=LGkvzk^IzP373T< zhfoPF>(Zkypx1;?w`q1#Nw4qK(%9WnE!lYGu9wp&YKoz@U3B7NYS*iQ{L@G*=QQn* z_;AZKx8IOuzO`z?%)(pmv-MO;o^C??x01cg3w0|V*zCUiLvmpUSOn(K6=&J^mt!en zI>XyDs8ziJIkwNrm6lWHhjlor+wNC1T)V4X#MeQ?asd7kJyWm}@x zw{~Zad14)Pjc@@%Dj|Yd0cjQ%(u2}UdUHd1>DZ$SL4i*dHTIcW)@b;;Vs>fU&2M*E zDmdVMXKeqA24#acid!-xK^9JeiNl(G5HyiYg&n+$*bzo>y&TBsR6P{=`Y-7``T&gb|?cw0?b4Hfmcp5Vq zc&{iBc|YY870so*t3B(pO62=!`_8TC1{$aX5 zVcmf`ZBbUsLB3iPF9RBtnp{yl$DC+m!!%d#{AE-nSBj;;g_5T$aThvm zVU*{InDo0y112LQ-Ux@%5lhNhSvy1qbKB4sAFK9-&+aKa4_GHJcg)q(x1f%971Hue zsqT&*GrU@wdh)4wztc|LeDPV4GG+0I?-6q4#|!61yn|V{n5SdjX7nASNq#?*sIG0Q zoLWQ?SkxD->=yh^sSaIS+~3#WN*n)NF4^c~!xuRfg=>SDIL7S=skp<%&CeaL^)##c z)GT4v+bjxg@8v%CI&eYW(_nF!@d%r>^{(o(I>OgvcwU8vNj87*DUDOu6$jS31H6%%Md;g?C#{3ye<63Lpp6i@dj zNeZI&1%>U@mz6v5Y~m@^omXt=?C24C#}n&RSTDS(YM`)Ca~)p1*D_oy?K*ptEki2Y zRD?FFsYEOH^kbe0?}x_!EM{5SA6gub>X3573dWa9U7ONmYRNyoQ|N+b*DOzk=KHx% z$2XY_-;bd05DSpUKD7)i z-Lc4?yyQH;?{j%{iE{BIZ))vE`OXZD3I4C`Tnj%2yL;*Ozr~CORb;l=-SR8_Y!%>M zk5sJo>{0HGIT@4C>6hua$;KzDDj*+gG+ELj@4s)L)QHt4AjDl-Zs?1!U~XC~-#D`q0<{Fj5$9`CiuVJhm_mPp3+$wgNCm@+#Gz`t3ll48Xgk`Ff z!lywmg%_jcv9-LV*H>zr{WgEu?#g``LN`kMwG!+x=%aVm9axuY<>cInVjr^Wbmw{$ zsMt`Y;()%9peU~@+f2j!MpCiz^I2~>KU=fSK+Bp^>id*U%!XH}q`s!6%GN z{{_91L$Y_PH||&4QXp5luO>9Mt7UZhUV#C2w&_q~<=!C26Pam3N-~X^zGF{%H1a9y zI+Q-r^~hJF4rN0QE~k&5wWeGEUTc5@FAtESg{!AS#I5~2vf%B((s$etJAfa&J-8wT z3+D7b#D2Gaahfub(Z=3Bvrn|PSS@=eL+d`X@^ZhjYP}qNbG?{`rNvksbMwupRx38q zV;AfAuu7*+bo$e{9P8^h5{QxSp+ipAXePP!^~GTOD~~;|y7$0wmcRTA#{c%om)g5) zj>Y8YRMp!_I6dF)@!(UY{Q5A{V;HqW#DML!(l0iWw=3E_%7f1ahXpZ)9<%&ZbNb zOpp*j#3ATh#fy1S%{pJuk_Fid52F&_U)=Y8cud5%@X<{e{X~ z6I=>(&Yf=3zGI=DN6X9T)ke9qg#E(vipHl?yayeOJPa=cd`lEA)9sOvNosb{z3JwM znQ1qjHtPP&=XSqFOfi{}k}B?^jN#0))BDO;ENiPO%VT4gPBrW! zM;*OrOvyoG0iC#}(&qWwlTmsn#j;!HvF~OX_>^M#L>HF)wiPYqFYS8ucCFyTW5N|fY85BRQKlC74)Xc zu_pbHc|7vWi`JSw?#iq<2Z<6JT4qqdBrDqHU*wLPf|WHq15TD&`d$IazSlW=aH zcWK;H*%8l?Is{FE@DHGaN9~Zs`0$5^vJOVi4+l*+*$i7pDp!AOvxC%KsiVjfqoxz;ksS?294813JmzQGVxA&+1LVqpQD7caE@y(PpYAZem+goOXTUlR{R^TXU6$?=PFH1dtM` zAKrZp<|?yCct?N7OK{;`sH6V^T*KOd8?ykhn*~rM=CB_^)7=$_e8vK5y48 zvOnKtKAvBQ@vo34-%CR{~E^X}{im%G$^V*m@vyD?W$`Lt1 zZO1h`UWDFH|KSHaSEWfCw@GJ=`Vo$sxl^d1n}OJGTS^^)stlA=ywt?MhO7Y+nV0`C zQM^|N|L5y-1o-$sv;18I&*wss@L$U5U`Q&zkib^xKhcOjjDT|CK4fU{D$OZvqo6PV z(&<=N&?qQ!&zy#!0nOB0k03pzfPYpaCVs}>h819Nz;r^(0|v$X-It#H(D5-jS1>_g zO$jg|J?hDWMM%ccjG79jNp;=qs`6+m<{ z4B(W2x4wolP>bPo4H5m<%^Q|J4^WYrFCZ1XKQEN3O_C@Tjuq0acXeFw4zf_LBx#~t zxXg*w5y1O%LJ3lK5+xwkt&N?`Ibq%t}LAIB;m;`_=4bp#9;kJ)mMsXcI^NYfHczGe9Xib%|5_2QLe61^^{# z)F)1|Is+4T9vfjcIADxpSgCSO%CNXu1Fvxo6+4Fz6ecklcZa{WnPCzen&2dc6e(Zb zQihi(hsvBv3>GH!9~UlhkHim?y2A`7HGxN3DQ&&FLBI=JLkA&jPM+nj*8sd!FO&`q ze7^w?v*6k8PlH;W3URXvULh39Rtpr=|IG%i7fNcj5;qM8%rqi4I9%YU1S^fXI)lIq zV?t#P_#^gTn*m-X5K8jI{!ar~o$`q*34U%_cNoX}I+#tW?@$Y!>ODWnL2mHI@ z0Dwv6@&#hT>kUAKrT4+dT$#^5&9@40c&0cMyu=S59H!+zViRB5^f3Qd7_f}Jl9o$; z?GYyBLWP}%142@C0c0>mm&8>E-)?YGX@Y)<`a92)ywM1=JfWiM!vP^Vp8zr#1wvHR z<+)3k770c64TgydNs4;Ed%MchcF8F%+b&ixumZt;0j^QUlCEzIt z+-7mOt9ttY{R2EF3M%tCLQrUi6d*GhM*+$VPkDjDuL&cN87~2blvZ#K4xZ@&Wk8-I zV1VX*kRJf3A9$()6rM4h0NxM@OF(f3?YOR1la(jIEW7e{^*%>ad{YEurTROkvJNBuf;&nR-(iH3oQIV$sdUmas~ER z$T=wm;I>3~z&TXOUVp^Kg`bn+SXK-E4QtcNTmfHw9z+q5|98;bPxX*ltc3B{&>^rz zlYswujevz+0HXn;vq`v1a5V4;P$(U9JPA4?@t^?TABRU=dwekMH7AhZTMju~jSdMT z8KHyXO(aY5>(v(*o(2qz%#H>s5+0fd<$RDtmUG#9D`97(REcxCP)6}zs$70CKbTCG z5gvi}_k@x#!Wr^}_@Q;=DG8(GpjwT-L}HA;Z3z8d4-kSeb0pRSVVDz?aL;8DgakoP z02>(eM1qYl`T)wtnn{9=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/cli": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "commander": "^4.0.1", + "convert-source-map": "^2.0.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.2.0", + "make-dir": "^2.1.0", + "slash": "^2.0.0" + }, + "bin": { + "babel": "bin/babel.js", + "babel-external-helpers": "bin/babel-external-helpers.js" + }, + "engines": { + "node": ">=6.9.0" + }, + "optionalDependencies": { + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", + "chokidar": "^3.4.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/cli/node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@babel/cli/node_modules/slash": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "license": "ISC" + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.2", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "license": "MIT", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.1", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-external-helpers": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.11", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.22.20", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.20", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.15", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.15", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.15", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.15", + "@babel/plugin-transform-modules-systemjs": "^7.22.11", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.22.15", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.22.19", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.15", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-typescript": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "license": "MIT" + }, + "node_modules/@babel/runtime": { + "version": "7.23.1", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@calblueprint/eslint-config-react": { + "version": "0.0.3", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", + "eslint": "^8.28.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "prettier": "^2.7.1", + "typescript": "^4.3.0" + } + }, + "node_modules/@calblueprint/prettier-config": { + "version": "0.0.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": "^2.8.4" + } + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.9.1", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.51.0", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.4.2", + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "6.4.2", + "hasInstallScript": true, + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.4.2", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.4.2", + "hasInstallScript": true, + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "13.5.4", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "13.5.2", + "license": "MIT", + "dependencies": { + "glob": "7.1.7" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.5.4", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8-no-fsevents.3", + "license": "MIT", + "optional": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@remix-run/router": { + "version": "1.10.0", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.5.1", + "license": "MIT" + }, + "node_modules/@supabase/functions-js": { + "version": "2.1.5", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/gotrue-js": { + "version": "2.55.0", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.14", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "1.8.4", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.8.0", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14", + "@types/phoenix": "^1.5.4", + "@types/websocket": "^1.0.3", + "websocket": "^1.0.34" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.5.4", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.38.0", + "license": "MIT", + "dependencies": { + "@supabase/functions-js": "^2.1.5", + "@supabase/gotrue-js": "^2.54.2", + "@supabase/node-fetch": "^2.6.14", + "@supabase/postgrest-js": "^1.8.4", + "@supabase/realtime-js": "^2.8.0", + "@supabase/storage-js": "^2.5.4" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.2", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/eslint": { + "version": "8.44.3", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.5", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.13", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.6.3", + "license": "MIT" + }, + "node_modules/@types/phoenix": { + "version": "1.6.2", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.8", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.2.22", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.7", + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.4", + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.5.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stylis": { + "version": "4.2.1", + "license": "MIT" + }, + "node_modules/@types/websocket": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/acorn": { + "version": "8.10.0", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "license": "ISC", + "optional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.7", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "license": "ISC" + }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.8.2", + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.2.1", + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.5", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.4", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2", + "core-js-compat": "^3.32.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.2", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/big.js": { + "version": "5.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/bufferutil": { + "version": "4.0.7", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelize": { + "version": "1.0.1", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001546", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "license": "ISC", + "optional": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.33.0", + "license": "MIT", + "dependencies": { + "browserslist": "^4.22.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "license": "MIT" + }, + "node_modules/d": { + "version": "1.0.1", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "license": "BSD-2-Clause" + }, + "node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.544", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.22.2", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.15", + "license": "MIT", + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.0.1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.51.0", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.51.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + }, + "engines": { + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-next": { + "version": "13.5.2", + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "13.5.2", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "license": "ISC", + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.28.1", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.findlastindex": "^1.2.2", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.8.0", + "has": "^1.0.3", + "is-core-module": "^2.13.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.6", + "object.groupby": "^1.0.0", + "object.values": "^1.1.6", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esniff/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, + "node_modules/espree": { + "version": "9.6.1", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/events": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "license": "ISC" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.15.0", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.3", + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "license": "BSD-2-Clause" + }, + "node_modules/globals": { + "version": "13.23.0", + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "license": "MIT" + }, + "node_modules/has": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "license": "MIT", + "optional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "license": "MIT", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.6", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/next": { + "version": "13.5.4", + "license": "MIT", + "dependencies": { + "@next/env": "13.5.4", + "@swc/helpers": "0.5.2", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.31", + "styled-jsx": "5.1.1", + "watchpack": "2.4.0" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=16.14.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "13.5.4", + "@next/swc-darwin-x64": "13.5.4", + "@next/swc-linux-arm64-gnu": "13.5.4", + "@next/swc-linux-arm64-musl": "13.5.4", + "@next/swc-linux-x64-gnu": "13.5.4", + "@next/swc-linux-x64-musl": "13.5.4", + "@next/swc-win32-arm64-msvc": "13.5.4", + "@next/swc-win32-ia32-msvc": "13.5.4", + "@next/swc-win32-x64-msvc": "13.5.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-google-fonts": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/next-google-fonts/-/next-google-fonts-2.2.0.tgz", + "integrity": "sha512-TCtNp+uu0vof2X8Xfptfw96Unc3zsUekBY2l4g2mGAX+U8QO/yfAaEioGhFCwU05M8NbMgwP5C8V40Vtwp87iQ==", + "deprecated": "As of Next.js 10.2, Google Fonts are automatically optimized! For more info, see https://github.com/joe-bell/next-google-fonts", + "peerDependencies": { + "next": ">= 10.0.7", + "react": ">= 17.0.1", + "react-dom": ">= 17.0.1" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "license": "ISC" + }, + "node_modules/next/node_modules/@next/swc-darwin-x64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", + "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", + "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-arm64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", + "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-x64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", + "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-x64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", + "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", + "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", + "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-win32-x64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", + "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/node-gyp-build": { + "version": "4.6.1", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.7", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/object.hasown": { + "version": "1.1.3", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "license": "MIT", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react": { + "version": "18.2.0", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-feather": { + "version": "2.0.10", + "license": "MIT", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": ">=16.8.6" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "license": "MIT" + }, + "node_modules/react-router": { + "version": "6.17.0", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.10.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.17.0", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.10.0", + "react-router": "6.17.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-toastify": { + "version": "9.1.3", + "license": "MIT", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "license": "MIT", + "optional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "license": "MIT", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/resolve": { + "version": "1.22.6", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.10", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-components": { + "version": "6.0.8", + "license": "MIT", + "dependencies": { + "@babel/cli": "^7.21.0", + "@babel/core": "^7.21.0", + "@babel/helper-module-imports": "^7.18.6", + "@babel/plugin-external-helpers": "^7.18.6", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.7", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@babel/traverse": "^7.21.2", + "@emotion/is-prop-valid": "^1.2.1", + "@emotion/unitless": "^0.8.0", + "@types/stylis": "^4.0.2", + "css-to-react-native": "^3.2.0", + "csstype": "^3.1.2", + "postcss": "^8.4.23", + "shallowequal": "^1.1.0", + "stylis": "^4.3.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "babel-plugin-styled-components": ">= 2", + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "babel-plugin-styled-components": { + "optional": true + } + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/stylis": { + "version": "4.3.0", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.21.0", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "license": "MIT" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "license": "MIT" + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/type": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.10", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "license": "BSD-2-Clause" + }, + "node_modules/webpack": { + "version": "5.88.2", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket": { + "version": "1.0.34", + "license": "Apache-2.0", + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "license": "MIT", + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/yaeti": { + "version": "0.0.6", + "license": "MIT", + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", + "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", + "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", + "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", + "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", + "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", + "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", + "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", + "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..952e86e2 --- /dev/null +++ b/package.json @@ -0,0 +1,49 @@ +{ + "name": "shanti-project", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint:check": "npx eslint .", + "lint:fix": "npx eslint . --fix", + "prettier:check": "npx prettier --check .", + "prettier:fix": "npx prettier --write ." + }, + "dependencies": { + "@fortawesome/fontawesome-free": "^6.4.2", + "@fortawesome/free-solid-svg-icons": "^6.4.2", + "@fortawesome/react-fontawesome": "^0.2.0", + "@supabase/supabase-js": "^2.37.0", + "@types/node": "20.6.3", + "@types/react": "18.2.22", + "@types/react-dom": "18.2.7", + "dotenv": "^16.3.1", + "eslint-config-next": "13.5.2", + "next": "^13.5.4", + "next-google-fonts": "^2.2.0", + "react": "^18.2.0", + "react-dom": "18.2.0", + "react-feather": "^2.0.10", + "react-router-dom": "^6.17.0", + "react-toastify": "^9.1.3", + "styled-components": "^6.0.8" + }, + "devDependencies": { + "@calblueprint/eslint-config-react": "^0.0.3", + "@calblueprint/prettier-config": "^0.0.1", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", + "eslint": "^8.50.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "file-loader": "^6.2.0", + "prettier": "^2.8.8", + "typescript": "^4.9.5" + } +} diff --git a/public/check.svg b/public/check.svg new file mode 100644 index 00000000..dbeb8fb5 --- /dev/null +++ b/public/check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/images/Arrow_Left_MD.png b/public/images/Arrow_Left_MD.png new file mode 100644 index 0000000000000000000000000000000000000000..82ecb97ce358c698110a57cc041eb7eb7baece8c GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^;vmey1|%P7U0DF6I14-?iy0WWg+Z8+Vb&Z8pde#$ zkh>GZx^prwfgF}}M_)$E)e-c@N`~{vajv*C{Z>QLDF)IqVrSshQQ9SL5n5AFd zhUzIYitZjW^*m?lnR_UTMP<0%C~1o=6BWD0uEhN7S+gLc)M{6bjqOqyYps`tEcwf# z`m-~$wrkn_brQvoB$Dl?h`ZDrVtH}ywnXtiZGTP4c2xGgtlX>RnXB*b?pH^Hk)YEYPhCp00i_ I>zopr03&}~kN^Mx literal 0 HcmV?d00001 diff --git a/public/images/Cart.png b/public/images/Cart.png new file mode 100644 index 0000000000000000000000000000000000000000..743667a66018897a35f61195c2e82cb94e7cee69 GIT binary patch literal 1142 zcmV-+1d02JP)z2*;h`%FL@xe;;@2(c=%U2B zE|;sJ8t5|*^swcp_xJaHRuV;!xR3<^3cnLo_(D=g=tS`H^3p@q#Z$owdNMl>9LFi= z^Z63$jZFX8+}ym_+S(eREXf>@G+r*{f1z^f(VYpd>w1s^$LYm&Vk`;#DLk6cjgrg= zY;8%aop{?=64*Omt6yYBK$>5*dM1+sdw9crgc18BGaxdK7jH|`39i6r390PKlu$)< zxxF@Dlu81)BX7?Ot@dH?^8ixe5y&SdVGBJ zS65fB(T`r!c;WA`FTZ4oC6-uXiT?p_92gxI0+R#S`+XTYtpJaYsOV&oS-f}(@q&&A zL{1qu;PGS_8A+1YoD{r1V2-LaU}p4WyRb5^pwZH?%mKC}i4$pT(_Mq%yEssjXn~0b zG~DAAz|$z|?DqEdBsvy~1|`X@g=8!Ee-ZE8YL;Ebt0v}*hWxy$H7(=?dCZ@tuB)hH zkdx=<=PGhr{9hg49W3BjyRi>*pbUhY%zdGsuQ{+5%BBeu<0Ke@rS3UbfB`C)Fq8@v zmH{rl#q$?F`W%`U^yAhtV-v=yQJsjA=vfAO2WEG%Y8Ow9mt7g2B1+>;=$4cQupt`g zb|vA`%as~s!U;OUPHm96VhIwx=sgne zKTvpjt76`Ql4)j{98(17%f*B@yRn^VzA1^MYa5Z)zQjL^-&ec?ST5ECN&o-=07*qo IM6N<$f_%pj?*IS* literal 0 HcmV?d00001 diff --git a/public/images/PAWS.png b/public/images/PAWS.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4e4407d616c98833aa6b4fd98caf9e1a597141 GIT binary patch literal 84860 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 literal 0 HcmV?d00001 diff --git a/public/images/Profile.png b/public/images/Profile.png new file mode 100644 index 0000000000000000000000000000000000000000..3f04c46ff90fb59af2158e90bc72e3d133d386a0 GIT binary patch literal 1154 zcmV-|1bzF7P)&@_Xc09W?i%5wQnNbmk@I23de0*$ItJPpU9(!ntQATJxzPr1N#W9?b zUteF}2hq-Z?<zKOd)cs@LmXyZ=H!&B1lw zdEi3x32(4{FRc^54ZFV!xF8?#2Jf<)*6Hc#DPT#zFN*?t4`U7^xI+J}KE@*r(mc|q z0fc&n*uW-7Q!;K+iJyr>I9Xvy5@tbSfz=%ImAPmxAv{hq0b~(DEyIj1twoEAQg7i* zB@LVj+W$u$=u5-du98}YyW|FJ3wtqN{@Hqj=l=Ee^|?4kVe%x6tw9?k>F3kTB*q}R zF1N*n$kTtr%k)t7`Am<3q7RZ0>Iq5@C1>L&>Vf%L{P6J5_#eT^+*nyz+2q1RkAnUD z`iqoR>j z=3ON|(0xQdc`Jt33QKCeN5+zE!My~k43hV4^ zlIe04sv*v8t89&5P5mXioHaPHH)cLk7<-KT`M`ZU4#f7E)&T!T(HtY>9Z^1lnR94Z zWrg?~u@r%ZcC(|_a1GjNNddeke->FapSquCxW>X{z%=mQ=Fz1+{e~RPY``=K->VFe zIfTY1fi|>!$bOdDOyo)WfLbcsl-qNWH^GMw^08?OQ0JMe&oB@skXVVQAxJi98hF>z z%mDl0nqU)y}gYvzyt%F{1(rl%nvH+_~z!OYn~&>X7=qD>fsc5 zkT@X`g9POHe*;ZBO8{ZRncpyg{%yD65FsL246K32uH=9@u;8q3@C;YmnL?DmC+e>> z-@qtC$pDj+obp8UOqg;GtcZv5ta51my}k(_Gsm!Rfr6*f7y3bRV3HGb7El0ZzYkM8 z(sr6PW^^(z7e|@QyZh>4INcD=BlGun5>HK?Jy`AdaoFxyt1ag}g{Kj%vx UfaF`v5&!@I07*qoM6N<$g58oR>Hq)$ literal 0 HcmV?d00001 diff --git a/public/images/ShantiLogo.png b/public/images/ShantiLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..bcce3127562685ba123833824727fb86f6f2a587 GIT binary patch literal 4473 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 LNkvXXu0mjfS*p3{ literal 0 HcmV?d00001 diff --git a/public/images/profile (1).svg b/public/images/profile (1).svg new file mode 100644 index 00000000..eedf96e6 --- /dev/null +++ b/public/images/profile (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/profile blue version-2.svg b/public/images/profile blue version-2.svg new file mode 100644 index 00000000..86a2ed1c --- /dev/null +++ b/public/images/profile blue version-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/next.svg b/public/next.svg new file mode 100644 index 00000000..5174b28c --- /dev/null +++ b/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/ready.svg b/public/ready.svg new file mode 100644 index 00000000..3e356ae2 --- /dev/null +++ b/public/ready.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/public/right_arrow.svg b/public/right_arrow.svg new file mode 100644 index 00000000..36957c93 --- /dev/null +++ b/public/right_arrow.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 00000000..d2f84222 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/x.svg b/public/x.svg new file mode 100644 index 00000000..495c7fc5 --- /dev/null +++ b/public/x.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/api/supabase/auth/auth.tsx b/src/api/supabase/auth/auth.tsx new file mode 100644 index 00000000..7ea5f70b --- /dev/null +++ b/src/api/supabase/auth/auth.tsx @@ -0,0 +1,28 @@ +/* eslint-disable */ + +import supabase from '../createClient'; + +export const handleSignUp = async (email: string, password: string) => { + const { data, error } = await supabase.auth.signUp({ + email, + password, + }); + console.log(error); +}; + +export const signInWithEmail = async (email: string, password: string) => { + const { data, error } = await supabase.auth.signInWithPassword({ + email, + password, + }); +}; + +export const signOut = async () => { + const { + data: { user }, + } = await supabase.auth.getUser(); + console.log('hi'); + console.log(user); + const { error } = await supabase.auth.signOut(); + console.log(user); +}; diff --git a/src/api/supabase/createClient.tsx b/src/api/supabase/createClient.tsx new file mode 100644 index 00000000..53892337 --- /dev/null +++ b/src/api/supabase/createClient.tsx @@ -0,0 +1,20 @@ +import { createClient } from '@supabase/supabase-js'; +import dotenv from 'dotenv'; + +dotenv.config(); + +if ( + !process.env.NEXT_PUBLIC_SUPABASE_URL || + !process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY +) { + throw new Error( + 'No Supabase environment variables detected, please make sure they are in place!', + ); +} + +const supabase = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY, +); + +export default supabase; diff --git a/src/api/supabase/queries/button_queries.ts b/src/api/supabase/queries/button_queries.ts new file mode 100644 index 00000000..191ce031 --- /dev/null +++ b/src/api/supabase/queries/button_queries.ts @@ -0,0 +1,32 @@ +import { StorefrontButtons } from '../../../schema/schema'; +import supabase from '../createClient'; + +export async function fetchButtonCategories(): Promise { + const { data: buttons, error } = await supabase + .from('storefront_buttons') + .select('*'); + if (error) { + throw new Error(`Error fetching buttons: ${error.message}`); + } + + return buttons; +} + +export async function convertButtonNumberToCategory( + id: string, +): Promise { + const { data: buttonsCategory, error } = await supabase + .from('storefront_buttons') + .select('*') + .eq('id', id) + .single(); + if (error) { + throw new Error(`Error fetching buttons: ${error.message}`); + } + + return buttonsCategory.name; +} + +export async function fetchButton() { + return 0; +} diff --git a/src/api/supabase/queries/cart_queries.ts b/src/api/supabase/queries/cart_queries.ts new file mode 100644 index 00000000..c8062040 --- /dev/null +++ b/src/api/supabase/queries/cart_queries.ts @@ -0,0 +1,263 @@ +import supabase from '../createClient'; + +import { fetchUser } from './user_queries'; +import { Product, ProductWithQuantity } from '../../../schema/schema'; +import { fetchProductByID } from './product_queries'; +import { convertButtonNumberToCategory } from './button_queries'; +// define cart item type +export type CartItem = { + id: number; + product_id: number; + quantity: number; +}; + +/** + * get cart item by id + * @param number - cart item id + * @returns Promise - A CartItem object. + */ +export async function fetchCartItem(cartItemID: number): Promise { + const { data, error } = await supabase + .from('order_product') + .select('*') + .eq('id', cartItemID) + .single(); + + if (error) { + throw new Error(`Error fetching cart item: ${error.message}`); + } + return data; +} + +/** + * get cart items in a user's cart + * @returns Promise - An array of CartItem objects. + */ +export async function fetchCart(): Promise { + const user = await fetchUser(); + + // Check if the user has a cart_id + if (!user.cart_id) { + throw new Error('User does not have a cart.'); + } + + const cartID = user.cart_id; + const { data, error } = await supabase + .from('order') + .select('*') + .match({ id: cartID }) + .limit(1); + + if (error) { + throw new Error(`Error fetching cart: ${error.message}`); + } + const products = data[0].order_product_id_array; + if (products !== null && products !== undefined) { + const productPromises = products.map(async (productID: number) => { + const product = await fetchCartItem(productID); + return product; + }); + const fetchedProducts = await Promise.all(productPromises); + return fetchedProducts; + } + + return [] as CartItem[]; +} + +export async function fetchCartItems(): Promise { + const cart = await fetchCart(); + const productPromises = cart.map(async (item: CartItem) => { + const product = await fetchProductByID(item.product_id); + return product; + }); + const fetchedProducts = await Promise.all(productPromises); + + return fetchedProducts; +} + +/** + * update cart + * @param cartID - cart id + * @param cartIDArray - cart id array + */ +async function updateCart(cartID: number, cartIDArray: number[]) { + await supabase + .from('order') + .update({ order_product_id_array: cartIDArray }) + .match({ id: cartID }); +} + +/** + * add product to cart + * @param productID - product id + * @param quantity - quantity of product + */ +export async function addToCart(productID: number, quantity: number) { + const items = await fetchCart(); + + // check if product is already in cart + + const existingItem = items.find( + item => Number(item.product_id) === Number(productID), + ); + + if (existingItem) { + if (existingItem !== undefined && existingItem !== null) { + const newQuantity = existingItem.quantity + quantity; + await supabase + .from('order_product') + .update({ quantity: newQuantity }) + .match({ id: existingItem.id }); + } + } else { + const { data, error } = await supabase + .from('order_product') + .insert([{ product_id: productID, quantity }]) + .select('*') + .single(); + if (error) { + throw new Error(`Error adding to cart: ${error.message}`); + } + // append to existing cart + const user = await fetchUser(); + const cartID = user.cart_id; + const productIdArray = items.map(item => item.id); + productIdArray.push(data.id); + updateCart(cartID, productIdArray); + } +} + +/** + * decrease quantity of product in cart + * @param productID - product id + * @param quantity - quantity of product + */ +export async function decreaseFromCart(productID: number, quantity: number) { + const items = await fetchCart(); + const existingItem = items.find(item => item.product_id === productID); + if (existingItem) { + const newQuantity = existingItem.quantity - quantity; + if (newQuantity <= 0) { + await supabase + .from('order_product') + .delete() + .match({ id: existingItem.id }) + .select('*') + .single(); + + // remove from existing cart + const user = await fetchUser(); + const cartID = user.cart_id; + const productIdArray = items.map(item => item.id); + const index = productIdArray.indexOf(existingItem.id); + productIdArray.splice(index, 1); + updateCart(cartID, productIdArray); + } else { + await supabase + .from('order_product') + .update({ quantity: newQuantity }) + .eq('id', existingItem.id); + } + } +} + +/** + * remove product from cart + * @param productID - product id + */ +export async function removeCartItem(productID: number) { + decreaseFromCart(productID, Infinity); +} + +/** + * clear cart + */ +export async function clearCart() { + const user = await fetchUser(); + const cartID = user.cart_id; + updateCart(cartID, []); +} + +/** + * @returns the number of items stored within the cart if there is no items then returns 0 + */ + +export async function totalNumberOfItemsInCart(): Promise { + const cart = await fetchCart(); + if (cart.length === 0 || cart === null || cart === null) { + return 0; + } + return cart.reduce((acc, item) => acc + item.quantity, 0); +} + +export async function fetchCartItemsWithQuantity(): Promise< + ProductWithQuantity[] +> { + const cart = await fetchCart(); + const productPromises = cart.map(async (item: CartItem) => { + const product = await fetchProductByID(item.product_id); + return { + name: product.name, + quantity: item.quantity, + photo: product.photo, + id: product.id, + category: await convertButtonNumberToCategory(product.category), + }; + }); + + const fetchedProducts = await Promise.all(productPromises); + + return fetchedProducts; +} + +export async function fetchCartIdFromUser() { + const user = await fetchUser(); + const cartID = user.cart_id; + return cartID; +} +/** + * get cart items in a user's cart by cart_id + * @returns Promise - An array of CartItem objects. + */ +export async function fetchCartById(cartId: string): Promise { + const { data, error } = await supabase + .from('order') + .select('*') + .match({ id: cartId }) + .limit(1); + + if (error) { + throw new Error(`Error fetching cart: ${error.message}`); + } + const products = data[0].order_product_id_array; + if (products !== null && products !== undefined) { + const productPromises = products.map(async (productID: number) => { + const product = await fetchCartItem(productID); + return product; + }); + const fetchedProducts = await Promise.all(productPromises); + return fetchedProducts; + } + + return [] as CartItem[]; +} + +export async function fetchCartItemsWithQuantityByID( + id: string | null, +): Promise { + if (id == null) throw new Error('no cartID'); + const cart = await fetchCartById(id); + const productPromises = cart.map(async (item: CartItem) => { + const product = await fetchProductByID(item.product_id); + return { + name: product.name, + quantity: item.quantity, + photo: product.photo, + id: product.id, + category: await convertButtonNumberToCategory(product.category), + }; + }); + + const fetchedProducts = await Promise.all(productPromises); + return fetchedProducts; +} diff --git a/src/api/supabase/queries/delivery_queries.ts b/src/api/supabase/queries/delivery_queries.ts new file mode 100644 index 00000000..baa88631 --- /dev/null +++ b/src/api/supabase/queries/delivery_queries.ts @@ -0,0 +1,15 @@ +import supabase from '../createClient'; + +export type DeliveryTimes = { + delivery_group: number; + delivery_time: number; +}; + +export async function fetchDeliveryTimes(): Promise { + const { data, error } = await supabase.from('delivery_times').select('*'); + + if (error) { + throw new Error(`Error fetching delivery times: ${error.message}`); + } + return data; +} diff --git a/src/api/supabase/queries/order_queries.ts b/src/api/supabase/queries/order_queries.ts new file mode 100644 index 00000000..e011398d --- /dev/null +++ b/src/api/supabase/queries/order_queries.ts @@ -0,0 +1,272 @@ +/* eslint-disable no-console */ +// + +import { + Order, + OrderProduct, + OrderStatus, + Product, +} from '../../../schema/schema'; +import { fetchUser } from './user_queries'; +import { fetchProductByID } from './product_queries'; +import supabase from '../createClient'; + +/** + * Fetches all orders from the database. + * @returns Promise - An array of Order objects. + */ +export async function getOrderById(orderId: number): Promise { + const { data: order, error } = await supabase + .from('order') // Update to the "Order" table + .select('*') + .eq('id', orderId) + .single(); + if (error) { + throw new Error(`Error fetching order: ${error.message}`); + } + return order; +} + +/** + * creates a new order for the user + */ +export async function createOrder() { + const user = await fetchUser(); + + const { data: order, error } = await supabase + .from('order') + .insert({ user_id: user.id }) + .select('*') + .single(); + if (error) { + throw new Error(`Error creating order: ${error.message}`); + } + + await supabase + .from('profiles') + .update({ cart_id: order.id }) + .match({ id: user.id }); +} + +/** + * gets all orders by user id and sorted it by creation data + * @param Order[] - An array of Order objects. + * @returns Promise - An array of Order objects. + */ +function sortOrdersByCreated(orders: Order[]): Order[] { + return orders.sort( + (a, b) => + new Date(b.created_at).getTime() - new Date(a.created_at).getTime(), + ); +} + +/** + * gets all orders by user id and sorted it by creation data + * @param Order[] - An array of Order objects. + * @returns Promise - An array of Order objects. + */ +export async function fetchOrdersByUser(): Promise { + const user = await fetchUser(); + const userId = user.id; + const { data, error } = await supabase + .from('order') + .select('*') + .eq('user_id', userId) + .neq('order_status', 'In Progress'); + + if (error) { + throw new Error(`Error fetching orders for user: ${error.message}`); + } + + return data; +} + +/** + * gets all orders by user id and sorted it by creation data + * @param Order[] - An array of Order objects. + * @returns Promise - An array of Order objects. + */ +export async function fetchOrdersByUserIdSorted(): Promise { + const orders = await fetchOrdersByUser(); + return sortOrdersByCreated(orders); +} + +/** + * gets all orders by user id and sorted it by creation data and get the first n orders + * @param Order[] - An array of Order objects. + * @returns Promise - An array of Order objects. + */ +export async function fetchNOrdersByUserIdSorted(n: number): Promise { + const orders = await fetchOrdersByUser(); + return sortOrdersByCreated(orders).slice(0, n); +} + +export async function fetchOrderIdsByUserIdSorted(): Promise { + const ordersProm = await fetchOrdersByUser(); + const orders = sortOrdersByCreated(ordersProm); + return orders.map(order => order.id); +} + +export async function fetchOrderProductById( + productId: number, +): Promise { + const { data: orderProduct, error } = await supabase + .from('order_product') + .select('*') + .eq('id', productId) + .single(); + if (error) { + throw new Error(`Error fetching order product: ${error.message}`); + } + return orderProduct; +} + +export async function fetchProductFromOrderProduct( + orderProductId: number, +): Promise { + const orderProduct = await fetchOrderProductById(orderProductId); + const product = await fetchProductByID(orderProduct.product_id); + return product; +} + +export async function fetchProductsFromOrder( + orderId: number, +): Promise { + const order = await getOrderById(orderId); + const products = order.order_product_id_array; + + const productPromises = products.map(async (productID: number) => { + const product = await fetchProductFromOrderProduct(productID); + return product; + }); + const fetchedProducts = await Promise.all(productPromises); + + return fetchedProducts; +} + +export async function fetchProductWithQuantityById( + productId: number, +): Promise { + const { data: orderProduct, error } = await supabase + .from('product') + .select('*') + .eq('id', productId) + .single(); + if (error) { + throw new Error(`Error fetching order product: ${error.message}`); + } + return orderProduct; +} + +export async function fetchOrderProductsbyOrderId( + orderId: number, +): Promise { + const order = await getOrderById(orderId); + const orderProductIds = order.order_product_id_array; + + const newOrderProducts = await Promise.all( + orderProductIds.map(orderProductId => + fetchOrderProductById(orderProductId), + ), + ); + + const orderProducts = await Promise.all( + newOrderProducts.map(async orderProduct => + fetchProductWithQuantityById(orderProduct.product_id), + ), + ); + + return orderProducts; +} + +/** + * gets all orders by user id and sorted it by creation data + * @param Order[] - An array of Order objects. + * @returns Promise - An array of Order objects. + */ +export async function fetchCurrentOrdersByUser(): Promise { + const user = await fetchUser(); + const userCartId = user.cart_id; + const { data, error } = await supabase + .from('order') + .select('*') + .eq('id', userCartId); + + if (error) { + throw new Error(`Error fetching orders for user: ${error.message}`); + } + + return data; +} + +export async function fetchRecentOrderProducts(): Promise { + const order = await fetchNOrdersByUserIdSorted(1); + const orderProductIds = order[0].order_product_id_array; + + const orderProducts = await Promise.all( + orderProductIds.map(async orderProductId => { + try { + const orderProduct = await fetchOrderProductById(orderProductId); + return orderProduct; + } catch (error) { + throw new Error(`Error fetching order product array.`); + } + }), + ); + + return orderProducts; +} + +export async function updateOrderPickupId(orderId: number, pickupId: number) { + await supabase + .from('order') + .update({ pickup_time_id: pickupId }) + .eq('id', orderId); +} + +export async function updateCartPickupId(pickupId: number) { + const user = await fetchUser(); + const cartId = user.cart_id; + await supabase + .from('order') + .update({ pickup_time_id: pickupId }) + .eq('id', cartId); +} + +/* Update the status of an order */ +export async function updateOrderStatus( + orderId: number, + orderStatus: OrderStatus, +) { + await supabase + .from('order') + .update({ order_status: orderStatus }) + .eq('id', orderId); +} +/** + * Gets user's most recent order + * @returns Promise - The most recent Order object, or throws an error if no order is found. + */ +export async function fetchCartIdFromUserfetchMostRecentOrderByUser(): Promise { + const user = await fetchUser(); + const userId = user.id; + const { data, error } = await supabase + .from('order') + .select('*') + .eq('user_id', userId) + .order('created_at', { ascending: false }) // Order by creation date in descending order + .limit(1); // Limit to only one order + + if (error) { + throw new Error( + `Error fetching most recent order for user: ${error.message}`, + ); + } + + if (data.length === 0) { + throw new Error('No orders found for the user.'); + } + + // Return the first order in the data array + return data[0]; +} diff --git a/src/api/supabase/queries/pickup_queries.ts b/src/api/supabase/queries/pickup_queries.ts new file mode 100644 index 00000000..fd56dc46 --- /dev/null +++ b/src/api/supabase/queries/pickup_queries.ts @@ -0,0 +1,69 @@ +import { Pickup } from '../../../schema/schema'; +import supabase from '../createClient'; + +/** + * + * @returns all the pickup times from the database + */ +export async function fetchPickupData(): Promise { + const { data: pickupTimes, error } = await supabase + .from('pickup_times') + .select('*'); + + if (error) { + throw new Error(`Error fetching pickup times: ${error.message}`); + } + return pickupTimes || []; +} + +/** + * + * @param pickupID + * @returns fetches a single pickup time by its ID + */ +export async function fetchPickupTimesByID(pickupID: number): Promise { + const { data: pickupTimes, error } = await supabase + .from('pickup_times') + .select('*') + .eq('id', pickupID) + .single(); + + if (error) { + throw new Error(`Error fetching pickup times: ${error.message}`); + } + + return pickupTimes; +} + +/** + * + * @returns most recevnt pickup + */ +export async function fetchRecentPickupTimes(): Promise { + const { data: getTimes, error } = await supabase + .from('pickup_times') + .select('*') + .limit(2); + + if (error) { + throw new Error(`Error fetching pickup times: ${error.message}`); + } + return getTimes; +} + +/** + * + * @returns 2 most recent pickup times + */ +export async function fetchNRecentPickupTimes(n: number): Promise { + const { data: getTimes, error } = await supabase + .from('pickup_times') + .select('*') + .order('start_time', { ascending: true }) + .limit(n); + + if (error) { + throw new Error(`Error fetching pickup times: ${error.message}`); + } + return getTimes; +} diff --git a/src/api/supabase/queries/product_queries.ts b/src/api/supabase/queries/product_queries.ts new file mode 100644 index 00000000..67396986 --- /dev/null +++ b/src/api/supabase/queries/product_queries.ts @@ -0,0 +1,144 @@ +import { Product, StorefrontButtons } from '../../../schema/schema'; +import supabase from '../createClient'; +import { fetchUser } from './user_queries'; + +/** + * Fetches all products from the database. + * @returns Promise - An array of Product objects. + */ +export async function fetchProducts(): Promise { + const { data: products, error } = await supabase.from('product').select('*'); + if (error) { + throw new Error(`Error fetching products: ${error.message}`); + } + + return products; +} + +export async function fetchUnprescribedProducts(): Promise { + const { data: products, error } = await supabase + .from('product') + .select('*') + .eq('prescribed', false); + if (error) { + throw new Error(`Error fetching products: ${error.message}`); + } + return products; +} + +export async function fetchUserProducts(): Promise { + const products = await fetchUnprescribedProducts(); + const user = await fetchUser(); + + const { data: prescribed, error } = await supabase + .from('product') + .select('*') + .eq('prescribed', true); + if (error) { + throw new Error(`Error fetching products: ${error.message}`); + } + + for (let i = 0; i < prescribed.length; i += 1) { + if (prescribed[i].id) { + if (user.pet_prescription.includes(prescribed[i].id)) { + products.push(prescribed[i]); + } + } + } + + return products; +} + +/** + * Fetches a single product by its ID. + * @param productId - The unique identifier for the product. + * @returns Promise - The Product object. + */ +export async function fetchProductByID(productId: number): Promise { + const { data: product, error } = await supabase + .from('product') + .select('*') + .eq('id', productId) + .single(); + + if (error) { + throw new Error(`Error fetching product: ${error.message}`); + } + + return product; +} + +/** + * @param productType + * @returns the products that match the productType + */ +export async function filterProduct(productType: string): Promise { + const { data: products, error } = await supabase + .from('product') + .select('*') + .eq('category', productType); + + if (error) { + throw new Error(`Error fetching products: ${error.message}`); + } + + return products; +} + +export async function convertCategoryToNumber( + productType: string, +): Promise { + const { data: buttonVal, error } = await supabase + .from('storefront_buttons') + .select('*') + .eq('name', productType) + .single(); + + if (error) { + throw new Error(`Error fetching products: ${error.message}`); + } + return buttonVal.id; +} + +export async function fetchUnprescribedCategory( + productType: string, +): Promise { + const productTypeConverted = await convertCategoryToNumber(productType); + + const { data: products, error } = await supabase + .from('product') + .select('*') + .eq('prescribed', false) + .eq('category', productTypeConverted); + if (error) { + throw new Error(`Error fetching products: ${error.message}`); + } + return products; +} + +export async function filterUserProducts( + productType: string, +): Promise { + const products = await fetchUnprescribedCategory(productType); + const user = await fetchUser(); + + const { data: prescribed, error } = await supabase + .from('product') + .select('*') + .eq('prescribed', true) + .eq('category', productType); + + if (error) { + throw new Error(`Error fetching products: ${error.message}`); + } + + for (let i = 0; i < prescribed.length; i += 1) { + if (prescribed[i].id) { + if (user.pet_prescription.includes(prescribed[i].id)) { + products.push(prescribed[i]); + } + } + } + + return products; +} diff --git a/src/api/supabase/queries/tests/order_test.ts b/src/api/supabase/queries/tests/order_test.ts new file mode 100644 index 00000000..c1f2ace7 --- /dev/null +++ b/src/api/supabase/queries/tests/order_test.ts @@ -0,0 +1,7 @@ +export function tester1() { + return 0; +} + +export function tester2() { + return 0; +} diff --git a/src/api/supabase/queries/tests/pickup_test.ts b/src/api/supabase/queries/tests/pickup_test.ts new file mode 100644 index 00000000..c1f2ace7 --- /dev/null +++ b/src/api/supabase/queries/tests/pickup_test.ts @@ -0,0 +1,7 @@ +export function tester1() { + return 0; +} + +export function tester2() { + return 0; +} diff --git a/src/api/supabase/queries/tests/product_test.ts b/src/api/supabase/queries/tests/product_test.ts new file mode 100644 index 00000000..98bc9637 --- /dev/null +++ b/src/api/supabase/queries/tests/product_test.ts @@ -0,0 +1,25 @@ +/* eslint-disable no-console */ +// + +import { fetchProducts, fetchProductByID } from '../product_queries'; // Replace './your-module' with the actual path to your module + +// Test fetching all products +export async function testFetchProducts() { + try { + const result = await fetchProducts(); + console.log('Fetch Products Result:', result); + } catch (error) { + console.error('Test Fetch Products Error:', error); + } +} + +// Test fetching a product by name +export async function testFetchProductByName() { + const productId = 1; // Replace with a valid product name + try { + const result = await fetchProductByID(productId); + console.log('Fetch Product by Name Result:', result); + } catch (error) { + console.error('Test Fetch Product by Name Error:', error); + } +} diff --git a/src/api/supabase/queries/tests/user_test.ts b/src/api/supabase/queries/tests/user_test.ts new file mode 100644 index 00000000..c1f2ace7 --- /dev/null +++ b/src/api/supabase/queries/tests/user_test.ts @@ -0,0 +1,7 @@ +export function tester1() { + return 0; +} + +export function tester2() { + return 0; +} diff --git a/src/api/supabase/queries/user_queries.ts b/src/api/supabase/queries/user_queries.ts new file mode 100644 index 00000000..6a6c75a8 --- /dev/null +++ b/src/api/supabase/queries/user_queries.ts @@ -0,0 +1,157 @@ +import supabase from '../createClient'; +import { User, Product } from '../../../schema/schema'; +import { fetchProductByID } from './product_queries'; + +/** + * fetchUser is a function that fetches the user data from the database and returns the user object. + * @returns a user object + */ +export async function fetchUser(): Promise { + const { + data: { session }, + error, + } = await supabase.auth.getSession(); + + if (error) { + throw new Error(`Error fetching session: ${error.message}`); + } + + if (!session) { + throw new Error(`Session is null`); + } + + const { user } = session; + + if (user !== null) { + const { data, error: error1 } = await supabase + .from('profiles') + .select() + .eq('id', user.id) + .single(); + + if (error1) { + throw new Error(`Error fetching user: ${error1.message}`); + } + + return data as User; + } + + throw new Error('User is null'); +} + +/** + * fetchUserByUUID is a function that fetches the user data from the database and returns the user object. + * @param uuid: a string that is the user's uuid + * @returns a user object + */ +export async function fetchUserByUUID(uuid: string) { + try { + const { data: user, error } = await supabase + .from('profiles') + .select('*') + .eq('id', uuid) + .single(); + + if (error) { + throw new Error(`Error fetching user data: ${error.message}`); + } + + return user; + } catch (error) { + throw new Error(`Error`); + throw error; + } +} + +/** + * addOrRemoveProductFromFavorite is a function that adds or removes from the user's profiles -> fav_items column based on the state of the heart button. + * @param product: product object to add/remove to user's favorites + * @param isFav: a boolean tracking whether to remove an item from user's favorites + */ + +export async function addOrRemoveProductFromFavorite( + product: Product, + isFav: boolean, +) { + const user = await fetchUser(); + + const favItems = user.fav_items; + + const productID = product.id; + + if (isFav) { + favItems.push(productID); + } else { + const index = favItems.indexOf(productID); + favItems.splice(index, 1); + } + + await supabase + .from('profiles') + .update({ fav_items: favItems }) + .match({ id: user.id }); +} + +/** + * arrayOfFavorites grabs the users favorite items from profiles->fav_items where each fav_item is being tracked by the product_id stored as a string and matches those product_id to the proper product object and stores the product object in an array. + * @returns an array of product objects + */ + +export async function arrayOfFavorites(): Promise { + const user = await fetchUser(); + const favItems = user.fav_items; + if (favItems.length === 0) { + return []; + } + const arrayOfProducts = await Promise.all( + favItems.map(item => fetchProductByID(item)), + ); + + return arrayOfProducts; +} + +/** + * fetchUserAddress: Get's a user's address based on their UUID + * @param uuid: String containing the uuid of the user + */ +export async function fetchUserAddress(uuid: string) { + try { + const { data: user, error } = await supabase + .from('address') + .select('*') + .eq('user_id', uuid) + .single(); + + if (error) { + throw new Error(`Error fetching user data: ${error.message}`); + } + + return user; + } catch (error) { + throw new Error(`Error:`); + } +} + +/** + * fetchUserAddress: Get's a user's address based on their UUID + * @param uuid: String containing the uuid of the user + */ +export async function fetchCurrentUserAddress() { + try { + const user = await fetchUser(); + const { data: address, error } = await supabase + .from('address') + .select('*') + .eq('user_id', user.id) + .limit(1) + .single(); + + if (error) { + console.error('Error fetching user data:', error); + } + return address; + } catch (error) { + console.error('Error:', error); + throw error; + } +} diff --git a/src/app/[productId]/Buttons.tsx b/src/app/[productId]/Buttons.tsx new file mode 100644 index 00000000..9cc8d802 --- /dev/null +++ b/src/app/[productId]/Buttons.tsx @@ -0,0 +1,53 @@ +import React, { useState } from 'react'; +import { toast } from 'react-toastify'; +import { Plus, Minus } from 'react-feather'; +import { Body1Bold } from '@/styles/fonts'; +import { + ButtonsWrapper, + AddToCartButton, + QuantityButton, + PlusMinusButton, +} from './styles'; + +import { addToCart } from '../../api/supabase/queries/cart_queries'; + +export default function Buttons(props: { productNumber: number }) { + const [quantity, setQuantity] = useState(1); + const { productNumber } = props; + + const increaseQuantity = () => { + setQuantity(quantity + 1); + }; + + const decreaseQuantity = () => { + if (quantity > 1) { + setQuantity(quantity - 1); + } + }; + + // used hyphen instead of dash for display + const changeCart = () => { + addToCart(productNumber, quantity); + if (quantity <= 1) { + toast(`you have added ${quantity} item to the cart!`); + } else { + toast(`you have added ${quantity} items to the cart!`); + } + }; + + return ( + + + + + + {quantity} + + + + + + Add to cart + + ); +} diff --git a/src/app/[productId]/page.tsx b/src/app/[productId]/page.tsx new file mode 100644 index 00000000..55cd995a --- /dev/null +++ b/src/app/[productId]/page.tsx @@ -0,0 +1,114 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { Body1, Heading1, Body2Light, Body2Bold, Body3 } from '@/styles/fonts'; +import { + fetchProductByID, + fetchUserProducts, +} from '../../api/supabase/queries/product_queries'; +import BackButton from '../../components/BackButton/BackButton'; +import 'react-toastify/dist/ReactToastify.css'; + +import { + ImageContainer, + TextContainer, + DescriptionContainer, + ToastPopUP, + Fullscreen, + LeftColumnDiv, + FavoritePopup, + HeartContainer, + HeartIcon, + TopRightContainer, +} from './styles'; +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; +import NavBar from '../../components/NavBarFolder/NavBar'; +import { Product } from '../../schema/schema'; +import Buttons from './Buttons'; + +export default function ItemDisplay({ + params, +}: { + params: { productId: number }; +}) { + const [Item, setItem] = useState(); + const [IsFavorite, setIsFavorite] = useState(false); + const [FilteredProducts, setFilteredProducts] = useState([]); + + useEffect(() => { + async function fetchProducts() { + try { + const response = await fetchProductByID(params.productId); + response.category = await convertButtonNumberToCategory( + response.category, + ); + const data = (await fetchUserProducts()) as Product[]; + + setIsFavorite(!!data.find(item => item.id === params.productId)); + if (response) { + setItem(response); + setFilteredProducts(data); + } + } catch (error) { + // console.error(error); + } + } + + fetchProducts(); + }, [params.productId]); + + async function handleFavorite() { + await addOrRemoveProductFromFavorite( + await fetchProductByID(params.productId), + !IsFavorite, + ); + setIsFavorite(!IsFavorite); + } + + return ( + + + + + + + + + {Item?.name} + + + + + {Item?.name} + handleFavorite()}> + + + {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} + + + + + + + Category: {Item?.category} + + + Product Details: + + {Item?.description} + + + + + ); +} diff --git a/src/app/[productId]/styles.ts b/src/app/[productId]/styles.ts new file mode 100644 index 00000000..285c5f76 --- /dev/null +++ b/src/app/[productId]/styles.ts @@ -0,0 +1,140 @@ +import styled from 'styled-components'; +import { ToastContainer } from 'react-toastify'; +import { Body3 } from '@/styles/fonts'; +import { Heart } from 'react-feather'; +import COLORS from '../../styles/colors'; + +export const LeftColumnDiv = styled.div` + display: flex; + flex-direction: column; + gap: 25px; +`; + +export const DescriptionContainer = styled.div` + display: flex; + margin-top: 50px; + width: 1440px; + height: 400px; + justify-content: space-around; + align-self: center; + justify-self: center; +`; + +export const TopRightContainer = styled.div` + display: flex; + justify-content: space-between; + width: 440px; +`; + +export const ImageContainer = styled.div` + width: 500px; + height: 500px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + background-color: ${COLORS.lightGrey}; +`; + +export const TextContainer = styled.div` + width: 440px; + height: 350px; + margin-top: 41px; +`; + +export const ButtonsWrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + width: 450px; + height: 50px; + margin-top: 40px; +`; + +export const QuantityButton = styled.div` + display: flex; + justify-content: space-evenly; + align-items: center; + width: 165px; + height: 50px; + border-radius: 8px; + background-color: ${COLORS.white}; + border: 2px solid ${COLORS.navy}; + color: ${COLORS.navy}; +`; + +export const PlusMinusButton = styled.button` + width: 25px; + height: 25px; + align-items: center; + justify-content: center; + background-color: transparent; + border-color: transparent; + font-size: 20px; + color: ${COLORS.navy}; +`; + +export const AddToCartButton = styled.button` + width: 265px; + height: 50px; + border-radius: 8px; + background-color: ${COLORS.navy}; + font-family: 'Public Sans', sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; + color: ${COLORS.white}; + border-color: transparent; +`; + +export const HeartIcon = styled(Heart)<{ $favorited: boolean }>` + width: 30px; + height: 30px; + color: ${props => (props.$favorited ? COLORS.marineBlue : COLORS.black)}; + fill: ${props => (props.$favorited ? COLORS.marineBlue : 'none')}; + position: relative; +`; + +export const HeartContainer = styled.button` + right: 16px; + top: 16px; + background-color: transparent; + border: none; + cursor: pointer; +`; + +export const FavoritePopup = styled.div` + position: absolute; + visibility: hidden; + width: 150px; + border-radius: 8px; + padding: 8px; + // Find better way to refactor this, it shouldn't need a calc + transform: translate(calc(-50% + 15px), -40px); + z-index: 1; + + color: ${COLORS.black}; + background: ${COLORS.lightPeriwinkle}; + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + + ${Body3} { + display: inline; + } + + ${HeartContainer}:hover & { + visibility: visible; + } +`; + +export const ToastPopUP = styled(ToastContainer)` + position: fixed; + z-index: 100; + transform: translatey(90px); +`; + +export const Fullscreen = styled.div` + width: 100%; + height: 100%; + display: grid; +`; diff --git a/src/app/cart/Buttons.tsx b/src/app/cart/Buttons.tsx new file mode 100644 index 00000000..e06950e1 --- /dev/null +++ b/src/app/cart/Buttons.tsx @@ -0,0 +1,74 @@ +import React from 'react'; + +import { QuantityButton, PlusMinusButton } from './styles'; + +import { + decreaseFromCart, + addToCart, +} from '../../api/supabase/queries/cart_queries'; + +import { ProductWithQuantity } from '../../schema/schema'; + +export default function Buttons(props: { + productNumber: number; + quantity: number; + setNumberOfItems: (count: number) => void; + numberOfItems: number; + count: number; + setCount: (count: number) => void; + cart: ProductWithQuantity[]; + setCart: (category: ProductWithQuantity[]) => void; +}) { + const { + productNumber, + + setNumberOfItems, + numberOfItems, + count, + setCount, + cart, + setCart, + } = props; + + const increaseQuantity = () => { + setCount(count + 1); + addToCart(productNumber, 1); + setNumberOfItems(numberOfItems + 1); + const indexOfItem = cart.findIndex(item => item.id === productNumber); + cart[indexOfItem].quantity += 1; + setCart(cart); + }; + + const decreaseQuantity = () => { + if (count > 1) { + setCount(count - 1); + decreaseFromCart(productNumber, 1); + setNumberOfItems(numberOfItems - 1); + const indexOfItem = cart.findIndex(item => item.id === productNumber); + cart[indexOfItem].quantity -= 1; + setCart(cart); + } + }; + + // used hyphen instead of dash for display + + return ( + + + – + + {count} + + + + + + ); +} diff --git a/src/app/cart/cartItem.tsx b/src/app/cart/cartItem.tsx new file mode 100644 index 00000000..8d461e89 --- /dev/null +++ b/src/app/cart/cartItem.tsx @@ -0,0 +1,69 @@ +'use client'; + +import { useState } from 'react'; +import { Body2, Heading4Bold } from '@/styles/fonts'; +import { removeCartItem } from '../../api/supabase/queries/cart_queries'; +import { + FavoriteDiv, + TrashIcon, + TransparentButton, + LabelBox, + ImageBackground, + CategorySpacing, +} from './styles'; + +import Buttons from './Buttons'; + +import { ProductWithQuantity } from '../../schema/schema'; + +export default function CartItem(props: { + cartItemProduct: ProductWithQuantity; + cart: ProductWithQuantity[]; + setCart: (category: ProductWithQuantity[]) => void; + setNumberOfItems: (count: number) => void; + numberOfItems: number; +}) { + const { cartItemProduct, setCart, cart, setNumberOfItems, numberOfItems } = + props; + const [count, setCount] = useState(cartItemProduct.quantity); + async function removeProduct() { + setNumberOfItems(numberOfItems - count); + + const tempCart = cart.filter( + cartItem => cartItem.id !== cartItemProduct.id, + ) as ProductWithQuantity[]; + setCart(tempCart); + removeCartItem(cartItemProduct.id); + } + + return ( + + + {cartItemProduct.name} + + + {cartItemProduct.name} + + Category: {cartItemProduct.category} + + + + removeProduct()}> + + + + ); +} diff --git a/src/app/cart/page.tsx b/src/app/cart/page.tsx new file mode 100644 index 00000000..21be107b --- /dev/null +++ b/src/app/cart/page.tsx @@ -0,0 +1,91 @@ +'use client'; + +import { useRouter } from 'next/navigation'; +import { useState, useEffect } from 'react'; +import { fetchUser } from '@/api/supabase/queries/user_queries'; +import { Heading1 } from '@/styles/fonts'; +import BackButton from '../../components/BackButton/BackButton'; + +import OrderSummary from '../../components/OrderSummaryFolder/OrderSummary'; + +import { + fetchCartItemsWithQuantity, + totalNumberOfItemsInCart, +} from '../../api/supabase/queries/cart_queries'; +import CartItem from './cartItem'; +import NavBar from '../../components/NavBarFolder/NavBar'; +import { + CartItemsDiv, + PageDiv, + CheckoutButton, + LeftColumnDiv, + RightColumnDiv, + ContentDiv, + OrderSumSectionSpacing, +} from './styles'; + +import { ProductWithQuantity } from '../../schema/schema'; + +export default function OrderPage() { + const [numberOfItems, setNumberOfItems] = useState(0); + const [cart, setCart] = useState([]); + const [deliveryEnabled, setDeliveryEnabled] = useState(false); + const router = useRouter(); + useEffect(() => { + async function fetchProducts() { + setNumberOfItems(await totalNumberOfItemsInCart()); + setCart(await fetchCartItemsWithQuantity()); + const data = await fetchUser(); + setDeliveryEnabled(data.delivery_allowed); + } + + fetchProducts(); + }, []); + + const checkDelivery = () => { + if (deliveryEnabled) { + router.push('/delivery'); + } else { + router.push('/pickup'); + } + }; + + return ( + + +
+ +
+ + + + Cart + + {cart.map(cartItem => ( + + ))} + + + + + + checkDelivery()} + disabled={numberOfItems === 0} + > + Check Out + + + + +
+ ); +} diff --git a/src/app/cart/styles.tsx b/src/app/cart/styles.tsx new file mode 100644 index 00000000..ee956f99 --- /dev/null +++ b/src/app/cart/styles.tsx @@ -0,0 +1,383 @@ +import styled from 'styled-components'; + +import { Trash2 } from 'react-feather'; +import COLORS from '../../styles/colors'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import Footer from '../../components/FooterFolder/Footer'; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: center; +`; + +export const ImageBackground = styled.div` + width: 200px; + height: 200px; + background-color: ${COLORS.lightGrey}; + display: flex; + justify-content: center; + align-items: center; +`; + +export const CartItemsDiv = styled.div` + display: flex; + flex-direction: column; + align-items: center; + border-radius: 10px; + overflow: auto; + gap: 32px; + margin-top: 20px; +`; + +export const ImageDiv = styled.div` + width: 30px; + height: 30px; + color: ${COLORS.black}; +`; + +export const BackDiv = styled.button` + display: flex; + flex-direction: row; + align: center; + color: black; + background-color: transparent; + border: transparent; + margin-bottom: 25px; + margin-top: 25px; +`; + +export const OutterBox = styled.div` + width: 900px; + margin-left: 300px; +`; + +export const Backtext = styled.p` + padding-top: 5px; +`; + +export const TrashIcon = styled(Trash2)` + width: 30px; + height: 30px; + color: navy; + margin-right: 30px; + margin-left: 50px; + margin-top: 28px; +`; + +export const FooterMoved = styled(Footer)` + transform: translateY(300px); +`; + +export const TransparentButton = styled.button` + background-color: transparent; + border: transparent; + margin-left: 40px; + margin-bottom: 25px; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: relative; +`; + +export const ButtonsWrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + width: 200px; + height: 50px; + margin-top: 20px; + padding: 30px; +`; + +export const QuantityButton = styled.div` + display: flex; + justify-content: space-evenly; + align-items: center; + width: 165px; + height: 50px; + border-radius: 8px; + font-size: 18px; + font-weight: bold; + background-color: ${COLORS.white}; + border: 2px solid ${COLORS.navy}; + color: ${COLORS.navy}; + cursor: pointer; + margin-left: 200px; +`; + +export const PlusMinusButton = styled.button` + width: 25px; + height: 25px; + align-items: center; + justify-content: center; + background-color: transparent; + border-color: transparent; + font-size: 20px; + color: ${COLORS.navy}; +`; + +export const Label = styled.p` + margin-top: 20px; +`; + +export const LabelBox = styled.div` + width: 150px; + margin-left: 50px; +`; + +export const ContentDiv = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + padding-left: 50px; + background-color: ${COLORS.offWhite}; +`; + +export const BackButtonDiv1 = styled.div` + display: flex; + flex-direction: row; + gap: 200px; + margin-bottom: 55px; + text-align: left; + width: 800px; + padding-left: 40px; + padding-right: 40px; +`; + +export const Wrapper = styled.div` + min-height: 100%; /*or 100vh */ + position: relative; + background: var(--Light-Periwinkle, #f4f7ff); + justify-content: space-evenly; + align-items: center; + padding-top: 25px; + padding-bottom: 25px; + padding-left: 20px; + gap: 20px; +`; + +export const OrderSummaryDiv = styled.div` + overflow: auto; + width: 350px; + height: 300px; + padding: 20px; +`; + +export const ItemSummaryDiv = styled.div` + display: flex; + flex-direction: row; + margin-bottom: 20px; + justify-content: space-between; +`; + +export const OrderTotalDiv = styled.div` + height: 50px; + padding-top: 10px; + width: 350px; + padding-left: 0px; + border-top: 1px black solid; + display: flex; + flex-flow: row; + justify-content: space-between; +`; + +export const LeftColumnDiv1 = styled.div` + display: flex; + flex-flow: column; + gap: 16px; +`; + +export const CheckoutButton1 = styled.button` + background: #1b3679; + + height: 40px; + margin-top: 20px; + + border: none; + border-radius: 5px; + + color: var(--White, #fff); + text-align: center; + font-family: 'Public Sans', sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const Qty = styled.p` + width: 100%; + padding-left: 290px; +`; + +export const RightColumnDiv1 = styled.div` + display: flex; + flex-flow: column; +`; + +export const WhiteBackgroundDiv = styled.div` + border-radius: 8px; + background: var(--White, #fff); + height: 430px; + width: 350px; + padding-top: 20px; + + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; + +export const HeaderShiftRight = styled.h2` + margin-right: 30px; +`; + +export const PShiftRight = styled.p` + margin-right: 30px; +`; + +export const HeaderShiftLeft = styled.h2` + margin-left: 15px; +`; + +export const PShiftLeft = styled.p` + margin-left: 15px; +`; + +export const PageDiv = styled.div` + height: auto; + width: 100%; + display: flex; + flex-direction: column; + + background-color: ${COLORS.offWhite}; +`; + +export const LeftColumnDiv = styled.div` + flex: 1; + padding-right: 20px; + margin-top: 20px; +`; + +export const InformationText = styled.div` + width: 730px; + height: 50px; + border-radius: 4px; + margin-top: 14px; + margin-bottom: 14px; + border: 1px solid ${COLORS.neutralGrey}; + background: ${COLORS.lightGrey}; + display: flex; /* Use flexbox */ + align-items: center; /* Center vertically */ + font-size: 20px; + font-style: normal; + font-weight: 400; + line-height: normal; + padding-left: 20px; +`; + +export const DeliveryContainer = styled.div` + margin-left: 80px; + margin-right: 80px; + margin-bottom: 80px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; +`; + +export const Container = styled.div` + display: flex; + flex-direction: col; +`; + +export const InformationContainer = styled.div` + width: 100%; + height: 100%; + margin-left: 25px; +`; + +export const OutterDiv = styled.div` + display: flex; + flex-direction: column; +`; + +export const OrderButton = styled.button` + margin-top: 26px; + width: 350px; + height: 50px; + flex-shrink: 0; + align-items: center; + background: ${COLORS.navy}; + border-radius: 8px; + color: ${COLORS.white}; + font-size: 20px; + font-family: 'Public Sans', sans-serif; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const OrderSummary = styled.div` + width: 350px; + height: 360px; + border-radius: 8px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.15); + align-items: center; +`; + +export const OrderContainer = styled.div` + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: end; + justify-content: center; +`; + +export const RightColumnDiv = styled.div` + flex: 1; + margin-top: 30px; + padding-left: 20px; +`; + +export const Heading = styled.h1` + font-family: 'Public Sans', sans-serif; + color: black; + margin-bottom: 20px; + font-size: 30px; +`; + +export const BackButtonDiv = styled.div` + display: flex; + flex-direction: row; + text-align: left; + width: 800px; + margin-left: 110px; + margin-bottom: 40px; +`; + +export const CheckoutButton = styled.button` + width: 350px; + background: #1b3679; + color: white; + border: none; + border-radius: 5px; + padding: 10px 20px; + font-size: 18px; + cursor: pointer; + margin-top: 20px; + + &:hover { + background: #0e2351; + } +`; + +export const CategorySpacing = styled.div` + margin-top: 15px; +`; + +export const OrderSumSectionSpacing = styled.div` + margin-left: 135px; +`; diff --git a/src/app/delivery/itemRows.tsx b/src/app/delivery/itemRows.tsx new file mode 100644 index 00000000..9a724bc2 --- /dev/null +++ b/src/app/delivery/itemRows.tsx @@ -0,0 +1,62 @@ +import React, { useEffect, useState } from 'react'; +import { OrderProduct } from '../../schema/schema'; +import { fetchProductByID } from '../../api/supabase/queries/product_queries'; +import { + ItemQuantityContainer, + ItemQuantityRow, + ItemText, + QuantityText, + TotalContainer, +} from './styles'; + +function ItemRows({ products }: { products: OrderProduct[] }) { + const [productDetails, setProductDetails] = useState<{ + [key: number]: string; + }>({}); + + useEffect(() => { + // Fetch product details for each product ID + const fetchProductDetails = async () => { + const details: { [key: number]: string } = {}; + + // Create an array of promises + const productPromises = products.map(async product => { + const productData = await fetchProductByID(product.product_id); + details[product.product_id] = productData.name; + }); + + // Wait for all promises to resolve + await Promise.all(productPromises); + + setProductDetails(details); + }; + + fetchProductDetails(); + }, [products]); + + const totalQuantity = products.reduce( + (total, productVal) => total + productVal.quantity, + 0, + ); + + return ( +
+ + {products.map(productVal => ( + + {productDetails[productVal.product_id]} + {productVal.quantity} + + ))} + + + + Order Total + {totalQuantity} + + +
+ ); +} + +export default ItemRows; diff --git a/src/app/delivery/page.tsx b/src/app/delivery/page.tsx new file mode 100644 index 00000000..1e66b420 --- /dev/null +++ b/src/app/delivery/page.tsx @@ -0,0 +1,100 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { useRouter } from 'next/navigation'; +import { + fetchUser, + fetchUserAddress, +} from '@/api/supabase/queries/user_queries'; +import querystring from 'querystring'; +import { + createOrder, + fetchCurrentOrdersByUser, + updateOrderStatus, +} from '@/api/supabase/queries/order_queries'; +import BackButton from '../../components/BackButton/BackButton'; +import { + fetchCartIdFromUser, + fetchCartItemsWithQuantity, + totalNumberOfItemsInCart, +} from '../../api/supabase/queries/cart_queries'; +import { Heading1, Normal700Text } from '../../styles/fonts'; +import { + ProductWithQuantity, + User, + Address, + OrderStatus, +} from '../../schema/schema'; +import OrderSummary from '../../components/OrderSummaryFolder/OrderSummary'; +import NavBar from '../../components/NavBarFolder/NavBar'; +import { + DeliveryContainer, + OrderContainer, + OrderButton, + InformationContainer, + InformationText, + BackButtonDiv, + OutterDiv, +} from './styles'; + +export default function App() { + const [numberOfItems, setNumberOfItems] = useState(0); + const [cart, setCart] = useState([]); + const [Profile, setProfile] = useState(); + const [UserAddress, setUserAddress] = useState
(); + const router = useRouter(); + useEffect(() => { + async function fetchProducts() { + setNumberOfItems(await totalNumberOfItemsInCart()); + setCart(await fetchCartItemsWithQuantity()); + } + async function fetchUserData() { + const data = await fetchUser(); // change the function to grab the cartItems as products + setProfile(data); + const address = await fetchUserAddress(data.id); + setUserAddress(address); + } + fetchUserData(); + fetchProducts(); + }, []); + + return ( +
+ + + + + + + + Shipping + Name + + {`${Profile?.first_name} ${Profile?.last_name}`} + + Address + + {UserAddress?.street}, {UserAddress?.city}, {UserAddress?.zipcode} + + + + + { + const orderID = await fetchCartIdFromUser(); + await updateOrderStatus(orderID, OrderStatus.Submitted); + await createOrder(); + const newestOrder = await fetchCartIdFromUser(); + await updateOrderStatus(newestOrder, OrderStatus.inProgress); + const queryString = querystring.stringify({ orderID }); + router.push(`/orderConfirmationDelivery?${queryString}`); + }} + > + Place Order + + + + +
+ ); +} diff --git a/src/app/delivery/styles.ts b/src/app/delivery/styles.ts new file mode 100644 index 00000000..eccef97a --- /dev/null +++ b/src/app/delivery/styles.ts @@ -0,0 +1,157 @@ +import styled from 'styled-components'; +import NavBar from '../../components/NavBarFolder/NavBar'; +import COLORS from '../../styles/colors'; + +export const DeliveryContainer = styled.div` + margin-left: 80px; + margin-right: 80px; + margin-bottom: 80px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +`; + +export const OutterBox = styled.div` + display: flex; + flex-direction: column; + align-items: center; +`; + +export const OrderSummaryText = styled.div` + margin-top: 27px; + margin-left: 30px; + text-align: left; + width: 285px; + height: 35px; + font-style: normal; + font-weight: 700; + line-height: normal; + font-size: 30px; +`; + +export const QtyText = styled.div` + margin-top: 30px; + margin-right: 20px; + margin-bottom: 5px; + font-style: normal; + font-weight: 400; + line-height: normal; + text-align: right; +`; + +export const ItemText = styled.div` + font-style: normal; + font-weight: 400; + line-height: normal; +`; + +export const QuantityText = styled.div` + font-style: normal; + font-weight: 400; + line-height: normal; + text-align: right; +`; + +export const InformationContainer = styled.div` + width: 730px; + height: 400px; + margin: 40px; +`; + +export const InformationText = styled.div` + width: 730px; + height: 50px; + border-radius: 4px; + margin-top: 14px; + margin-bottom: 14px; + border: 1px solid ${COLORS.neutralGrey}; + background: ${COLORS.lightGrey}; + display: flex; /* Use flexbox */ + align-items: center; /* Center vertically */ + font-size: 20px; + font-style: normal; + font-weight: 400; + line-height: normal; + padding-left: 20px; +`; + +export const OrderContainer = styled.div` + margin-top: 50px; + width: 350px; + height: 500px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +`; + +export const OrderSummary = styled.div` + width: 350px; + height: 360px; + border-radius: 8px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.15); + align-items: center; +`; + +export const ItemQuantityContainer = styled.div` + padding-top: 200px + width: 300px; + height: 170px; + display: flex; + flex-direction: column; + overflow-y: auto; + align-items: center; + justify-content: center; +`; + +export const ItemQuantityRow = styled.div` + width: 285px; + height: 25px; + display: flex; + justify-content: space-between; + margin-bottom: 30px; +`; + +export const TotalContainer = styled.div` + width: 350px; + height: 75px; + border-top: 1px solid black; + display: flex; + align-items: center; + justify-content: center; +`; + +export const OrderButton = styled.button` + margin-top: 26px; + width: 350px; + height: 50px; + flex-shrink: 0; + align-items: center; + background: ${COLORS.navy}; + border-radius: 8px; + color: ${COLORS.white}; + font-size: 20px; + font-family: 'Public Sans', sans-serif; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: static; +`; + +export const BackButtonDiv = styled.div` + display: flex; + flex-direction: row; + text-align: left; + width: 800px; + margin-left: 40px; +`; + +export const OutterDiv = styled.div` + display: flex; + flex-direction: column; +`; diff --git a/src/app/favicon.ico b/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/src/app/favorites/individualItem.tsx b/src/app/favorites/individualItem.tsx new file mode 100644 index 00000000..7b9eea0c --- /dev/null +++ b/src/app/favorites/individualItem.tsx @@ -0,0 +1,78 @@ +import React, { useEffect, useState } from 'react'; + +import { useRouter } from 'next/navigation'; + +import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; + +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { + HeartIcon, + Hover, + FavoriteDiv, + ProductNameDiv, + ViewItem, + TransparentButton, +} from './styles'; + +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; + +import { Product } from '../../schema/schema'; + +export default function IndividualItem(props: { + favorite: Product; + setFavorites: (category: Product[]) => void; + Favorites: Product[]; +}) { + const { favorite, Favorites, setFavorites } = props; + const router = useRouter(); + const [hovering, setHovering] = useState(false); + + useEffect(() => { + async function changeCategory() { + try { + favorite.category = await convertButtonNumberToCategory( + favorite.category, + ); + } catch (error) { + // console.error(error); + } + } + + changeCategory(); + }, [favorite]); + + async function clickFunctions(props2: { fav: Product }) { + const { fav } = props2; + addOrRemoveProductFromFavorite(fav, false); + setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); + } + + return ( + + {favorite.name} + + + {favorite.name} + Category: {favorite.category} + router.push(`/${favorite.id}`)}> + View Item + + + + clickFunctions({ fav: favorite })} + onMouseEnter={() => setHovering(true)} + onMouseLeave={() => setHovering(false)} + > + + Remove from favorites + + + + + ); +} diff --git a/src/app/favorites/page.tsx b/src/app/favorites/page.tsx new file mode 100644 index 00000000..6c00e83a --- /dev/null +++ b/src/app/favorites/page.tsx @@ -0,0 +1,46 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { Heading1 } from '@/styles/fonts'; +import BackButton from '../../components/BackButton/BackButton'; + +import { arrayOfFavorites } from '../../api/supabase/queries/user_queries'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import { OutterFavoriteDiv, OutterBox, Fullscreen } from './styles'; +import IndividualItem from './individualItem'; + +import { Product } from '../../schema/schema'; + +export default function FavoritesPage() { + const [Favorites, setFavorites] = useState([]); + + async function fetchProducts() { + const data = (await arrayOfFavorites()) as Product[]; + setFavorites(data); + } + useEffect(() => { + fetchProducts(); + }, []); + + return ( + + + + + Favorites + + {Favorites.map(favorite => ( + + ))} + + + + ); +} diff --git a/src/app/favorites/styles.ts b/src/app/favorites/styles.ts new file mode 100644 index 00000000..479119e8 --- /dev/null +++ b/src/app/favorites/styles.ts @@ -0,0 +1,132 @@ +import styled from 'styled-components'; + +import { Heart } from 'react-feather'; +import Link from 'next/link'; +import COLORS from '@/styles/colors'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-around; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; +`; + +export const OutterFavoriteDiv = styled.div` + display: flex; + flex-direction: column; + align-items: center; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 800px; + height: 650px; + overflow: scroll; + margin-top: 10px; +`; + +export const BackDiv = styled.button` + display: flex; + flex-direction: row; + align: center; + color: black; + background-color: transparent; + border: transparent; + margin-bottom: 25px; + margin-top: 25px; +`; + +export const OutterBox = styled.div` + width: 800px; + height: 100%; + margin-top: 40px; + display: flex; + flex-direction: column; + gap: 20px; + margin-bottom: 20px; +`; + +export const Backtext = styled.p` + padding-top: 5px; +`; + +export const HeartIcon = styled(Heart)` + color: #333286; + width: 30px; + height: 30px; + fill: #333286; + margin-right: 25px; + margin-bottom: 40px; +`; + +export const TransparentButton = styled.button` + background-color: transparent; + border: transparent; + cursor: pointer; +`; + +export const Hover = styled.div<{ $ishovering?: boolean }>` + visibility: ${props => (props.$ishovering ? 'visible' : 'hidden')}; + transform: translate(-10px, 0px); + margin-bottom: 7px; + color: black; + border: none; + width: 156px; + height: 26px; + border-radius: 8px; + background: var(--Light-Periwinkle, #f4f7ff); + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + padding-top: 6px; + position: relative; + text-align: center; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: relative; +`; + +export const ProductNameDiv = styled.div` + width: 350px; +`; + +export const ViewItem = styled.button` + background: #1b3679; + color: #fbfbfb; + text-align: center; + width: 132px; + height: 28px; + flex-shrink: 0; + margin-top: 26px; + padding-top: 3px; + padding-right: 10px; + padding-left: 10px; + padding-bottom: 3px; + border: none; + border-radius: 5px; + line-height: normal; + border-radius: 14px; +`; + +export const Fullscreen = styled.div` + width: 100vw; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; +`; + +export const ImageLinkWrapper = styled(Link)` + width: 100px; + height: 100px; + background-color: ${COLORS.lightGrey}; + padding: 32px; + margin-bottom: 8px; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 1px 1px 4px 1px rgba(0, 0, 0, 0.1); +`; diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 00000000..5b0dbd13 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,106 @@ +:root { + --max-width: 1100px; + --border-radius: 12px; + --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', + 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', + 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace; + + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; + + --primary-glow: conic-gradient( + from 180deg at 50% 50%, + #16abff33 0deg, + #0885ff33 55deg, + #54d6ff33 120deg, + #0071ff33 160deg, + transparent 360deg + ); + --secondary-glow: radial-gradient( + rgba(255, 255, 255, 1), + rgba(255, 255, 255, 0) + ); + + --tile-start-rgb: 239, 245, 249; + --tile-end-rgb: 228, 232, 233; + --tile-border: conic-gradient( + #00000080, + #00000040, + #00000030, + #00000020, + #00000010, + #00000010, + #00000080 + ); + + --callout-rgb: 238, 240, 241; + --callout-border-rgb: 172, 175, 176; + --card-rgb: 180, 185, 188; + --card-border-rgb: 131, 134, 135; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + + --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); + --secondary-glow: linear-gradient( + to bottom right, + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0.3) + ); + + --tile-start-rgb: 2, 13, 46; + --tile-end-rgb: 2, 5, 19; + --tile-border: conic-gradient( + #ffffff80, + #ffffff40, + #ffffff30, + #ffffff20, + #ffffff10, + #ffffff10, + #ffffff80 + ); + + --callout-rgb: 20, 20, 20; + --callout-border-rgb: 108, 108, 108; + --card-rgb: 100, 100, 100; + --card-border-rgb: 200, 200, 200; + } +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + min-height: 100vh; +} +button { + &:hover { + cursor: pointer; + } +} +body { + background: white; + color: black; +} + +a { + color: inherit; + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + html { + color-scheme: dark; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 00000000..42fb4ff2 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,23 @@ +import './globals.css'; +import type { Metadata } from 'next'; +// eslint-disable-next-line camelcase +import { Public_Sans } from 'next/font/google'; + +const publicSans = Public_Sans({ subsets: ['latin'] }); + +export const metadata: Metadata = { + title: 'Shanti Project', + description: 'Application Created by Blueprint', +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx new file mode 100644 index 00000000..aeff396f --- /dev/null +++ b/src/app/login/page.tsx @@ -0,0 +1,99 @@ +'use client'; + +import { useState } from 'react'; + +import Image from 'next/image'; +import supabase from '@/api/supabase/createClient'; +import { Body1, Heading1 } from '@/styles/fonts'; +import LoginForm from '../../components/LoginFormFolder/LoginForm'; + +import { + Fullscreen, + LoginBox, + LoginContent, + WelcomeSign, + Button, + ErrorMessage, + EyeOffIcon, + EyeIcon, +} from './styles'; + +export default function App() { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [isError, setIsError] = useState(false); + const [showPassword, setShowPassword] = useState(false); + + const handleLogin = async () => { + const { error } = await supabase.auth.signInWithPassword({ + email, + password, + }); + + setErrorMessage(''); + + if (error) { + setErrorMessage('Incorrect email or password'); + setIsError(true); + } else { + window.location.href = '/storefront'; + } + }; + + async function applyFilter( + e: React.KeyboardEvent, + ) { + const keypressed = e.code; + if (keypressed === 'Enter') { + handleLogin(); + } + } + + + return ( + + logo pic + + + + Welcome + + + + {showPassword ? ( + setShowPassword(false)} + style={{ cursor: 'pointer' }} + /> + ) : ( + setShowPassword(true)} + style={{ cursor: 'pointer' }} + /> + )} + + {errorMessage && {errorMessage}} + + + + + ); +} diff --git a/src/app/login/styles.ts b/src/app/login/styles.ts new file mode 100644 index 00000000..03fb0708 --- /dev/null +++ b/src/app/login/styles.ts @@ -0,0 +1,89 @@ +import { EyeOff, Eye } from 'react-feather'; +import styled from 'styled-components'; +import COLORS from '../../styles/colors'; + +export const LoginBox = styled.div` + display: flex; + width: 500px; + height: 420px; + justify-self: center; + align-self: center; + background-color: ${COLORS.white}; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); + border-radius: 10px; +`; + +export const LoginContent = styled.div` + margin-left: 40px; + flex-direction: column; + align-self: center; + justify-self: center; + text-color: ${COLORS.black}; +`; + +export const Button = styled.button` + color: ${COLORS.white}; + width: 420px; + height: 40px; + border-radius: 8px; + background: ${COLORS.navy}; + border: transparent; +`; + +export const WelcomeSign = styled.div` + color: ${COLORS.navy}; +`; + +export const FormHeaders = styled.p` + color: ${COLORS.black}; + font-size: 18px; + font-style: normal; + font-weight: 400; + line-height: normal; + margin-top: 20px; + margin-bottom: 10px; +`; + +export const ErrorMessage = styled.div` + transform: translateY(-250%); + margin-bottom: 20px; + width: 420px; + color: ${COLORS.darkRed}; + text-align: left; + font-size: 13px; + font-style: normal; + font-weight: 300; + line-height: normal; + z-index: 0; + position: absolute; +`; + +export const EyeOffIcon = styled(EyeOff)` + stroke-width: 1.5; + width: 20px; + height: 20px; + color: ${COLORS.black}; + margin: 20px; + transform: translateY(-250%) translateX(1800%); +`; + +export const EyeIcon = styled(Eye)` + stroke-width: 1.5; + width: 20px; + height: 20px; + color: ${COLORS.black}; + margin: 20px; + transform: translateY(-250%) translateX(1800%); +`; + +export const Fullscreen = styled.div` + width: 100%; + height: 100vh; + display: grid; + background-color: ${COLORS.lightGrey}; +`; + +export const InputField = styled.div` + position: relative; + background-color: ${COLORS.lightGrey}; +`; diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx new file mode 100644 index 00000000..1652742e --- /dev/null +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -0,0 +1,176 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { + fetchUser, + fetchCurrentUserAddress, +} from '@/api/supabase/queries/user_queries'; + +import { + Body1, + Body2, + Body2Light, + Heading3Bold, + Heading4Bold, +} from '@/styles/fonts'; +import { useSearchParams } from 'next/navigation'; +import { + DeliveryTimes, + fetchDeliveryTimes, +} from '@/api/supabase/queries/delivery_queries'; +import BackButton from '../../components/BackButton/BackButton'; + +import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import { + FavoriteDiv, + OutterFavoriteDiv, + LabelBox, + ScrollDiv, + ShippingDetailsDiv, + BottomColumnDiv, + LeftColumnDiv, + RightColumnDiv, + DetailsHeader, + PageDiv, + CenterDiv, + Quantity, +} from './styles'; + +import { Product, User, Address } from '../../schema/schema'; +import { Body1Bold } from '../orderPage/styles'; +import { BackButtonDiv } from '../orderConfirmationPickUp/styles'; + +export default function OrderConfirmationDelivery() { + const [Cart, setCart] = useState([]); + const [user, setUser] = useState(); + const [userAddress, setUserAddress] = useState
(); + const searchParams = useSearchParams(); + const orderIDFromSearch = searchParams.get('orderID'); + const [delivTimes, setDelivTimes] = useState([]); + useEffect(() => { + async function fetchProducts() { + const cartItems = (await fetchCartItemsWithQuantityByID( + orderIDFromSearch, + )) as Product[]; + setCart(cartItems); + } + + async function setUserDetails() { + const fetchedUser = await fetchUser(); + setUser(fetchedUser); + const address = await fetchCurrentUserAddress(); + setUserAddress(address); + } + async function fetchDelivTimes() { + const deliv = await fetchDeliveryTimes(); + setDelivTimes(deliv); + } + + fetchProducts(); + setUserDetails(); + fetchDelivTimes(); + }, []); + + function organizeDelivTime() { + const userGrp = user?.delivery_group == null ? 1 : user?.delivery_group; + const Time = delivTimes[userGrp]?.delivery_time.toLocaleString(); + const date = + Time == null ? ['0', '0', '0'] : Time?.substring(0, 10).split('-'); + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const dateStr = `${months[parseInt(date[1], 10) - 1]} ${date[2]}, ${ + date[0] + }`; + return `${dateStr}`; + } + + return ( +
+ + + + + + + + + + Your order has been submitted + + Order No. {orderIDFromSearch} + + {Cart.map(cartItem => ( + + {cartItem.name} + +
+ + Quantity: + + + {cartItem.quantity} + +
+
+ + + Quantity: {cartItem.quantity} + + +
+ ))} +
+
+
+ + + Delivery Information + Estimated Date + {organizeDelivTime()} + Location + + {userAddress?.street}, {userAddress?.city},{' '} + {userAddress?.zipcode} + + + +
+
+
+
+ ); +} diff --git a/src/app/orderConfirmationDelivery/styles.ts b/src/app/orderConfirmationDelivery/styles.ts new file mode 100644 index 00000000..618a5919 --- /dev/null +++ b/src/app/orderConfirmationDelivery/styles.ts @@ -0,0 +1,247 @@ +import styled from 'styled-components'; + +import { Heart } from 'react-feather'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: space-between; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; +`; + +export const Quantity = styled.div` + display: flex; + align-self: center; + justify-content: flex-start; + margin-right: 40px; +`; + +export const OrderDetailsDiv = styled.div` + width: 750px; + height: auto; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; +`; + +export const CenterDiv = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; +`; + +export const OutterFavoriteDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 650px; + height: auto; + max-height: 793px; + margin-top: 5px; + margin-bottom: 50px; + gap: 24px; + padding: 36px 32px; +`; + +export const ScrollDiv = styled.div` + overflow: scroll; + width: 100%; +`; + +export const BackDiv = styled.button` + display: flex; + flex-direction: row; + align: center; + color: black; + background-color: transparent; + border: transparent; + margin-bottom: 25px; + margin-top: 25px; + margin-left: 25px; + width: 100%; +`; + +export const OutterBox = styled.div` + width: 750px; + height: auto; + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; +`; + +export const Backtext = styled.p` + color: var(--Black, #101010); + /* Body 1 - Bold, button */ + font-family: Public Sans; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const HeartIcon = styled(Heart)` + color: #333286; + width: 30px; + height: 30px; + fill: #333286; +`; + +export const TransparentButton = styled.button` + background-color: transparent; + border: transparent; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: static; +`; + +export const Label = styled.p` + margin-top: 9px; +`; + +export const Category = styled.p` + margin-top: 10px; +`; + +export const LabelBox = styled.div` + width: 150px; + height: 100%; + display: flex; + align-self: center; + flex-direction: column; + gap: 9px; +`; + +export const HeaderText = styled.h3` + color: var(--Black, #101010); + margin-top: 30px; + margin-bottom: 20px; + text: center; + color: var(--Black, #101010); + font-family: Public Sans; + font-size: 35px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const ShippingDetailsDiv = styled.div` + display: flex; + flex-direction: column; + align-items: space-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 467px; + height: auto; + max-height: 793px; + margin-top: 10px; + margin-bottom: 50px; + padding: 36px 34px; + gap: 33px; +`; + +export const DetailsHeader = styled.p` + color: var(--Navy, #1b3679); + font-family: Public Sans, sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const DetailsText = styled.p` + color: var(--Black, #101010); + font-family: Public Sans; + font-size: 17px; + font-style: normal; + font-weight: 400; + line-height: normal; + margin-top: 20px; +`; + +export const BottomColumnDiv = styled.div` + display: flex; + flex-flow: row; + align-items: space-evenly; + justify-content: space-around; + width: 100%; +`; + +export const PageDiv = styled.div` + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + width: 100%; +`; + +export const TopColumnDiv = styled.div` + display: flex; + flex-flow: column; + align-items: flex-start; + justify-content: space-around; + margin-bottom: 20px; +`; + +export const OrderSummaryDiv = styled.div` + overflow: scroll; + width: 350px; + height: 300px; +`; + +export const ItemSummaryDiv = styled.div` + display: flex; + flex-direction: row; + margin-bottom: 20px; + justify-content: space-between; + padding-left: 10px; + padding-right: 10px; +`; + +export const OrderTotalDiv = styled.div` + height: 50px; + padding-top: 10px; + width: 350px; + padding-left: 0px; + border-top: 1px black solid; + display: flex; + flex-flow: row; + justify-content: space-between; +`; + +export const LeftColumnDiv = styled.div` + margin-top: 30px; + display: flex; + flex-flow: column; + justify-content: space-evenly; + align-items: space-evenly; + gap: 20px; +`; +export const RightColumnDiv = styled.div` + display: flex; + flex-flow: column; + margin-left: 20px; + margin-top: 123px; +`; + +export const WhiteBackgroundDiv = styled.div` + border-radius: 8px; + background: var(--White, #fff); + height: 430px; + width: 350px; + padding-top: 20px; + + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx new file mode 100644 index 00000000..9a93cb72 --- /dev/null +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -0,0 +1,158 @@ +'use client'; + +import { useState, useEffect } from 'react'; + +import { fetchUser } from '@/api/supabase/queries/user_queries'; +import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; +import { getOrderById } from '@/api/supabase/queries/order_queries'; +import { + Body1, + Body1Bold, + Body2Light, + Heading3Bold, + Heading4Bold, +} from '@/styles/fonts'; +import { useSearchParams } from 'next/navigation'; +import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; + +import BackButton from '../../components/BackButton/BackButton'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import { + TextDiv, + TextDiv1, + BackButtonDiv, + FavoriteDiv, + OutterFavoriteDiv, + LabelBox, + LabelBox1, + ScrollDiv, + ShippingDetailsDiv, + ImageDiv, + BottomColumnDiv, + Wrapper, + LeftColumnDiv, + RightColumnDiv, + DetailsHeader, + PageDiv, + CenterDiv, +} from './styles'; + +import { Product, User, Pickup } from '../../schema/schema'; + +export default function OrderConfirmationPickUp() { + const [Cart, setCart] = useState([]); + const [user, setUser] = useState(); + const [pickupTime, setPickupTime] = useState(); + const searchParams = useSearchParams(); + const orderIDFromSearch = searchParams.get('orderID'); + + useEffect(() => { + async function fetchProducts() { + const cartItems = (await fetchCartItemsWithQuantityByID( + orderIDFromSearch, + )) as Product[]; + setCart(cartItems); + } + + async function setUserDetails() { + const fetchedUser = await fetchUser(); + setUser(fetchedUser); + const currOrder = await getOrderById(Number(orderIDFromSearch)); + const pickup = await fetchPickupTimesByID(currOrder.pickup_time_id); + setPickupTime(pickup); + } + + fetchProducts(); + setUserDetails(); + }, []); + + function organizePickupTime() { + const startTime = pickupTime?.start_time.toLocaleString(); + const date = + startTime == null + ? ['0', '0', '0'] + : startTime?.substring(0, 10).split('-'); + const dateStr = `${date[1]}/${date[2]}/${date[0]}`; + return `${dateStr}`; + } + + return ( +
+ + + + + + + + + + Your order has been submitted + + + + Order No. {orderIDFromSearch} + + + {Cart.map(cartItem => ( + + + {cartItem.name} + + + {cartItem.name} +
+ + Category: {cartItem.category} + +
+ +
+ + Quantity: + + + {cartItem.quantity} + +
+
+
+ ))} +
+
+
+ + + Pickup Information + Time Slot + {organizePickupTime()} (10:00 am - 12:30 pm) + Location + 3170 23rd Street, San Francisco, CA 94110 + + +
+
+
+
+ ); +} diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts new file mode 100644 index 00000000..4f2e25a8 --- /dev/null +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -0,0 +1,325 @@ +import styled from 'styled-components'; + +import { Heart } from 'react-feather'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; + margin-right: 20px; +`; + +export const OutterFavoriteDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 800px; + max-height: 100%; + margin-top: 20px; + margin-right: 60px; + margin-left: 60px; + padding-right: 20px; + padding-left: 10px; + padding-top: 10px; +`; + +export const ScrollDiv = styled.div` + overflow: scroll; + width: 100%; +`; + +export const ImageDiv = styled.div` + box-shadow: 1px 1px 4px 1px rgba(0, 0, 0, 0.08); + width: 150px; + height: 150px; + margin-left: 30px; + display: flex; + justify-content: center; + align-items: center; +`; + +export const Wrapper = styled.div` + padding: 15px; + display: flex; + justify-content: center; + align-items: center; +`; + +export const BackDiv = styled.button` + display: flex; + flex-direction: row; + align: center; + color: black; + background-color: transparent; + border: transparent; + margin-bottom: 25px; + margin-top: 25px; + margin-left: 25px; +`; + +export const OutterBox = styled.div` + width: 900px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +`; + +export const CenterBox = styled.div` + display: flex; + justify-content: center; +`; + +export const Backtext = styled.p` + color: var(--Black, #101010); + + /* Body 1 - Bold, button */ + font-family: Public Sans; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const HeartIcon = styled(Heart)` + color: #333286; + width: 30px; + height: 30px; + fill: #333286; +`; + +export const TransparentButton = styled.button` + background-color: transparent; + border: transparent; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: static; +`; + +export const Label = styled.p` + margin-top: 20px; +`; + +export const LabelBox1 = styled.div` + width: 250px; + height: 100%; + padding: 20px; +`; + +export const LabelBox = styled.div` + width: 150px; + height: 100%; + padding: 20px; + gap: 50px; + margin-right: 30px; +`; + +export const HeaderText = styled.h3` + color: var(--Black, #101010); + margin-top: 30px; + margin-bottom: 20px; + text: center; + color: var(--Black, #101010); + font-family: Public Sans; + font-size: 35px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const AddressText = styled.p` + color: var(--Black, #101010); + font-family: Public Sans; + font-size: 17px; + font-style: normal; + font-weight: 400; + line-height: normal; + margin-bottom: 20px; + margin-left: 45px; +`; + +export const DateText = styled.p` + color: var(--Black, #101010); + margin-top: 20px; + margin-left: 45px; + + font-family: Public Sans; + font-size: 25px; + font-style: normal; + font-weight: 700; + line-height: normal; + text-decoration-line: underline; +`; + +export const PickUpText = styled.p` + color: var(--Marine-Blue, #333286); + text-align: right; + /* Body 2 - Bold */ + font-family: Public Sans; + font-size: 15px; + font-style: normal; + font-weight: 700; + line-height: normal; + margin-top: 15px; +`; + +export const ColDiv = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + width: 750px; +`; + +export const AddressDiv = styled.div` + position: relative; + display: flex; + align-items: flex-end; +`; + +export const TopColumnDiv = styled.div` + display: flex; + flex-flow: column; + align-items: flex-start; + justify-content: space-around; + margin-bottom: 20px; +`; + +export const OrderSummaryDiv = styled.div` + overflow: scroll; + width: 350px; + height: 300px; +`; + +export const ItemSummaryDiv = styled.div` + display: flex; + flex-direction: row; + margin-bottom: 20px; + justify-content: space-between; + padding-left: 10px; + padding-right: 10px; +`; + +export const OrderTotalDiv = styled.div` + height: 50px; + padding-top: 10px; + width: 350px; + padding-left: 0px; + border-top: 1px black solid; + display: flex; + flex-flow: row; + justify-content: space-between; +`; + +export const LeftColumnDiv = styled.div` + display: flex; + flex-flow: column; + justify-content: space-evenly; + align-items: space-evenly; + width: 100%; +`; +export const RightColumnDiv = styled.div` + display: flex; + flex-flow: column; + align-items: start; + margin-left: 10px; + width: 100%; +`; + +export const BackButtonDiv = styled.div` + display: flex; + flex-direction: row; + text-align: left; + width: 800px; + margin-left: 80px; + margin-top: 40px; +`; + +export const WhiteBackgroundDiv = styled.div` + border-radius: 8px; + background: var(--White, #fff); + height: 430px; + width: 350px; + padding-top: 20px; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; + +export const BottomColumnDiv = styled.div` + display: flex; + flex-direction: row; + align-items: space-evenly; + justify-content: space-around; + width: 100%; + margin-left: 20px; + margin-bottom: 30px; + gap: 30px; +`; + +export const TextDiv = styled.div` + display: flex; + flex-direction: row; + margin-left: 60px; + margin-top: 20px; + margin-bottom: 20px; +`; + +export const TextDiv1 = styled.div` + display: flex; + flex-direction: row; + padding: 10px; + margin-left: 20px; + margin-top: 15px; +`; + +export const PageDiv = styled.div` + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + width: 100%; +`; + +export const ShippingDetailsDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 467px; + height: auto; + max-height: 100%; + padding: 36px 34px; + gap: 33px; + max-height: 100%; + margin-top: 205px; + margin-bottom: 30px; + margin-right: 40px; +`; + +export const DetailsHeader = styled.p` + color: var(--Navy, #1b3679); + font-family: Public Sans, sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const CenterDiv = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 20px; +`; diff --git a/src/app/orderHistory/page.tsx b/src/app/orderHistory/page.tsx new file mode 100644 index 00000000..e02c8e1e --- /dev/null +++ b/src/app/orderHistory/page.tsx @@ -0,0 +1,51 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import { Heading1, Body1 } from '@/styles/fonts'; +import OrderDetailsWithProducts from '../../components/OrderHistory/OrderHistoryBox'; +import { fetchOrderIdsByUserIdSorted } from '../../api/supabase/queries/order_queries'; +import Footer from '../../components/FooterFolder/Footer'; +import { + OrderHistoryContainer, + OutterBox, + NavBarMovedUP, + Fullscreen, +} from './styles'; +import BackButton from '../../components/BackButton/BackButton'; + +function OrderHistory() { + const [orderIds, setOrderIds] = useState([]); + + useEffect(() => { + const fetchIds = async () => { + const ids = await fetchOrderIdsByUserIdSorted(); + setOrderIds(ids); + }; + + fetchIds(); + }, []); + + return ( + + + + +
+ Order History +
+ + {orderIds.length > 0 ? ( + orderIds.map((orderId: number) => ( + + )) + ) : ( + No Order + )} + +
+
+ + ); +} + +export default OrderHistory; diff --git a/src/app/orderHistory/styles.ts b/src/app/orderHistory/styles.ts new file mode 100644 index 00000000..a93abdc1 --- /dev/null +++ b/src/app/orderHistory/styles.ts @@ -0,0 +1,54 @@ +// styles.ts (for styled-components) +import styled from 'styled-components'; +import COLORS from '@/styles/colors'; +import NavBar from '../../components/NavBarFolder/NavBar'; + +import Footer from '../../components/FooterFolder/Footer'; + +export const FooterMoved = styled(Footer)` + left: 0; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: relative; +`; + +export const OutterBox = styled.div` + width: 800px; + margin-top: 40px; + margin-bottom: 70px; +`; + +export const OrderHistoryContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + border-radius: 10px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 800px; // Width of the outer box + height: auto; + margin-top: 10px; + padding-top: 40px; +`; + +export const OrderHistoryBox = styled.div` + width: 100%; // Make internal box take full width of the container + margin: 20px 0; // Keep vertical spacing between orders + padding: 30px; // Inner spacing for content inside the box + border-radius: 8px; + background: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: column; + gap: 20px; + overflow-y: auto; +`; +export const Fullscreen = styled.div` + width: 100%; + height: 100%; + display: flex; + align-items: center; + flex-direction: column; + background-color: ${COLORS.offWhite}; +`; diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx new file mode 100644 index 00000000..6d2d0fd9 --- /dev/null +++ b/src/app/orderPage/page.tsx @@ -0,0 +1,115 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { Body1, Body2 } from '@/styles/fonts'; +import { useSearchParams } from 'next/navigation'; +import BackButton from '../../components/BackButton/BackButton'; + +import { + fetchOrderProductsbyOrderId, + getOrderById, +} from '../../api/supabase/queries/order_queries'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import { + FavoriteDiv, + Body1Bold, + OutterFavoriteDiv, + BackButtonDiv, + OutterBox, + OutterDiv, + Heading, + ProductNameDiv, + StatusButton, +} from './styles'; + +import { ProductWithQuantity, Order } from '../../schema/schema'; + +function formatDate(date: string | undefined): string { + if (!date) return ''; + + const monthNames = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const res: Date = new Date(date); + + const month = monthNames[res.getMonth()]; + const day = res.getDate(); + const year = res.getFullYear(); + + return `${month} ${day}, ${year}`; +} + +export default function OrderPage() { + const [orders, setOrders] = useState([]); + const searchParams = useSearchParams(); + const orderIDFromSearch = searchParams.get('orderID'); + let currOrderId = 0; + if (orderIDFromSearch !== null) { + currOrderId = parseInt(orderIDFromSearch, 10); + } else { + currOrderId = 32; + } + + const [order, setOrder] = useState(); + + useEffect(() => { + async function fetchProducts() { + const data = (await fetchOrderProductsbyOrderId( + currOrderId, + )) as ProductWithQuantity[]; + const currOrder = await getOrderById(currOrderId); + setOrders(data); + setOrder(currOrder); + } + fetchProducts(); + }, []); + + return ( +
+ + + + + + + + {formatDate(order?.created_at)} + + {' '} + {order?.order_status}{' '} + + + + {orders.map(product => ( + + {product.name} + + {product.name} + Category: {product.category} + + + ))} + + +
+ ); +} diff --git a/src/app/orderPage/styles.ts b/src/app/orderPage/styles.ts new file mode 100644 index 00000000..c2c236bb --- /dev/null +++ b/src/app/orderPage/styles.ts @@ -0,0 +1,141 @@ +import styled from 'styled-components'; + +import { Heart } from 'react-feather'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: start; + justify-content: space-around; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; +`; + +export const OutterFavoriteDiv = styled.div` + display: flex; + flex-direction: column; + align-items: center; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 800px; + height: 700px; + overflow: scroll; + margin-top: 20px; +`; + +export const BackDiv = styled.button` + display: flex; + flex-direction: row; + align: center; + color: black; + background-color: transparent; + border: transparent; + margin-bottom: 25px; + margin-top: 25px; +`; + +export const OutterBox = styled.div` + width: 800px; + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: 100%; + margin-bottom: 100px; +`; + +export const Heading = styled.h1` + font-family: 'Public Sans', sans-serif; + color: black; + margin-bottom: 0px; + font-size: 30px; +`; + +export const OutterDiv = styled.div` + display: flex; + flex-direction: row; + gap: 200px; + width: 800px; +`; + +export const BackButtonDiv = styled.div` + display: flex; + flex-direction: row; + gap: 200px; + margin-bottom: 55px; + text-align: left; + width: 800px; +`; + +export const Backtext = styled.p` + padding-top: 5px; +`; + +export const HeartIcon = styled(Heart)` + color: #333286; + width: 30px; + height: 30px; + fill: #333286; + margin-right: 25px; +`; + +export const TransparentButton = styled.button` + background-color: transparent; + border: transparent; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: relative; +`; + +export const ProductNameDiv = styled.div` + width: 350px; + height: 100%; + gap: 40px; +`; + +export const ViewItem = styled.button` + background: #1b3679; + color: #fbfbfb; + text-align: center; + width: 132px; + height: 28px; + flex-shrink: 0; + margin-top: 26px; + padding-top: 3px; + padding-right: 10px; + padding-left: 10px; + padding-bottom: 3px; + border: none; + border-radius: 5px; + line-height: normal; + border-radius: 14px; +`; + +export const StatusButton = styled.button` + margin-left: auto; + margin-right: 0; + color: black; + text-align: center; + width: 210px; + height: 30px; + flex-shrink: 0; + padding-top: 3px; + padding-right: 10px; + padding-left: 10px; + padding-bottom: 3px; + border: none; + border-radius: 16.5px; + background: var(--Baby-Blue, #c7ddff); +`; + +export const Body1Bold = styled.p` + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: normal; +`; diff --git a/src/app/page.module.css b/src/app/page.module.css new file mode 100644 index 00000000..6676d2c6 --- /dev/null +++ b/src/app/page.module.css @@ -0,0 +1,229 @@ +.main { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + padding: 6rem; + min-height: 100vh; +} + +.description { + display: inherit; + justify-content: inherit; + align-items: inherit; + font-size: 0.85rem; + max-width: var(--max-width); + width: 100%; + z-index: 2; + font-family: var(--font-mono); +} + +.description a { + display: flex; + justify-content: center; + align-items: center; + gap: 0.5rem; +} + +.description p { + position: relative; + margin: 0; + padding: 1rem; + background-color: rgba(var(--callout-rgb), 0.5); + border: 1px solid rgba(var(--callout-border-rgb), 0.3); + border-radius: var(--border-radius); +} + +.code { + font-weight: 700; + font-family: var(--font-mono); +} + +.grid { + display: grid; + grid-template-columns: repeat(4, minmax(25%, auto)); + max-width: 100%; + width: var(--max-width); +} + +.card { + padding: 1rem 1.2rem; + border-radius: var(--border-radius); + background: rgba(var(--card-rgb), 0); + border: 1px solid rgba(var(--card-border-rgb), 0); + transition: background 200ms, border 200ms; +} + +.card span { + display: inline-block; + transition: transform 200ms; +} + +.card h2 { + font-weight: 600; + margin-bottom: 0.7rem; +} + +.card p { + margin: 0; + opacity: 0.6; + font-size: 0.9rem; + line-height: 1.5; + max-width: 30ch; +} + +.center { + display: flex; + justify-content: center; + align-items: center; + position: relative; + padding: 4rem 0; +} + +.center::before { + background: var(--secondary-glow); + border-radius: 50%; + width: 480px; + height: 360px; + margin-left: -400px; +} + +.center::after { + background: var(--primary-glow); + width: 240px; + height: 180px; + z-index: -1; +} + +.center::before, +.center::after { + content: ''; + left: 50%; + position: absolute; + filter: blur(45px); + transform: translateZ(0); +} + +.logo { + position: relative; +} +/* Enable hover only on non-touch devices */ +@media (hover: hover) and (pointer: fine) { + .card:hover { + background: rgba(var(--card-rgb), 0.1); + border: 1px solid rgba(var(--card-border-rgb), 0.15); + } + + .card:hover span { + transform: translateX(4px); + } +} + +@media (prefers-reduced-motion) { + .card:hover span { + transform: none; + } +} + +/* Mobile */ +@media (max-width: 700px) { + .content { + padding: 4rem; + } + + .grid { + grid-template-columns: 1fr; + margin-bottom: 120px; + max-width: 320px; + text-align: center; + } + + .card { + padding: 1rem 2.5rem; + } + + .card h2 { + margin-bottom: 0.5rem; + } + + .center { + padding: 8rem 0 6rem; + } + + .center::before { + transform: none; + height: 300px; + } + + .description { + font-size: 0.8rem; + } + + .description a { + padding: 1rem; + } + + .description p, + .description div { + display: flex; + justify-content: center; + position: fixed; + width: 100%; + } + + .description p { + align-items: center; + inset: 0 0 auto; + padding: 2rem 1rem 1.4rem; + border-radius: 0; + border: none; + border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); + background: linear-gradient( + to bottom, + rgba(var(--background-start-rgb), 1), + rgba(var(--callout-rgb), 0.5) + ); + background-clip: padding-box; + backdrop-filter: blur(24px); + } + + .description div { + align-items: flex-end; + pointer-events: none; + inset: auto 0 0; + padding: 2rem; + height: 200px; + background: linear-gradient( + to bottom, + transparent 0%, + rgb(var(--background-end-rgb)) 40% + ); + z-index: 1; + } +} + +/* Tablet and Smaller Desktop */ +@media (min-width: 701px) and (max-width: 1120px) { + .grid { + grid-template-columns: repeat(2, 50%); + } +} + +@media (prefers-color-scheme: dark) { + .vercelLogo { + filter: invert(1); + } + + .logo { + filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70); + } +} + +@keyframes rotate { + from { + transform: rotate(360deg); + } + to { + transform: rotate(0deg); + } +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 00000000..ad5ea152 --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,88 @@ +'use client'; + +import { useState } from 'react'; +import Image from 'next/image'; +import supabase from '@/api/supabase/createClient'; +import { Body1, Heading1 } from '@/styles/fonts'; +import LoginForm from '@/components/LoginFormFolder/LoginForm'; + +import { + Fullscreen, + LoginBox, + LoginContent, + WelcomeSign, + Button, + ErrorMessage, + EyeOffIcon, + EyeIcon, +} from './login/styles'; + +export default function App() { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [isError, setIsError] = useState(false); + const [showPassword, setShowPassword] = useState(false); + + const handleLogin = async () => { + const { error } = await supabase.auth.signInWithPassword({ + email, + password, + }); + + setErrorMessage(''); + + if (error) { + setErrorMessage('Incorrect email or password'); + setIsError(true); + } else { + window.location.href = '/storefront'; + } + }; + + return ( + + logo pic + + + + Welcome + + + + {showPassword ? ( + setShowPassword(false)} + style={{ cursor: 'pointer' }} + /> + ) : ( + setShowPassword(true)} + style={{ cursor: 'pointer' }} + /> + )} + + {errorMessage && {errorMessage}} + + + + + ); +} diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx new file mode 100644 index 00000000..bd8d8ea3 --- /dev/null +++ b/src/app/pickup/page.tsx @@ -0,0 +1,196 @@ +'use client'; + +// import { GlobalStyle } from "@/styles/components"; + +import 'react-toastify/dist/ReactToastify.css'; +import { toast } from 'react-toastify'; +import { ArrowLeft } from 'react-feather'; +import { fetchUser } from '@/api/supabase/queries/user_queries'; +import querystring from 'querystring'; +import { + fetchCartIdFromUser, + fetchCartItemsWithQuantity, + totalNumberOfItemsInCart, +} from '@/api/supabase/queries/cart_queries'; +import { useState, useEffect } from 'react'; +import { useRouter } from 'next/navigation'; +import { Body1, Heading4Bold } from '@/styles/fonts'; +import { fetchNRecentPickupTimes } from '@/api/supabase/queries/pickup_queries'; +import { + updateCartPickupId, + updateOrderStatus, + createOrder, +} from '@/api/supabase/queries/order_queries'; +import { + Pickup, + User, + ProductWithQuantity, + OrderStatus, +} from '@/schema/schema'; +import OrderSummary from '../../components/OrderSummaryFolder/OrderSummary'; +import NavBar from '../../components/NavBarFolder/NavBar'; +import { + BackDiv, + Backtext, + PageDiv, + CheckoutButton, + ForceColumnDiv, + RightColumnDiv, + PickupContent, + PickupContainer, + PickupTimeButton, + ToastPopUP, +} from './styles'; + +function DateInfoComponent(date: { date: unknown }) { + const date1 = new Date(date.date as string); + const daysOfWeek = [ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + ]; + const getDayOfWeek = daysOfWeek[date1.getDay()]; + + const dateAsMonthDay = date1.toLocaleDateString(undefined, { + month: 'long', + day: 'numeric', + }); + + return { + getDayOfWeek, + dateAsMonthDay, + }; +} + +// + +export default function PickUp() { + const [Cart, setCart] = useState([]); + const [numberOfItems, setNumberOfItems] = useState(0); + const router = useRouter(); + const [Time, setTimes] = useState([]); + const [Profile, setProfile] = useState(); + const [selectedPickupIndex, setSelectedPickupIndex] = useState(0); + useEffect(() => { + async function fetchProducts() { + setNumberOfItems(await totalNumberOfItemsInCart()); + const data = await fetchCartItemsWithQuantity(); // change the function to grab the cartItems as products + setCart(data); + } + async function fetchTimes() { + const data = await fetchNRecentPickupTimes(2); // change the function to grab the cartItems as products + setTimes(data); + } + fetchProducts(); + fetchTimes(); + }, []); + + useEffect(() => { + async function fetchUserData() { + const data = await fetchUser(); // change the function to grab the cartItems as products + setProfile(data); + } + fetchUserData(); + }, []); + + const handleButtonClick = (index: number) => { + setSelectedPickupIndex(index); + }; + + return ( +
+ + + + + router.push('/cart')}> + + Back + + + + Pick Up + + Name + + {Profile?.first_name} {Profile?.last_name} + + Phone Number + {Profile?.phone_numbers} +
+ Time Slot +
+
+ {' '} + Pick Up times: 10:00 AM - 12:00 PM{' '} +
+
+ Location: 3170 23rd Street, San Francisco, CA 94110 +
+
+ {Time.map(time => ( + handleButtonClick(time.id)} + > +
+ {String( + DateInfoComponent({ date: time.start_time }) + ?.getDayOfWeek, + )} +
+
+ { + DateInfoComponent({ date: time.start_time }) + ?.dateAsMonthDay + } +
+
+ ))} +
+
+
+ + + + { + if (selectedPickupIndex !== 0) { + await updateCartPickupId(selectedPickupIndex); // TODO double check if this is correct + const orderID = await fetchCartIdFromUser(); + await updateOrderStatus(orderID, OrderStatus.Submitted); + await createOrder(); + const newestOrder = await fetchCartIdFromUser(); + await updateOrderStatus(newestOrder, OrderStatus.inProgress); + const queryString = querystring.stringify({ orderID }); + router.push(`/orderConfirmationPickUp?${queryString}`); + } + if (selectedPickupIndex === 0) { + toast(`You must select a pick-up date!`); + toast.clearWaitingQueue(); + } + }} + > + Checkout + + +
+
+ ); +} diff --git a/src/app/pickup/styles.ts b/src/app/pickup/styles.ts new file mode 100644 index 00000000..af517b07 --- /dev/null +++ b/src/app/pickup/styles.ts @@ -0,0 +1,272 @@ +import styled from 'styled-components'; + +import { ToastContainer } from 'react-toastify'; +import COLORS from '../../styles/colors'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import Footer from '../../components/FooterFolder/Footer'; + +export const PickupContainer = styled.div` + width: 730px; + height: 400px; + padding-left: 22px; +`; + +export const PickupContent = styled.div` + width: 730px; + height: 50px; + border-radius: 4px; + margin-top: 14px; + margin-bottom: 14px; + border: 1px solid ${COLORS.neutralGrey}; + background: ${COLORS.lightGrey}; + display: flex; /* Use flexbox */ + align-items: center; /* Center vertically */ + font-size: 20px; + font-style: normal; + font-weight: 400; + line-height: normal; + padding-left: 20px; +`; + +export const PickupTimeButton = styled.button<{ $isSelected?: boolean }>` + background: ${props => + props.$isSelected ? COLORS.periwinkle : COLORS.lightGrey}; + height: 124px; + width: 242px; + margin-top: 20px; + margin-right: 31px; + margin-bottom: 20px; + + border: none; + border-radius: 5px; + + color: black; + text-align: center; + font-family: 'Public Sans', sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; + + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: start; + justify-content: space-around; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; +`; + +export const OutterFavoriteDiv = styled.div` + display: flex; + flex-direction: column; + align-items: center; + border-radius: 10px; + + width: 800px; + height: 500px; + overflow: scroll; + margin-top: 10px; +`; + +export const BackDiv = styled.button` + display: flex; + flex-direction: row; + align: center; + color: black; + background-color: transparent; + border: transparent; + margin-bottom: 25px; + margin-top: 25px; +`; + +export const OutterBox = styled.div` + width: 900px; + margin-left: 300px; +`; + +export const Backtext = styled.p` + padding-top: 5px; +`; + +export const NavBarZeroIndex = styled(NavBar)` + z-index: 0; + position: fixed; + margin-bottom: 100px; +`; + +export const FooterMoved = styled(Footer)` + transform: translateY(300px); +`; + +export const TransparentButton = styled.button` + background-color: transparent; + border: transparent; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: static; +`; + +export const ButtonsWrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + width: 200px; + height: 50px; + margin-top: 20px; +`; + +export const QtyText = styled.div` + margin-top: 30px; + margin-right: 20px; + margin-bottom: 5px; + font-style: normal; + font-weight: 400; + line-height: normal; + text-align: right; +`; + +export const ItemText = styled.div` + font-style: normal; + font-weight: 400; + line-height: normal; +`; + +export const QuantityText = styled.div` + font-style: normal; + font-weight: 400; + line-height: normal; + text-align: right; +`; + +export const Label = styled.p` + margin-top: 20px; +`; + +export const LabelBox = styled.div` + width: 150px; + height: 100%; +`; + +export const PageDiv = styled.div` + display: flex; + flex-flow: row; + width: 100%; + justify-content: space-around; +`; + +export const OrderSummaryDiv = styled.div` + overflow: scroll; + width: 350px; + height: 300px; +`; + +export const ItemSummaryDiv = styled.div` + display: flex; + flex-direction: row; + margin-bottom: 20px; + justify-content: space-between; + padding-left: 10px; + padding-right: 10px; +`; + +export const OrderTotalDiv = styled.div` + height: 50px; + padding-top: 10px; + width: 350px; + padding-left: 0px; + border-top: 1px black solid; + display: flex; + flex-flow: row; + justify-content: space-between; +`; + +export const ForceColumnDiv = styled.div` + display: flex; + flex-flow: column; + margin-left: 50px; +`; + +export const CheckoutButton = styled.button` + background: #1b3679; + + height: 40px; + margin-top: 20px; + + border: none; + border-radius: 5px; + + color: var(--White, #fff); + text-align: center; + font-family: 'Public Sans', sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const Qty = styled.p` + width: 100%; + padding-left: 290px; +`; + +export const OrderButton = styled.button` + margin-top: 26px; + width: 350px; + height: 50px; + flex-shrink: 0; + align-items: center; + background: ${COLORS.navy}; + border-radius: 8px; + color: ${COLORS.white}; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const RightColumnDiv = styled.div` + display: flex; + flex-flow: column; + margin-left: 150px; + margin-top: 100px; +`; + +export const WhiteBackgroundDiv = styled.div` + border-radius: 8px; + background: var(--White, #fff); + height: 430px; + width: 350px; + padding-top: 20px; + + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; + +export const HeaderShiftRight = styled.h2` + margin-right: 30px; +`; + +export const PShiftRight = styled.p` + margin-right: 30px; +`; + +export const HeaderShiftLeft = styled.h2` + margin-left: 15px; +`; + +export const PShiftLeft = styled.p` + margin-left: 15px; +`; + +export const ToastPopUP = styled(ToastContainer)` + position: fixed; + z-index: 100; + transform: translatey(90px); +`; diff --git a/src/app/profileScreen/individualItem.tsx b/src/app/profileScreen/individualItem.tsx new file mode 100644 index 00000000..69288d69 --- /dev/null +++ b/src/app/profileScreen/individualItem.tsx @@ -0,0 +1,64 @@ +import React, { useEffect, useState } from 'react'; + +import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; + +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { HeartIcon, Hover, FavoriteDiv, ProductNameDiv } from './styles'; + +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; + +import { Product } from '../../schema/schema'; +import { TransparentButton } from '../favorites/styles'; + +export default function IndividualItem(props: { + favorite: Product; + setFavorites: (category: Product[]) => void; + Favorites: Product[]; +}) { + const { favorite, Favorites, setFavorites } = props; + const [hovering, setHovering] = useState(false); + + // useEffect(() => { + // async function changeCategory() { + // try { + // favorite.category = await convertButtonNumberToCategory( + // favorite.category, + // ); + // } catch (error) { + // // console.error(error); + // } + // } + + // changeCategory(); + // }, []); + + async function clickFunctions(props2: { fav: Product }) { + const { fav } = props2; + addOrRemoveProductFromFavorite(fav, false); + setFavorites(Favorites.filter(Prod => Prod.id !== fav.id)); + } + + return ( + + {favorite.name} + + {favorite.name} + Category: {favorite.category} + + clickFunctions({ fav: favorite })} + onMouseEnter={() => setHovering(true)} + onMouseLeave={() => setHovering(false)} + > + + Remove from favorites + + + + + ); +} diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx new file mode 100644 index 00000000..995716f3 --- /dev/null +++ b/src/app/profileScreen/page.tsx @@ -0,0 +1,430 @@ +'use client'; + +import { useRouter } from 'next/navigation'; +import { toast, ToastContainer } from 'react-toastify'; +import { useEffect, useState } from 'react'; +import { + Heading2, + Body3, + Heading3, + Heading1, + Body1Bold, + Body2Bold, + Body2, +} from '@/styles/fonts'; +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { + arrayOfFavorites, + fetchUser, + fetchCurrentUserAddress, +} from '@/api/supabase/queries/user_queries'; +import { + Address, + Order, + ProductWithQuantity, + Product, + User, +} from '@/schema/schema'; +import ViewAllButton from '@/components/ViewAllButton/ViewAllButton'; +import { + fetchOrdersByUserIdSorted, + fetchOrderProductById, + fetchProductWithQuantityById, +} from '@/api/supabase/queries/order_queries'; +import { Check, CheckCircle, X, Send } from 'react-feather'; +import BackButton from '../../components/BackButton/BackButton'; +import { + LogOutButton, + NavBarMovedUP, + AccountDetails, + HeadingBack, + HeadingSpacing, + TextSpacing, + OrderHistory, + FavoritesContainer, + BackButtonDiv, + BlankSpace, + HeaderDiv, + MostRecentOrder, + ColumnDiv, + LogOutDiv, + Fullscreen, + MessageDiv, +} from './styles'; +import { signOut } from '../../api/supabase/auth/auth'; +import 'react-toastify/dist/ReactToastify.css'; +import IndividualItem from './individualItem'; + +function FavoriteSection(props: { + Favorites: Product[]; + setFavorites: (category: Product[]) => void; +}) { + const { Favorites, setFavorites } = props; + if (Favorites.length > 0) { + return ( +
+ + + Favorites + + + {Favorites.slice(0, 2).map(favorite => ( + + ))} + +
+ ); + } + return ( +
+ + + Favorites + + + + No Favorite Items + + +
+ ); +} + +function OrderHistorySection(props: { Orders: Order[] }) { + const { Orders } = props; + const [firstOrderProducts, setFirstOrderProducts] = useState< + ProductWithQuantity[] + >([]); + const [fD, setFormattedDate] = useState(''); + + useEffect(() => { + async function fetchFirstOrderProducts() { + if (Orders.length > 0) { + const firstOrder = Orders.filter( + order => order.order_product_id_array.length !== 0, + )[0]; + // handleErrorlater + if (firstOrder) { + const firstOrderProductIds = firstOrder.order_product_id_array.slice( + 0, + 3, + ); + + const productIds = await Promise.all( + firstOrderProductIds.map(productId => + fetchOrderProductById(productId).then( + orderproduct => orderproduct.product_id, + ), + ), + ); + + const productArray = await Promise.all( + productIds.map(async productId => + fetchProductWithQuantityById(productId).then(product => product), + ), + ); + + setFirstOrderProducts(productArray); + + const timestamp = firstOrder.created_at; + const date = new Date(timestamp); + const options: Intl.DateTimeFormatOptions = { + month: 'long', + day: 'numeric', + year: 'numeric', + }; + const formattedDate = date.toLocaleDateString('en-US', options); + setFormattedDate(formattedDate); + } + } + } + fetchFirstOrderProducts(); + }, [Orders]); + + if (firstOrderProducts.length > 0) { + let backgroundColor = 'transparent'; + if (Orders[0].order_status === 'Submitted') { + backgroundColor = 'var(--Greyish, #E6E6E6)'; + } else if (Orders[0].order_status === 'Rejected') { + backgroundColor = '#FFDDDD'; + } else if (Orders[0].order_status === 'Confirmed') { + backgroundColor = '#C7DDFF'; + } + let icon; + if (Orders[0].order_status === 'Submitted') { + icon = ; + } else if (Orders[0].order_status === 'Rejected') { + icon = ; + } else if (Orders[0].order_status === 'Confirmed') { + icon = ; + } else { + icon = null; + } + return ( +
+ + + Order History + + +
+ + Order No. {Orders[0].id} + + + {fD} + +
+ {icon} + + {Orders[0].order_status} + +
+ + {firstOrderProducts.map(product => ( +
+ {product.name} +
+ ))} +
+
+
+
+ ); + } + return ( +
+ + + Order History + + + + No Current Orders to Display + + +
+ ); +} +function AccountDetailSectionDelivery(props: { user: User }) { + const { user } = props; + const [UserAddress, setUserAddress] = useState
(); + + useEffect(() => { + async function getUserAddress() { + const address = await fetchCurrentUserAddress(); + setUserAddress(address); + } + getUserAddress(); + }, []); + return ( +
+ + Account Details + + Name + + + + {user?.first_name} {user?.last_name} + + + + Email + + + {user?.email} + + + + Phone + + + {user?.phone_numbers} + + + Address + + + + {UserAddress?.street}, {UserAddress?.city}, {UserAddress?.zipcode} + + + +
+ ); +} +function AccountDetailSectionPickUp(props: { user: User }) { + const { user } = props; + + return ( +
+ + Account Details + + + Name + + + + {user?.first_name} {user?.last_name} + + + + Email + + + {user?.email} + + + + Phone Number + + + {user?.phone_numbers} + + +
+ ); +} +function LogoutSection() { + const router = useRouter(); + + const showToastMessage = () => { + signOut(); + toast("You've been Logged Out! Redirecting...", { + position: toast.POSITION.TOP_CENTER, + }); + setTimeout(() => { + router.push('/login'); + }, 3000); + }; + + return ( +
+ + showToastMessage()}>Log Out + +
+ ); +} + +export default function Profile() { + const [Favorites, setFavorites] = useState([]); + const [user, setUser] = useState(); + + const [Orders, setOrder] = useState([]); + + async function fetchOrders() { + const data = (await fetchOrdersByUserIdSorted()) as Order[]; + setOrder(data); + } + + async function getUser() { + const data = await fetchUser(); + setUser(data); + } + useEffect(() => { + async function fetchProducts() { + const data = (await arrayOfFavorites()) as Product[]; + console.log(data); + data.forEach( + async product => + (product.category = await convertButtonNumberToCategory( + product.category, + )), + ); + console.log(data); + // console.log(data); + setFavorites(data); + } + fetchProducts(); + fetchOrders(); + getUser(); + }, []); + if (user === undefined) { + return

Loading User

; + } + return ( + + + + + + + + + + My Profile + + + + + {user.delivery_allowed ? ( + + ) : ( + + )} + + + + + + + + + + ); +} diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts new file mode 100644 index 00000000..1ae59176 --- /dev/null +++ b/src/app/profileScreen/styles.ts @@ -0,0 +1,185 @@ +import styled from 'styled-components'; + +import { ToastContainer } from 'react-toastify'; + +import { Heart } from 'react-feather'; + +import COLORS from '@/styles/colors'; +import NavBar from '../../components/NavBarFolder/NavBar'; + +import Footer from '../../components/FooterFolder/Footer'; + +export const TextSpacing = styled.div` + margin-top: 10px; +`; +export const HeadingSpacing = styled.div` + margin-top: 20px; +`; + +export const HeadingBack = styled.div` + width: 500px; + margin-right: 75px; +`; + +export const AccountDetails = styled.div` + margin-top: 50px; + margin-right: 30px; + width: 500px; + height: 350px; + border-radius: 10px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + display: flex; + flex-direction: column; + align-items: left; + padding-top: 29px; + padding-right: 29px; + padding-left: 29px; + padding-bottom: 29px; +`; + +export const OrderHistory = styled.div` + margin-top: 50px; + width: 600px; + height: 350px; + border-radius: 10px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + padding-top: 23px; + padding-right: 23px; + padding-left: 23px; + padding-bottom: 23px; +`; + +export const FavoritesContainer = styled.div` + margin-top: 50px; + + width: 600px; + height: 350px; + border-radius: 10px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + padding-top: 23px; + padding-right: 23px; + padding-left: 23px; + padding-bottom: 23px; +`; + +export const LogOutButton = styled.button` + background: ${COLORS.navy}; + color: #fff; + text-align: center; + font-size: 20px; + font-family: 'Public Sans', sans-serif; + font-style: normal; + font-weight: 600; + line-height: normal; + border: transparent; + border-radius: 5px; + width: 405px; + height: 50px; +`; +/* transform: translateY(200px); */ + +export const PopUp = styled(ToastContainer)` + transform: translate(-150px, 250px); + position: fixed; +`; + +export const FooterMoved = styled(Footer)` + transform: translateY(50px); +`; + +export const NavBarMovedUP = styled(NavBar)` + position: relative; +`; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-around; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; +`; + +export const HeartIcon = styled(Heart)` + color: #333286; + width: 25px; + height: 25px; + fill: #333286; + margin-bottom: 40px; +`; + +export const Hover = styled.div<{ $ishovering?: boolean }>` + visibility: ${props => (props.$ishovering ? 'visible' : 'hidden')}; + transform: translate(0px, -1px); + margin-bottom: 7px; + color: black; + border: none; + width: 156px; + height: 26px; + border-radius: 8px; + background: var(--Light-Periwinkle, #f4f7ff); + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + padding-top: 6px; + position: relative; + text-align: center; +`; + +export const BackButtonDiv = styled.div` + margin-bottom: 30px; + margin-top: 50px; +`; + +export const HeaderDiv = styled.div` + display: flex; + width: 100%; + + align-items: center; + justify-content: space-between; +`; + +export const ProductNameDiv = styled.div` + width: 250px; +`; + +export const BlankSpace = styled.div` + width: 250px; + height: 200px; +`; + +export const Fullscreen = styled.div` + width: 100%; + height: 100%; +`; + +export const MostRecentOrder = styled.div` + display: flex; + flex-direction: row; +`; + +export const ColumnDiv = styled.div` + display: flex; + flex-direction: column; + width: 100%; + align-items: center; +`; + +export const LogOutDiv = styled.div` + margin-top: 50px; + margin-right: 30px; + display: flex; + justify-content: center; + width: 500px; + height: 350px; +`; + +export const MessageDiv = styled.div` + display: flex; + width: 100%; + justify-content: center; + align-items: center; + height: 250px; +`; diff --git a/src/app/profileScreen/stylesOld.ts b/src/app/profileScreen/stylesOld.ts new file mode 100644 index 00000000..0a335813 --- /dev/null +++ b/src/app/profileScreen/stylesOld.ts @@ -0,0 +1,128 @@ +import styled, { createGlobalStyle } from 'styled-components'; + +import { ToastContainer } from 'react-toastify'; + +import { Heart } from 'react-feather'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import Footer from '../../components/FooterFolder/Footer'; + +export const GlobalStyle = createGlobalStyle` + body { + background:white; + color: black; + overflow: visible; + + } +`; + +export const TextSpacing = styled.div` + margin-top: 10px; +`; +export const HeadingSpacing = styled.div` + margin-top: 30px; +`; + +export const HeadingBack = styled.div` + margin-left: 171px; + margin-top: px; +`; + +export const AccountDetails = styled.div` + margin-left: 189px; + margin-top: 80px; + width: 350px; + height: 290px; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + display: flex; + flex-direction: column; + align-items: left; + padding-right: 30px; +`; + +export const OrderHistory = styled.div` + margin-left: 700px; + margin-top: -291px; + margin-bottom: 47px; + width: 543.4px; + height: 290px; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + padding-top: 10px; + padding-right: 10px; + padding-left: 10px; + padding-bottom: 10px; +`; + +export const FavoritesContainer = styled.div` + margin-left: 700px; + width: 543.4px; + height: 290px; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + padding-top: 10px; + padding-right: 10px; + padding-left: 10px; + padding-bottom: 10px; +`; + +export const LogOutButton = styled.button` + background: #00507f; + color: #fff; + text-align: center; + font-size: 25px; + font-family: normal; + font-style: normal; + font-weight: 500; + line-height: normal; + border: transparent; + border-radius: 5px; + width: 350px; + height: 300px; + z-index: 1000; + margin-top: 70px; + padding-top: 10px; + padding-right: 10px; + padding-left: 10px; + padding-bottom: 10px; +`; +/* transform: translateY(200px); */ + +export const PopUp = styled(ToastContainer)` + transform: translate(-150px, 250px); + position: fixed; +`; + +export const FooterMoved = styled(Footer)` + transform: translateY(400px); +`; + +export const NavBarMovedUP = styled(NavBar)` + position: relative; +`; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: start; + justify-content: space-around; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; +`; + +export const HeartIcon = styled(Heart)` + color: #333286; + width: 20px; + height: 20px; + fill: #333286; +`; + +export const BackButtonDiv = styled.div` + margin-bottom: 68px; +`; diff --git a/src/app/storefront/IndividualItem.tsx b/src/app/storefront/IndividualItem.tsx new file mode 100644 index 00000000..9687e7e6 --- /dev/null +++ b/src/app/storefront/IndividualItem.tsx @@ -0,0 +1,53 @@ +import React, { useState } from 'react'; + +import { Body1, Body3 } from '@/styles/fonts'; + +import { + ImageLinkWrapper, + HeartIcon, + HeartContainer, + FavoritePopup, + OuterDiv, +} from './styles'; + +import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; + +import { Product } from '../../schema/schema'; + +export default function IndividualItem(props: { + product: Product; + products: Product[]; +}) { + const { product, products } = props; + const [IsFavorite, setIsFavorite] = useState( + !!products.find(item => item.id === product.id), + ); + + async function handleFavorite() { + await addOrRemoveProductFromFavorite(product, !IsFavorite); + setIsFavorite(!IsFavorite); + } + return ( + + {/* */} + + {product.name} + + handleFavorite()}> + + + {IsFavorite ? 'Remove from favorites' : 'Add to favorites'} + + + + + + {/* */} + {product.name} + + ); +} diff --git a/src/app/storefront/StoreFrontNavBar.tsx b/src/app/storefront/StoreFrontNavBar.tsx new file mode 100644 index 00000000..c1644826 --- /dev/null +++ b/src/app/storefront/StoreFrontNavBar.tsx @@ -0,0 +1,161 @@ +import Image from 'next/image'; +import React, { useEffect, useState } from 'react'; + +import { fetchButtonCategories } from '@/api/supabase/queries/button_queries'; +import { Body2 } from '@/styles/fonts'; +import { totalNumberOfItemsInCart } from '../../api/supabase/queries/cart_queries'; + +import { + NavBarComp, + ButtonsDiv, + CartTotalCircle, + UserProfileIcon, + ShoppingCartIcon, + IconWithLabelLink, +} from '../../components/NavBarFolder/styles'; + +import { Product, StorefrontButtons } from '../../schema/schema'; + +import { + ButtonsContainer, + FrontButton, + BackButton, + FrontArrow, + BackArrow, +} from './styles'; + +import ProductButtons from './productButtons'; + +export default function StoreFrontNavBar(props: { + setFilteredProducts: (category: Product[]) => void; + setCategoryWord: (word: string) => void; + clickedButton: number; + setClickedButton: (clicked: number) => void; +}) { + const { + setFilteredProducts, + setCategoryWord, + setClickedButton, + clickedButton, + } = props; + + const [data, setData] = useState(0); + const [isZero, setIsZero] = useState(true); + const [buttonCategories, setButtonCategories] = useState( + [], + ); + const [buttonDisplay, setButtonDisplay] = useState([]); + const [ind, setInd] = useState(0); + let newInd = 0; + const [reachedStart, setReachedStart] = useState(false); + const [reachedEnd, setReachedEnd] = useState(true); + + useEffect(() => { + const fetchData = async () => { + setData(await totalNumberOfItemsInCart()); + }; + fetchData(); + }, []); + + useEffect(() => { + const changeData = async () => { + if (data > 0) { + setIsZero(false); + } + }; + changeData(); + }, [data]); + + useEffect(() => { + const fetchButtonCat = async () => { + setButtonCategories(await fetchButtonCategories()); + }; + fetchButtonCat(); + }, []); + + useEffect(() => { + const displayedButtons = async () => { + const button = await fetchButtonCategories(); + setButtonDisplay(button.slice(0, 4)); + }; + displayedButtons(); + }, []); + + const changeDisplay = (direction: number, index: number) => { + setButtonDisplay(buttonCategories.slice(index, index + 4)); + }; + + const handlePrevious = () => { + if (ind > 0) { + if (ind % 4 !== 0) { + newInd = 4 * (Math.floor(buttonCategories.length / 4) - 1); + } else { + newInd = ind - 4; + } + setInd(newInd); + changeDisplay(-1, newInd); + setReachedStart(!(newInd === 0)); + } + setReachedEnd(true); + }; + + const handleNext = () => { + if (ind + 4 < buttonCategories.length) { + const remainder = buttonCategories.length - ind - 4; + if (remainder < 4) { + newInd = buttonCategories.length - 4; + } else { + newInd = ind + 4; + } + setInd(newInd); + changeDisplay(1, newInd); + } + setReachedEnd(ind + 5 < buttonCategories.length); + setReachedStart(true); + }; + + return ( + + + Shanti Logo + + + + + + {buttonDisplay.map((type, index) => ( + + ))} + + + + + + + + + User + + + + Cart + {data} + + + + ); +} diff --git a/src/app/storefront/buttonValues.tsx b/src/app/storefront/buttonValues.tsx new file mode 100644 index 00000000..e64d498e --- /dev/null +++ b/src/app/storefront/buttonValues.tsx @@ -0,0 +1,24 @@ +export const buttons = [ + { + name: 'All', + value: 'All', + count: 0, + }, + { + name: 'Dog', + value: 'Dog', + count: 1, + }, + { + name: 'Cat', + value: 'Cat', + count: 2, + }, + { + name: 'Other', + value: 'Other', + count: 3, + }, +]; + +export const empty = []; diff --git a/src/app/storefront/page.tsx b/src/app/storefront/page.tsx new file mode 100644 index 00000000..2997f665 --- /dev/null +++ b/src/app/storefront/page.tsx @@ -0,0 +1,51 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import { Heading1Bold } from '@/styles/fonts'; +import Storefront from './storefrontItems'; + +import Footer from '../../components/FooterFolder/Footer'; +import { StorefrontWrapper } from './styles'; +import { fetchUserProducts } from '../../api/supabase/queries/product_queries'; +import { Product } from '../../schema/schema'; + +import StoreFrontNavBar from './StoreFrontNavBar'; + +export default function App() { + const [FilteredProducts, setFilteredProducts] = useState([]); + + const [CategoryWord, setCategoryWord] = useState('All'); + + const [clickedButton, setClickedButton] = useState(0); + + useEffect(() => { + async function fetchAllProducts() { + try { + const data = (await fetchUserProducts()) as Product[]; + setFilteredProducts(data); + } catch (error) { + // console.log(error); + } + } + + fetchAllProducts(); + }, []); + + return ( +
+ + + + Shop {CategoryWord} + + + +
+
+ ); +} diff --git a/src/app/storefront/productButtons.tsx b/src/app/storefront/productButtons.tsx new file mode 100644 index 00000000..23b99371 --- /dev/null +++ b/src/app/storefront/productButtons.tsx @@ -0,0 +1,96 @@ +import React from 'react'; + +import { fetchButtonCategories } from '@/api/supabase/queries/button_queries'; +import { + CategoryButton, + CategoryButtonLabel, + IndividualContainer, +} from './styles'; + +import { + fetchUserProducts, + filterUserProducts, +} from '../../api/supabase/queries/product_queries'; + +import { Product } from '../../schema/schema'; + +export default function ProductButtons(props: { + value: string; + setFiltredProducts: (category: Product[]) => void; + content: string; + setCategoryWord: (word: string) => void; + index: number; + setClickedButton: (clicked: number) => void; + clickedButton: number; +}) { + const { + value, + content, + setFiltredProducts, + setCategoryWord, + index, + setClickedButton, + clickedButton, + } = props; + + async function applyFilter( + e: React.MouseEvent, + ) { + // which button is clicked + + const category = e.currentTarget.value; + const productItem = await fetchUserProducts(); + const buttonCategories = await fetchButtonCategories(); + + for (let i = 0; i < buttonCategories.length; i += 1) { + if (buttonCategories[i].name === category) { + const ind = buttonCategories[i].id - 1; + if (ind === clickedButton) { + setCategoryWord('All'); + + setClickedButton(0); + + if (productItem !== null) { + setFiltredProducts(productItem); + } + return; + } + setClickedButton(ind); + + setCategoryWord(buttonCategories[i].name); + + break; + } + } + + // Changing the Color of the Button + + // Applying the filter to the categories of the product + + if (category !== 'All') { + const products = await filterUserProducts(category); + if (products !== null) { + setFiltredProducts(products); + } + } else { + const products = await fetchUserProducts(); + if (products !== null) { + setFiltredProducts(products); + } + } + } + + return ( + + applyFilter(e)} + /> + + {content} + + + ); +} diff --git a/src/app/storefront/storefrontItems.tsx b/src/app/storefront/storefrontItems.tsx new file mode 100644 index 00000000..e23174e0 --- /dev/null +++ b/src/app/storefront/storefrontItems.tsx @@ -0,0 +1,34 @@ +import React, { useState, useEffect } from 'react'; + +import { StorefrontItemsWrapper } from './styles'; + +import IndividualItem from './IndividualItem'; + +import { Product } from '../../schema/schema'; + +import { arrayOfFavorites } from '../../api/supabase/queries/user_queries'; + +function Storefront({ products }: { products: Product[] }) { + const [Favorites, setFavorites] = useState([]); + async function fetchProducts() { + const data = (await arrayOfFavorites()) as Product[]; + setFavorites(data); + } + useEffect(() => { + fetchProducts(); + }, []); + + return ( + + {products.map(productVal => ( + + ))} + + ); +} + +export default Storefront; diff --git a/src/app/storefront/styles.ts b/src/app/storefront/styles.ts new file mode 100644 index 00000000..57a7aa12 --- /dev/null +++ b/src/app/storefront/styles.ts @@ -0,0 +1,254 @@ +import styled from 'styled-components'; + +import { + Heart, + User, + ShoppingCart, + ChevronLeft, + ChevronRight, +} from 'react-feather'; + +import { Body3 } from '@/styles/fonts'; + +import Link from 'next/link'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import COLORS from '../../styles/colors'; + +export const StickyHeader = styled.div` + position: fixed; + background-color: ${COLORS.periwinkle}; + filter: drop-shadow(0px 4px 7px rgba(0, 0, 0, 0.1)); + width: 1470px; + height: 10px; + z-index: 2; +`; + +export const CategoryButton = styled.button<{ $selected?: boolean }>` + background-color: ${props => + props.$selected ? COLORS.navy : COLORS.babyBlue}; + border-radius: 50%; + width: 60px; + height: 60px; + border: transparent; + cursor: pointer; +`; + +export const CategoryButtonLabel = styled.p<{ $selected?: boolean }>` + color: ${props => (props.$selected ? COLORS.navy : COLORS.black)}; + text-align: center; + font-family: 'Public Sans', sans-serif; + padding-top: 5px; + font-size: 18px; + font-style: normal; + font-weight: 500; + line-height: normal; +`; + +export const IndividualContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; +`; + +export const ItemContainer = styled.div` + width: 290px; + height: 290px; + flex-direction: row; +`; + +export const ButtonsContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + position: flex; + align-items: center; + padding-left: 32px; + padding-right: 32px; + max-width: 750px; + width: 100%; +`; + +export const NavButton = styled.button` + margin-top: 30px; + margin-right: 25px; + color: ${COLORS.white}; + text-align: center; + font-family: sans-serif; + font-size: 15px; + font-style: normal; + font-weight: normal; + line-height: normal; + width: 70px; + height: 40px; + background: ${COLORS.black}; + border: transparent; + border-radius: 5px; + float: right; +`; + +export const ImageLinkWrapper = styled(Link)` + width: 300px; + height: 300px; + background-color: ${COLORS.lightGrey}; + padding: 32px; + margin-bottom: 8px; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; + +export const StorefrontWrapper = styled.div` + padding: 30px; + display: flex; + flex-direction: column; + gap: 32px; +`; + +export const StorefrontItemsWrapper = styled.div` + display: grid; + grid-template-columns: repeat(auto-fill, 300px); + grid-gap: 32px; + justify-content: space-between; +`; + +export const HeartIcon = styled(Heart)<{ $favorited: boolean }>` + width: 30px; + height: 30px; + color: ${props => (props.$favorited ? COLORS.marineBlue : COLORS.black)}; + fill: ${props => (props.$favorited ? COLORS.marineBlue : 'none')}; + position: relative; +`; + +export const HeartContainer = styled.button` + position: absolute; + right: 16px; + top: 16px; + background-color: transparent; + border: none; + cursor: pointer; +`; + +export const NavBarZeroIndex = styled(NavBar)` + position: fixed; +`; + +export const CartTotalCircle = styled.div<{ $isZero?: boolean }>` + width: 20px; + height: 20px; + background: ${COLORS.marineBlue}; + border-radius: 50%; + text-align: center; + transform: translate(19px, -58px); + color: ${COLORS.white}; + display: ${props => (props.$isZero ? 'none' : 'content')}; +`; + +export const UserProfileIcon = styled(User)` + margin-left: 5px; +`; + +export const ShoppingCartIcon = styled(ShoppingCart)` + margin-left: 3px; +`; + +export const NavBarComp = styled.nav` + display: flex; + flex-direction: row; + justify-content: space-between; + padding-left: 30px; + padding-right: 30px; + height: 140px; + padding-top: 20px; + position: fixed; + width: 100%; + background: ${COLORS.lightPeriwinkle}; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); + z-index: 100; +`; + +export const ButtonsDiv = styled.div` + width: 200px; + display: flex; + flex-direction: row; + justify-content: space-around; + padding-top: 15px; +`; + +export const LocationDiv = styled.div` + display: flex; + flex-direction: column; + width: 300px; + height: 250px; + margin-right: 60px; + color: ${COLORS.black}; + font-family: Public Sans; + font-style: normal; + line-height: normal; +`; + +export const Addie = styled.p` + margin-top: 30px; + margin-bottom: 30px; +`; + +export const FavoritePopup = styled.div` + position: absolute; + visibility: hidden; + width: 150px; + border-radius: 8px; + padding: 8px; + // Find better way to refactor this, it shouldn't need a calc + transform: translate(calc(-50% + 15px), -40px); + z-index: 1; + + color: ${COLORS.black}; + background: ${COLORS.lightPeriwinkle}; + box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2); + + ${Body3} { + display: inline; + } + + ${HeartContainer}:hover & { + visibility: visible; + } +`; + +export const OuterDiv = styled.div` + width: 300px; + height: 375px; + position: relative; +`; + +export const FrontArrow = styled(ChevronLeft)` + width: 30px; + height: 30px; + position: relative; +`; + +export const FrontButton = styled.button<{ $reachedStart?: boolean }>` + position: relative; + color: ${COLORS.black}; + background-color: transparent; + border: none; + visibility: ${props => (props.$reachedStart ? 'visible' : 'hidden')}; + cursor: pointer; +`; + +export const BackArrow = styled(ChevronRight)` + width: 30px; + height: 30px; + position: relative; +`; + +export const BackButton = styled.button<{ $reachedEnd?: boolean }>` + position: relative; + color: ${COLORS.black}; + background-color: transparent; + border: none; + visibility: ${props => (props.$reachedEnd ? 'visible' : 'hidden')}; + cursor: pointer; +`; diff --git a/src/app/types/types.txt b/src/app/types/types.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/app/util/util.txt b/src/app/util/util.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx new file mode 100644 index 00000000..bff2d899 --- /dev/null +++ b/src/components/BackButton/BackButton.tsx @@ -0,0 +1,12 @@ +import { Body1Bold } from '@/styles/fonts'; +import { BackLink, ArrowLeftIcon } from './styles'; + +export default function BackButton(props: { destination: string }) { + const { destination } = props; + return ( + + + Back + + ); +} diff --git a/src/components/BackButton/styles.ts b/src/components/BackButton/styles.ts new file mode 100644 index 00000000..4abb943e --- /dev/null +++ b/src/components/BackButton/styles.ts @@ -0,0 +1,22 @@ +import styled from 'styled-components'; +import { ArrowLeft } from 'react-feather'; +import Link from 'next/link'; +import COLORS from '../../styles/colors'; + +export const BackLink = styled(Link)` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + color: ${COLORS.black}; + width: 75px; + + &:hover { + text-decoration: underline; + } +`; + +export const ArrowLeftIcon = styled(ArrowLeft)` + width: 20px; + height: 20px; +`; diff --git a/src/components/FooterFolder/Footer.tsx b/src/components/FooterFolder/Footer.tsx new file mode 100644 index 00000000..45fa2c42 --- /dev/null +++ b/src/components/FooterFolder/Footer.tsx @@ -0,0 +1,127 @@ +import { Body1 } from '@/styles/fonts'; + +import Image from 'next/image'; +import { useRouter } from 'next/navigation'; + +import { + MySpanIcon, + WordDiv, + WordDiv1, + YoutubeIcon, + FacebookIcon, + InstagramIcon, + Body1New, + Body2New, + Heading, + SVGWrapper, + MySpan, + Wrapper, + LinkDiv, + ContactDiv, + MissionDiv, + Body1Bold, + ArrowUpRightIcon, +} from './styles'; + +export default function Footer({ ...rest }) { + const router = useRouter(); + return ( +
+ + + Contact Us + Phone: (415) 674-4700 + + { + window.location.href = + 'https://www.facebook.com/ShantiProjectSF/'; + }} + > + + + + + { + window.location.href = + 'https://www.youtube.com/channel/UCc3DMrL7_KDOzeJNVkoFrsA'; + }} + > + + + + + { + window.location.href = + 'https://www.instagram.com/shantiprojectsf/'; + }} + > + + + + + + + + + Mission District + + 3170 23rd Street + San Francisco, CA 94110 + + + { + window.location.href = + 'https://maps.app.goo.gl/LJWvkdhwrRMhjEZs7'; + }} + > + SEE ON MAP + + + + + + + router.push('/storefront')} + > + Shop + + router.push('/profileScreen')} + > + Profile + + router.push('/cart')} + > + Cart + + + + logo pic + +
+ ); +} diff --git a/src/components/FooterFolder/Location.tsx b/src/components/FooterFolder/Location.tsx new file mode 100644 index 00000000..9055951c --- /dev/null +++ b/src/components/FooterFolder/Location.tsx @@ -0,0 +1,17 @@ +import { LocationDiv, Addie } from '../NavBarFolder/styles'; + +export default function Location(props: { + District: string; + Address: string; + Phone: string; +}) { + const { District, Address, Phone } = props; + + return ( + +

{District}

+ {Address} +

{Phone}

+
+ ); +} diff --git a/src/components/FooterFolder/styles.ts b/src/components/FooterFolder/styles.ts new file mode 100644 index 00000000..1829fe3f --- /dev/null +++ b/src/components/FooterFolder/styles.ts @@ -0,0 +1,159 @@ +import styled from 'styled-components'; +import { ArrowUpRight, Facebook, Instagram, Youtube } from 'react-feather'; +import COLORS from '../../styles/colors'; + +export const Heading = styled.h1` + font-family: 'Public Sans', sans-serif; + color: black; + font-size: 40px; +`; + +export const ContactDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + margin-left: 40px; + margin-right: 40px; + gap: 18px; +`; + +export const LinkDiv = styled.div` + display: flex; + align-items: flex-start; + gap: 60px; + margin-left: 40px; + margin-right: 40px; +`; + +export const Body1Bold = styled.p` + font-size: 20px; + font-style: normal; + font-weight: 600; + line-height: normal; +`; + +export const Body1New = styled.p` + font-weight: 350; + font-size: 20px; + font-style: normal; + line-height: normal; +`; + +export const Body2New = styled.p` + font-size: 15px; + font-style: normal; + line-height: normal; +`; + +export const MissionDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + margin-left: 40px; + margin-right: 40px; + gap: 10px; +`; + +export const WordDiv = styled.div` + gap: 0px; +`; + +export const WordDiv1 = styled.div` + gap: 0px; + display: flex; + flex-direction: row; +`; + +export const Heading1Bold = styled.div` + font-family: 'Public Sans'; + font-size: 40px; + font-style: normal; + font-weight: 800; + line-height: normal; +`; + +export const ArrowUpRightIcon = styled(ArrowUpRight)` + stroke-width: 1.5; + width: 20px; + height: 20px; +`; + +export const YoutubeIcon = styled(Youtube)` + stroke-width: 1.5; + width: 33px; + height: 33px; +`; + +export const FacebookIcon = styled(Facebook)` + stroke-width: 1.5; + width: 33px; + height: 33px; +`; + +export const InstagramIcon = styled(Instagram)` + stroke-width: 1.5; + width: 33px; + height: 33px; +`; + +export const FooterDiv = styled.div` + font-family: 'Public Sans'; + color: ${COLORS.black}; + border-top: 2px solid ${COLORS.black}; + display: flex; + width: 1440px; + height: 288px; + padding: 48px 88px; + justify-content: center; + align-items: center; + gap: 90px; +`; + +export const SVGWrapper = styled.div` + display: flex; + align-items: flex-start; + gap: 20px; + flex-wrap: wrap; + flex-direction: row; + justify-content: space-evenly; +`; + +export const Wrapper = styled.div` + min-height: 100%; /*or 100vh */ + position: relative; + background: var(--Light-Periwinkle, #f4f7ff); + display: flex; + flex-wrap: wrap; + flex-direction: row; + justify-content: space-evenly; + align-items: center; + padding-top: 25px; + padding-bottom: 25px; + padding-right: 10px; + padding-left: 10px; + gap: 50px; +`; + +export const LocationDiv = styled.div` + display: flex; + flex-direction: column; + width: 300px; + height: 250px; + margin-right: 60px; + color: ${COLORS.black}; + font-family: Public Sans; + font-style: normal; + line-height: normal; +`; + +export const MySpan = styled.span` + &:hover { + text-decoration: underline; + } +`; + +export const MySpanIcon = styled.span` + :hover { + stroke-width: 2; + } +`; diff --git a/src/components/InputFieldsFolder/InputFields.tsx b/src/components/InputFieldsFolder/InputFields.tsx new file mode 100644 index 00000000..21625e58 --- /dev/null +++ b/src/components/InputFieldsFolder/InputFields.tsx @@ -0,0 +1,56 @@ +'use client'; + +import { useState } from 'react'; +import { Heading4 } from '@/styles/fonts'; +import { FormHeaders, Input } from './styles'; + +export default function InputFields(props: { + text: string; + placeholder: string; + inputType: string; + changeUserName: (newUsername: string) => void; + changePassword: (newPassword: string) => void; + isPassword: boolean; + isError: boolean; +}) { + const { + text, + placeholder, + inputType, + changeUserName, + changePassword, + isPassword, + isError, + } = props; + + const [inputValue, setInputValue] = useState(''); + + const handleChange = (e: React.ChangeEvent) => { + const { value } = e.target; + setInputValue(value); + + if (isPassword) { + changePassword(value); + } else { + changeUserName(value); + } + }; + + return ( +
+
+ + {text} + + +
+
+ ); +} diff --git a/src/components/InputFieldsFolder/styles.ts b/src/components/InputFieldsFolder/styles.ts new file mode 100644 index 00000000..2fa8ed20 --- /dev/null +++ b/src/components/InputFieldsFolder/styles.ts @@ -0,0 +1,56 @@ +import { EyeOff, Eye } from 'react-feather'; +import styled from 'styled-components'; +import COLORS from '../../styles/colors'; + +export const Input1 = styled.input<{ $pickColor?: boolean }>` + color: ${props => (props.$pickColor ? '#203354' : COLORS.black)}; + background: ${props => (props.$pickColor ? '#ADD8E6' : COLORS.lightGrey)}; + stroke-width: 1px; + width: 420px; + height: 40px; + padding-left: 10px; + border-color: ${COLORS.black}; +`; + +export const FormHeaders = styled.div` + color: ${COLORS.black}; + margin-top: 20px; + margin-bottom: 10px; +`; + +export const Input = styled.input<{ + $pickColor?: boolean; + $wrongLogin?: boolean; +}>` + &:focus { + border: 1.5px solid ${COLORS.navy}; + background: ${COLORS.skyBlue}; + outline: none; + color: ${COLORS.navy}; + } + stroke-width: 1px; + color: ${COLORS.black}; + border: 1.5px solid + ${props => (props.$wrongLogin ? COLORS.darkRed : COLORS.neutralGrey)}; + background: ${props => + props.$pickColor ? COLORS.lightRed : COLORS.lightGrey}; + width: 420px; + height: 40px; + padding-left: 10px; +`; + +export const EyeOffIcon = styled(EyeOff)` + stroke-width: 1.5; + width: 20px; + height: 20px; + color: black; + margin: 20px 20px 20px 20px; +`; + +export const EyeIcon = styled(Eye)` + stroke-width: 1.5; + width: 20px; + height: 20px; + color: black; + margin: 20px 20px 20px 20px; +`; diff --git a/src/components/LoginFormFolder/LoginForm.tsx b/src/components/LoginFormFolder/LoginForm.tsx new file mode 100644 index 00000000..684399e6 --- /dev/null +++ b/src/components/LoginFormFolder/LoginForm.tsx @@ -0,0 +1,34 @@ +'use client'; + +import InputFields from '../InputFieldsFolder/InputFields'; + +export default function LoginForm(props: { + changeUserName: (newUsername: string) => void; + changePassword: (newPassword: string) => void; + isError: boolean; + showPassword: boolean; +}) { + const { isError, changeUserName, changePassword, showPassword} = props; + return ( +
+ + +
+ ); +} diff --git a/src/components/NavBarFolder/NavBar.tsx b/src/components/NavBarFolder/NavBar.tsx new file mode 100644 index 00000000..c0f92fd5 --- /dev/null +++ b/src/components/NavBarFolder/NavBar.tsx @@ -0,0 +1,62 @@ +import Image from 'next/image'; +import React, { useEffect, useState } from 'react'; + +import { Body2, Body2Bold } from '@/styles/fonts'; +import { totalNumberOfItemsInCart } from '../../api/supabase/queries/cart_queries'; + +import { + NavBarComp, + ButtonsDiv, + CartTotalCircle, + UserProfileIcon, + ShoppingCartIcon, + IconWithLabelLink, +} from './styles'; + +export default function NavBar({ ...rest }) { + const [data, setData] = useState(0); + const [isZero, setIsZero] = useState(true); + + useEffect(() => { + const fetchData = async () => { + setData(await totalNumberOfItemsInCart()); + }; + fetchData(); + }, []); + + useEffect(() => { + const changeData = async () => { + if (data > 0) { + setIsZero(false); + } + }; + changeData(); + }, [data]); + + return ( + + + Shanti Logo + + + + + + User + + + + Cart + + {data} + + + + + ); +} diff --git a/src/components/NavBarFolder/styles.ts b/src/components/NavBarFolder/styles.ts new file mode 100644 index 00000000..f96c286f --- /dev/null +++ b/src/components/NavBarFolder/styles.ts @@ -0,0 +1,74 @@ +import styled from 'styled-components'; + +import { User, ShoppingCart } from 'react-feather'; +import Link from 'next/link'; +import COLORS from '../../styles/colors'; + +export const CartTotalCircle = styled.div<{ $isZero?: boolean }>` + display: ${props => (props.$isZero ? 'none' : 'content')}; + width: 24px; + height: 24px; + border-radius: 50%; + position: absolute; + top: -13px; + right: -13px; + display: flex; + justify-content: center; + align-items: center; + color: ${COLORS.white}; + background: ${COLORS.marineBlue}; +`; + +export const UserProfileIcon = styled(User)` + color: ${COLORS.black}; +`; + +export const ShoppingCartIcon = styled(ShoppingCart)` + color: ${COLORS.black}; +`; + +export const NavBarComp = styled.nav` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 16px 32px; + position: relative; + width: 100%; + background: ${COLORS.lightPeriwinkle}; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; + +export const ButtonsDiv = styled.div` + width: 100px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +`; + +export const LocationDiv = styled.div` + display: flex; + flex-direction: column; + width: 300px; + height: 250px; + margin-right: 60px; + color: ${COLORS.black}; + font-family: Public Sans; + font-style: normal; + line-height: normal; +`; + +export const Addie = styled.p` + margin-top: 30px; + margin-bottom: 30px; +`; + +export const IconWithLabelLink = styled(Link)` + display: flex; + flex-direction: column; + align-items: center; + text-decoration: none; + color: ${COLORS.black}; + position: relative; +`; diff --git a/src/components/OrderHistory/ImageCarousel.tsx b/src/components/OrderHistory/ImageCarousel.tsx new file mode 100644 index 00000000..159adb28 --- /dev/null +++ b/src/components/OrderHistory/ImageCarousel.tsx @@ -0,0 +1,21 @@ +/* eslint-disable react/no-array-index-key */ +import React from 'react'; +import { GalleryContainer, ImageContainer, GalleryImage } from './styles'; + +interface ImageGalleryProps { + images: string[]; // Array of image URLs +} + +export default function ImageGallery(props: ImageGalleryProps) { + const { images } = props; + + return ( + + {images.map((image, index) => ( + + + + ))} + + ); +} diff --git a/src/components/OrderHistory/OrderHistoryBox.tsx b/src/components/OrderHistory/OrderHistoryBox.tsx new file mode 100644 index 00000000..392271dc --- /dev/null +++ b/src/components/OrderHistory/OrderHistoryBox.tsx @@ -0,0 +1,61 @@ +'use client'; + +// Importing the required components and styles +import React, { useState, useEffect } from 'react'; +import { Order, Product } from '../../schema/schema'; +import { + getOrderById, + fetchProductsFromOrder, +} from '../../api/supabase/queries/order_queries'; +import ImageCarousel from './ImageCarousel'; +import OrderHistoryText from './OrderHistoryText'; +import { RowDiv } from './styles'; + +interface OrderDetailsWithProductsProps { + orderId: number; +} + +export default function OrderDetailsWithProducts({ + orderId, +}: OrderDetailsWithProductsProps) { + const [order, setOrder] = useState(null); + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + const fetchData = async () => { + setLoading(true); + try { + const fetchedOrder = await getOrderById(orderId); + const fetchedProducts = await fetchProductsFromOrder(orderId); + setOrder(fetchedOrder); + setProducts(fetchedProducts); + } finally { + setLoading(false); + } + }; + + fetchData(); + }, [orderId]); + + if (loading) { + return
Loading...
; + } + + if (!order) { + return
; + } + + const imageUrls = products.map(product => product.photo).slice(0, 3); + + return ( + + + + + ); +} diff --git a/src/components/OrderHistory/OrderHistoryText.tsx b/src/components/OrderHistory/OrderHistoryText.tsx new file mode 100644 index 00000000..3c109481 --- /dev/null +++ b/src/components/OrderHistory/OrderHistoryText.tsx @@ -0,0 +1,166 @@ +import React from 'react'; +import { useRouter } from 'next/navigation'; + +import querystring from 'querystring'; +import { Heading4Bold, Body1, OrderStatusFont } from '@/styles/fonts'; +import { + ViewOrderButton, + ArrowIcon, + OrderStatusDiv, + CheckStyled, + OrderStatusApprovedDiv, + CrossStyled, + OrderStatusSubmittedDiv, + LoaderStyled, +} from './styles'; // Adjust the import path as necessary +import { Order, OrderStatus } from '../../schema/schema'; + +function formatDate(isoString: string) { + const options: Intl.DateTimeFormatOptions = { + year: 'numeric', + month: 'long', + day: 'numeric', + }; + const date = new Date(isoString); + return date.toLocaleDateString('en-US', options); +} + +interface OrderDetailsProps { + date: string; + orderNumber: string; + order: Order; +} + +export default function OrderDetails(props: OrderDetailsProps) { + const { date, orderNumber, order } = props; + const router = useRouter(); + + const viewOrder = (orderID: string) => { + const queryString = querystring.stringify({ orderID }); + router.push(`/orderPage?${queryString}`); + }; + if (order.order_status === OrderStatus.Rejected) { + return ( +
+
+ Order No. {orderNumber} + viewOrder(orderNumber)}> + View Order + + +
+ + + {formatDate(date)} + + + + Order Rejected + +
+ ); + } + if (order.order_status === OrderStatus.Complete) { + return ( +
+
+ Order No. {orderNumber} + viewOrder(orderNumber)}> + View Order + + +
+ + + {formatDate(date)} + + + + Order Approved + +
+ ); + } + if (order.order_status === OrderStatus.Submitted) { + return ( +
+
+ Order No. {orderNumber} + viewOrder(orderNumber)}> + View Order + + +
+ + + {formatDate(date)} + + + + Order Submitted + +
+ ); + } + return

; +} diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts new file mode 100644 index 00000000..fec7e6c7 --- /dev/null +++ b/src/components/OrderHistory/styles.ts @@ -0,0 +1,218 @@ +// styles.ts +import styled from 'styled-components'; +import { X, Check, Loader } from 'react-feather'; +import COLORS from '../../styles/colors'; + +export const containerStyle = styled.div` + width: 250px; // This width might be too small if it's meant to contain the OrderDiv + height: 250px; + margin-right: auto; // Center the container if that's the intention + margin-left: auto; // Center the container if that's the intention + color: ${COLORS.black}; + font-family: Public Sans; + font-size: 20px; + font-style: normal; + line-height: normal; +`; + +export const imageGalleryStyle = { + display: 'flex', + overflowX: 'auto', + gap: '10px', + // Add more styles as needed +}; + +export const viewButtonStyle = { + marginTop: '10px', + backgroundColor: 'blue', + color: 'white', + padding: '10px 20px', + cursor: 'pointer', + // Add more styles as needed +}; + +export const ViewOrderButton = styled.button` + overflow: hidden; + color: var(--Black, #101010); + text-align: right; + text-overflow: ellipsis; + line-height: normal; + background: none; + border: none; + cursor: pointer; + display: flex; + align-items: center; + &:hover { + text-decoration: underline; + } +`; + +export const ArrowIcon = styled.div` + width: 0; + height: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid var(--Black, #101010); + margin-left: 5px; +`; + +export const OrderDiv = styled.div` + display: flex; + flex-direction: row; + align-items: start; + justify-content: space-between; // Changed to space-between to align items to the edges + width: 100%; + margin-bottom: 50px; + margin-top: 30px; + padding-left: 30px; // Adjust as necessary to align with the left edge + padding-right: 130px; // Adjust as necessary to align with the right edge +`; + +export const OrderApproved = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; /* Assuming you want the checkmark and text to be at the start */ + background-color: #cee8be; /* Or the exact color from the image */ + color: white; + color: var(--Black, #101010); + font-family: 'Public Sans'; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; + + border-radius: 20px; /* Adjust for the exact curvature you want */ + gap: 14px; /* Space between the checkmark and text */ + width: 245px; + margin-top: 18px; + padding-left: 10px; /* Adjust as necessary to align with the left edge */ + padding-right: 10px; /* Adjust as necessary to align with the right edge */ + padding-top: 5px; /* Adjust as necessary to align with the top edge */ + padding-bottom: 5px; /* Adjust as necessary to align with the bottom edge */ +`; + +export const OrderReject = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; /* Assuming you want the checkmark and text to be at the start */ + background-color: #fdd; /* Or the exact color from the image */ + color: white; + color: var(--Black, #101010); + font-family: 'Public Sans'; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; + + border-radius: 20px; /* Adjust for the exact curvature you want */ + gap: 14px; /* Space between the checkmark and text */ + width: 245px; + margin-top: 18px; + padding-left: 10px; /* Adjust as necessary to align with the left edge */ + padding-right: 10px; /* Adjust as necessary to align with the right edge */ + padding-top: 5px; /* Adjust as necessary to align with the top edge */ + padding-bottom: 5px; /* Adjust as necessary to align with the bottom edge */ +`; + +export const OrderReady = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; /* Assuming you want the checkmark and text to be at the start */ + background-color: #fdd; /* Or the exact color from the image */ + color: white; + color: var(--Black, #101010); + font-family: 'Public Sans'; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; + + border-radius: 20px; /* Adjust for the exact curvature you want */ + gap: 14px; /* Space between the checkmark and text */ + width: 245px; + margin-top: 18px; + padding-left: 10px; /* Adjust as necessary to align with the left edge */ + padding-right: 10px; /* Adjust as necessary to align with the right edge */ + padding-top: 5px; /* Adjust as necessary to align with the top edge */ + padding-bottom: 5px; /* Adjust as necessary to align with the bottom edge */ +`; + +export const GalleryContainer = styled.div` + display: flex; + overflow-x: auto; + gap: 10px; + padding: 10px; +`; + +export const ImageContainer = styled.div` + flex: 0 0 auto; + background-color: var(--Greyish, #e6e6e6); + width: 124px; + height: 124px; + display: flex; + justify-content: center; + align-items: center; +`; + +export const GalleryImage = styled.img` + height: 115px; + width: 115px; + display: block; +`; + +export const RowDiv = styled.div` + width: 700px; + height: 300px; + margin-bottom: 20px; +`; + +export const OrderStatusDiv = styled.div` + width: 300px; + height: 35px; + background: var(--Light-Red, #fdd); + display: flex; + justify-content: center; + align-items: center; + border-radius: 20px; + margin-top: 15px; +`; + +export const OrderStatusApprovedDiv = styled.div` + width: 300px; + height: 35px; + background: var(--Lime-Green, #cee8be); + display: flex; + justify-content: center; + align-items: center; + border-radius: 20px; + margin-top: 15px; +`; + +export const OrderStatusSubmittedDiv = styled.div` + width: 300px; + height: 35px; + background: var(--Baby-Blue, #c7ddff); + display: flex; + justify-content: center; + align-items: center; + border-radius: 20px; + margin-top: 15px; +`; + +export const CrossStyled = styled(X)` + stroke-width: 5px; + margin-right: 10px; +`; + +export const CheckStyled = styled(Check)` + stroke-width: 5px; + margin-right: 10px; +`; + +export const LoaderStyled = styled(Loader)` + stroke-width: 3px; + margin-right: 10px; +`; diff --git a/src/components/OrderSummaryFolder/OrderSummary.tsx b/src/components/OrderSummaryFolder/OrderSummary.tsx new file mode 100644 index 00000000..9cf046cc --- /dev/null +++ b/src/components/OrderSummaryFolder/OrderSummary.tsx @@ -0,0 +1,48 @@ +'use client'; + +import { Body1, Heading2Bold, Body1Bold, Body2Light } from '@/styles/fonts'; +import { + OrderSummaryDiv, + HeaderShiftRight, + OrderTotalDiv, + WhiteBackgroundDiv, + AlignItemCenter, + ItemSummaryDiv, + OrderSummaryHeaderDiv, + ItemNameDiv, +} from './styles'; +import { ProductWithQuantity } from '../../schema/schema'; + +export default function OrderSummary(props: { + cart: ProductWithQuantity[]; + numberOfItems: number; +}) { + const { cart, numberOfItems } = props; + + return ( + + Order Summary + + + PRODUCT NAME + QTY + + + {cart.map(cartItem => ( + + + {cartItem.name} + + + {cartItem.quantity} + + ))} + + + + Order Total + {numberOfItems} + + + ); +} diff --git a/src/components/OrderSummaryFolder/styles.ts b/src/components/OrderSummaryFolder/styles.ts new file mode 100644 index 00000000..16fd4a3f --- /dev/null +++ b/src/components/OrderSummaryFolder/styles.ts @@ -0,0 +1,77 @@ +import COLORS from '@/styles/colors'; +import styled from 'styled-components'; + +export const OrderSummaryDiv = styled.div` + overflow: scroll; + width: 300px; + height: 300px; + display: flex; + flex-direction: column; +`; + +export const ItemSummaryDiv = styled.div` + display: flex; + flex-direction: row; + margin-bottom: 20px; + justify-content: space-between; +`; + +export const OrderTotalDiv = styled.div` + height: 50px; + padding-top: 5px; + width: 100%; + border-top: 1px black solid; + display: flex; + flex-flow: row; + align-items: center; + justify-content: space-between; +`; + +export const Qty = styled.p` + width: 100%; +`; + +export const WhiteBackgroundDiv = styled.div` + border-radius: 8px; + background: var(--White, #fff); + height: 455px; + width: 350px; + padding: 20px; + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); + display: flex; + justify-content: center; + align-items: flex-start; + flex-direction: column; +`; + +export const HeaderShiftRight = styled.h2` + margin-right: 30px; +`; + +export const PShiftRight = styled.p` + margin-right: 30px; +`; + +export const PShiftLeft = styled.p` + margin-left: 15px; +`; + +export const OrderSummaryHeaderDiv = styled.div` + display: flex; + width: 300px; + justify-content: space-between; + align-items: center; + flex-direction: row; + margin-bottom: 15px; + color: ${COLORS.marineBlue}; +`; + +export const ItemNameDiv = styled.div` + width: 200px; + overflow: hidden; +`; + +export const AlignItemCenter = styled.div` + margin-left: 10px; + margin-top: 10px; +`; diff --git a/src/components/PickUpFolder/PickupButton.tsx b/src/components/PickUpFolder/PickupButton.tsx new file mode 100644 index 00000000..824bb2d1 --- /dev/null +++ b/src/components/PickUpFolder/PickupButton.tsx @@ -0,0 +1,22 @@ +/* eslint-disable */ +import { useState } from 'react'; + +function PickupButton({}: { + day: string; + date: string; + start: string; + end: string; +}) { + const [isSelected, setIsSelected] = useState(false); + + // const defaultStyle = 'bg-[#4b711d]/[0.13] text-[#4B711D] border-[#547829]'; + // const selectedStyle = 'bg-[#547829] text-white border-[#547829]'; + + // const handleClick = () => { + setIsSelected(!isSelected); + // }; + + return
@@ -156,7 +157,7 @@ export default function OrderDetails(props: OrderDetailsProps) { {formatDate(date)}
- + Order Submitted
diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index c321c849..b5adf0ef 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -1,6 +1,6 @@ // styles.ts import styled from 'styled-components'; -import { X, Check, Loader } from 'react-feather'; +import { X, Check, Send, Loader } from 'react-feather'; import COLORS from '../../styles/colors'; export const containerStyle = styled.div` @@ -166,7 +166,8 @@ export const GalleryImage = styled.img` export const RowDiv = styled.div` width: 700px; height: 400px; - margin-bottom: 50px; + margin-bottom: 20px; + margin-top: 20px; `; export const OrderStatusDiv = styled.div` @@ -194,7 +195,7 @@ export const OrderStatusApprovedDiv = styled.div` export const OrderStatusSubmittedDiv = styled.div` width: 300px; height: 35px; - background: var(--Baby-Blue, #c7ddff); + background: var(--Greyish, #E6E6E6); display: flex; justify-content: center; align-items: center; @@ -212,7 +213,7 @@ export const CheckStyled = styled(Check)` margin-right: 10px; `; -export const LoaderStyled = styled(Loader)` +export const SendStyle = styled(Send)` stroke-width: 3px; margin-right: 10px; `; diff --git a/src/components/ViewAllButton/ViewAllButton.tsx b/src/components/ViewAllButton/ViewAllButton.tsx index a5a574f4..d629c442 100644 --- a/src/components/ViewAllButton/ViewAllButton.tsx +++ b/src/components/ViewAllButton/ViewAllButton.tsx @@ -1,15 +1,14 @@ import Link from 'next/link'; -import { ArrowRight } from 'react-feather'; -import { Body1Point5 } from '@/styles/fonts'; -import { ViewAllDiv } from './styles'; +import { Body2, Body2Bold } from '@/styles/fonts'; +import { ArrowRightIcon, ViewAllDiv } from './styles'; export default function BackButton(props: { destination: string }) { const { destination } = props; return ( - View All - + View All + ); diff --git a/src/components/ViewAllButton/styles.ts b/src/components/ViewAllButton/styles.ts index 248778df..17ce6d93 100644 --- a/src/components/ViewAllButton/styles.ts +++ b/src/components/ViewAllButton/styles.ts @@ -1,7 +1,11 @@ import styled from 'styled-components'; +import { ArrowRight } from 'react-feather'; import COLORS from '../../styles/colors'; + export const ViewAllDiv = styled.div` + width: 80px; + gap: 5px; display: flex; align-items: center; color: ${COLORS.black}; @@ -13,3 +17,8 @@ export const ViewAllDiv = styled.div` `; export const placeHolder = ''; + +export const ArrowRightIcon = styled(ArrowRight)` + width: 20px; + height: 20px; +`; From f9d3c304ef2c7f90134f6e10aff403c82c34c14c Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 14:39:57 -0700 Subject: [PATCH 19/43] save --- src/app/orderConfirmationDelivery/page.tsx | 1 - src/app/profileScreen/page.tsx | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx index 1652742e..6fa3eaf0 100644 --- a/src/app/orderConfirmationDelivery/page.tsx +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -9,7 +9,6 @@ import { import { Body1, Body2, - Body2Light, Heading3Bold, Heading4Bold, } from '@/styles/fonts'; diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 995716f3..15e5006a 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -389,6 +389,7 @@ export default function Profile() { fetchOrders(); getUser(); }, []); + if (user === undefined) { return

Loading User

; } From 1d4191bd3e2d0a77ade2c56370137b9bfd4ad628 Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 14:40:05 -0700 Subject: [PATCH 20/43] ip --- src/app/orderConfirmationPickUp/page.tsx | 24 +++++++++++++---------- src/app/orderConfirmationPickUp/styles.ts | 18 ++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index c9b612ce..c358b909 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -9,41 +9,45 @@ import { getOrderById, } from '@/api/supabase/queries/order_queries'; import { + Body2Bold, + Body2, + Heading3Bold, Body1, Body1Bold, - Body2Light, - Heading3Bold, Heading4Bold, + Body2Light, } from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; -import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; +import { fetchCartItemsWithQuantity,fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; import BackButton from '../../components/BackButton/BackButton'; import NavBar from '../../components/NavBarFolder/NavBar'; import { - TextDiv, - TextDiv1, - BackButtonDiv, FavoriteDiv, + ColDiv, OutterFavoriteDiv, + TextDiv1, + OutterBox, + Label, LabelBox, - LabelBox1, ScrollDiv, ShippingDetailsDiv, ImageDiv, BottomColumnDiv, - Wrapper, + LabelBox1, LeftColumnDiv, RightColumnDiv, DetailsHeader, PageDiv, CenterDiv, + BackButtonDiv, + TextDiv, } from './styles'; import { Product, User, Pickup } from '../../schema/schema'; - + export default function OrderConfirmationPickUp() { const [Cart, setCart] = useState([]); const [user, setUser] = useState(); @@ -97,7 +101,7 @@ export default function OrderConfirmationPickUp() { - Order No. {orderIDFromSearch} + Order No. {user?.cart_id} {Cart.map(cartItem => ( diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index 4f2e25a8..e357575d 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -26,9 +26,8 @@ export const OutterFavoriteDiv = styled.div` max-height: 100%; margin-top: 20px; margin-right: 60px; - margin-left: 60px; - padding-right: 20px; - padding-left: 10px; + margin-left: 40px; + padding-right: 15px; padding-top: 10px; `; @@ -232,7 +231,6 @@ export const RightColumnDiv = styled.div` display: flex; flex-flow: column; align-items: start; - margin-left: 10px; width: 100%; `; @@ -241,8 +239,8 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; - margin-left: 80px; - margin-top: 40px; + margin-left: 60px; + margin-bottom: 40px; `; export const WhiteBackgroundDiv = styled.div` @@ -261,6 +259,7 @@ export const BottomColumnDiv = styled.div` justify-content: space-around; width: 100%; margin-left: 20px; + margin-right: 20px; margin-bottom: 30px; gap: 30px; `; @@ -268,7 +267,7 @@ export const BottomColumnDiv = styled.div` export const TextDiv = styled.div` display: flex; flex-direction: row; - margin-left: 60px; + margin-left: 40px; margin-top: 20px; margin-bottom: 20px; `; @@ -287,6 +286,7 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; + margin-bottom: 40px; `; export const ShippingDetailsDiv = styled.div` @@ -296,7 +296,7 @@ export const ShippingDetailsDiv = styled.div` border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 467px; + width: 475px; height: auto; max-height: 100%; padding: 36px 34px; @@ -322,4 +322,4 @@ export const CenterDiv = styled.div` justify-content: center; width: 100%; padding: 20px; -`; +`; \ No newline at end of file From 704ad419b596c8deed9a9fd59b15ed58c37d8ffd Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 14:41:01 -0700 Subject: [PATCH 21/43] ip --- src/app/orderConfirmationPickUp/page.tsx | 3 +- src/app/orderConfirmationPickUp/styles.ts | 47 +++++++++++++++-------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index c358b909..5f1b8215 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -40,6 +40,7 @@ import { LeftColumnDiv, RightColumnDiv, DetailsHeader, + Wrapper2, PageDiv, CenterDiv, BackButtonDiv, @@ -77,7 +78,6 @@ export default function OrderConfirmationPickUp() { function organizePickupTime() { const startTime = pickupTime?.start_time.toLocaleString(); - const endTime = pickupTime?.end_time.toLocaleString(); const date = startTime == null ? ['0', '0', '0'] @@ -159,6 +159,7 @@ export default function OrderConfirmationPickUp() {
+
diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index e357575d..255792de 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -9,10 +9,10 @@ export const FavoriteDiv = styled.div` flex-direction: row; align-items: center; justify-content: space-between; - width: 100%; + width: 750px; margin-bottom: 50px; margin-top: 30px; - margin-right: 20px; + margin-right: 10px; `; export const OutterFavoriteDiv = styled.div` @@ -22,18 +22,19 @@ export const OutterFavoriteDiv = styled.div` border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 800px; max-height: 100%; + max-width: 750px; margin-top: 20px; - margin-right: 60px; - margin-left: 40px; - padding-right: 15px; - padding-top: 10px; + margin-right: 10px; + margin-left: 20px; + padding-right: 7px; + padding-top: 7px; `; export const ScrollDiv = styled.div` overflow: scroll; - width: 100%; + overflow-x: hidden; + max-width: 100%; `; export const ImageDiv = styled.div` @@ -225,13 +226,13 @@ export const LeftColumnDiv = styled.div` flex-flow: column; justify-content: space-evenly; align-items: space-evenly; - width: 100%; + width: 800px; `; export const RightColumnDiv = styled.div` display: flex; flex-flow: column; - align-items: start; - width: 100%; + align-items: left; + width: 475px; `; export const BackButtonDiv = styled.div` @@ -239,8 +240,9 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; - margin-left: 60px; + margin-left: 40px; margin-bottom: 40px; + margin-top: 20px; `; export const WhiteBackgroundDiv = styled.div` @@ -252,6 +254,14 @@ export const WhiteBackgroundDiv = styled.div` box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); `; + +export const Wrapper2 = styled.div` + display: flex; + flex-direction: col; + align-items: space-evenly; + justify-content: space-around; +`; + export const BottomColumnDiv = styled.div` display: flex; flex-direction: row; @@ -261,15 +271,15 @@ export const BottomColumnDiv = styled.div` margin-left: 20px; margin-right: 20px; margin-bottom: 30px; - gap: 30px; + gap: 10px; `; export const TextDiv = styled.div` display: flex; flex-direction: row; - margin-left: 40px; - margin-top: 20px; - margin-bottom: 20px; + margin-left: 20px; + margin-top: 10px; + margin-bottom: 10px; `; export const TextDiv1 = styled.div` @@ -286,10 +296,12 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; + position: relative; margin-bottom: 40px; `; export const ShippingDetailsDiv = styled.div` + display: flex; flex-direction: column; align-items: flex-start; @@ -302,7 +314,7 @@ export const ShippingDetailsDiv = styled.div` padding: 36px 34px; gap: 33px; max-height: 100%; - margin-top: 205px; + margin-top: 75px; margin-bottom: 30px; margin-right: 40px; `; @@ -320,6 +332,7 @@ export const CenterDiv = styled.div` display: flex; align-items: center; justify-content: center; + position: relative; width: 100%; padding: 20px; `; \ No newline at end of file From 257f0042c117136c1e57d13c61d714c1d5636a0d Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 14:42:46 -0700 Subject: [PATCH 22/43] ip --- src/app/orderConfirmationPickUp/page.tsx | 12 +- src/app/orderConfirmationPickUp/styles.ts | 16 +- src/app/orderHistory/page.tsx | 9 +- src/app/orderHistory/styles.ts | 24 +++ src/app/orderPage/page.tsx | 122 +++++++++++---- src/app/orderPage/styles.ts | 146 ++++++++++++++++-- src/app/profileScreen/page.tsx | 47 +++--- src/app/profileScreen/styles.ts | 59 +++++-- src/components/BackButton/BackButton.tsx | 8 + src/components/BackButton/styles.ts | 9 ++ .../OrderHistory/OrderHistoryText.tsx | 13 +- src/components/OrderHistory/styles.ts | 12 +- .../ViewAllButton/ViewAllButton.tsx | 9 +- src/components/ViewAllButton/styles.ts | 9 ++ 14 files changed, 390 insertions(+), 105 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 5f1b8215..090e4bc1 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -4,6 +4,7 @@ import { useState, useEffect } from 'react'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; import { fetchCurrentOrdersByUser, getOrderById, @@ -34,13 +35,11 @@ import { LabelBox, ScrollDiv, ShippingDetailsDiv, - ImageDiv, BottomColumnDiv, - LabelBox1, LeftColumnDiv, RightColumnDiv, DetailsHeader, - Wrapper2, + ImageDiv, PageDiv, CenterDiv, BackButtonDiv, @@ -56,10 +55,13 @@ export default function OrderConfirmationPickUp() { const searchParams = useSearchParams(); const orderIDFromSearch = searchParams.get('orderID'); + useEffect(() => { async function fetchProducts() { + const cartItems = (await fetchCartItemsWithQuantityByID( orderIDFromSearch, + )) as Product[]; setCart(cartItems); } @@ -116,13 +118,13 @@ export default function OrderConfirmationPickUp() { }} /> - + {cartItem.name}
Category: {cartItem.category} -
+
+ +<<<<<<< HEAD
Order History
+======= +
+ Order History +>>>>>>> b287da7 (temp) {orderIds.length > 0 ? ( orderIds.map((orderId: number) => ( diff --git a/src/app/orderHistory/styles.ts b/src/app/orderHistory/styles.ts index a93abdc1..4746ba4c 100644 --- a/src/app/orderHistory/styles.ts +++ b/src/app/orderHistory/styles.ts @@ -13,6 +13,17 @@ export const NavBarMovedUP = styled(NavBar)` position: relative; `; +export const BackButtonDiv = styled.div` + display: flex; + flex-direction: row; + gap: 200px; + margin-bottom: 30px; + margin-top: 50px; + text-align: left; + width: 800px; + padding-right: 40px; +`; + export const OutterBox = styled.div` width: 800px; margin-top: 40px; @@ -20,16 +31,29 @@ export const OutterBox = styled.div` `; export const OrderHistoryContainer = styled.div` + display: flex; flex-direction: column; align-items: center; border-radius: 10px; +<<<<<<< HEAD background: ${COLORS.white}; box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); width: 800px; // Width of the outer box height: auto; margin-top: 10px; padding-top: 40px; +======= + background: var(--White, #fff); + background-color: pink; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 800px; // Width of the outer box + height: 700px; + overflow: scroll; + margin-top: 20px; + margin-bottom: 50px; + padding: 0; // Ensure there's no padding pushing the internal boxes inward +>>>>>>> b287da7 (temp) `; export const OrderHistoryBox = styled.div` diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index 6d2d0fd9..27bfbf09 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -1,7 +1,8 @@ 'use client'; import { useState, useEffect } from 'react'; -import { Body1, Body2 } from '@/styles/fonts'; +import { Check, X, Send } from 'react-feather'; +import { Body1, Body2Light, Heading3Bold, Heading4Bold, Body2, Heading2, Body1Bold } from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; import BackButton from '../../components/BackButton/BackButton'; @@ -14,13 +15,23 @@ import NavBar from '../../components/NavBarFolder/NavBar'; import { FavoriteDiv, - Body1Bold, OutterFavoriteDiv, BackButtonDiv, + DetailsHeader, + RightColumnDiv, + TextDiv, + TextDiv1, OutterBox, OutterDiv, - Heading, + ImageDiv, + BottomColumnDiv, + ShippingDetailsDiv, + LabelBox, + LeftColumnDiv, + ScrollDiv, ProductNameDiv, + PageDiv, + CenterDiv, StatusButton, } from './styles'; @@ -76,40 +87,87 @@ export default function OrderPage() { } fetchProducts(); }, []); + + const status = order?.order_status?.toLowerCase() || 'default'; return (
+ + + + + + + + + {formatDate(order?.created_at)} + + + + Order No + + + {orders.map(product => ( + + + {product.name} + - - - - - - {formatDate(order?.created_at)} - - {' '} - {order?.order_status}{' '} - - - - {orders.map(product => ( - - {product.name} - - {product.name} - Category: {product.category} - - - ))} - - + + {product.name} +
+ + Category: {product.category} + +
+ +
+ + Quantity: + + + {product.quantity} + +
+
+
+ ))} +
+
+
+ + + Pickup Information + Time Slot + Location + 3170 23rd Street, San Francisco, CA 94110 + + +
+ +
+
); } + + + diff --git a/src/app/orderPage/styles.ts b/src/app/orderPage/styles.ts index c2c236bb..122fc5fe 100644 --- a/src/app/orderPage/styles.ts +++ b/src/app/orderPage/styles.ts @@ -5,16 +5,50 @@ import { Heart } from 'react-feather'; import NavBar from '../../components/NavBarFolder/NavBar'; export const FavoriteDiv = styled.div` +display: flex; +flex-direction: row; +align-items: center; +justify-content: space-between; +width: 100%; +margin-bottom: 50px; +margin-top: 30px; +margin-right: 20px; +margin-left: 40px; +gap: 70px; +`; + +export const BottomColumnDiv = styled.div` display: flex; flex-direction: row; - align-items: start; + align-items: space-evenly; justify-content: space-around; width: 100%; - margin-bottom: 50px; - margin-top: 30px; + margin-left: 10px; + margin-bottom: 30px; + gap: 10px; `; -export const OutterFavoriteDiv = styled.div` +export const ScrollDiv = styled.div` + overflow: scroll; + overflow-x: hidden; + max-width: 100%; +`; + +export const ImageDiv = styled.p` + width: 150px; + height: 150px; + align-items: center; + justify-content: center; + display: flex; + margin-right: 20px; +`; + +export const LabelBox = styled.div` + width: 200px; + height: 100%; +`; + +export const OutterFavoriteDiv = styled.div` display: flex; flex-direction: column; align-items: center; @@ -25,6 +59,7 @@ export const OutterFavoriteDiv = styled.div` height: 700px; overflow: scroll; margin-top: 20px; + padding-top: 15px; `; export const BackDiv = styled.button` @@ -66,7 +101,8 @@ export const BackButtonDiv = styled.div` display: flex; flex-direction: row; gap: 200px; - margin-bottom: 55px; + margin-bottom: 50px; + margin-top: 50px; text-align: left; width: 800px; `; @@ -116,26 +152,116 @@ export const ViewItem = styled.button` border-radius: 14px; `; -export const StatusButton = styled.button` +export const StatusButton = styled.button<{ status: string }>` margin-left: auto; margin-right: 0; color: black; text-align: center; - width: 210px; + max-width: 100%; height: 30px; flex-shrink: 0; padding-top: 3px; - padding-right: 10px; - padding-left: 10px; + padding-right: 30px; + padding-left: 30px; padding-bottom: 3px; + display: flex; + gap: 15px; + flex-direction: row; + align-items: center; /* Center vertically */ + justify-content: center; border: none; border-radius: 16.5px; - background: var(--Baby-Blue, #c7ddff); + background-color: ${props => { + switch (props.status) { + case 'submitted': + return 'var(--Greyish, #E6E6E6)'; + case 'rejected': + return 'var(--Light-Red, #FDD)'; + case 'approved': + return 'var(--Lime-Green, #CEE8BE)'; + default: + return 'white'; + } + }}; `; + export const Body1Bold = styled.p` font-size: 16px; font-style: normal; font-weight: 600; line-height: normal; `; + +export const PageDiv = styled.div` + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + width: 100%; +`; + +export const CenterDiv = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 20px; +`; + +export const DetailsHeader = styled.p` + color: var(--Navy, #1b3679); + font-family: Public Sans, sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const ShippingDetailsDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 467px; + height: auto; + max-height: 100%; + padding: 36px 34px; + gap: 33px; + max-height: 100%; + margin-top: 93px; + margin-bottom: 30px; + margin-right: 40px; +`; + +export const RightColumnDiv = styled.div` + display: flex; + flex-flow: column; + align-items: start; + margin-left: 10px; + width: 100%; +`; + +export const TextDiv1 = styled.div` + display: flex; + flex-direction: row; + margin-top: 20px; +`; + +export const TextDiv = styled.div` + display: flex; + flex-direction: row; + margin-left: 60px; + margin-top: 20px; + margin-bottom: 20px; +`; + +export const LeftColumnDiv = styled.div` + display: flex; + flex-flow: column; + justify-content: space-evenly; + align-items: space-evenly; + width: 100%; +`; \ No newline at end of file diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 0b98511a..6a46952f 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -10,6 +10,7 @@ import { Heading1, Body1Bold, Body2Bold, + Body2Light, Body2, } from '@/styles/fonts'; import { @@ -36,8 +37,10 @@ import BackButton from '../../components/BackButton/BackButton'; import { LogOutButton, NavBarMovedUP, - AccountDetails, + AccountDetailsDeliv, + AccountDetailsPickUp, HeadingBack, + Spacing, HeadingSpacing, TextSpacing, OrderHistory, @@ -81,14 +84,15 @@ function FavoriteSection(props: { {favorite.name} -

- {favorite.name} -
- Product ID: {favorite.id} -

+ + {favorite.name} + + + Category: {favorite.category} +
clickFunctions({ fav: favorite })} @@ -206,13 +210,13 @@ function OrderHistorySection(props: { Orders: Order[] }) { > Order No. {Orders[0].id} - {fD} - +
{icon} @@ -287,38 +291,37 @@ function AccountDetailSectionDelivery(props: { user: User }) { }, []); return (
- + Account Details Name - + {user?.first_name} {user?.last_name} - + Email - {user?.email} + {user?.email} - Phone - {user?.phone_numbers} + {user?.phone_numbers} Address - + {UserAddress?.street}, {UserAddress?.city}, {UserAddress?.zipcode} - + - +
); } @@ -327,7 +330,7 @@ function AccountDetailSectionPickUp(props: { user: User }) { return (
- + Account Details @@ -351,7 +354,7 @@ function AccountDetailSectionPickUp(props: { user: User }) { {user?.phone_numbers} - +
); } @@ -433,7 +436,7 @@ export default function Profile() { - + diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 1ee1f70b..c5e39346 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -21,9 +21,8 @@ export const HeadingBack = styled.div` margin-right: 75px; `; -export const AccountDetails = styled.div` - margin-top: 50px; - margin-right: 30px; +export const AccountDetailsDeliv = styled.div` + margin-top: 40px; width: 500px; height: 350px; border-radius: 10px; @@ -35,25 +34,41 @@ export const AccountDetails = styled.div` padding-top: 29px; padding-right: 29px; padding-left: 29px; - padding-bottom: 29px; + padding-bottom: 32px; +`; + +export const AccountDetailsPickUp = styled.div` + margin-top: 40px; + width: 500px; + height: 310px; + border-radius: 10px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + display: flex; + flex-direction: column; + align-items: left; + padding-top: 29px; + padding-right: 29px; + padding-left: 29px; + padding-bottom: 32px; + margin-bottom: 40px; `; export const OrderHistory = styled.div` - margin-top: 50px; + margin-top: 40px; width: 600px; height: 350px; border-radius: 10px; background: ${COLORS.white}; box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - padding-top: 23px; - padding-right: 23px; - padding-left: 23px; - padding-bottom: 23px; + padding-top: 29px; + padding-right: 29px; + padding-left: 29px; + padding-bottom: 29px; + margin-left: 60px; `; export const FavoritesContainer = styled.div` - margin-top: 50px; - width: 600px; height: 350px; border-radius: 10px; @@ -63,6 +78,8 @@ export const FavoritesContainer = styled.div` padding-right: 23px; padding-left: 23px; padding-bottom: 23px; + margin-left: 30px; + margin-top: 40px; `; export const LogOutButton = styled.button` @@ -75,9 +92,16 @@ export const LogOutButton = styled.button` font-weight: 600; line-height: normal; border: transparent; +<<<<<<< HEAD border-radius: 5px; width: 405px; height: 50px; +======= + border-radius: 10px; + width: 500px; + height: 55px; + margin-top: 40px; +>>>>>>> b287da7 (temp) `; /* transform: translateY(200px); */ @@ -100,7 +124,7 @@ export const FavoriteDiv = styled.div` align-items: center; justify-content: space-around; width: 100%; - margin-bottom: 50px; + margin-bottom: 20px; margin-top: 30px; `; @@ -112,8 +136,13 @@ export const HeartIcon = styled(Heart)` `; export const BackButtonDiv = styled.div` +<<<<<<< HEAD margin-bottom: 30px; margin-top: 50px; +======= + margin-top: 50px; + margin-bottom: 40px; +>>>>>>> b287da7 (temp) `; export const HeaderDiv = styled.div` @@ -128,6 +157,11 @@ export const ProductNameDiv = styled.div` width: 250px; `; +export const Spacing = styled.div` + height: 10px; + width: 100%; +`; + export const BlankSpace = styled.div` width: 250px; height: 200px; @@ -151,7 +185,6 @@ export const ColumnDiv = styled.div` `; export const LogOutDiv = styled.div` - margin-top: 50px; margin-right: 30px; display: flex; justify-content: center; diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index bff2d899..1ec02351 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -1,4 +1,8 @@ +<<<<<<< HEAD import { Body1Bold } from '@/styles/fonts'; +======= +import { Body1, Body2Bold } from '@/styles/fonts'; +>>>>>>> b287da7 (temp) import { BackLink, ArrowLeftIcon } from './styles'; export default function BackButton(props: { destination: string }) { @@ -6,7 +10,11 @@ export default function BackButton(props: { destination: string }) { return ( +<<<<<<< HEAD Back +======= + Back +>>>>>>> b287da7 (temp) ); } diff --git a/src/components/BackButton/styles.ts b/src/components/BackButton/styles.ts index 4abb943e..f8bfe12c 100644 --- a/src/components/BackButton/styles.ts +++ b/src/components/BackButton/styles.ts @@ -9,14 +9,23 @@ export const BackLink = styled(Link)` align-items: center; justify-content: space-between; color: ${COLORS.black}; +<<<<<<< HEAD width: 75px; +======= + width: 60px; +>>>>>>> b287da7 (temp) &:hover { text-decoration: underline; } `; export const ArrowLeftIcon = styled(ArrowLeft)` +<<<<<<< HEAD width: 20px; height: 20px; +======= + width: 18px; + height: 18px; +>>>>>>> b287da7 (temp) `; diff --git a/src/components/OrderHistory/OrderHistoryText.tsx b/src/components/OrderHistory/OrderHistoryText.tsx index 3c109481..d2c1d1b7 100644 --- a/src/components/OrderHistory/OrderHistoryText.tsx +++ b/src/components/OrderHistory/OrderHistoryText.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { useRouter } from 'next/navigation'; +import { Check, CheckCircle, X, Send } from 'react-feather'; import querystring from 'querystring'; -import { Heading4Bold, Body1, OrderStatusFont } from '@/styles/fonts'; +import { Heading4Bold, Body1, Body2, OrderStatusFont } from '@/styles/fonts'; import { ViewOrderButton, ArrowIcon, @@ -11,7 +12,7 @@ import { OrderStatusApprovedDiv, CrossStyled, OrderStatusSubmittedDiv, - LoaderStyled, + SendStyle, } from './styles'; // Adjust the import path as necessary import { Order, OrderStatus } from '../../schema/schema'; @@ -61,7 +62,7 @@ export default function OrderDetails(props: OrderDetailsProps) { > Order No. {orderNumber} viewOrder(orderNumber)}> - View Order + View Order
@@ -102,7 +103,7 @@ export default function OrderDetails(props: OrderDetailsProps) { > Order No. {orderNumber} viewOrder(orderNumber)}> - View Order + View Order
@@ -143,7 +144,7 @@ export default function OrderDetails(props: OrderDetailsProps) { > Order No. {orderNumber} viewOrder(orderNumber)}> - View Order + View Order
@@ -156,7 +157,7 @@ export default function OrderDetails(props: OrderDetailsProps) { {formatDate(date)} - + Order Submitted
diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index fec7e6c7..546d6c2b 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -1,6 +1,6 @@ // styles.ts import styled from 'styled-components'; -import { X, Check, Loader } from 'react-feather'; +import { X, Check, Send, Loader } from 'react-feather'; import COLORS from '../../styles/colors'; export const containerStyle = styled.div` @@ -165,8 +165,14 @@ export const GalleryImage = styled.img` export const RowDiv = styled.div` width: 700px; +<<<<<<< HEAD height: 300px; margin-bottom: 20px; +======= + height: 400px; + margin-bottom: 20px; + margin-top: 20px; +>>>>>>> b287da7 (temp) `; export const OrderStatusDiv = styled.div` @@ -194,7 +200,7 @@ export const OrderStatusApprovedDiv = styled.div` export const OrderStatusSubmittedDiv = styled.div` width: 300px; height: 35px; - background: var(--Baby-Blue, #c7ddff); + background: var(--Greyish, #E6E6E6); display: flex; justify-content: center; align-items: center; @@ -212,7 +218,7 @@ export const CheckStyled = styled(Check)` margin-right: 10px; `; -export const LoaderStyled = styled(Loader)` +export const SendStyle = styled(Send)` stroke-width: 3px; margin-right: 10px; `; diff --git a/src/components/ViewAllButton/ViewAllButton.tsx b/src/components/ViewAllButton/ViewAllButton.tsx index a5a574f4..d629c442 100644 --- a/src/components/ViewAllButton/ViewAllButton.tsx +++ b/src/components/ViewAllButton/ViewAllButton.tsx @@ -1,15 +1,14 @@ import Link from 'next/link'; -import { ArrowRight } from 'react-feather'; -import { Body1Point5 } from '@/styles/fonts'; -import { ViewAllDiv } from './styles'; +import { Body2, Body2Bold } from '@/styles/fonts'; +import { ArrowRightIcon, ViewAllDiv } from './styles'; export default function BackButton(props: { destination: string }) { const { destination } = props; return ( - View All - + View All + ); diff --git a/src/components/ViewAllButton/styles.ts b/src/components/ViewAllButton/styles.ts index 248778df..17ce6d93 100644 --- a/src/components/ViewAllButton/styles.ts +++ b/src/components/ViewAllButton/styles.ts @@ -1,7 +1,11 @@ import styled from 'styled-components'; +import { ArrowRight } from 'react-feather'; import COLORS from '../../styles/colors'; + export const ViewAllDiv = styled.div` + width: 80px; + gap: 5px; display: flex; align-items: center; color: ${COLORS.black}; @@ -13,3 +17,8 @@ export const ViewAllDiv = styled.div` `; export const placeHolder = ''; + +export const ArrowRightIcon = styled(ArrowRight)` + width: 20px; + height: 20px; +`; From d545b6665b0d40c9f5c811dcb7da5c765969d95f Mon Sep 17 00:00:00 2001 From: Noah Hernandez <63211322+oahnh@users.noreply.github.com> Date: Sun, 21 Apr 2024 14:50:32 -0700 Subject: [PATCH 23/43] fix: fetchProducts correctly retrieves category name for favorites --- src/app/profileScreen/page.tsx | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 995716f3..7f1f3277 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -371,20 +371,20 @@ export default function Profile() { const data = await fetchUser(); setUser(data); } + async function fetchProducts() { + const data = (await arrayOfFavorites()) as Product[]; + const mapCategories = await Promise.all( + data.map(async product => { + const updateCategory = await convertButtonNumberToCategory( + product.category, + ); + return { ...product, category: updateCategory }; + }), + ); + setFavorites(mapCategories); + } + useEffect(() => { - async function fetchProducts() { - const data = (await arrayOfFavorites()) as Product[]; - console.log(data); - data.forEach( - async product => - (product.category = await convertButtonNumberToCategory( - product.category, - )), - ); - console.log(data); - // console.log(data); - setFavorites(data); - } fetchProducts(); fetchOrders(); getUser(); From 46a8b0359eb827142b5b9bedb518d8db5ecd4830 Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 15:01:24 -0700 Subject: [PATCH 24/43] fixed after rebasing --- src/app/orderConfirmationPickUp/page.tsx | 4 -- src/app/orderConfirmationPickUp/styles.ts | 5 +-- src/app/orderHistory/page.tsx | 13 +------ src/app/orderHistory/styles.ts | 14 +------ src/app/orderPage/page.tsx | 47 +++++++++++++---------- src/app/orderPage/styles.ts | 32 +++++++-------- src/app/profileScreen/page.tsx | 11 ++---- src/app/profileScreen/styles.ts | 12 ------ src/components/BackButton/BackButton.tsx | 18 +-------- src/components/BackButton/styles.ts | 19 --------- src/components/FooterFolder/Footer.tsx | 4 +- src/components/FooterFolder/styles.ts | 3 +- src/components/OrderHistory/styles.ts | 2 +- src/components/ViewAllButton/styles.ts | 1 - 14 files changed, 56 insertions(+), 129 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index fd2d7c18..87f454cf 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -55,13 +55,10 @@ export default function OrderConfirmationPickUp() { const searchParams = useSearchParams(); const orderIDFromSearch = searchParams.get('orderID'); - useEffect(() => { async function fetchProducts() { - const cartItems = (await fetchCartItemsWithQuantityByID( orderIDFromSearch, - )) as Product[]; setCart(cartItems); } @@ -161,7 +158,6 @@ export default function OrderConfirmationPickUp() { -
diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index 5e993154..d31ade33 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -99,14 +99,12 @@ export const Label = styled.p` margin-top: 20px; `; - export const ImageDiv = styled.p` width: 150px; height: 150px; align-items: center; justify-content: center; display: flex; - `; export const LabelBox = styled.div` @@ -244,7 +242,6 @@ export const WhiteBackgroundDiv = styled.div` box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); `; - export const Wrapper2 = styled.div` display: flex; flex-direction: col; @@ -331,4 +328,4 @@ export const CenterDiv = styled.div` position: relative; width: 100%; padding: 20px; -`; \ No newline at end of file +`; diff --git a/src/app/orderHistory/page.tsx b/src/app/orderHistory/page.tsx index 6c57ea2a..232de1e7 100644 --- a/src/app/orderHistory/page.tsx +++ b/src/app/orderHistory/page.tsx @@ -31,20 +31,9 @@ function OrderHistory() { - -<<<<<<< HEAD -<<<<<<< HEAD -
- Order History -
-======= +
Order History ->>>>>>> b287da7 (temp) -======= - - Order History ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 {orderIds.length > 0 ? ( orderIds.map((orderId: number) => ( diff --git a/src/app/orderHistory/styles.ts b/src/app/orderHistory/styles.ts index 4746ba4c..f6d06db4 100644 --- a/src/app/orderHistory/styles.ts +++ b/src/app/orderHistory/styles.ts @@ -36,24 +36,12 @@ export const OrderHistoryContainer = styled.div` flex-direction: column; align-items: center; border-radius: 10px; -<<<<<<< HEAD background: ${COLORS.white}; box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); width: 800px; // Width of the outer box height: auto; - margin-top: 10px; - padding-top: 40px; -======= - background: var(--White, #fff); - background-color: pink; - box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 800px; // Width of the outer box - height: 700px; - overflow: scroll; margin-top: 20px; - margin-bottom: 50px; - padding: 0; // Ensure there's no padding pushing the internal boxes inward ->>>>>>> b287da7 (temp) + padding-top: 10px; `; export const OrderHistoryBox = styled.div` diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index 27bfbf09..ef75b971 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -2,7 +2,16 @@ import { useState, useEffect } from 'react'; import { Check, X, Send } from 'react-feather'; -import { Body1, Body2Light, Heading3Bold, Heading4Bold, Body2, Heading2, Body1Bold } from '@/styles/fonts'; +import { + Body1, + Body2Light, + Heading3Bold, + Heading4Bold, + Body3, + Body2, + Heading2, + Body1Bold, +} from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; import BackButton from '../../components/BackButton/BackButton'; @@ -87,7 +96,7 @@ export default function OrderPage() { } fetchProducts(); }, []); - + const status = order?.order_status?.toLowerCase() || 'default'; return ( @@ -101,24 +110,24 @@ export default function OrderPage() { - {formatDate(order?.created_at)} + Order No. {order?.id} - - Order No - + + Order Date: {order?.id} + - {orders.map(product => ( - - - {product.name} - + {orders.map(product => ( + + + {product.name} + {product.name} @@ -162,12 +171,8 @@ export default function OrderPage() {
-
); } - - - diff --git a/src/app/orderPage/styles.ts b/src/app/orderPage/styles.ts index 122fc5fe..9424e7aa 100644 --- a/src/app/orderPage/styles.ts +++ b/src/app/orderPage/styles.ts @@ -5,16 +5,16 @@ import { Heart } from 'react-feather'; import NavBar from '../../components/NavBarFolder/NavBar'; export const FavoriteDiv = styled.div` -display: flex; -flex-direction: row; -align-items: center; -justify-content: space-between; -width: 100%; -margin-bottom: 50px; -margin-top: 30px; -margin-right: 20px; -margin-left: 40px; -gap: 70px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; + margin-right: 20px; + margin-left: 40px; + gap: 70px; `; export const BottomColumnDiv = styled.div` @@ -25,7 +25,7 @@ export const BottomColumnDiv = styled.div` width: 100%; margin-left: 10px; margin-bottom: 30px; - gap: 10px; + gap: 20px; `; export const ScrollDiv = styled.div` @@ -48,10 +48,10 @@ export const LabelBox = styled.div` height: 100%; `; -export const OutterFavoriteDiv = styled.div` +export const OutterFavoriteDiv = styled.div` display: flex; flex-direction: column; - align-items: center; + align-items: left; border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); @@ -60,6 +60,7 @@ export const OutterFavoriteDiv = styled.div` overflow: scroll; margin-top: 20px; padding-top: 15px; + margin-left: 60px; `; export const BackDiv = styled.button` @@ -185,7 +186,6 @@ export const StatusButton = styled.button<{ status: string }>` }}; `; - export const Body1Bold = styled.p` font-size: 16px; font-style: normal; @@ -242,12 +242,14 @@ export const RightColumnDiv = styled.div` align-items: start; margin-left: 10px; width: 100%; + margin-top: 8px; `; export const TextDiv1 = styled.div` display: flex; flex-direction: row; margin-top: 20px; + background-color: pink; `; export const TextDiv = styled.div` @@ -264,4 +266,4 @@ export const LeftColumnDiv = styled.div` justify-content: space-evenly; align-items: space-evenly; width: 100%; -`; \ No newline at end of file +`; diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 6a46952f..588c86d3 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -87,12 +87,9 @@ function FavoriteSection(props: { style={{ width: '100px', height: '100px' }} /> - - {favorite.name} - - - Category: {favorite.category} - + {favorite.name} + + Category: {favorite.category} clickFunctions({ fav: favorite })} @@ -436,7 +433,7 @@ export default function Profile() { - + diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 016c1444..5272fd80 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -92,22 +92,10 @@ export const LogOutButton = styled.button` font-weight: 600; line-height: normal; border: transparent; -<<<<<<< HEAD -<<<<<<< HEAD - border-radius: 5px; - width: 405px; - height: 50px; -======= -======= ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 border-radius: 10px; width: 500px; height: 55px; margin-top: 40px; -<<<<<<< HEAD ->>>>>>> b287da7 (temp) -======= ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 `; /* transform: translateY(200px); */ diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index d10762db..a59c6d92 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -1,12 +1,4 @@ -<<<<<<< HEAD -<<<<<<< HEAD -import { Body1Bold } from '@/styles/fonts'; -======= -import { Body1, Body2Bold } from '@/styles/fonts'; ->>>>>>> b287da7 (temp) -======= -import { Body1, Body2Bold } from '@/styles/fonts'; ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 +import { Body1Bold, Body1, Body2Bold } from '@/styles/fonts'; import { BackLink, ArrowLeftIcon } from './styles'; export default function BackButton(props: { destination: string }) { @@ -14,15 +6,7 @@ export default function BackButton(props: { destination: string }) { return ( -<<<<<<< HEAD -<<<<<<< HEAD - Back -======= Back ->>>>>>> b287da7 (temp) -======= - Back ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 ); } diff --git a/src/components/BackButton/styles.ts b/src/components/BackButton/styles.ts index d20ac5bd..34fe39e8 100644 --- a/src/components/BackButton/styles.ts +++ b/src/components/BackButton/styles.ts @@ -9,32 +9,13 @@ export const BackLink = styled(Link)` align-items: center; justify-content: space-between; color: ${COLORS.black}; -<<<<<<< HEAD -<<<<<<< HEAD - width: 75px; - -======= - width: 60px; ->>>>>>> b287da7 (temp) -======= width: 60px; ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 &:hover { text-decoration: underline; } `; export const ArrowLeftIcon = styled(ArrowLeft)` -<<<<<<< HEAD -<<<<<<< HEAD - width: 20px; - height: 20px; -======= - width: 18px; - height: 18px; ->>>>>>> b287da7 (temp) -======= width: 18px; height: 18px; ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 `; diff --git a/src/components/FooterFolder/Footer.tsx b/src/components/FooterFolder/Footer.tsx index 45fa2c42..7cb4eef9 100644 --- a/src/components/FooterFolder/Footer.tsx +++ b/src/components/FooterFolder/Footer.tsx @@ -26,7 +26,7 @@ import { export default function Footer({ ...rest }) { const router = useRouter(); return ( -
+ Contact Us @@ -122,6 +122,6 @@ export default function Footer({ ...rest }) { }} /> -
+ ); } diff --git a/src/components/FooterFolder/styles.ts b/src/components/FooterFolder/styles.ts index 1829fe3f..e9c70d54 100644 --- a/src/components/FooterFolder/styles.ts +++ b/src/components/FooterFolder/styles.ts @@ -119,7 +119,8 @@ export const SVGWrapper = styled.div` `; export const Wrapper = styled.div` - min-height: 100%; /*or 100vh */ + min-height: 100%; + width:100%; position: relative; background: var(--Light-Periwinkle, #f4f7ff); display: flex; diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index b82b034c..bc97dbb0 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -203,7 +203,7 @@ export const OrderStatusApprovedDiv = styled.div` export const OrderStatusSubmittedDiv = styled.div` width: 300px; height: 35px; - background: var(--Greyish, #E6E6E6); + background: var(--Greyish, #e6e6e6); display: flex; justify-content: center; align-items: center; diff --git a/src/components/ViewAllButton/styles.ts b/src/components/ViewAllButton/styles.ts index 17ce6d93..c77c4441 100644 --- a/src/components/ViewAllButton/styles.ts +++ b/src/components/ViewAllButton/styles.ts @@ -2,7 +2,6 @@ import styled from 'styled-components'; import { ArrowRight } from 'react-feather'; import COLORS from '../../styles/colors'; - export const ViewAllDiv = styled.div` width: 80px; gap: 5px; From 5330746ed7a40c90263e1fb6999c8e464c4739a6 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 15:18:10 -0700 Subject: [PATCH 25/43] finshed --- src/api/supabase/queries/product_queries.ts | 2 +- src/app/login/page.tsx | 17 +- src/app/orderConfirmationDelivery/page.tsx | 30 +-- src/app/orderPageDelivery/page.tsx | 211 +++++++++++++++ src/app/orderPageDelivery/styles.ts | 265 +++++++++++++++++++ src/app/profileScreen/page.tsx | 10 +- src/components/LoginFormFolder/LoginForm.tsx | 2 +- 7 files changed, 491 insertions(+), 46 deletions(-) create mode 100644 src/app/orderPageDelivery/page.tsx create mode 100644 src/app/orderPageDelivery/styles.ts diff --git a/src/api/supabase/queries/product_queries.ts b/src/api/supabase/queries/product_queries.ts index 67396986..85ec9fbb 100644 --- a/src/api/supabase/queries/product_queries.ts +++ b/src/api/supabase/queries/product_queries.ts @@ -64,7 +64,7 @@ export async function fetchProductByID(productId: number): Promise { if (error) { throw new Error(`Error fetching product: ${error.message}`); } - + return product; } diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index aeff396f..bae4f37c 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -40,16 +40,13 @@ export default function App() { window.location.href = '/storefront'; } }; - - async function applyFilter( - e: React.KeyboardEvent, - ) { - const keypressed = e.code; - if (keypressed === 'Enter') { - handleLogin(); - } + + async function applyFilter(e: React.KeyboardEvent) { + const keypressed = e.code; + if (keypressed === 'Enter') { + handleLogin(); + } } - return ( @@ -89,7 +86,7 @@ export default function App() { )} {errorMessage && {errorMessage}} - diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx index 6fa3eaf0..3a538d50 100644 --- a/src/app/orderConfirmationDelivery/page.tsx +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -9,6 +9,7 @@ import { import { Body1, Body2, + Body2Light, Heading3Bold, Heading4Bold, } from '@/styles/fonts'; @@ -40,7 +41,6 @@ import { import { Product, User, Address } from '../../schema/schema'; import { Body1Bold } from '../orderPage/styles'; -import { BackButtonDiv } from '../orderConfirmationPickUp/styles'; export default function OrderConfirmationDelivery() { const [Cart, setCart] = useState([]); @@ -92,9 +92,7 @@ export default function OrderConfirmationDelivery() { 'November', 'December', ]; - const dateStr = `${months[parseInt(date[1], 10) - 1]} ${date[2]}, ${ - date[0] - }`; + const dateStr = `${months[parseInt(date[1], 10)]} ${date[2]}, ${date[0]}`; return `${dateStr}`; } @@ -103,9 +101,6 @@ export default function OrderConfirmationDelivery() { - - - @@ -125,25 +120,8 @@ export default function OrderConfirmationDelivery() { }} /> -
- - Quantity: - - - {cartItem.quantity} - -
+ {cartItem.name} + Category: {cartItem.category}
diff --git a/src/app/orderPageDelivery/page.tsx b/src/app/orderPageDelivery/page.tsx new file mode 100644 index 00000000..25a8feae --- /dev/null +++ b/src/app/orderPageDelivery/page.tsx @@ -0,0 +1,211 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { + fetchUser, + fetchCurrentUserAddress, +} from '@/api/supabase/queries/user_queries'; + +import { + Body1, + Body2, + Body2Light, + Heading2Bold, + Heading3Bold, + Heading4Bold, +} from '@/styles/fonts'; +import { useSearchParams } from 'next/navigation'; +import { + DeliveryTimes, + fetchDeliveryTimes, +} from '@/api/supabase/queries/delivery_queries'; +import { + fetchOrderProductsbyOrderId, + getOrderById, +} from '@/api/supabase/queries/order_queries'; +import BackButton from '../../components/BackButton/BackButton'; + +import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +import { + FavoriteDiv, + OutterFavoriteDiv, + LabelBox, + ScrollDiv, + ShippingDetailsDiv, + BottomColumnDiv, + LeftColumnDiv, + RightColumnDiv, + DetailsHeader, + PageDiv, + CenterDiv, + Quantity, + StatusButton, +} from './styles'; + +import { + Product, + User, + Address, + ProductWithQuantity, + Order, +} from '../../schema/schema'; +import { Body1Bold } from '../orderPage/styles'; +import { BackButtonDiv } from '../orderConfirmationPickUp/styles'; + +export default function OrderConfirmationDelivery() { + const [orders, setOrders] = useState([]); + const searchParams = useSearchParams(); + const orderIDFromSearch = searchParams.get('orderID'); + let currOrderId = 0; + const [delivTimes, setDelivTimes] = useState([]); + + if (orderIDFromSearch !== null) { + currOrderId = parseInt(orderIDFromSearch, 10); + } else { + currOrderId = 32; + } + + const [order, setOrder] = useState(); + const [userAddress, setUserAddress] = useState
(); + const [user, setUser] = useState(); + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + + useEffect(() => { + async function fetchProducts() { + const data = (await fetchOrderProductsbyOrderId( + currOrderId, + )) as ProductWithQuantity[]; + const currOrder = await getOrderById(currOrderId); + setOrders(data); + setOrder(currOrder); + } + + async function setUserDetails() { + const fetchedUser = await fetchUser(); + setUser(fetchedUser); + const address = await fetchCurrentUserAddress(); + setUserAddress(address); + } + async function fetchDelivTimes() { + const deliv = await fetchDeliveryTimes(); + setDelivTimes(deliv); + } + + fetchDelivTimes(); + fetchProducts(); + setUserDetails(); + }, []); + + function organizeDelivTime() { + const userGrp = user?.delivery_group == null ? 1 : user?.delivery_group; + const Time = delivTimes[userGrp]?.delivery_time.toLocaleString(); + const date = + Time == null ? ['0', '0', '0'] : Time?.substring(0, 10).split('-'); + const dateStr = `${months[parseInt(date[1], 10) - 1]} ${date[2]}, ${ + date[0] + }`; + return `${dateStr}`; + } + + function organizeOrderDate() { + const Time = order?.created_at.toLocaleString(); + const date = + Time == null ? ['0', '0', '0'] : Time?.substring(0, 10).split('-'); + const dateStr = `${months[parseInt(date[1], 10) - 1]} ${date[2]}, ${ + date[0] + }`; + return `${dateStr}`; + } + + function organizeOrderTime() { + const Time = order?.created_at.toLocaleString(); + console.log(Time); + let ampm = 'AM'; + const date = + Time == null ? ['00', '00'] : Time?.substring(11, 16).split(':'); + + console.log(date); + if (parseInt(date[0], 10) >= 12) { + date[0] = (parseInt(date[0], 10) - 12).toLocaleString(); + ampm = 'PM'; + } + const timeStr = `${date[0]}:${date[1]} ${ampm}`; + return `${timeStr}`; + } + + return ( +
+ + + + + + + Order No. {orderIDFromSearch} + + Order Date: {organizeOrderDate()} + Order Time: {organizeOrderTime()} + + {orders.map(product => ( + + {product.name} + + {product.name} + Category: {product.category} + + + + Quantity: {product.quantity} + + + + ))} + + + + + + {' '} + {order?.order_status}{' '} + + + Delivery Information + Estimated Date + {organizeDelivTime()} + Location + + {userAddress?.street}, {userAddress?.city},{' '} + {userAddress?.zipcode} + + + + + + +
+ ); +} diff --git a/src/app/orderPageDelivery/styles.ts b/src/app/orderPageDelivery/styles.ts new file mode 100644 index 00000000..588dc25c --- /dev/null +++ b/src/app/orderPageDelivery/styles.ts @@ -0,0 +1,265 @@ +import styled from 'styled-components'; + +import { Heart } from 'react-feather'; + +import NavBar from '../../components/NavBarFolder/NavBar'; + +export const FavoriteDiv = styled.div` + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: space-between; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; +`; + +export const Quantity = styled.div` + display: flex; + align-self: center; + justify-content: flex-start; + margin-right: 40px; +`; + +export const OrderDetailsDiv = styled.div` + width: 750px; + height: auto; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; +`; + +export const CenterDiv = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; +`; + +export const OutterFavoriteDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 650px; + height: auto; + max-height: 793px; + margin-top: 5px; + margin-bottom: 50px; + gap: 24px; + padding: 36px 32px; +`; + +export const ScrollDiv = styled.div` + overflow: scroll; + width: 100%; +`; + +export const BackDiv = styled.button` + display: flex; + flex-direction: row; + align: center; + color: black; + background-color: transparent; + border: transparent; + margin-bottom: 25px; + margin-top: 25px; + margin-left: 25px; + width: 100%; +`; + +export const OutterBox = styled.div` + width: 750px; + height: auto; + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; +`; + +export const Backtext = styled.p` + color: var(--Black, #101010); + /* Body 1 - Bold, button */ + font-family: Public Sans; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const HeartIcon = styled(Heart)` + color: #333286; + width: 30px; + height: 30px; + fill: #333286; +`; + +export const TransparentButton = styled.button` + background-color: transparent; + border: transparent; +`; + +export const NavBarMovedUP = styled(NavBar)` + position: static; +`; + +export const Label = styled.p` + margin-top: 9px; +`; + +export const Category = styled.p` + margin-top: 10px; +`; + +export const LabelBox = styled.div` + width: 150px; + height: 100%; + display: flex; + align-self: center; + flex-direction: column; + gap: 9px; +`; + +export const HeaderText = styled.h3` + color: var(--Black, #101010); + margin-top: 30px; + margin-bottom: 20px; + text: center; + color: var(--Black, #101010); + font-family: Public Sans; + font-size: 35px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const ShippingDetailsDiv = styled.div` + display: flex; + flex-direction: column; + align-items: space-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 467px; + height: auto; + max-height: 793px; + margin-top: 10px; + margin-bottom: 50px; + padding: 36px 34px; + gap: 33px; +`; + +export const DetailsHeader = styled.p` + color: var(--Navy, #1b3679); + font-family: Public Sans, sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const DetailsText = styled.p` + color: var(--Black, #101010); + font-family: Public Sans; + font-size: 17px; + font-style: normal; + font-weight: 400; + line-height: normal; + margin-top: 20px; +`; + +export const BottomColumnDiv = styled.div` + display: flex; + flex-flow: row; + align-items: space-evenly; + justify-content: space-around; + width: 100%; +`; + +export const PageDiv = styled.div` + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + width: 100%; +`; + +export const TopColumnDiv = styled.div` + display: flex; + flex-flow: column; + align-items: flex-start; + justify-content: space-around; + margin-bottom: 20px; +`; + +export const OrderSummaryDiv = styled.div` + overflow: scroll; + width: 350px; + height: 300px; +`; + +export const ItemSummaryDiv = styled.div` + display: flex; + flex-direction: row; + margin-bottom: 20px; + justify-content: space-between; + padding-left: 10px; + padding-right: 10px; +`; + +export const OrderTotalDiv = styled.div` + height: 50px; + padding-top: 10px; + width: 350px; + padding-left: 0px; + border-top: 1px black solid; + display: flex; + flex-flow: row; + justify-content: space-between; +`; + +export const LeftColumnDiv = styled.div` + margin-top: 30px; + display: flex; + flex-flow: column; + justify-content: space-evenly; + align-items: space-evenly; + gap: 20px; +`; +export const RightColumnDiv = styled.div` + display: flex; + flex-flow: column; + margin-left: 20px; + margin-top: 84px; +`; + +export const WhiteBackgroundDiv = styled.div` + border-radius: 8px; + background: var(--White, #fff); + height: 430px; + width: 350px; + padding-top: 20px; + + box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); +`; + +export const StatusButton = styled.button` + margin-left: auto; + margin-right: 0; + color: black; + text-align: center; + width: 210px; + height: 30px; + flex-shrink: 0; + padding-top: 3px; + padding-right: 10px; + padding-left: 10px; + padding-bottom: 3px; + border: none; + border-radius: 16.5px; + background: var(--Baby-Blue, #c7ddff); + margin-bottom: 14px; +`; diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 15e5006a..a7213cb2 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -374,13 +374,7 @@ export default function Profile() { useEffect(() => { async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; - console.log(data); - data.forEach( - async product => - (product.category = await convertButtonNumberToCategory( - product.category, - )), - ); + console.log(data); // console.log(data); setFavorites(data); @@ -389,7 +383,7 @@ export default function Profile() { fetchOrders(); getUser(); }, []); - + if (user === undefined) { return

Loading User

; } diff --git a/src/components/LoginFormFolder/LoginForm.tsx b/src/components/LoginFormFolder/LoginForm.tsx index 684399e6..6604f84f 100644 --- a/src/components/LoginFormFolder/LoginForm.tsx +++ b/src/components/LoginFormFolder/LoginForm.tsx @@ -8,7 +8,7 @@ export default function LoginForm(props: { isError: boolean; showPassword: boolean; }) { - const { isError, changeUserName, changePassword, showPassword} = props; + const { isError, changeUserName, changePassword, showPassword } = props; return (
Date: Sun, 21 Apr 2024 15:34:54 -0700 Subject: [PATCH 26/43] finshed --- src/app/orderPageDelivery/page.tsx | 4 ++-- .../OrderHistory/OrderHistoryText.tsx | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/app/orderPageDelivery/page.tsx b/src/app/orderPageDelivery/page.tsx index 25a8feae..0b78c29e 100644 --- a/src/app/orderPageDelivery/page.tsx +++ b/src/app/orderPageDelivery/page.tsx @@ -55,7 +55,7 @@ import { import { Body1Bold } from '../orderPage/styles'; import { BackButtonDiv } from '../orderConfirmationPickUp/styles'; -export default function OrderConfirmationDelivery() { +export default function OrderPageDelivery() { const [orders, setOrders] = useState([]); const searchParams = useSearchParams(); const orderIDFromSearch = searchParams.get('orderID'); @@ -156,7 +156,7 @@ export default function OrderConfirmationDelivery() { - + Order No. {orderIDFromSearch} Order Date: {organizeOrderDate()} diff --git a/src/components/OrderHistory/OrderHistoryText.tsx b/src/components/OrderHistory/OrderHistoryText.tsx index 3c109481..329e4500 100644 --- a/src/components/OrderHistory/OrderHistoryText.tsx +++ b/src/components/OrderHistory/OrderHistoryText.tsx @@ -1,8 +1,9 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import querystring from 'querystring'; import { Heading4Bold, Body1, OrderStatusFont } from '@/styles/fonts'; +import { fetchUser } from '@/api/supabase/queries/user_queries'; import { ViewOrderButton, ArrowIcon, @@ -34,10 +35,24 @@ interface OrderDetailsProps { export default function OrderDetails(props: OrderDetailsProps) { const { date, orderNumber, order } = props; const router = useRouter(); + const [deliveryEnabled, setDeliveryEnabled] = useState(false); + + useEffect(() => { + async function fetchDelivery() { + const data = await fetchUser(); + setDeliveryEnabled(data.delivery_allowed); + } + + fetchDelivery(); + }, []); const viewOrder = (orderID: string) => { const queryString = querystring.stringify({ orderID }); - router.push(`/orderPage?${queryString}`); + if (deliveryEnabled) { + router.push(`/orderPageDelivery?${queryString}`); + } else { + router.push(`/orderPage?${queryString}`); + } }; if (order.order_status === OrderStatus.Rejected) { return ( From c5f1306d87c64d1e87a82fe6cd9689fe0244db52 Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 15:35:00 -0700 Subject: [PATCH 27/43] Week 7 and 8 Sprint --- src/app/delivery/page.tsx | 1 - src/app/orderConfirmationDelivery/page.tsx | 6 +- src/app/orderConfirmationPickUp/page.tsx | 13 +- src/app/orderConfirmationPickUp/styles.ts | 14 +- src/app/orderHistory/styles.ts | 2 +- src/app/orderPage/page.tsx | 76 ++++---- src/app/orderPage/styles.ts | 13 +- src/app/pickup/page.tsx | 3 +- src/app/profileScreen/page.tsx | 3 +- src/app/profileScreen/styles.ts | 8 - src/app/storefront/productButtons.tsx | 1 - src/components/BackButton/BackButton.tsx | 2 +- src/components/FooterFolder/Footer.tsx | 180 +++++++++--------- src/components/FooterFolder/styles.ts | 4 +- .../OrderHistory/OrderHistoryText.tsx | 1 - src/components/OrderHistory/styles.ts | 2 +- .../ViewAllButton/ViewAllButton.tsx | 2 +- 17 files changed, 154 insertions(+), 177 deletions(-) diff --git a/src/app/delivery/page.tsx b/src/app/delivery/page.tsx index 1e66b420..6d7540e6 100644 --- a/src/app/delivery/page.tsx +++ b/src/app/delivery/page.tsx @@ -9,7 +9,6 @@ import { import querystring from 'querystring'; import { createOrder, - fetchCurrentOrdersByUser, updateOrderStatus, } from '@/api/supabase/queries/order_queries'; import BackButton from '../../components/BackButton/BackButton'; diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx index c82042cb..1ea95717 100644 --- a/src/app/orderConfirmationDelivery/page.tsx +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -6,7 +6,7 @@ import { fetchCurrentUserAddress, } from '@/api/supabase/queries/user_queries'; -import { Body1, Body2Light, Heading3Bold, Heading4Bold } from '@/styles/fonts'; +import { Body1, Heading3Bold, Heading4Bold } from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; import BackButton from '../../components/BackButton/BackButton'; @@ -29,7 +29,6 @@ import { } from './styles'; import { Product, User, Address } from '../../schema/schema'; -import { Body1Bold } from '../orderPage/styles'; import { BackButtonDiv } from '../orderConfirmationPickUp/styles'; export default function OrderConfirmationDelivery() { @@ -43,7 +42,6 @@ export default function OrderConfirmationDelivery() { const cartItems = (await fetchCartItemsWithQuantityByID( orderIDFromSearch, )) as Product[]; - console.log(cartItems); setCart(cartItems); } @@ -56,7 +54,7 @@ export default function OrderConfirmationDelivery() { fetchProducts(); setUserDetails(); - }, []); + }, ); return (
diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 87f454cf..9dc9630b 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -4,14 +4,8 @@ import { useState, useEffect } from 'react'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; -import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { getOrderById } from '@/api/supabase/queries/order_queries'; import { - fetchCurrentOrdersByUser, - getOrderById, -} from '@/api/supabase/queries/order_queries'; -import { - Body2Bold, - Body2, Heading3Bold, Body1, Body1Bold, @@ -26,11 +20,8 @@ import NavBar from '../../components/NavBarFolder/NavBar'; import { FavoriteDiv, - ColDiv, OutterFavoriteDiv, TextDiv1, - OutterBox, - Label, LabelBox, ScrollDiv, ShippingDetailsDiv, @@ -73,7 +64,7 @@ export default function OrderConfirmationPickUp() { fetchProducts(); setUserDetails(); - }, []); + }); function organizePickupTime() { const startTime = pickupTime?.start_time.toLocaleString(); diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index d31ade33..62262800 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -23,10 +23,7 @@ export const OutterFavoriteDiv = styled.div` border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); -<<<<<<< HEAD -======= width: 700px; ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 max-height: 100%; max-width: 750px; margin-top: 20px; @@ -99,7 +96,7 @@ export const Label = styled.p` margin-top: 20px; `; -export const ImageDiv = styled.p` +export const ImageDiv = styled.div` width: 150px; height: 150px; align-items: center; @@ -255,12 +252,8 @@ export const BottomColumnDiv = styled.div` align-items: space-evenly; justify-content: space-around; width: 100%; -<<<<<<< HEAD margin-left: 20px; margin-right: 20px; -======= - margin-left: 10px; ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 margin-bottom: 30px; gap: 10px; `; @@ -290,7 +283,6 @@ export const PageDiv = styled.div` `; export const ShippingDetailsDiv = styled.div` - display: flex; flex-direction: column; align-items: flex-start; @@ -303,11 +295,7 @@ export const ShippingDetailsDiv = styled.div` padding: 36px 34px; gap: 33px; max-height: 100%; -<<<<<<< HEAD margin-top: 75px; -======= - margin-top: 93px; ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 margin-bottom: 30px; margin-right: 40px; `; diff --git a/src/app/orderHistory/styles.ts b/src/app/orderHistory/styles.ts index f6d06db4..3ef05566 100644 --- a/src/app/orderHistory/styles.ts +++ b/src/app/orderHistory/styles.ts @@ -28,10 +28,10 @@ export const OutterBox = styled.div` width: 800px; margin-top: 40px; margin-bottom: 70px; + min-height: 50px; `; export const OrderHistoryContainer = styled.div` - display: flex; flex-direction: column; align-items: center; diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index ef75b971..69493174 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -1,18 +1,16 @@ 'use client'; import { useState, useEffect } from 'react'; -import { Check, X, Send } from 'react-feather'; import { Body1, Body2Light, Heading3Bold, - Heading4Bold, - Body3, - Body2, Heading2, Body1Bold, } from '@/styles/fonts'; +import { fetchUser } from '@/api/supabase/queries/user_queries'; import { useSearchParams } from 'next/navigation'; +import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; import BackButton from '../../components/BackButton/BackButton'; import { @@ -29,22 +27,19 @@ import { DetailsHeader, RightColumnDiv, TextDiv, - TextDiv1, - OutterBox, - OutterDiv, ImageDiv, BottomColumnDiv, ShippingDetailsDiv, LabelBox, + TextDiv2, LeftColumnDiv, ScrollDiv, - ProductNameDiv, PageDiv, CenterDiv, - StatusButton, + TextDiv1, } from './styles'; -import { ProductWithQuantity, Order } from '../../schema/schema'; +import { ProductWithQuantity, Order, Pickup, User } from '../../schema/schema'; function formatDate(date: string | undefined): string { if (!date) return ''; @@ -72,8 +67,18 @@ function formatDate(date: string | undefined): string { return `${month} ${day}, ${year}`; } +function formatTime(date: string | undefined): string { + if (!date) return ''; + + const hour = date.substring(11, 13); + const minute = date.substring(14, 16); + + return `${hour}:${minute}`; +} + export default function OrderPage() { const [orders, setOrders] = useState([]); + const [pickupTime, setPickupTime] = useState(); const searchParams = useSearchParams(); const orderIDFromSearch = searchParams.get('orderID'); let currOrderId = 0; @@ -83,6 +88,13 @@ export default function OrderPage() { currOrderId = 32; } + async function setUserDetails() { + const fetchedUser = await fetchUser(); + const currOrder = await getOrderById(Number(orderIDFromSearch)); + const pickup = await fetchPickupTimesByID(currOrder.pickup_time_id); + setPickupTime(pickup); + } + const [order, setOrder] = useState(); useEffect(() => { @@ -95,9 +107,19 @@ export default function OrderPage() { setOrder(currOrder); } fetchProducts(); - }, []); + setUserDetails(); + }); - const status = order?.order_status?.toLowerCase() || 'default'; + function organizePickupTime() { + const startTime = pickupTime?.start_time.toLocaleString(); + + const date = + startTime == null + ? ['0', '0', '0'] + : startTime?.substring(0, 10).split('-'); + const dateStr = `${date[1]}/${date[2]}/${date[0]}`; + return `${dateStr}`; + } return (
@@ -113,9 +135,12 @@ export default function OrderPage() { Order No. {order?.id} - - Order Date: {order?.id} - + + Order Date: {formatDate(order?.created_at)} + + + Order Time: {formatTime(order?.created_at)} + {orders.map(product => ( @@ -137,25 +162,7 @@ export default function OrderPage() { -
- - Quantity: - - - {product.quantity} - -
+ Quantity: {product.quantity}
))} @@ -166,6 +173,7 @@ export default function OrderPage() { Pickup Information Time Slot + {organizePickupTime()} (10:00 am - 12:30 pm) Location 3170 23rd Street, San Francisco, CA 94110 diff --git a/src/app/orderPage/styles.ts b/src/app/orderPage/styles.ts index 9424e7aa..52092ced 100644 --- a/src/app/orderPage/styles.ts +++ b/src/app/orderPage/styles.ts @@ -104,6 +104,7 @@ export const BackButtonDiv = styled.div` gap: 200px; margin-bottom: 50px; margin-top: 50px; + margin-left: 60px; text-align: left; width: 800px; `; @@ -231,7 +232,7 @@ export const ShippingDetailsDiv = styled.div` padding: 36px 34px; gap: 33px; max-height: 100%; - margin-top: 93px; + margin-top: 52px; margin-bottom: 30px; margin-right: 40px; `; @@ -248,15 +249,21 @@ export const RightColumnDiv = styled.div` export const TextDiv1 = styled.div` display: flex; flex-direction: row; + margin-left: 40px; margin-top: 20px; - background-color: pink; `; export const TextDiv = styled.div` display: flex; flex-direction: row; margin-left: 60px; - margin-top: 20px; +`; + +export const TextDiv2 = styled.div` + display: flex; + flex-direction: row; + margin-left: 40px; + margin-top: 5px; margin-bottom: 20px; `; diff --git a/src/app/pickup/page.tsx b/src/app/pickup/page.tsx index 097b878e..534e5b32 100644 --- a/src/app/pickup/page.tsx +++ b/src/app/pickup/page.tsx @@ -10,7 +10,7 @@ import { totalNumberOfItemsInCart, } from '@/api/supabase/queries/cart_queries'; import { useState, useEffect } from 'react'; -import { useRouter, useSearchParams } from 'next/navigation'; +import { useRouter } from 'next/navigation'; import { Heading4Bold } from '@/styles/fonts'; import { fetchNRecentPickupTimes } from '@/api/supabase/queries/pickup_queries'; import { @@ -157,7 +157,6 @@ export default function PickUp() { await updateOrderStatus(orderID, OrderStatus.Submitted); await createOrder(); const newestOrder = await fetchCartIdFromUser(); - console.log(newestOrder); await updateOrderStatus(newestOrder, OrderStatus.inProgress); const queryString = querystring.stringify({ orderID }); router.push(`/orderConfirmationPickUp?${queryString}`); diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 588c86d3..fb6a1639 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -5,7 +5,6 @@ import { toast, ToastContainer } from 'react-toastify'; import { useEffect, useState } from 'react'; import { Heading2, - Body3, Heading3, Heading1, Body1Bold, @@ -32,7 +31,7 @@ import { fetchOrderProductById, fetchProductWithQuantityById, } from '@/api/supabase/queries/order_queries'; -import { Check, CheckCircle, X, Send } from 'react-feather'; +import { Check, X, Send } from 'react-feather'; import BackButton from '../../components/BackButton/BackButton'; import { LogOutButton, diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 5272fd80..a3db9031 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -130,16 +130,8 @@ export const HeartIcon = styled(Heart)` `; export const BackButtonDiv = styled.div` -<<<<<<< HEAD -<<<<<<< HEAD - margin-bottom: 30px; margin-top: 50px; -======= -======= ->>>>>>> b287da70273f0befb5c5c6b437883b203f43b605 - margin-top: 50px; margin-bottom: 40px; ->>>>>>> b287da7 (temp) `; export const HeaderDiv = styled.div` diff --git a/src/app/storefront/productButtons.tsx b/src/app/storefront/productButtons.tsx index 076e25a4..23b99371 100644 --- a/src/app/storefront/productButtons.tsx +++ b/src/app/storefront/productButtons.tsx @@ -68,7 +68,6 @@ export default function ProductButtons(props: { // Applying the filter to the categories of the product if (category !== 'All') { - console.log(category); const products = await filterUserProducts(category); if (products !== null) { setFiltredProducts(products); diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index a59c6d92..d639e431 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -1,4 +1,4 @@ -import { Body1Bold, Body1, Body2Bold } from '@/styles/fonts'; +import { Body2Bold } from '@/styles/fonts'; import { BackLink, ArrowLeftIcon } from './styles'; export default function BackButton(props: { destination: string }) { diff --git a/src/components/FooterFolder/Footer.tsx b/src/components/FooterFolder/Footer.tsx index 7cb4eef9..bb9714ef 100644 --- a/src/components/FooterFolder/Footer.tsx +++ b/src/components/FooterFolder/Footer.tsx @@ -23,105 +23,103 @@ import { ArrowUpRightIcon, } from './styles'; -export default function Footer({ ...rest }) { +export default function Footer() { const router = useRouter(); return ( - - - - Contact Us - Phone: (415) 674-4700 - - { - window.location.href = - 'https://www.facebook.com/ShantiProjectSF/'; - }} - > - - - - - { - window.location.href = - 'https://www.youtube.com/channel/UCc3DMrL7_KDOzeJNVkoFrsA'; - }} - > - - - - - { - window.location.href = - 'https://www.instagram.com/shantiprojectsf/'; - }} - > - - - - - - - - - Mission District - - 3170 23rd Street - San Francisco, CA 94110 - - - { - window.location.href = - 'https://maps.app.goo.gl/LJWvkdhwrRMhjEZs7'; - }} - > - SEE ON MAP - - - - - - - + + Contact Us + Phone: (415) 674-4700 + + { + window.location.href = + 'https://www.facebook.com/ShantiProjectSF/'; + }} + > + + + + + router.push('/storefront')} + onClick={() => { + window.location.href = + 'https://www.youtube.com/channel/UCc3DMrL7_KDOzeJNVkoFrsA'; + }} > - Shop - - + + + + router.push('/profileScreen')} + onClick={() => { + window.location.href = + 'https://www.instagram.com/shantiprojectsf/'; + }} > - Profile - - + + + + + + + + Mission District + + 3170 23rd Street + San Francisco, CA 94110 + + + router.push('/cart')} + onClick={() => { + window.location.href = + 'https://maps.app.goo.gl/LJWvkdhwrRMhjEZs7'; + }} > - Cart - - + SEE ON MAP + + + + + + + router.push('/storefront')} + > + Shop + + router.push('/profileScreen')} + > + Profile + + router.push('/cart')} + > + Cart + + - logo pic - - + logo pic + ); } diff --git a/src/components/FooterFolder/styles.ts b/src/components/FooterFolder/styles.ts index e9c70d54..98701886 100644 --- a/src/components/FooterFolder/styles.ts +++ b/src/components/FooterFolder/styles.ts @@ -119,8 +119,8 @@ export const SVGWrapper = styled.div` `; export const Wrapper = styled.div` - min-height: 100%; - width:100%; + min-height: 100%; + width: 100%; position: relative; background: var(--Light-Periwinkle, #f4f7ff); display: flex; diff --git a/src/components/OrderHistory/OrderHistoryText.tsx b/src/components/OrderHistory/OrderHistoryText.tsx index d2c1d1b7..d5c78ab5 100644 --- a/src/components/OrderHistory/OrderHistoryText.tsx +++ b/src/components/OrderHistory/OrderHistoryText.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { useRouter } from 'next/navigation'; -import { Check, CheckCircle, X, Send } from 'react-feather'; import querystring from 'querystring'; import { Heading4Bold, Body1, Body2, OrderStatusFont } from '@/styles/fonts'; diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index bc97dbb0..35756710 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -1,6 +1,6 @@ // styles.ts import styled from 'styled-components'; -import { X, Check, Send, Loader } from 'react-feather'; +import { X, Check, Send } from 'react-feather'; import COLORS from '../../styles/colors'; export const containerStyle = styled.div` diff --git a/src/components/ViewAllButton/ViewAllButton.tsx b/src/components/ViewAllButton/ViewAllButton.tsx index d629c442..2298c75a 100644 --- a/src/components/ViewAllButton/ViewAllButton.tsx +++ b/src/components/ViewAllButton/ViewAllButton.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import { Body2, Body2Bold } from '@/styles/fonts'; +import { Body2 } from '@/styles/fonts'; import { ArrowRightIcon, ViewAllDiv } from './styles'; export default function BackButton(props: { destination: string }) { From 0c497ffa604d1a861f8fac67277446b2133764a5 Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 15:36:45 -0700 Subject: [PATCH 28/43] Week 7 and 8 Sprint --- src/app/orderConfirmationDelivery/page.tsx | 2 +- src/app/orderPage/page.tsx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/orderConfirmationDelivery/page.tsx b/src/app/orderConfirmationDelivery/page.tsx index 1ea95717..c35cbd09 100644 --- a/src/app/orderConfirmationDelivery/page.tsx +++ b/src/app/orderConfirmationDelivery/page.tsx @@ -54,7 +54,7 @@ export default function OrderConfirmationDelivery() { fetchProducts(); setUserDetails(); - }, ); + }); return (
diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index 69493174..e6cb6488 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -39,7 +39,7 @@ import { TextDiv1, } from './styles'; -import { ProductWithQuantity, Order, Pickup, User } from '../../schema/schema'; +import { ProductWithQuantity, Order, Pickup } from '../../schema/schema'; function formatDate(date: string | undefined): string { if (!date) return ''; @@ -89,7 +89,6 @@ export default function OrderPage() { } async function setUserDetails() { - const fetchedUser = await fetchUser(); const currOrder = await getOrderById(Number(orderIDFromSearch)); const pickup = await fetchPickupTimesByID(currOrder.pickup_time_id); setPickupTime(pickup); From 1df609fca57872bb9c807598fc631939c5d95f25 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 15:40:10 -0700 Subject: [PATCH 29/43] finshed --- src/app/profileScreen/page.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 995716f3..1d401529 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -375,13 +375,6 @@ export default function Profile() { async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; console.log(data); - data.forEach( - async product => - (product.category = await convertButtonNumberToCategory( - product.category, - )), - ); - console.log(data); // console.log(data); setFavorites(data); } From d6d6ff7630a9e677227e59186cbd2a9631e5f5c1 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 15:42:21 -0700 Subject: [PATCH 30/43] r --- src/api/supabase/queries/product_queries.ts | 2 +- src/app/login/page.tsx | 17 +++++++---------- src/components/LoginFormFolder/LoginForm.tsx | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/api/supabase/queries/product_queries.ts b/src/api/supabase/queries/product_queries.ts index 67396986..85ec9fbb 100644 --- a/src/api/supabase/queries/product_queries.ts +++ b/src/api/supabase/queries/product_queries.ts @@ -64,7 +64,7 @@ export async function fetchProductByID(productId: number): Promise { if (error) { throw new Error(`Error fetching product: ${error.message}`); } - + return product; } diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index aeff396f..bae4f37c 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -40,16 +40,13 @@ export default function App() { window.location.href = '/storefront'; } }; - - async function applyFilter( - e: React.KeyboardEvent, - ) { - const keypressed = e.code; - if (keypressed === 'Enter') { - handleLogin(); - } + + async function applyFilter(e: React.KeyboardEvent) { + const keypressed = e.code; + if (keypressed === 'Enter') { + handleLogin(); + } } - return ( @@ -89,7 +86,7 @@ export default function App() { )} {errorMessage && {errorMessage}} - diff --git a/src/components/LoginFormFolder/LoginForm.tsx b/src/components/LoginFormFolder/LoginForm.tsx index 684399e6..6604f84f 100644 --- a/src/components/LoginFormFolder/LoginForm.tsx +++ b/src/components/LoginFormFolder/LoginForm.tsx @@ -8,7 +8,7 @@ export default function LoginForm(props: { isError: boolean; showPassword: boolean; }) { - const { isError, changeUserName, changePassword, showPassword} = props; + const { isError, changeUserName, changePassword, showPassword } = props; return (
Date: Sun, 21 Apr 2024 15:45:20 -0700 Subject: [PATCH 31/43] merge --- src/app/profileScreen/page.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index a7213cb2..770e2699 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -374,10 +374,15 @@ export default function Profile() { useEffect(() => { async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; - - console.log(data); - // console.log(data); - setFavorites(data); + const mapCategories = await Promise.all( + data.map(async product => { + const updateCategory = await convertButtonNumberToCategory( + product.category, + ); + return { ...product, category: updateCategory }; + }), + ); + setFavorites(mapCategories); } fetchProducts(); fetchOrders(); From e1f3c07f950442971f915caff4b3208989b6ab92 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 15:46:32 -0700 Subject: [PATCH 32/43] merge --- src/app/profileScreen/page.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 770e2699..5840177c 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -371,6 +371,7 @@ export default function Profile() { const data = await fetchUser(); setUser(data); } + useEffect(() => { async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; From 5c2b151f49ef2a0b65f016a62cd88962ac42ac17 Mon Sep 17 00:00:00 2001 From: Monique Cheng Date: Sun, 21 Apr 2024 15:49:13 -0700 Subject: [PATCH 33/43] fixed --- src/app/profileScreen/page.tsx | 2 +- src/components/OrderHistory/OrderHistoryText.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 5840177c..a2f54978 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -371,7 +371,7 @@ export default function Profile() { const data = await fetchUser(); setUser(data); } - + useEffect(() => { async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; diff --git a/src/components/OrderHistory/OrderHistoryText.tsx b/src/components/OrderHistory/OrderHistoryText.tsx index 329e4500..0135fce1 100644 --- a/src/components/OrderHistory/OrderHistoryText.tsx +++ b/src/components/OrderHistory/OrderHistoryText.tsx @@ -46,14 +46,14 @@ export default function OrderDetails(props: OrderDetailsProps) { fetchDelivery(); }, []); - const viewOrder = (orderID: string) => { + async function viewOrder(orderID: string) { const queryString = querystring.stringify({ orderID }); if (deliveryEnabled) { router.push(`/orderPageDelivery?${queryString}`); } else { router.push(`/orderPage?${queryString}`); } - }; + } if (order.order_status === OrderStatus.Rejected) { return (
Date: Sun, 21 Apr 2024 14:40:05 -0700 Subject: [PATCH 34/43] ip --- src/app/orderConfirmationPickUp/page.tsx | 24 +++++++++++++---------- src/app/orderConfirmationPickUp/styles.ts | 18 ++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 9a93cb72..d838035a 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -6,41 +6,45 @@ import { fetchUser } from '@/api/supabase/queries/user_queries'; import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; import { getOrderById } from '@/api/supabase/queries/order_queries'; import { + Body2Bold, + Body2, + Heading3Bold, Body1, Body1Bold, - Body2Light, - Heading3Bold, Heading4Bold, + Body2Light, } from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; -import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; +import { fetchCartItemsWithQuantity,fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; import BackButton from '../../components/BackButton/BackButton'; import NavBar from '../../components/NavBarFolder/NavBar'; import { - TextDiv, - TextDiv1, - BackButtonDiv, FavoriteDiv, + ColDiv, OutterFavoriteDiv, + TextDiv1, + OutterBox, + Label, LabelBox, - LabelBox1, ScrollDiv, ShippingDetailsDiv, ImageDiv, BottomColumnDiv, - Wrapper, + LabelBox1, LeftColumnDiv, RightColumnDiv, DetailsHeader, PageDiv, CenterDiv, + BackButtonDiv, + TextDiv, } from './styles'; import { Product, User, Pickup } from '../../schema/schema'; - + export default function OrderConfirmationPickUp() { const [Cart, setCart] = useState([]); const [user, setUser] = useState(); @@ -93,7 +97,7 @@ export default function OrderConfirmationPickUp() { - Order No. {orderIDFromSearch} + Order No. {user?.cart_id} {Cart.map(cartItem => ( diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index 4f2e25a8..e357575d 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -26,9 +26,8 @@ export const OutterFavoriteDiv = styled.div` max-height: 100%; margin-top: 20px; margin-right: 60px; - margin-left: 60px; - padding-right: 20px; - padding-left: 10px; + margin-left: 40px; + padding-right: 15px; padding-top: 10px; `; @@ -232,7 +231,6 @@ export const RightColumnDiv = styled.div` display: flex; flex-flow: column; align-items: start; - margin-left: 10px; width: 100%; `; @@ -241,8 +239,8 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; - margin-left: 80px; - margin-top: 40px; + margin-left: 60px; + margin-bottom: 40px; `; export const WhiteBackgroundDiv = styled.div` @@ -261,6 +259,7 @@ export const BottomColumnDiv = styled.div` justify-content: space-around; width: 100%; margin-left: 20px; + margin-right: 20px; margin-bottom: 30px; gap: 30px; `; @@ -268,7 +267,7 @@ export const BottomColumnDiv = styled.div` export const TextDiv = styled.div` display: flex; flex-direction: row; - margin-left: 60px; + margin-left: 40px; margin-top: 20px; margin-bottom: 20px; `; @@ -287,6 +286,7 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; + margin-bottom: 40px; `; export const ShippingDetailsDiv = styled.div` @@ -296,7 +296,7 @@ export const ShippingDetailsDiv = styled.div` border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 467px; + width: 475px; height: auto; max-height: 100%; padding: 36px 34px; @@ -322,4 +322,4 @@ export const CenterDiv = styled.div` justify-content: center; width: 100%; padding: 20px; -`; +`; \ No newline at end of file From be5b77764b8cad62ce73c4b7a7a5f42dd954be94 Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 14:41:01 -0700 Subject: [PATCH 35/43] ip --- src/app/orderConfirmationPickUp/page.tsx | 2 + src/app/orderConfirmationPickUp/styles.ts | 47 +++++++++++++++-------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index d838035a..70ae174d 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -37,6 +37,7 @@ import { LeftColumnDiv, RightColumnDiv, DetailsHeader, + Wrapper2, PageDiv, CenterDiv, BackButtonDiv, @@ -155,6 +156,7 @@ export default function OrderConfirmationPickUp() { +
diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index e357575d..255792de 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -9,10 +9,10 @@ export const FavoriteDiv = styled.div` flex-direction: row; align-items: center; justify-content: space-between; - width: 100%; + width: 750px; margin-bottom: 50px; margin-top: 30px; - margin-right: 20px; + margin-right: 10px; `; export const OutterFavoriteDiv = styled.div` @@ -22,18 +22,19 @@ export const OutterFavoriteDiv = styled.div` border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 800px; max-height: 100%; + max-width: 750px; margin-top: 20px; - margin-right: 60px; - margin-left: 40px; - padding-right: 15px; - padding-top: 10px; + margin-right: 10px; + margin-left: 20px; + padding-right: 7px; + padding-top: 7px; `; export const ScrollDiv = styled.div` overflow: scroll; - width: 100%; + overflow-x: hidden; + max-width: 100%; `; export const ImageDiv = styled.div` @@ -225,13 +226,13 @@ export const LeftColumnDiv = styled.div` flex-flow: column; justify-content: space-evenly; align-items: space-evenly; - width: 100%; + width: 800px; `; export const RightColumnDiv = styled.div` display: flex; flex-flow: column; - align-items: start; - width: 100%; + align-items: left; + width: 475px; `; export const BackButtonDiv = styled.div` @@ -239,8 +240,9 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; - margin-left: 60px; + margin-left: 40px; margin-bottom: 40px; + margin-top: 20px; `; export const WhiteBackgroundDiv = styled.div` @@ -252,6 +254,14 @@ export const WhiteBackgroundDiv = styled.div` box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); `; + +export const Wrapper2 = styled.div` + display: flex; + flex-direction: col; + align-items: space-evenly; + justify-content: space-around; +`; + export const BottomColumnDiv = styled.div` display: flex; flex-direction: row; @@ -261,15 +271,15 @@ export const BottomColumnDiv = styled.div` margin-left: 20px; margin-right: 20px; margin-bottom: 30px; - gap: 30px; + gap: 10px; `; export const TextDiv = styled.div` display: flex; flex-direction: row; - margin-left: 40px; - margin-top: 20px; - margin-bottom: 20px; + margin-left: 20px; + margin-top: 10px; + margin-bottom: 10px; `; export const TextDiv1 = styled.div` @@ -286,10 +296,12 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; + position: relative; margin-bottom: 40px; `; export const ShippingDetailsDiv = styled.div` + display: flex; flex-direction: column; align-items: flex-start; @@ -302,7 +314,7 @@ export const ShippingDetailsDiv = styled.div` padding: 36px 34px; gap: 33px; max-height: 100%; - margin-top: 205px; + margin-top: 75px; margin-bottom: 30px; margin-right: 40px; `; @@ -320,6 +332,7 @@ export const CenterDiv = styled.div` display: flex; align-items: center; justify-content: center; + position: relative; width: 100%; padding: 20px; `; \ No newline at end of file From eafc73cb69588acc4c29ecea20f9f30f12dab02e Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Sun, 21 Apr 2024 17:24:56 -0700 Subject: [PATCH 36/43] ip --- src/app/orderConfirmationPickUp/page.tsx | 22 +-- src/app/orderConfirmationPickUp/styles.ts | 16 +- src/app/orderHistory/page.tsx | 11 +- src/app/orderHistory/styles.ts | 24 +++ src/app/orderPage/page.tsx | 122 +++++++++++---- src/app/orderPage/styles.ts | 146 ++++++++++++++++-- src/app/profileScreen/page.tsx | 34 ++-- src/app/profileScreen/styles.ts | 59 +++++-- src/components/BackButton/BackButton.tsx | 4 +- src/components/BackButton/styles.ts | 9 ++ .../OrderHistory/OrderHistoryText.tsx | 13 +- src/components/OrderHistory/styles.ts | 12 +- .../ViewAllButton/ViewAllButton.tsx | 9 +- src/components/ViewAllButton/styles.ts | 9 ++ 14 files changed, 381 insertions(+), 109 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 70ae174d..4c67f978 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -4,7 +4,11 @@ import { useState, useEffect } from 'react'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; -import { getOrderById } from '@/api/supabase/queries/order_queries'; +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { + fetchCurrentOrdersByUser, + getOrderById, +} from '@/api/supabase/queries/order_queries'; import { Body2Bold, Body2, @@ -15,7 +19,10 @@ import { Body2Light, } from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; -import { fetchCartItemsWithQuantity,fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; +import { + fetchCartItemsWithQuantity, + fetchCartItemsWithQuantityByID, +} from '../../api/supabase/queries/cart_queries'; import BackButton from '../../components/BackButton/BackButton'; @@ -31,13 +38,11 @@ import { LabelBox, ScrollDiv, ShippingDetailsDiv, - ImageDiv, BottomColumnDiv, - LabelBox1, LeftColumnDiv, RightColumnDiv, DetailsHeader, - Wrapper2, + ImageDiv, PageDiv, CenterDiv, BackButtonDiv, @@ -45,7 +50,7 @@ import { } from './styles'; import { Product, User, Pickup } from '../../schema/schema'; - + export default function OrderConfirmationPickUp() { const [Cart, setCart] = useState([]); const [user, setUser] = useState(); @@ -113,13 +118,13 @@ export default function OrderConfirmationPickUp() { }} /> - + {cartItem.name}
Category: {cartItem.category} -
+
-
diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index 255792de..60860ab3 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -12,7 +12,8 @@ export const FavoriteDiv = styled.div` width: 750px; margin-bottom: 50px; margin-top: 30px; - margin-right: 10px; + margin-right: 20px; + gap: 40px; `; export const OutterFavoriteDiv = styled.div` @@ -25,10 +26,11 @@ export const OutterFavoriteDiv = styled.div` max-height: 100%; max-width: 750px; margin-top: 20px; - margin-right: 10px; - margin-left: 20px; - padding-right: 7px; - padding-top: 7px; + margin-right: 60px; + margin-left: 60px; + padding-right: 20px; + padding-left: 40px; + padding-top: 10px; `; export const ScrollDiv = styled.div` @@ -285,9 +287,7 @@ export const TextDiv = styled.div` export const TextDiv1 = styled.div` display: flex; flex-direction: row; - padding: 10px; - margin-left: 20px; - margin-top: 15px; + margin-top: 20px; `; export const PageDiv = styled.div` diff --git a/src/app/orderHistory/page.tsx b/src/app/orderHistory/page.tsx index e02c8e1e..232de1e7 100644 --- a/src/app/orderHistory/page.tsx +++ b/src/app/orderHistory/page.tsx @@ -1,7 +1,7 @@ 'use client'; import React, { useEffect, useState } from 'react'; -import { Heading1, Body1 } from '@/styles/fonts'; +import { Heading2, Body1 } from '@/styles/fonts'; import OrderDetailsWithProducts from '../../components/OrderHistory/OrderHistoryBox'; import { fetchOrderIdsByUserIdSorted } from '../../api/supabase/queries/order_queries'; import Footer from '../../components/FooterFolder/Footer'; @@ -10,6 +10,7 @@ import { OutterBox, NavBarMovedUP, Fullscreen, + BackButtonDiv, } from './styles'; import BackButton from '../../components/BackButton/BackButton'; @@ -29,10 +30,10 @@ function OrderHistory() { - -
- Order History -
+ + + + Order History {orderIds.length > 0 ? ( orderIds.map((orderId: number) => ( diff --git a/src/app/orderHistory/styles.ts b/src/app/orderHistory/styles.ts index a93abdc1..4746ba4c 100644 --- a/src/app/orderHistory/styles.ts +++ b/src/app/orderHistory/styles.ts @@ -13,6 +13,17 @@ export const NavBarMovedUP = styled(NavBar)` position: relative; `; +export const BackButtonDiv = styled.div` + display: flex; + flex-direction: row; + gap: 200px; + margin-bottom: 30px; + margin-top: 50px; + text-align: left; + width: 800px; + padding-right: 40px; +`; + export const OutterBox = styled.div` width: 800px; margin-top: 40px; @@ -20,16 +31,29 @@ export const OutterBox = styled.div` `; export const OrderHistoryContainer = styled.div` + display: flex; flex-direction: column; align-items: center; border-radius: 10px; +<<<<<<< HEAD background: ${COLORS.white}; box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); width: 800px; // Width of the outer box height: auto; margin-top: 10px; padding-top: 40px; +======= + background: var(--White, #fff); + background-color: pink; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 800px; // Width of the outer box + height: 700px; + overflow: scroll; + margin-top: 20px; + margin-bottom: 50px; + padding: 0; // Ensure there's no padding pushing the internal boxes inward +>>>>>>> b287da7 (temp) `; export const OrderHistoryBox = styled.div` diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index 6d2d0fd9..27bfbf09 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -1,7 +1,8 @@ 'use client'; import { useState, useEffect } from 'react'; -import { Body1, Body2 } from '@/styles/fonts'; +import { Check, X, Send } from 'react-feather'; +import { Body1, Body2Light, Heading3Bold, Heading4Bold, Body2, Heading2, Body1Bold } from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; import BackButton from '../../components/BackButton/BackButton'; @@ -14,13 +15,23 @@ import NavBar from '../../components/NavBarFolder/NavBar'; import { FavoriteDiv, - Body1Bold, OutterFavoriteDiv, BackButtonDiv, + DetailsHeader, + RightColumnDiv, + TextDiv, + TextDiv1, OutterBox, OutterDiv, - Heading, + ImageDiv, + BottomColumnDiv, + ShippingDetailsDiv, + LabelBox, + LeftColumnDiv, + ScrollDiv, ProductNameDiv, + PageDiv, + CenterDiv, StatusButton, } from './styles'; @@ -76,40 +87,87 @@ export default function OrderPage() { } fetchProducts(); }, []); + + const status = order?.order_status?.toLowerCase() || 'default'; return (
+ + + + + + + + + {formatDate(order?.created_at)} + + + + Order No + + + {orders.map(product => ( + + + {product.name} + - - - - - - {formatDate(order?.created_at)} - - {' '} - {order?.order_status}{' '} - - - - {orders.map(product => ( - - {product.name} - - {product.name} - Category: {product.category} - - - ))} - - + + {product.name} +
+ + Category: {product.category} + +
+ +
+ + Quantity: + + + {product.quantity} + +
+
+
+ ))} +
+
+
+ + + Pickup Information + Time Slot + Location + 3170 23rd Street, San Francisco, CA 94110 + + +
+ +
+
); } + + + diff --git a/src/app/orderPage/styles.ts b/src/app/orderPage/styles.ts index c2c236bb..122fc5fe 100644 --- a/src/app/orderPage/styles.ts +++ b/src/app/orderPage/styles.ts @@ -5,16 +5,50 @@ import { Heart } from 'react-feather'; import NavBar from '../../components/NavBarFolder/NavBar'; export const FavoriteDiv = styled.div` +display: flex; +flex-direction: row; +align-items: center; +justify-content: space-between; +width: 100%; +margin-bottom: 50px; +margin-top: 30px; +margin-right: 20px; +margin-left: 40px; +gap: 70px; +`; + +export const BottomColumnDiv = styled.div` display: flex; flex-direction: row; - align-items: start; + align-items: space-evenly; justify-content: space-around; width: 100%; - margin-bottom: 50px; - margin-top: 30px; + margin-left: 10px; + margin-bottom: 30px; + gap: 10px; `; -export const OutterFavoriteDiv = styled.div` +export const ScrollDiv = styled.div` + overflow: scroll; + overflow-x: hidden; + max-width: 100%; +`; + +export const ImageDiv = styled.p` + width: 150px; + height: 150px; + align-items: center; + justify-content: center; + display: flex; + margin-right: 20px; +`; + +export const LabelBox = styled.div` + width: 200px; + height: 100%; +`; + +export const OutterFavoriteDiv = styled.div` display: flex; flex-direction: column; align-items: center; @@ -25,6 +59,7 @@ export const OutterFavoriteDiv = styled.div` height: 700px; overflow: scroll; margin-top: 20px; + padding-top: 15px; `; export const BackDiv = styled.button` @@ -66,7 +101,8 @@ export const BackButtonDiv = styled.div` display: flex; flex-direction: row; gap: 200px; - margin-bottom: 55px; + margin-bottom: 50px; + margin-top: 50px; text-align: left; width: 800px; `; @@ -116,26 +152,116 @@ export const ViewItem = styled.button` border-radius: 14px; `; -export const StatusButton = styled.button` +export const StatusButton = styled.button<{ status: string }>` margin-left: auto; margin-right: 0; color: black; text-align: center; - width: 210px; + max-width: 100%; height: 30px; flex-shrink: 0; padding-top: 3px; - padding-right: 10px; - padding-left: 10px; + padding-right: 30px; + padding-left: 30px; padding-bottom: 3px; + display: flex; + gap: 15px; + flex-direction: row; + align-items: center; /* Center vertically */ + justify-content: center; border: none; border-radius: 16.5px; - background: var(--Baby-Blue, #c7ddff); + background-color: ${props => { + switch (props.status) { + case 'submitted': + return 'var(--Greyish, #E6E6E6)'; + case 'rejected': + return 'var(--Light-Red, #FDD)'; + case 'approved': + return 'var(--Lime-Green, #CEE8BE)'; + default: + return 'white'; + } + }}; `; + export const Body1Bold = styled.p` font-size: 16px; font-style: normal; font-weight: 600; line-height: normal; `; + +export const PageDiv = styled.div` + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + width: 100%; +`; + +export const CenterDiv = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 20px; +`; + +export const DetailsHeader = styled.p` + color: var(--Navy, #1b3679); + font-family: Public Sans, sans-serif; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: normal; +`; + +export const ShippingDetailsDiv = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + border-radius: 10px; + background: var(--White, #fff); + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + width: 467px; + height: auto; + max-height: 100%; + padding: 36px 34px; + gap: 33px; + max-height: 100%; + margin-top: 93px; + margin-bottom: 30px; + margin-right: 40px; +`; + +export const RightColumnDiv = styled.div` + display: flex; + flex-flow: column; + align-items: start; + margin-left: 10px; + width: 100%; +`; + +export const TextDiv1 = styled.div` + display: flex; + flex-direction: row; + margin-top: 20px; +`; + +export const TextDiv = styled.div` + display: flex; + flex-direction: row; + margin-left: 60px; + margin-top: 20px; + margin-bottom: 20px; +`; + +export const LeftColumnDiv = styled.div` + display: flex; + flex-flow: column; + justify-content: space-evenly; + align-items: space-evenly; + width: 100%; +`; \ No newline at end of file diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index ae34f0c0..0717a352 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -10,6 +10,7 @@ import { Heading1, Body1Bold, Body2Bold, + Body2Light, Body2, } from '@/styles/fonts'; import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; @@ -36,8 +37,10 @@ import BackButton from '../../components/BackButton/BackButton'; import { LogOutButton, NavBarMovedUP, - AccountDetails, + AccountDetailsDeliv, + AccountDetailsPickUp, HeadingBack, + Spacing, HeadingSpacing, TextSpacing, OrderHistory, @@ -185,13 +188,13 @@ function OrderHistorySection(props: { Orders: Order[] }) { > Order No. {Orders[0].id} - {fD} - +
{icon} @@ -266,38 +269,37 @@ function AccountDetailSectionDelivery(props: { user: User }) { }, []); return (
- + Account Details Name - + {user?.first_name} {user?.last_name} - + Email - {user?.email} + {user?.email} - Phone - {user?.phone_numbers} + {user?.phone_numbers} Address - + {UserAddress?.street}, {UserAddress?.city}, {UserAddress?.zipcode} - + - +
); } @@ -306,7 +308,7 @@ function AccountDetailSectionPickUp(props: { user: User }) { return (
- + Account Details @@ -330,7 +332,7 @@ function AccountDetailSectionPickUp(props: { user: User }) { {user?.phone_numbers} - +
); } @@ -421,7 +423,7 @@ export default function Profile() { - + diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 1ae59176..d9981199 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -21,9 +21,8 @@ export const HeadingBack = styled.div` margin-right: 75px; `; -export const AccountDetails = styled.div` - margin-top: 50px; - margin-right: 30px; +export const AccountDetailsDeliv = styled.div` + margin-top: 40px; width: 500px; height: 350px; border-radius: 10px; @@ -35,25 +34,41 @@ export const AccountDetails = styled.div` padding-top: 29px; padding-right: 29px; padding-left: 29px; - padding-bottom: 29px; + padding-bottom: 32px; +`; + +export const AccountDetailsPickUp = styled.div` + margin-top: 40px; + width: 500px; + height: 310px; + border-radius: 10px; + background: ${COLORS.white}; + box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); + display: flex; + flex-direction: column; + align-items: left; + padding-top: 29px; + padding-right: 29px; + padding-left: 29px; + padding-bottom: 32px; + margin-bottom: 40px; `; export const OrderHistory = styled.div` - margin-top: 50px; + margin-top: 40px; width: 600px; height: 350px; border-radius: 10px; background: ${COLORS.white}; box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - padding-top: 23px; - padding-right: 23px; - padding-left: 23px; - padding-bottom: 23px; + padding-top: 29px; + padding-right: 29px; + padding-left: 29px; + padding-bottom: 29px; + margin-left: 60px; `; export const FavoritesContainer = styled.div` - margin-top: 50px; - width: 600px; height: 350px; border-radius: 10px; @@ -63,6 +78,8 @@ export const FavoritesContainer = styled.div` padding-right: 23px; padding-left: 23px; padding-bottom: 23px; + margin-left: 30px; + margin-top: 40px; `; export const LogOutButton = styled.button` @@ -75,9 +92,16 @@ export const LogOutButton = styled.button` font-weight: 600; line-height: normal; border: transparent; +<<<<<<< HEAD border-radius: 5px; width: 405px; height: 50px; +======= + border-radius: 10px; + width: 500px; + height: 55px; + margin-top: 40px; +>>>>>>> b287da7 (temp) `; /* transform: translateY(200px); */ @@ -100,7 +124,7 @@ export const FavoriteDiv = styled.div` align-items: center; justify-content: space-around; width: 100%; - margin-bottom: 50px; + margin-bottom: 20px; margin-top: 30px; `; @@ -129,8 +153,13 @@ export const Hover = styled.div<{ $ishovering?: boolean }>` `; export const BackButtonDiv = styled.div` +<<<<<<< HEAD margin-bottom: 30px; margin-top: 50px; +======= + margin-top: 50px; + margin-bottom: 40px; +>>>>>>> b287da7 (temp) `; export const HeaderDiv = styled.div` @@ -145,6 +174,11 @@ export const ProductNameDiv = styled.div` width: 250px; `; +export const Spacing = styled.div` + height: 10px; + width: 100%; +`; + export const BlankSpace = styled.div` width: 250px; height: 200px; @@ -168,7 +202,6 @@ export const ColumnDiv = styled.div` `; export const LogOutDiv = styled.div` - margin-top: 50px; margin-right: 30px; display: flex; justify-content: center; diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index bff2d899..d639e431 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -1,4 +1,4 @@ -import { Body1Bold } from '@/styles/fonts'; +import { Body2Bold } from '@/styles/fonts'; import { BackLink, ArrowLeftIcon } from './styles'; export default function BackButton(props: { destination: string }) { @@ -6,7 +6,7 @@ export default function BackButton(props: { destination: string }) { return ( - Back + Back ); } diff --git a/src/components/BackButton/styles.ts b/src/components/BackButton/styles.ts index 4abb943e..f8bfe12c 100644 --- a/src/components/BackButton/styles.ts +++ b/src/components/BackButton/styles.ts @@ -9,14 +9,23 @@ export const BackLink = styled(Link)` align-items: center; justify-content: space-between; color: ${COLORS.black}; +<<<<<<< HEAD width: 75px; +======= + width: 60px; +>>>>>>> b287da7 (temp) &:hover { text-decoration: underline; } `; export const ArrowLeftIcon = styled(ArrowLeft)` +<<<<<<< HEAD width: 20px; height: 20px; +======= + width: 18px; + height: 18px; +>>>>>>> b287da7 (temp) `; diff --git a/src/components/OrderHistory/OrderHistoryText.tsx b/src/components/OrderHistory/OrderHistoryText.tsx index 0135fce1..49f40893 100644 --- a/src/components/OrderHistory/OrderHistoryText.tsx +++ b/src/components/OrderHistory/OrderHistoryText.tsx @@ -1,8 +1,9 @@ import React, { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; +import { Check, CheckCircle, X, Send } from 'react-feather'; import querystring from 'querystring'; -import { Heading4Bold, Body1, OrderStatusFont } from '@/styles/fonts'; +import { Heading4Bold, Body1, OrderStatusFont, Body2 } from '@/styles/fonts'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import { ViewOrderButton, @@ -12,7 +13,7 @@ import { OrderStatusApprovedDiv, CrossStyled, OrderStatusSubmittedDiv, - LoaderStyled, + SendStyle, } from './styles'; // Adjust the import path as necessary import { Order, OrderStatus } from '../../schema/schema'; @@ -76,7 +77,7 @@ export default function OrderDetails(props: OrderDetailsProps) { > Order No. {orderNumber} viewOrder(orderNumber)}> - View Order + View Order
@@ -117,7 +118,7 @@ export default function OrderDetails(props: OrderDetailsProps) { > Order No. {orderNumber} viewOrder(orderNumber)}> - View Order + View Order
@@ -158,7 +159,7 @@ export default function OrderDetails(props: OrderDetailsProps) { > Order No. {orderNumber} viewOrder(orderNumber)}> - View Order + View Order
@@ -171,7 +172,7 @@ export default function OrderDetails(props: OrderDetailsProps) { {formatDate(date)} - + Order Submitted
diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index fec7e6c7..546d6c2b 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -1,6 +1,6 @@ // styles.ts import styled from 'styled-components'; -import { X, Check, Loader } from 'react-feather'; +import { X, Check, Send, Loader } from 'react-feather'; import COLORS from '../../styles/colors'; export const containerStyle = styled.div` @@ -165,8 +165,14 @@ export const GalleryImage = styled.img` export const RowDiv = styled.div` width: 700px; +<<<<<<< HEAD height: 300px; margin-bottom: 20px; +======= + height: 400px; + margin-bottom: 20px; + margin-top: 20px; +>>>>>>> b287da7 (temp) `; export const OrderStatusDiv = styled.div` @@ -194,7 +200,7 @@ export const OrderStatusApprovedDiv = styled.div` export const OrderStatusSubmittedDiv = styled.div` width: 300px; height: 35px; - background: var(--Baby-Blue, #c7ddff); + background: var(--Greyish, #E6E6E6); display: flex; justify-content: center; align-items: center; @@ -212,7 +218,7 @@ export const CheckStyled = styled(Check)` margin-right: 10px; `; -export const LoaderStyled = styled(Loader)` +export const SendStyle = styled(Send)` stroke-width: 3px; margin-right: 10px; `; diff --git a/src/components/ViewAllButton/ViewAllButton.tsx b/src/components/ViewAllButton/ViewAllButton.tsx index a5a574f4..d629c442 100644 --- a/src/components/ViewAllButton/ViewAllButton.tsx +++ b/src/components/ViewAllButton/ViewAllButton.tsx @@ -1,15 +1,14 @@ import Link from 'next/link'; -import { ArrowRight } from 'react-feather'; -import { Body1Point5 } from '@/styles/fonts'; -import { ViewAllDiv } from './styles'; +import { Body2, Body2Bold } from '@/styles/fonts'; +import { ArrowRightIcon, ViewAllDiv } from './styles'; export default function BackButton(props: { destination: string }) { const { destination } = props; return ( - View All - + View All + ); diff --git a/src/components/ViewAllButton/styles.ts b/src/components/ViewAllButton/styles.ts index 248778df..17ce6d93 100644 --- a/src/components/ViewAllButton/styles.ts +++ b/src/components/ViewAllButton/styles.ts @@ -1,7 +1,11 @@ import styled from 'styled-components'; +import { ArrowRight } from 'react-feather'; import COLORS from '../../styles/colors'; + export const ViewAllDiv = styled.div` + width: 80px; + gap: 5px; display: flex; align-items: center; color: ${COLORS.black}; @@ -13,3 +17,8 @@ export const ViewAllDiv = styled.div` `; export const placeHolder = ''; + +export const ArrowRightIcon = styled(ArrowRight)` + width: 20px; + height: 20px; +`; From 0f37f3bc6fc7e21934fcfe40370f5b18f12c64bd Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Sun, 21 Apr 2024 17:25:47 -0700 Subject: [PATCH 37/43] ip --- src/app/orderConfirmationPickUp/page.tsx | 1 + src/app/orderConfirmationPickUp/styles.ts | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 4c67f978..b1e55dae 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -39,6 +39,7 @@ import { ScrollDiv, ShippingDetailsDiv, BottomColumnDiv, + LabelBox1, LeftColumnDiv, RightColumnDiv, DetailsHeader, diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index 60860ab3..d602face 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -27,9 +27,14 @@ export const OutterFavoriteDiv = styled.div` max-width: 750px; margin-top: 20px; margin-right: 60px; +<<<<<<< HEAD margin-left: 60px; padding-right: 20px; padding-left: 40px; +======= + margin-left: 40px; + padding-right: 15px; +>>>>>>> 83a7d69 (new branch) padding-top: 10px; `; @@ -233,8 +238,13 @@ export const LeftColumnDiv = styled.div` export const RightColumnDiv = styled.div` display: flex; flex-flow: column; +<<<<<<< HEAD align-items: left; width: 475px; +======= + align-items: start; + width: 100%; +>>>>>>> 83a7d69 (new branch) `; export const BackButtonDiv = styled.div` @@ -242,7 +252,11 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; +<<<<<<< HEAD margin-left: 40px; +======= + margin-left: 60px; +>>>>>>> 83a7d69 (new branch) margin-bottom: 40px; margin-top: 20px; `; @@ -279,9 +293,15 @@ export const BottomColumnDiv = styled.div` export const TextDiv = styled.div` display: flex; flex-direction: row; +<<<<<<< HEAD margin-left: 20px; margin-top: 10px; margin-bottom: 10px; +======= + margin-left: 40px; + margin-top: 20px; + margin-bottom: 20px; +>>>>>>> 83a7d69 (new branch) `; export const TextDiv1 = styled.div` @@ -296,7 +316,10 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; +<<<<<<< HEAD position: relative; +======= +>>>>>>> 83a7d69 (new branch) margin-bottom: 40px; `; From 2fa888a1b33257826fa40daae2e203f78cdc6a60 Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Sun, 21 Apr 2024 17:28:11 -0700 Subject: [PATCH 38/43] done --- src/app/orderConfirmationPickUp/page.tsx | 1 + src/app/orderConfirmationPickUp/styles.ts | 33 +++++------------------ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index b1e55dae..25ecdc61 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -44,6 +44,7 @@ import { RightColumnDiv, DetailsHeader, ImageDiv, + Wrapper2, PageDiv, CenterDiv, BackButtonDiv, diff --git a/src/app/orderConfirmationPickUp/styles.ts b/src/app/orderConfirmationPickUp/styles.ts index d602face..3c2edb3e 100644 --- a/src/app/orderConfirmationPickUp/styles.ts +++ b/src/app/orderConfirmationPickUp/styles.ts @@ -27,14 +27,9 @@ export const OutterFavoriteDiv = styled.div` max-width: 750px; margin-top: 20px; margin-right: 60px; -<<<<<<< HEAD margin-left: 60px; padding-right: 20px; padding-left: 40px; -======= - margin-left: 40px; - padding-right: 15px; ->>>>>>> 83a7d69 (new branch) padding-top: 10px; `; @@ -238,13 +233,9 @@ export const LeftColumnDiv = styled.div` export const RightColumnDiv = styled.div` display: flex; flex-flow: column; -<<<<<<< HEAD + align-items: left; width: 475px; -======= - align-items: start; - width: 100%; ->>>>>>> 83a7d69 (new branch) `; export const BackButtonDiv = styled.div` @@ -252,11 +243,9 @@ export const BackButtonDiv = styled.div` flex-direction: row; text-align: left; width: 800px; -<<<<<<< HEAD + margin-left: 40px; -======= - margin-left: 60px; ->>>>>>> 83a7d69 (new branch) + margin-bottom: 40px; margin-top: 20px; `; @@ -270,7 +259,6 @@ export const WhiteBackgroundDiv = styled.div` box-shadow: 0px 4px 7px 0px rgba(0, 0, 0, 0.1); `; - export const Wrapper2 = styled.div` display: flex; flex-direction: col; @@ -293,15 +281,10 @@ export const BottomColumnDiv = styled.div` export const TextDiv = styled.div` display: flex; flex-direction: row; -<<<<<<< HEAD + margin-left: 20px; margin-top: 10px; margin-bottom: 10px; -======= - margin-left: 40px; - margin-top: 20px; - margin-bottom: 20px; ->>>>>>> 83a7d69 (new branch) `; export const TextDiv1 = styled.div` @@ -316,15 +299,13 @@ export const PageDiv = styled.div` justify-content: flex-start; align-items: flex-start; width: 100%; -<<<<<<< HEAD + position: relative; -======= ->>>>>>> 83a7d69 (new branch) + margin-bottom: 40px; `; export const ShippingDetailsDiv = styled.div` - display: flex; flex-direction: column; align-items: flex-start; @@ -358,4 +339,4 @@ export const CenterDiv = styled.div` position: relative; width: 100%; padding: 20px; -`; \ No newline at end of file +`; From f258e5a1cf94ed77e74fa1db7f51a9053e346eee Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Sun, 21 Apr 2024 17:29:31 -0700 Subject: [PATCH 39/43] con --- src/app/orderConfirmationPickUp/page.tsx | 1 - src/app/orderPage/page.tsx | 42 +++++++++++++----------- src/app/profileScreen/page.tsx | 23 +++++++++++++ src/app/profileScreen/styles.ts | 9 +++++ src/components/BackButton/BackButton.tsx | 4 +++ src/components/BackButton/styles.ts | 9 +++++ src/components/OrderHistory/styles.ts | 3 ++ 7 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index 25ecdc61..d7fea822 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -39,7 +39,6 @@ import { ScrollDiv, ShippingDetailsDiv, BottomColumnDiv, - LabelBox1, LeftColumnDiv, RightColumnDiv, DetailsHeader, diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index 27bfbf09..b7bb5ad4 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -2,7 +2,15 @@ import { useState, useEffect } from 'react'; import { Check, X, Send } from 'react-feather'; -import { Body1, Body2Light, Heading3Bold, Heading4Bold, Body2, Heading2, Body1Bold } from '@/styles/fonts'; +import { + Body1, + Body2Light, + Heading3Bold, + Heading4Bold, + Body2, + Heading2, + Body1Bold, +} from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; import BackButton from '../../components/BackButton/BackButton'; @@ -87,7 +95,7 @@ export default function OrderPage() { } fetchProducts(); }, []); - + const status = order?.order_status?.toLowerCase() || 'default'; return ( @@ -101,24 +109,24 @@ export default function OrderPage() { - {formatDate(order?.created_at)} + {formatDate(order?.created_at)} - Order No + Order No. {order?.id} - {orders.map(product => ( - - - {product.name} - + {orders.map(product => ( + + + {product.name} + {product.name} @@ -162,12 +170,8 @@ export default function OrderPage() { -
); } - - - diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 0717a352..21b95954 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -72,12 +72,35 @@ function FavoriteSection(props: { {Favorites.slice(0, 2).map(favorite => ( +<<<<<<< HEAD +======= + + {favorite.name} + + + {favorite.name} + + + Category: {favorite.category} + + + clickFunctions({ fav: favorite })} + > + + + +>>>>>>> b287da7 (temp) ))} diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index d9981199..167d347a 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -92,15 +92,21 @@ export const LogOutButton = styled.button` font-weight: 600; line-height: normal; border: transparent; +<<<<<<< HEAD <<<<<<< HEAD border-radius: 5px; width: 405px; height: 50px; ======= +======= +>>>>>>> b287da7 (temp) border-radius: 10px; width: 500px; height: 55px; margin-top: 40px; +<<<<<<< HEAD +>>>>>>> b287da7 (temp) +======= >>>>>>> b287da7 (temp) `; /* transform: translateY(200px); */ @@ -153,10 +159,13 @@ export const Hover = styled.div<{ $ishovering?: boolean }>` `; export const BackButtonDiv = styled.div` +<<<<<<< HEAD <<<<<<< HEAD margin-bottom: 30px; margin-top: 50px; ======= +======= +>>>>>>> b287da7 (temp) margin-top: 50px; margin-bottom: 40px; >>>>>>> b287da7 (temp) diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index d639e431..c8433a62 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -1,4 +1,8 @@ +<<<<<<< HEAD import { Body2Bold } from '@/styles/fonts'; +======= +import { Body1, Body2Bold } from '@/styles/fonts'; +>>>>>>> b287da7 (temp) import { BackLink, ArrowLeftIcon } from './styles'; export default function BackButton(props: { destination: string }) { diff --git a/src/components/BackButton/styles.ts b/src/components/BackButton/styles.ts index f8bfe12c..b53ecc47 100644 --- a/src/components/BackButton/styles.ts +++ b/src/components/BackButton/styles.ts @@ -9,9 +9,13 @@ export const BackLink = styled(Link)` align-items: center; justify-content: space-between; color: ${COLORS.black}; +<<<<<<< HEAD <<<<<<< HEAD width: 75px; +======= + width: 60px; +>>>>>>> b287da7 (temp) ======= width: 60px; >>>>>>> b287da7 (temp) @@ -21,6 +25,7 @@ export const BackLink = styled(Link)` `; export const ArrowLeftIcon = styled(ArrowLeft)` +<<<<<<< HEAD <<<<<<< HEAD width: 20px; height: 20px; @@ -28,4 +33,8 @@ export const ArrowLeftIcon = styled(ArrowLeft)` width: 18px; height: 18px; >>>>>>> b287da7 (temp) +======= + width: 18px; + height: 18px; +>>>>>>> b287da7 (temp) `; diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index 546d6c2b..120f0927 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -172,6 +172,9 @@ export const RowDiv = styled.div` height: 400px; margin-bottom: 20px; margin-top: 20px; +<<<<<<< HEAD +>>>>>>> b287da7 (temp) +======= >>>>>>> b287da7 (temp) `; From f6e18b5f1ae8a4fb5edb18a8c0815e6dcb236bde Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 15:01:24 -0700 Subject: [PATCH 40/43] fixed after rebasing --- src/app/orderHistory/styles.ts | 14 +---------- src/app/orderPage/styles.ts | 32 +++++++++++++----------- src/app/profileScreen/page.tsx | 25 +----------------- src/app/profileScreen/styles.ts | 22 +--------------- src/components/BackButton/BackButton.tsx | 5 +--- src/components/BackButton/styles.ts | 16 +++++------- src/components/FooterFolder/Footer.tsx | 4 +-- src/components/FooterFolder/styles.ts | 3 ++- src/components/OrderHistory/styles.ts | 2 +- src/components/ViewAllButton/styles.ts | 1 - 10 files changed, 32 insertions(+), 92 deletions(-) diff --git a/src/app/orderHistory/styles.ts b/src/app/orderHistory/styles.ts index 4746ba4c..f6d06db4 100644 --- a/src/app/orderHistory/styles.ts +++ b/src/app/orderHistory/styles.ts @@ -36,24 +36,12 @@ export const OrderHistoryContainer = styled.div` flex-direction: column; align-items: center; border-radius: 10px; -<<<<<<< HEAD background: ${COLORS.white}; box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); width: 800px; // Width of the outer box height: auto; - margin-top: 10px; - padding-top: 40px; -======= - background: var(--White, #fff); - background-color: pink; - box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); - width: 800px; // Width of the outer box - height: 700px; - overflow: scroll; margin-top: 20px; - margin-bottom: 50px; - padding: 0; // Ensure there's no padding pushing the internal boxes inward ->>>>>>> b287da7 (temp) + padding-top: 10px; `; export const OrderHistoryBox = styled.div` diff --git a/src/app/orderPage/styles.ts b/src/app/orderPage/styles.ts index 122fc5fe..9424e7aa 100644 --- a/src/app/orderPage/styles.ts +++ b/src/app/orderPage/styles.ts @@ -5,16 +5,16 @@ import { Heart } from 'react-feather'; import NavBar from '../../components/NavBarFolder/NavBar'; export const FavoriteDiv = styled.div` -display: flex; -flex-direction: row; -align-items: center; -justify-content: space-between; -width: 100%; -margin-bottom: 50px; -margin-top: 30px; -margin-right: 20px; -margin-left: 40px; -gap: 70px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + width: 100%; + margin-bottom: 50px; + margin-top: 30px; + margin-right: 20px; + margin-left: 40px; + gap: 70px; `; export const BottomColumnDiv = styled.div` @@ -25,7 +25,7 @@ export const BottomColumnDiv = styled.div` width: 100%; margin-left: 10px; margin-bottom: 30px; - gap: 10px; + gap: 20px; `; export const ScrollDiv = styled.div` @@ -48,10 +48,10 @@ export const LabelBox = styled.div` height: 100%; `; -export const OutterFavoriteDiv = styled.div` +export const OutterFavoriteDiv = styled.div` display: flex; flex-direction: column; - align-items: center; + align-items: left; border-radius: 10px; background: var(--White, #fff); box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.2); @@ -60,6 +60,7 @@ export const OutterFavoriteDiv = styled.div` overflow: scroll; margin-top: 20px; padding-top: 15px; + margin-left: 60px; `; export const BackDiv = styled.button` @@ -185,7 +186,6 @@ export const StatusButton = styled.button<{ status: string }>` }}; `; - export const Body1Bold = styled.p` font-size: 16px; font-style: normal; @@ -242,12 +242,14 @@ export const RightColumnDiv = styled.div` align-items: start; margin-left: 10px; width: 100%; + margin-top: 8px; `; export const TextDiv1 = styled.div` display: flex; flex-direction: row; margin-top: 20px; + background-color: pink; `; export const TextDiv = styled.div` @@ -264,4 +266,4 @@ export const LeftColumnDiv = styled.div` justify-content: space-evenly; align-items: space-evenly; width: 100%; -`; \ No newline at end of file +`; diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 21b95954..cb79e494 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -72,35 +72,12 @@ function FavoriteSection(props: { {Favorites.slice(0, 2).map(favorite => ( -<<<<<<< HEAD -======= - - {favorite.name} - - - {favorite.name} - - - Category: {favorite.category} - - - clickFunctions({ fav: favorite })} - > - - - ->>>>>>> b287da7 (temp) ))} @@ -446,7 +423,7 @@ export default function Profile() { - + diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 167d347a..5d649e5c 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -92,22 +92,10 @@ export const LogOutButton = styled.button` font-weight: 600; line-height: normal; border: transparent; -<<<<<<< HEAD -<<<<<<< HEAD + border-radius: 5px; width: 405px; height: 50px; -======= -======= ->>>>>>> b287da7 (temp) - border-radius: 10px; - width: 500px; - height: 55px; - margin-top: 40px; -<<<<<<< HEAD ->>>>>>> b287da7 (temp) -======= ->>>>>>> b287da7 (temp) `; /* transform: translateY(200px); */ @@ -159,16 +147,8 @@ export const Hover = styled.div<{ $ishovering?: boolean }>` `; export const BackButtonDiv = styled.div` -<<<<<<< HEAD -<<<<<<< HEAD margin-bottom: 30px; margin-top: 50px; -======= -======= ->>>>>>> b287da7 (temp) - margin-top: 50px; - margin-bottom: 40px; ->>>>>>> b287da7 (temp) `; export const HeaderDiv = styled.div` diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index c8433a62..5a555cc1 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -1,8 +1,5 @@ -<<<<<<< HEAD import { Body2Bold } from '@/styles/fonts'; -======= -import { Body1, Body2Bold } from '@/styles/fonts'; ->>>>>>> b287da7 (temp) + import { BackLink, ArrowLeftIcon } from './styles'; export default function BackButton(props: { destination: string }) { diff --git a/src/components/BackButton/styles.ts b/src/components/BackButton/styles.ts index b53ecc47..821d8173 100644 --- a/src/components/BackButton/styles.ts +++ b/src/components/BackButton/styles.ts @@ -9,32 +9,28 @@ export const BackLink = styled(Link)` align-items: center; justify-content: space-between; color: ${COLORS.black}; -<<<<<<< HEAD -<<<<<<< HEAD - width: 75px; - -======= width: 60px; +<<<<<<< HEAD >>>>>>> b287da7 (temp) ======= width: 60px; >>>>>>> b287da7 (temp) +======= +>>>>>>> 46a8b03 (fixed after rebasing) &:hover { text-decoration: underline; } `; export const ArrowLeftIcon = styled(ArrowLeft)` -<<<<<<< HEAD -<<<<<<< HEAD - width: 20px; - height: 20px; -======= width: 18px; height: 18px; +<<<<<<< HEAD >>>>>>> b287da7 (temp) ======= width: 18px; height: 18px; >>>>>>> b287da7 (temp) +======= +>>>>>>> 46a8b03 (fixed after rebasing) `; diff --git a/src/components/FooterFolder/Footer.tsx b/src/components/FooterFolder/Footer.tsx index 45fa2c42..7cb4eef9 100644 --- a/src/components/FooterFolder/Footer.tsx +++ b/src/components/FooterFolder/Footer.tsx @@ -26,7 +26,7 @@ import { export default function Footer({ ...rest }) { const router = useRouter(); return ( -
+ Contact Us @@ -122,6 +122,6 @@ export default function Footer({ ...rest }) { }} /> -
+ ); } diff --git a/src/components/FooterFolder/styles.ts b/src/components/FooterFolder/styles.ts index 1829fe3f..e9c70d54 100644 --- a/src/components/FooterFolder/styles.ts +++ b/src/components/FooterFolder/styles.ts @@ -119,7 +119,8 @@ export const SVGWrapper = styled.div` `; export const Wrapper = styled.div` - min-height: 100%; /*or 100vh */ + min-height: 100%; + width:100%; position: relative; background: var(--Light-Periwinkle, #f4f7ff); display: flex; diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index 120f0927..fef970a7 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -203,7 +203,7 @@ export const OrderStatusApprovedDiv = styled.div` export const OrderStatusSubmittedDiv = styled.div` width: 300px; height: 35px; - background: var(--Greyish, #E6E6E6); + background: var(--Greyish, #e6e6e6); display: flex; justify-content: center; align-items: center; diff --git a/src/components/ViewAllButton/styles.ts b/src/components/ViewAllButton/styles.ts index 17ce6d93..c77c4441 100644 --- a/src/components/ViewAllButton/styles.ts +++ b/src/components/ViewAllButton/styles.ts @@ -2,7 +2,6 @@ import styled from 'styled-components'; import { ArrowRight } from 'react-feather'; import COLORS from '../../styles/colors'; - export const ViewAllDiv = styled.div` width: 80px; gap: 5px; From 358096cc7e87926033d60d712903b39130255981 Mon Sep 17 00:00:00 2001 From: CharlotteLaw Date: Sun, 21 Apr 2024 15:35:00 -0700 Subject: [PATCH 41/43] Week 7 and 8 Sprint --- src/app/delivery/page.tsx | 1 - src/app/orderConfirmationPickUp/page.tsx | 13 +- src/app/orderHistory/styles.ts | 2 +- src/app/orderPage/page.tsx | 64 ++++--- src/app/orderPage/styles.ts | 13 +- src/app/profileScreen/page.tsx | 3 +- src/components/BackButton/BackButton.tsx | 1 - src/components/FooterFolder/Footer.tsx | 180 +++++++++--------- src/components/FooterFolder/styles.ts | 4 +- .../OrderHistory/OrderHistoryText.tsx | 1 - src/components/OrderHistory/styles.ts | 2 +- .../ViewAllButton/ViewAllButton.tsx | 2 +- 12 files changed, 143 insertions(+), 143 deletions(-) diff --git a/src/app/delivery/page.tsx b/src/app/delivery/page.tsx index 1e66b420..6d7540e6 100644 --- a/src/app/delivery/page.tsx +++ b/src/app/delivery/page.tsx @@ -9,7 +9,6 @@ import { import querystring from 'querystring'; import { createOrder, - fetchCurrentOrdersByUser, updateOrderStatus, } from '@/api/supabase/queries/order_queries'; import BackButton from '../../components/BackButton/BackButton'; diff --git a/src/app/orderConfirmationPickUp/page.tsx b/src/app/orderConfirmationPickUp/page.tsx index d7fea822..647e04c0 100644 --- a/src/app/orderConfirmationPickUp/page.tsx +++ b/src/app/orderConfirmationPickUp/page.tsx @@ -4,14 +4,8 @@ import { useState, useEffect } from 'react'; import { fetchUser } from '@/api/supabase/queries/user_queries'; import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; -import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; +import { getOrderById } from '@/api/supabase/queries/order_queries'; import { - fetchCurrentOrdersByUser, - getOrderById, -} from '@/api/supabase/queries/order_queries'; -import { - Body2Bold, - Body2, Heading3Bold, Body1, Body1Bold, @@ -30,11 +24,8 @@ import NavBar from '../../components/NavBarFolder/NavBar'; import { FavoriteDiv, - ColDiv, OutterFavoriteDiv, TextDiv1, - OutterBox, - Label, LabelBox, ScrollDiv, ShippingDetailsDiv, @@ -77,7 +68,7 @@ export default function OrderConfirmationPickUp() { fetchProducts(); setUserDetails(); - }, []); + }); function organizePickupTime() { const startTime = pickupTime?.start_time.toLocaleString(); diff --git a/src/app/orderHistory/styles.ts b/src/app/orderHistory/styles.ts index f6d06db4..3ef05566 100644 --- a/src/app/orderHistory/styles.ts +++ b/src/app/orderHistory/styles.ts @@ -28,10 +28,10 @@ export const OutterBox = styled.div` width: 800px; margin-top: 40px; margin-bottom: 70px; + min-height: 50px; `; export const OrderHistoryContainer = styled.div` - display: flex; flex-direction: column; align-items: center; diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index b7bb5ad4..a730bdb3 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -1,7 +1,6 @@ 'use client'; import { useState, useEffect } from 'react'; -import { Check, X, Send } from 'react-feather'; import { Body1, Body2Light, @@ -11,7 +10,9 @@ import { Heading2, Body1Bold, } from '@/styles/fonts'; +import { fetchUser } from '@/api/supabase/queries/user_queries'; import { useSearchParams } from 'next/navigation'; +import { fetchPickupTimesByID } from '@/api/supabase/queries/pickup_queries'; import BackButton from '../../components/BackButton/BackButton'; import { @@ -28,22 +29,19 @@ import { DetailsHeader, RightColumnDiv, TextDiv, - TextDiv1, - OutterBox, - OutterDiv, ImageDiv, BottomColumnDiv, ShippingDetailsDiv, LabelBox, + TextDiv2, LeftColumnDiv, ScrollDiv, - ProductNameDiv, PageDiv, CenterDiv, - StatusButton, + TextDiv1, } from './styles'; -import { ProductWithQuantity, Order } from '../../schema/schema'; +import { ProductWithQuantity, Order, Pickup, User } from '../../schema/schema'; function formatDate(date: string | undefined): string { if (!date) return ''; @@ -71,8 +69,18 @@ function formatDate(date: string | undefined): string { return `${month} ${day}, ${year}`; } +function formatTime(date: string | undefined): string { + if (!date) return ''; + + const hour = date.substring(11, 13); + const minute = date.substring(14, 16); + + return `${hour}:${minute}`; +} + export default function OrderPage() { const [orders, setOrders] = useState([]); + const [pickupTime, setPickupTime] = useState(); const searchParams = useSearchParams(); const orderIDFromSearch = searchParams.get('orderID'); let currOrderId = 0; @@ -82,6 +90,13 @@ export default function OrderPage() { currOrderId = 32; } + async function setUserDetails() { + const fetchedUser = await fetchUser(); + const currOrder = await getOrderById(Number(orderIDFromSearch)); + const pickup = await fetchPickupTimesByID(currOrder.pickup_time_id); + setPickupTime(pickup); + } + const [order, setOrder] = useState(); useEffect(() => { @@ -94,9 +109,19 @@ export default function OrderPage() { setOrder(currOrder); } fetchProducts(); - }, []); + setUserDetails(); + }); - const status = order?.order_status?.toLowerCase() || 'default'; + function organizePickupTime() { + const startTime = pickupTime?.start_time.toLocaleString(); + + const date = + startTime == null + ? ['0', '0', '0'] + : startTime?.substring(0, 10).split('-'); + const dateStr = `${date[1]}/${date[2]}/${date[0]}`; + return `${dateStr}`; + } return (
@@ -136,25 +161,7 @@ export default function OrderPage() { -
- - Quantity: - - - {product.quantity} - -
+ Quantity: {product.quantity}
))} @@ -165,6 +172,7 @@ export default function OrderPage() { Pickup Information Time Slot + {organizePickupTime()} (10:00 am - 12:30 pm) Location 3170 23rd Street, San Francisco, CA 94110 diff --git a/src/app/orderPage/styles.ts b/src/app/orderPage/styles.ts index 9424e7aa..52092ced 100644 --- a/src/app/orderPage/styles.ts +++ b/src/app/orderPage/styles.ts @@ -104,6 +104,7 @@ export const BackButtonDiv = styled.div` gap: 200px; margin-bottom: 50px; margin-top: 50px; + margin-left: 60px; text-align: left; width: 800px; `; @@ -231,7 +232,7 @@ export const ShippingDetailsDiv = styled.div` padding: 36px 34px; gap: 33px; max-height: 100%; - margin-top: 93px; + margin-top: 52px; margin-bottom: 30px; margin-right: 40px; `; @@ -248,15 +249,21 @@ export const RightColumnDiv = styled.div` export const TextDiv1 = styled.div` display: flex; flex-direction: row; + margin-left: 40px; margin-top: 20px; - background-color: pink; `; export const TextDiv = styled.div` display: flex; flex-direction: row; margin-left: 60px; - margin-top: 20px; +`; + +export const TextDiv2 = styled.div` + display: flex; + flex-direction: row; + margin-left: 40px; + margin-top: 5px; margin-bottom: 20px; `; diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index cb79e494..70584754 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -5,7 +5,6 @@ import { toast, ToastContainer } from 'react-toastify'; import { useEffect, useState } from 'react'; import { Heading2, - Body3, Heading3, Heading1, Body1Bold, @@ -32,7 +31,7 @@ import { fetchOrderProductById, fetchProductWithQuantityById, } from '@/api/supabase/queries/order_queries'; -import { Check, CheckCircle, X, Send } from 'react-feather'; +import { Check, X, Send } from 'react-feather'; import BackButton from '../../components/BackButton/BackButton'; import { LogOutButton, diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index 5a555cc1..d639e431 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -1,5 +1,4 @@ import { Body2Bold } from '@/styles/fonts'; - import { BackLink, ArrowLeftIcon } from './styles'; export default function BackButton(props: { destination: string }) { diff --git a/src/components/FooterFolder/Footer.tsx b/src/components/FooterFolder/Footer.tsx index 7cb4eef9..bb9714ef 100644 --- a/src/components/FooterFolder/Footer.tsx +++ b/src/components/FooterFolder/Footer.tsx @@ -23,105 +23,103 @@ import { ArrowUpRightIcon, } from './styles'; -export default function Footer({ ...rest }) { +export default function Footer() { const router = useRouter(); return ( - - - - Contact Us - Phone: (415) 674-4700 - - { - window.location.href = - 'https://www.facebook.com/ShantiProjectSF/'; - }} - > - - - - - { - window.location.href = - 'https://www.youtube.com/channel/UCc3DMrL7_KDOzeJNVkoFrsA'; - }} - > - - - - - { - window.location.href = - 'https://www.instagram.com/shantiprojectsf/'; - }} - > - - - - - - - - - Mission District - - 3170 23rd Street - San Francisco, CA 94110 - - - { - window.location.href = - 'https://maps.app.goo.gl/LJWvkdhwrRMhjEZs7'; - }} - > - SEE ON MAP - - - - - - - + + Contact Us + Phone: (415) 674-4700 + + { + window.location.href = + 'https://www.facebook.com/ShantiProjectSF/'; + }} + > + + + + + router.push('/storefront')} + onClick={() => { + window.location.href = + 'https://www.youtube.com/channel/UCc3DMrL7_KDOzeJNVkoFrsA'; + }} > - Shop - - + + + + router.push('/profileScreen')} + onClick={() => { + window.location.href = + 'https://www.instagram.com/shantiprojectsf/'; + }} > - Profile - - + + + + + + + + Mission District + + 3170 23rd Street + San Francisco, CA 94110 + + + router.push('/cart')} + onClick={() => { + window.location.href = + 'https://maps.app.goo.gl/LJWvkdhwrRMhjEZs7'; + }} > - Cart - - + SEE ON MAP + + + + + + + router.push('/storefront')} + > + Shop + + router.push('/profileScreen')} + > + Profile + + router.push('/cart')} + > + Cart + + - logo pic - - + logo pic + ); } diff --git a/src/components/FooterFolder/styles.ts b/src/components/FooterFolder/styles.ts index e9c70d54..98701886 100644 --- a/src/components/FooterFolder/styles.ts +++ b/src/components/FooterFolder/styles.ts @@ -119,8 +119,8 @@ export const SVGWrapper = styled.div` `; export const Wrapper = styled.div` - min-height: 100%; - width:100%; + min-height: 100%; + width: 100%; position: relative; background: var(--Light-Periwinkle, #f4f7ff); display: flex; diff --git a/src/components/OrderHistory/OrderHistoryText.tsx b/src/components/OrderHistory/OrderHistoryText.tsx index 49f40893..34200de5 100644 --- a/src/components/OrderHistory/OrderHistoryText.tsx +++ b/src/components/OrderHistory/OrderHistoryText.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; -import { Check, CheckCircle, X, Send } from 'react-feather'; import querystring from 'querystring'; import { Heading4Bold, Body1, OrderStatusFont, Body2 } from '@/styles/fonts'; diff --git a/src/components/OrderHistory/styles.ts b/src/components/OrderHistory/styles.ts index fef970a7..419e1389 100644 --- a/src/components/OrderHistory/styles.ts +++ b/src/components/OrderHistory/styles.ts @@ -1,6 +1,6 @@ // styles.ts import styled from 'styled-components'; -import { X, Check, Send, Loader } from 'react-feather'; +import { X, Check, Send } from 'react-feather'; import COLORS from '../../styles/colors'; export const containerStyle = styled.div` diff --git a/src/components/ViewAllButton/ViewAllButton.tsx b/src/components/ViewAllButton/ViewAllButton.tsx index d629c442..2298c75a 100644 --- a/src/components/ViewAllButton/ViewAllButton.tsx +++ b/src/components/ViewAllButton/ViewAllButton.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import { Body2, Body2Bold } from '@/styles/fonts'; +import { Body2 } from '@/styles/fonts'; import { ArrowRightIcon, ViewAllDiv } from './styles'; export default function BackButton(props: { destination: string }) { From e16534abd61f149d4433049cee8ad9b342b1d249 Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Sun, 21 Apr 2024 17:34:14 -0700 Subject: [PATCH 42/43] msg --- src/app/orderPage/page.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/orderPage/page.tsx b/src/app/orderPage/page.tsx index a730bdb3..e8d035f3 100644 --- a/src/app/orderPage/page.tsx +++ b/src/app/orderPage/page.tsx @@ -41,7 +41,7 @@ import { TextDiv1, } from './styles'; -import { ProductWithQuantity, Order, Pickup, User } from '../../schema/schema'; +import { ProductWithQuantity, Order, Pickup } from '../../schema/schema'; function formatDate(date: string | undefined): string { if (!date) return ''; @@ -91,7 +91,6 @@ export default function OrderPage() { } async function setUserDetails() { - const fetchedUser = await fetchUser(); const currOrder = await getOrderById(Number(orderIDFromSearch)); const pickup = await fetchPickupTimesByID(currOrder.pickup_time_id); setPickupTime(pickup); From 31dd383322bda0ec09b87850515d80b223ba0cee Mon Sep 17 00:00:00 2001 From: Buyankhuu Tsolmonkhuu Date: Sun, 21 Apr 2024 17:49:53 -0700 Subject: [PATCH 43/43] buyankhuu's rebase --- src/app/cart/styles.tsx | 4 ++-- src/app/favorites/individualItem.tsx | 17 +---------------- src/app/favorites/page.tsx | 12 +++++++++++- src/app/login/page.tsx | 7 ------- src/app/orderConfirmationPickUp/page.tsx | 6 +----- src/app/orderPage/page.tsx | 13 +------------ src/app/orderPageDelivery/page.tsx | 15 ++------------- src/app/profileScreen/individualItem.tsx | 3 +-- src/app/profileScreen/page.tsx | 1 - src/app/profileScreen/styles.ts | 1 + 10 files changed, 20 insertions(+), 59 deletions(-) diff --git a/src/app/cart/styles.tsx b/src/app/cart/styles.tsx index ee956f99..b9593f7b 100644 --- a/src/app/cart/styles.tsx +++ b/src/app/cart/styles.tsx @@ -339,7 +339,7 @@ export const OrderContainer = styled.div` export const RightColumnDiv = styled.div` flex: 1; margin-top: 30px; - padding-left: 20px; + margin-bottom: 30px; `; export const Heading = styled.h1` @@ -379,5 +379,5 @@ export const CategorySpacing = styled.div` `; export const OrderSumSectionSpacing = styled.div` - margin-left: 135px; + margin-left: 65px; `; diff --git a/src/app/favorites/individualItem.tsx b/src/app/favorites/individualItem.tsx index 7b9eea0c..c93d7088 100644 --- a/src/app/favorites/individualItem.tsx +++ b/src/app/favorites/individualItem.tsx @@ -1,10 +1,9 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { useRouter } from 'next/navigation'; import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; -import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; import { HeartIcon, Hover, @@ -27,20 +26,6 @@ export default function IndividualItem(props: { const router = useRouter(); const [hovering, setHovering] = useState(false); - useEffect(() => { - async function changeCategory() { - try { - favorite.category = await convertButtonNumberToCategory( - favorite.category, - ); - } catch (error) { - // console.error(error); - } - } - - changeCategory(); - }, [favorite]); - async function clickFunctions(props2: { fav: Product }) { const { fav } = props2; addOrRemoveProductFromFavorite(fav, false); diff --git a/src/app/favorites/page.tsx b/src/app/favorites/page.tsx index 6c00e83a..506e203e 100644 --- a/src/app/favorites/page.tsx +++ b/src/app/favorites/page.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import { Heading1 } from '@/styles/fonts'; +import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; import BackButton from '../../components/BackButton/BackButton'; import { arrayOfFavorites } from '../../api/supabase/queries/user_queries'; @@ -18,7 +19,16 @@ export default function FavoritesPage() { async function fetchProducts() { const data = (await arrayOfFavorites()) as Product[]; - setFavorites(data); + const mapCategories = await Promise.all( + data.map(async product => { + const updateCategory = await convertButtonNumberToCategory( + product.category, + ); + return { ...product, category: updateCategory }; + }), + ); + + setFavorites(mapCategories); } useEffect(() => { fetchProducts(); diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index bae4f37c..89fbfbac 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -41,13 +41,6 @@ export default function App() { } }; - async function applyFilter(e: React.KeyboardEvent) { - const keypressed = e.code; - if (keypressed === 'Enter') { - handleLogin(); - } - } - return ( ([]); const [pickupTime, setPickupTime] = useState(); diff --git a/src/app/orderPageDelivery/page.tsx b/src/app/orderPageDelivery/page.tsx index 0b78c29e..07f89aaf 100644 --- a/src/app/orderPageDelivery/page.tsx +++ b/src/app/orderPageDelivery/page.tsx @@ -12,7 +12,6 @@ import { Body2Light, Heading2Bold, Heading3Bold, - Heading4Bold, } from '@/styles/fonts'; import { useSearchParams } from 'next/navigation'; import { @@ -25,8 +24,6 @@ import { } from '@/api/supabase/queries/order_queries'; import BackButton from '../../components/BackButton/BackButton'; -import { fetchCartItemsWithQuantityByID } from '../../api/supabase/queries/cart_queries'; - import NavBar from '../../components/NavBarFolder/NavBar'; import { @@ -45,15 +42,8 @@ import { StatusButton, } from './styles'; -import { - Product, - User, - Address, - ProductWithQuantity, - Order, -} from '../../schema/schema'; +import { User, Address, ProductWithQuantity, Order } from '../../schema/schema'; import { Body1Bold } from '../orderPage/styles'; -import { BackButtonDiv } from '../orderConfirmationPickUp/styles'; export default function OrderPageDelivery() { const [orders, setOrders] = useState([]); @@ -135,12 +125,11 @@ export default function OrderPageDelivery() { function organizeOrderTime() { const Time = order?.created_at.toLocaleString(); - console.log(Time); + let ampm = 'AM'; const date = Time == null ? ['00', '00'] : Time?.substring(11, 16).split(':'); - console.log(date); if (parseInt(date[0], 10) >= 12) { date[0] = (parseInt(date[0], 10) - 12).toLocaleString(); ampm = 'PM'; diff --git a/src/app/profileScreen/individualItem.tsx b/src/app/profileScreen/individualItem.tsx index 69288d69..f5f308ee 100644 --- a/src/app/profileScreen/individualItem.tsx +++ b/src/app/profileScreen/individualItem.tsx @@ -1,8 +1,7 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { Body1Bold, Body2, Body3 } from '@/styles/fonts'; -import { convertButtonNumberToCategory } from '@/api/supabase/queries/button_queries'; import { HeartIcon, Hover, FavoriteDiv, ProductNameDiv } from './styles'; import { addOrRemoveProductFromFavorite } from '../../api/supabase/queries/user_queries'; diff --git a/src/app/profileScreen/page.tsx b/src/app/profileScreen/page.tsx index 70584754..58df35a0 100644 --- a/src/app/profileScreen/page.tsx +++ b/src/app/profileScreen/page.tsx @@ -39,7 +39,6 @@ import { AccountDetailsDeliv, AccountDetailsPickUp, HeadingBack, - Spacing, HeadingSpacing, TextSpacing, OrderHistory, diff --git a/src/app/profileScreen/styles.ts b/src/app/profileScreen/styles.ts index 5d649e5c..b8c2ba74 100644 --- a/src/app/profileScreen/styles.ts +++ b/src/app/profileScreen/styles.ts @@ -196,6 +196,7 @@ export const LogOutDiv = styled.div` justify-content: center; width: 500px; height: 350px; + margin-top: 40px; `; export const MessageDiv = styled.div`