diff --git a/components/auth/ForgotPassword.tsx b/components/auth/ForgotPassword.tsx deleted file mode 100644 index dbac371c7..000000000 --- a/components/auth/ForgotPassword.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { FC, useEffect, useState, useCallback } from 'react' -import { validate } from 'email-validator' -import { useUI } from '@components/ui/context' -import { Logo, Button, Input } from '@components/ui' - -interface Props {} - -const ForgotPassword: FC = () => { - // Form State - const [email, setEmail] = useState('') - const [loading, setLoading] = useState(false) - const [message, setMessage] = useState('') - const [dirty, setDirty] = useState(false) - const [disabled, setDisabled] = useState(false) - - const { setModalView, closeModal } = useUI() - - const handleResetPassword = async (e: React.SyntheticEvent) => { - e.preventDefault() - - if (!dirty && !disabled) { - setDirty(true) - handleValidation() - } - } - - const handleValidation = useCallback(() => { - // Unable to send form unless fields are valid. - if (dirty) { - setDisabled(!validate(email)) - } - }, [email, dirty]) - - useEffect(() => { - handleValidation() - }, [handleValidation]) - - return ( -
-
- -
-
- {message && ( -
{message}
- )} - - -
- -
- - - Do you have an account? - {` `} - setModalView('LOGIN_VIEW')} - > - Log In - - -
-
- ) -} - -export default ForgotPassword diff --git a/components/auth/LoginView.tsx b/components/auth/LoginView.tsx deleted file mode 100644 index 35ff98f66..000000000 --- a/components/auth/LoginView.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { FC, useEffect, useState, useCallback } from 'react' -import { Logo, Button, Input } from '@components/ui' -import useLogin from '@framework/auth/use-login' -import { useUI } from '@components/ui/context' -import { validate } from 'email-validator' - -interface Props {} - -const LoginView: FC = () => { - // Form State - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') - const [loading, setLoading] = useState(false) - const [message, setMessage] = useState('') - const [dirty, setDirty] = useState(false) - const [disabled, setDisabled] = useState(false) - const { setModalView, closeModal } = useUI() - - const login = useLogin() - - const handleLogin = async (e: React.SyntheticEvent) => { - e.preventDefault() - - if (!dirty && !disabled) { - setDirty(true) - handleValidation() - } - - try { - setLoading(true) - setMessage('') - await login({ - email, - password, - }) - setLoading(false) - closeModal() - } catch ({ errors }) { - setMessage(errors[0].message) - setLoading(false) - } - } - - const handleValidation = useCallback(() => { - // Test for Alphanumeric password - const validPassword = /^(?=.*[a-zA-Z])(?=.*[0-9])/.test(password) - - // Unable to send form unless fields are valid. - if (dirty) { - setDisabled(!validate(email) || password.length < 7 || !validPassword) - } - }, [email, password, dirty]) - - useEffect(() => { - handleValidation() - }, [handleValidation]) - - return ( -
-
- -
-
- {message && ( - - )} - - - - -
- Don't have an account? - {` `} - setModalView('SIGNUP_VIEW')} - > - Sign Up - -
-
-
- ) -} - -export default LoginView diff --git a/components/auth/SignUpView.tsx b/components/auth/SignUpView.tsx deleted file mode 100644 index a85a3bc27..000000000 --- a/components/auth/SignUpView.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { FC, useEffect, useState, useCallback } from 'react' -import { validate } from 'email-validator' -import { Info } from '@components/icons' -import { useUI } from '@components/ui/context' -import { Logo, Button, Input } from '@components/ui' -import useSignup from '@framework/auth/use-signup' - -interface Props {} - -const SignUpView: FC = () => { - // Form State - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') - const [firstName, setFirstName] = useState('') - const [lastName, setLastName] = useState('') - const [loading, setLoading] = useState(false) - const [message, setMessage] = useState('') - const [dirty, setDirty] = useState(false) - const [disabled, setDisabled] = useState(false) - - const signup = useSignup() - const { setModalView, closeModal } = useUI() - - const handleSignup = async (e: React.SyntheticEvent) => { - e.preventDefault() - - if (!dirty && !disabled) { - setDirty(true) - handleValidation() - } - - try { - setLoading(true) - setMessage('') - await signup({ - email, - firstName, - lastName, - password, - }) - setLoading(false) - closeModal() - } catch ({ errors }) { - setMessage(errors[0].message) - setLoading(false) - } - } - - const handleValidation = useCallback(() => { - // Test for Alphanumeric password - const validPassword = /^(?=.*[a-zA-Z])(?=.*[0-9])/.test(password) - - // Unable to send form unless fields are valid. - if (dirty) { - setDisabled(!validate(email) || password.length < 7 || !validPassword) - } - }, [email, password, dirty]) - - useEffect(() => { - handleValidation() - }, [handleValidation]) - - return ( -
-
- -
-
- {message && ( -
{message}
- )} - - - - - - - - {' '} - - Info: Passwords must be longer than 7 chars and - include numbers.{' '} - - -
- -
- - - Do you have an account? - {` `} - setModalView('LOGIN_VIEW')} - > - Log In - - -
-
- ) -} - -export default SignUpView diff --git a/components/auth/index.ts b/components/auth/index.ts deleted file mode 100644 index 11571fac7..000000000 --- a/components/auth/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as LoginView } from './LoginView' -export { default as SignUpView } from './SignUpView' -export { default as ForgotPassword } from './ForgotPassword' diff --git a/components/cart/CartItem/CartItem.module.css b/components/cart/CartItem/CartItem.module.css deleted file mode 100644 index dd43314fb..000000000 --- a/components/cart/CartItem/CartItem.module.css +++ /dev/null @@ -1,32 +0,0 @@ -.root { - @apply flex flex-col py-4; -} - -.root:first-child { - padding-top: 0; -} - -.quantity { - appearance: textfield; - @apply w-8 border-accent-2 border mx-3 rounded text-center text-sm text-black; -} - -.quantity::-webkit-outer-spin-button, -.quantity::-webkit-inner-spin-button { - @apply appearance-none m-0; -} - -.productImage { - position: absolute; - transform: scale(1.9); - width: 100%; - height: 100%; - left: 30% !important; - top: 30% !important; - z-index: 1; -} - -.productName { - @apply font-medium cursor-pointer pb-1; - margin-top: -4px; -} diff --git a/components/cart/CartItem/CartItem.tsx b/components/cart/CartItem/CartItem.tsx deleted file mode 100644 index a59024e06..000000000 --- a/components/cart/CartItem/CartItem.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { ChangeEvent, FocusEventHandler, useEffect, useState } from 'react' -import cn from 'classnames' -import Image from 'next/image' -import Link from 'next/link' -import s from './CartItem.module.css' -import { Trash, Plus, Minus, Cross } from '@components/icons' -import { useUI } from '@components/ui/context' -import type { LineItem } from '@commerce/types/cart' -import usePrice from '@framework/product/use-price' -import useUpdateItem from '@framework/cart/use-update-item' -import useRemoveItem from '@framework/cart/use-remove-item' -import Quantity from '@components/ui/Quantity' - -type ItemOption = { - name: string - nameId: number - value: string - valueId: number -} - -const CartItem = ({ - item, - variant = 'default', - currencyCode, - ...rest -}: { - variant?: 'default' | 'display' - item: LineItem - currencyCode: string -}) => { - const { closeSidebarIfPresent } = useUI() - const [removing, setRemoving] = useState(false) - const [quantity, setQuantity] = useState(item.quantity) - const removeItem = useRemoveItem() - const updateItem = useUpdateItem({ item }) - - const { price } = usePrice({ - amount: item.variant.price * item.quantity, - baseAmount: item.variant.listPrice * item.quantity, - currencyCode, - }) - - const handleChange = async ({ - target: { value }, - }: ChangeEvent) => { - setQuantity(Number(value)) - await updateItem({ quantity: Number(value) }) - } - - const increaseQuantity = async (n = 1) => { - const val = Number(quantity) + n - setQuantity(val) - await updateItem({ quantity: val }) - } - - const handleRemove = async () => { - setRemoving(true) - try { - await removeItem(item) - } catch (error) { - setRemoving(false) - } - } - - // TODO: Add a type for this - const options = (item as any).options - - useEffect(() => { - // Reset the quantity state if the item quantity changes - if (item.quantity !== Number(quantity)) { - setQuantity(item.quantity) - } - }, [item.quantity]) - - return ( -
  • -
    -
    - - closeSidebarIfPresent()} - className={s.productImage} - width={150} - height={150} - src={item.variant.image!.url} - alt={item.variant.image!.altText} - unoptimized - /> - -
    -
    - - closeSidebarIfPresent()} - > - {item.name} - - - {options && options.length > 0 && ( -
    - {options.map((option: ItemOption, i: number) => ( -
    - {option.name} - {option.name === 'Color' ? ( - - ) : ( - - {option.value} - - )} - {i === options.length - 1 ? '' : } -
    - ))} -
    - )} - {variant === 'display' && ( -
    {quantity}x
    - )} -
    -
    - {price} -
    -
    - {variant === 'default' && ( - increaseQuantity(1)} - decrease={() => increaseQuantity(-1)} - /> - )} -
  • - ) -} - -export default CartItem diff --git a/components/cart/CartItem/index.ts b/components/cart/CartItem/index.ts deleted file mode 100644 index b5f6dc52f..000000000 --- a/components/cart/CartItem/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './CartItem' diff --git a/components/cart/CartSidebarView/CartSidebarView.module.css b/components/cart/CartSidebarView/CartSidebarView.module.css deleted file mode 100644 index c9ffbed50..000000000 --- a/components/cart/CartSidebarView/CartSidebarView.module.css +++ /dev/null @@ -1,11 +0,0 @@ -.root { - min-height: 100vh; -} - -.root.empty { - @apply bg-secondary text-secondary; -} - -.lineItemsList { - @apply py-4 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-2 border-accent-2; -} diff --git a/components/cart/CartSidebarView/CartSidebarView.tsx b/components/cart/CartSidebarView/CartSidebarView.tsx deleted file mode 100644 index 128b928a8..000000000 --- a/components/cart/CartSidebarView/CartSidebarView.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import cn from 'classnames' -import Link from 'next/link' -import { FC } from 'react' -import s from './CartSidebarView.module.css' -import CartItem from '../CartItem' -import { Button, Text } from '@components/ui' -import { useUI } from '@components/ui/context' -import { Bag, Cross, Check } from '@components/icons' -import useCart from '@framework/cart/use-cart' -import usePrice from '@framework/product/use-price' -import SidebarLayout from '@components/common/SidebarLayout' - -const CartSidebarView: FC = () => { - const { closeSidebar, setSidebarView } = useUI() - const { data, isLoading, isEmpty } = useCart() - - const { price: subTotal } = usePrice( - data && { - amount: Number(data.subtotalPrice), - currencyCode: data.currency.code, - } - ) - const { price: total } = usePrice( - data && { - amount: Number(data.totalPrice), - currencyCode: data.currency.code, - } - ) - const handleClose = () => closeSidebar() - const goToCheckout = () => setSidebarView('CHECKOUT_VIEW') - - const error = null - const success = null - - return ( - - {isLoading || isEmpty ? ( -
    - - - -

    - Your cart is empty -

    -

    - Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake. -

    -
    - ) : error ? ( -
    - - - -

    - We couldn’t process the purchase. Please check your card information - and try again. -

    -
    - ) : success ? ( -
    - - - -

    - Thank you for your order. -

    -
    - ) : ( - <> -
    - - - My Cart - - -
      - {data!.lineItems.map((item: any) => ( - - ))} -
    -
    - -
    -
      -
    • - Subtotal - {subTotal} -
    • -
    • - Taxes - Calculated at checkout -
    • -
    • - Shipping - FREE -
    • -
    -
    - Total - {total} -
    -
    - {process.env.COMMERCE_CUSTOMCHECKOUT_ENABLED ? ( - - ) : ( - - )} -
    -
    - - )} -
    - ) -} - -export default CartSidebarView diff --git a/components/cart/CartSidebarView/index.ts b/components/cart/CartSidebarView/index.ts deleted file mode 100644 index 0262e448e..000000000 --- a/components/cart/CartSidebarView/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './CartSidebarView' diff --git a/components/cart/index.ts b/components/cart/index.ts deleted file mode 100644 index 3e53fa34a..000000000 --- a/components/cart/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as CartSidebarView } from './CartSidebarView' -export { default as CartItem } from './CartItem' diff --git a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.module.css b/components/checkout/CheckoutSidebarView/CheckoutSidebarView.module.css deleted file mode 100644 index 34c1b487c..000000000 --- a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.root { - min-height: calc(100vh - 322px); -} - -.lineItemsList { - @apply py-4 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-2 border-accent-2; -} diff --git a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx b/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx deleted file mode 100644 index fb562e7af..000000000 --- a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import cn from 'classnames' -import Link from 'next/link' -import { FC } from 'react' -import CartItem from '@components/cart/CartItem' -import { Button, Text } from '@components/ui' -import { useUI } from '@components/ui/context' -import useCart from '@framework/cart/use-cart' -import usePrice from '@framework/product/use-price' -import ShippingWidget from '../ShippingWidget' -import PaymentWidget from '../PaymentWidget' -import SidebarLayout from '@components/common/SidebarLayout' -import s from './CheckoutSidebarView.module.css' - -const CheckoutSidebarView: FC = () => { - const { setSidebarView } = useUI() - const { data } = useCart() - - const { price: subTotal } = usePrice( - data && { - amount: Number(data.subtotalPrice), - currencyCode: data.currency.code, - } - ) - const { price: total } = usePrice( - data && { - amount: Number(data.totalPrice), - currencyCode: data.currency.code, - } - ) - - return ( - setSidebarView('CART_VIEW')} - > -
    - - Checkout - - - setSidebarView('PAYMENT_VIEW')} /> - setSidebarView('SHIPPING_VIEW')} /> - -
      - {data!.lineItems.map((item: any) => ( - - ))} -
    -
    - -
    -
      -
    • - Subtotal - {subTotal} -
    • -
    • - Taxes - Calculated at checkout -
    • -
    • - Shipping - FREE -
    • -
    -
    - Total - {total} -
    -
    - {/* Once data is correcly filled */} - {/* */} - -
    -
    -
    - ) -} - -export default CheckoutSidebarView diff --git a/components/checkout/CheckoutSidebarView/index.ts b/components/checkout/CheckoutSidebarView/index.ts deleted file mode 100644 index 168bc58f4..000000000 --- a/components/checkout/CheckoutSidebarView/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './CheckoutSidebarView' diff --git a/components/checkout/PaymentMethodView/PaymentMethodView.module.css b/components/checkout/PaymentMethodView/PaymentMethodView.module.css deleted file mode 100644 index f3880c72c..000000000 --- a/components/checkout/PaymentMethodView/PaymentMethodView.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.fieldset { - @apply flex flex-col my-3; -} - -.fieldset .label { - @apply text-accent-7 uppercase text-xs font-medium mb-2; -} - -.fieldset .input, -.fieldset .select { - @apply p-2 border border-accent-2 w-full text-sm font-normal; -} - -.fieldset .input:focus, -.fieldset .select:focus { - @apply outline-none shadow-outline-normal; -} diff --git a/components/checkout/PaymentMethodView/PaymentMethodView.tsx b/components/checkout/PaymentMethodView/PaymentMethodView.tsx deleted file mode 100644 index a5f6f4b51..000000000 --- a/components/checkout/PaymentMethodView/PaymentMethodView.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { FC } from 'react' -import cn from 'classnames' -import { Button, Text } from '@components/ui' -import { useUI } from '@components/ui/context' -import s from './PaymentMethodView.module.css' -import SidebarLayout from '@components/common/SidebarLayout' - -const PaymentMethodView: FC = () => { - const { setSidebarView } = useUI() - - return ( - setSidebarView('CHECKOUT_VIEW')}> -
    - Payment Method -
    -
    - - -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    -
    -
    -
    - -
    -
    - ) -} - -export default PaymentMethodView diff --git a/components/checkout/PaymentMethodView/index.ts b/components/checkout/PaymentMethodView/index.ts deleted file mode 100644 index 951b3c318..000000000 --- a/components/checkout/PaymentMethodView/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './PaymentMethodView' diff --git a/components/checkout/PaymentWidget/PaymentWidget.module.css b/components/checkout/PaymentWidget/PaymentWidget.module.css deleted file mode 100644 index 38dcab0c0..000000000 --- a/components/checkout/PaymentWidget/PaymentWidget.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.root { - @apply border border-accent-2 px-6 py-5 mb-4 text-center - flex items-center cursor-pointer hover:border-accent-4; -} diff --git a/components/checkout/PaymentWidget/PaymentWidget.tsx b/components/checkout/PaymentWidget/PaymentWidget.tsx deleted file mode 100644 index e1892934e..000000000 --- a/components/checkout/PaymentWidget/PaymentWidget.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { FC } from 'react' -import s from './PaymentWidget.module.css' -import { ChevronRight, CreditCard } from '@components/icons' - -interface ComponentProps { - onClick?: () => any -} - -const PaymentWidget: FC = ({ onClick }) => { - /* Shipping Address - Only available with checkout set to true - - This means that the provider does offer checkout functionality. */ - return ( -
    -
    - - - Add Payment Method - - {/* VISA #### #### #### 2345 */} -
    -
    - -
    -
    - ) -} - -export default PaymentWidget diff --git a/components/checkout/PaymentWidget/index.ts b/components/checkout/PaymentWidget/index.ts deleted file mode 100644 index 18cadea57..000000000 --- a/components/checkout/PaymentWidget/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './PaymentWidget' diff --git a/components/checkout/ShippingView/ShippingView.module.css b/components/checkout/ShippingView/ShippingView.module.css deleted file mode 100644 index 157d3174e..000000000 --- a/components/checkout/ShippingView/ShippingView.module.css +++ /dev/null @@ -1,21 +0,0 @@ -.fieldset { - @apply flex flex-col my-3; -} - -.fieldset .label { - @apply text-accent-7 uppercase text-xs font-medium mb-2; -} - -.fieldset .input, -.fieldset .select { - @apply p-2 border border-accent-2 w-full text-sm font-normal; -} - -.fieldset .input:focus, -.fieldset .select:focus { - @apply outline-none shadow-outline-normal; -} - -.radio { - @apply bg-black; -} diff --git a/components/checkout/ShippingView/ShippingView.tsx b/components/checkout/ShippingView/ShippingView.tsx deleted file mode 100644 index 1d03a2aac..000000000 --- a/components/checkout/ShippingView/ShippingView.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { FC } from 'react' -import cn from 'classnames' -import s from './ShippingView.module.css' -import Button from '@components/ui/Button' -import { useUI } from '@components/ui/context' -import SidebarLayout from '@components/common/SidebarLayout' - -const PaymentMethodView: FC = () => { - const { setSidebarView } = useUI() - - return ( - setSidebarView('CHECKOUT_VIEW')}> -
    -

    - Shipping -

    -
    -
    - - Same as billing address -
    -
    - - - Use a different shipping address - -
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    -
    -
    -
    - -
    -
    - ) -} - -export default PaymentMethodView diff --git a/components/checkout/ShippingView/index.ts b/components/checkout/ShippingView/index.ts deleted file mode 100644 index 428e7e4fe..000000000 --- a/components/checkout/ShippingView/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ShippingView' diff --git a/components/checkout/ShippingWidget/ShippingWidget.module.css b/components/checkout/ShippingWidget/ShippingWidget.module.css deleted file mode 100644 index 38dcab0c0..000000000 --- a/components/checkout/ShippingWidget/ShippingWidget.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.root { - @apply border border-accent-2 px-6 py-5 mb-4 text-center - flex items-center cursor-pointer hover:border-accent-4; -} diff --git a/components/checkout/ShippingWidget/ShippingWidget.tsx b/components/checkout/ShippingWidget/ShippingWidget.tsx deleted file mode 100644 index b072178b0..000000000 --- a/components/checkout/ShippingWidget/ShippingWidget.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { FC } from 'react' -import s from './ShippingWidget.module.css' -import { ChevronRight, MapPin } from '@components/icons' -import cn from 'classnames' - -interface ComponentProps { - onClick?: () => any -} - -const ShippingWidget: FC = ({ onClick }) => { - /* Shipping Address - Only available with checkout set to true - - This means that the provider does offer checkout functionality. */ - return ( -
    -
    - - - Add Shipping Address - - {/* - 1046 Kearny Street.
    - San Franssisco, California -
    */} -
    -
    - -
    -
    - ) -} - -export default ShippingWidget diff --git a/components/checkout/ShippingWidget/index.ts b/components/checkout/ShippingWidget/index.ts deleted file mode 100644 index 88e6dca4b..000000000 --- a/components/checkout/ShippingWidget/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ShippingWidget' diff --git a/components/common/Avatar/Avatar.tsx b/components/common/Avatar/Avatar.tsx deleted file mode 100644 index 663538450..000000000 --- a/components/common/Avatar/Avatar.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { FC, useRef, useEffect } from 'react' -import { useUserAvatar } from '@lib/hooks/useUserAvatar' - -interface Props { - className?: string - children?: any -} - -const Avatar: FC = ({}) => { - let ref = useRef() as React.MutableRefObject - let { userAvatar } = useUserAvatar() - - return ( -
    - {/* Add an image - We're generating a gradient as placeholder */} -
    - ) -} - -export default Avatar diff --git a/components/common/Avatar/index.ts b/components/common/Avatar/index.ts deleted file mode 100644 index a4600ec77..000000000 --- a/components/common/Avatar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Avatar' diff --git a/components/common/FeatureBar/FeatureBar.module.css b/components/common/FeatureBar/FeatureBar.module.css deleted file mode 100644 index a3cb61cd2..000000000 --- a/components/common/FeatureBar/FeatureBar.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.root { - @apply text-center p-6 bg-primary text-sm flex-row justify-center items-center font-medium fixed bottom-0 w-full z-30 transition-all duration-300 ease-out; - - @screen md { - @apply flex text-left; - } -} diff --git a/components/common/FeatureBar/FeatureBar.tsx b/components/common/FeatureBar/FeatureBar.tsx deleted file mode 100644 index 8923a721e..000000000 --- a/components/common/FeatureBar/FeatureBar.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import cn from 'classnames' -import s from './FeatureBar.module.css' - -interface FeatureBarProps { - className?: string - title: string - description?: string - hide?: boolean - action?: React.ReactNode -} - -const FeatureBar: React.FC = ({ - title, - description, - className, - action, - hide, -}) => { - const rootClassName = cn( - s.root, - { - transform: true, - 'translate-y-0 opacity-100': !hide, - 'translate-y-full opacity-0': hide, - }, - className - ) - return ( -
    - {title} - - {description} - - {action && action} -
    - ) -} - -export default FeatureBar diff --git a/components/common/FeatureBar/index.ts b/components/common/FeatureBar/index.ts deleted file mode 100644 index d78bc9d20..000000000 --- a/components/common/FeatureBar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './FeatureBar' diff --git a/components/common/Footer/Footer.module.css b/components/common/Footer/Footer.module.css deleted file mode 100644 index 2ba492086..000000000 --- a/components/common/Footer/Footer.module.css +++ /dev/null @@ -1,13 +0,0 @@ -.root { - @apply border-t border-accent-2; -} - -.link { - & > svg { - @apply transform duration-75 ease-linear; - } - - &:hover > svg { - @apply scale-110; - } -} diff --git a/components/common/Footer/Footer.tsx b/components/common/Footer/Footer.tsx deleted file mode 100644 index 04b80404e..000000000 --- a/components/common/Footer/Footer.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { FC } from 'react' -import cn from 'classnames' -import Link from 'next/link' -import { useRouter } from 'next/router' -import type { Page } from '@commerce/types/page' -import getSlug from '@lib/get-slug' -import { Github, Vercel } from '@components/icons' -import { Logo, Container } from '@components/ui' -import { I18nWidget } from '@components/common' -import s from './Footer.module.css' - -interface Props { - className?: string - children?: any - pages?: Page[] -} - -const links = [ - { - name: 'Home', - url: '/', - }, -] - -const Footer: FC = ({ className, pages }) => { - const { sitePages } = usePages(pages) - const rootClassName = cn(s.root, className) - - return ( - - ) -} - -function usePages(pages?: Page[]) { - const { locale } = useRouter() - const sitePages: Page[] = [] - - if (pages) { - pages.forEach((page) => { - const slug = page.url && getSlug(page.url) - if (!slug) return - if (locale && !slug.startsWith(`${locale}/`)) return - sitePages.push(page) - }) - } - - return { - sitePages: sitePages.sort(bySortOrder), - } -} - -// Sort pages by the sort order assigned in the BC dashboard -function bySortOrder(a: Page, b: Page) { - return (a.sort_order ?? 0) - (b.sort_order ?? 0) -} - -export default Footer diff --git a/components/common/Footer/index.ts b/components/common/Footer/index.ts deleted file mode 100644 index 5d06e9b71..000000000 --- a/components/common/Footer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Footer' diff --git a/components/common/Head/Head.tsx b/components/common/Head/Head.tsx deleted file mode 100644 index b2c0c997b..000000000 --- a/components/common/Head/Head.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { FC } from 'react' -import NextHead from 'next/head' -import { DefaultSeo } from 'next-seo' -import config from '@config/seo.json' - -const Head: FC = () => { - return ( - <> - - - - - - - ) -} - -export default Head diff --git a/components/common/Head/index.ts b/components/common/Head/index.ts deleted file mode 100644 index b317a124b..000000000 --- a/components/common/Head/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Head' diff --git a/components/common/HomeAllProductsGrid/HomeAllProductsGrid.module.css b/components/common/HomeAllProductsGrid/HomeAllProductsGrid.module.css deleted file mode 100644 index 91d1fdc60..000000000 --- a/components/common/HomeAllProductsGrid/HomeAllProductsGrid.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.root { - @apply flex flex-col w-full; - - @screen md { - @apply flex-row; - } -} diff --git a/components/common/HomeAllProductsGrid/HomeAllProductsGrid.tsx b/components/common/HomeAllProductsGrid/HomeAllProductsGrid.tsx deleted file mode 100644 index d0fac461f..000000000 --- a/components/common/HomeAllProductsGrid/HomeAllProductsGrid.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { FC } from 'react' -import Link from 'next/link' -import type { Product } from '@commerce/types/product' -import { Grid } from '@components/ui' -import { ProductCard } from '@components/product' -import s from './HomeAllProductsGrid.module.css' -import { getCategoryPath, getDesignerPath } from '@lib/search' -import { Category } from '@commerce/types/site' - -interface Props { - categories?: Category[] - brands?: any - products?: Product[] -} - -const HomeAllProductsGrid: FC = ({ - categories = [], - brands, - products = [], -}) => { - return ( -
    -
    - {categories.map((category) => ( -
    -
    {category.name}
    -
    - {products.slice(0, 4).map((product) => ( - - ))} -
    -
    - ))} -
    -
    - ) -} - -export default HomeAllProductsGrid diff --git a/components/common/HomeAllProductsGrid/index.ts b/components/common/HomeAllProductsGrid/index.ts deleted file mode 100644 index 31d313d16..000000000 --- a/components/common/HomeAllProductsGrid/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './HomeAllProductsGrid' diff --git a/components/common/I18nWidget/I18nWidget.module.css b/components/common/I18nWidget/I18nWidget.module.css deleted file mode 100644 index 269aa5f61..000000000 --- a/components/common/I18nWidget/I18nWidget.module.css +++ /dev/null @@ -1,46 +0,0 @@ -.root { - @apply relative; -} - -.button { - @apply h-10 px-2 rounded-md border border-accent-2 flex items-center justify-center transition-colors ease-linear; -} - -.button:hover { - @apply border-accent-3 shadow-sm; -} - -.button:focus { - @apply outline-none; -} - -.dropdownMenu { - @apply fixed right-0 top-12 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full; - - @screen lg { - @apply absolute border border-accent-1 shadow-lg w-56 h-auto; - } -} - -.closeButton { - @screen md { - @apply hidden; - } -} - -.item { - @apply flex cursor-pointer px-6 py-3 transition ease-in-out duration-150 text-primary leading-6 font-medium items-center; - text-transform: capitalize; -} - -.item:hover { - @apply bg-accent-1; -} - -.icon { - transition: transform 0.2s ease; -} - -.icon.active { - transform: rotate(180deg); -} diff --git a/components/common/I18nWidget/I18nWidget.tsx b/components/common/I18nWidget/I18nWidget.tsx deleted file mode 100644 index 58135f12a..000000000 --- a/components/common/I18nWidget/I18nWidget.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import cn from 'classnames' -import Link from 'next/link' -import { FC, useState } from 'react' -import { useRouter } from 'next/router' -import s from './I18nWidget.module.css' -import { Cross, ChevronUp } from '@components/icons' -import ClickOutside from '@lib/click-outside' -interface LOCALE_DATA { - name: string - img: { - filename: string - alt: string - } -} - -const LOCALES_MAP: Record = { - es: { - name: 'Español', - img: { - filename: 'flag-es-co.svg', - alt: 'Bandera Colombiana', - }, - }, - 'en-US': { - name: 'English', - img: { - filename: 'flag-en-us.svg', - alt: 'US Flag', - }, - }, -} - -const I18nWidget: FC = () => { - const [display, setDisplay] = useState(false) - const { - locale, - locales, - defaultLocale = 'en-US', - asPath: currentPath, - } = useRouter() - - const options = locales?.filter((val) => val !== locale) - const currentLocale = locale || defaultLocale - - return ( - setDisplay(false)}> - - - ) -} - -export default I18nWidget diff --git a/components/common/I18nWidget/index.ts b/components/common/I18nWidget/index.ts deleted file mode 100644 index 46525c3d4..000000000 --- a/components/common/I18nWidget/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './I18nWidget' diff --git a/components/common/Layout/Layout.module.css b/components/common/Layout/Layout.module.css deleted file mode 100644 index bb90675a6..000000000 --- a/components/common/Layout/Layout.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.root { - @apply h-full bg-primary mx-auto transition-colors duration-150; - max-width: 2460px; -} diff --git a/components/common/Layout/Layout.tsx b/components/common/Layout/Layout.tsx deleted file mode 100644 index ff6d72aaf..000000000 --- a/components/common/Layout/Layout.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import cn from 'classnames' -import React, { FC } from 'react' -import dynamic from 'next/dynamic' -import { useRouter } from 'next/router' -import { CommerceProvider } from '@framework' -import { useUI } from '@components/ui/context' -import type { Page } from '@commerce/types/page' -import { Navbar, Footer } from '@components/common' -import type { Category } from '@commerce/types/site' -import ShippingView from '@components/checkout/ShippingView' -import CartSidebarView from '@components/cart/CartSidebarView' -import { useAcceptCookies } from '@lib/hooks/useAcceptCookies' -import { Sidebar, Button, Modal, LoadingDots } from '@components/ui' -import PaymentMethodView from '@components/checkout/PaymentMethodView' -import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView' - -import LoginView from '@components/auth/LoginView' -import s from './Layout.module.css' - -const Loading = () => ( -
    - -
    -) - -const dynamicProps = { - loading: () => , -} - -const SignUpView = dynamic( - () => import('@components/auth/SignUpView'), - dynamicProps -) - -const ForgotPassword = dynamic( - () => import('@components/auth/ForgotPassword'), - dynamicProps -) - -const FeatureBar = dynamic( - () => import('@components/common/FeatureBar'), - dynamicProps -) - -interface Props { - pageProps: { - pages?: Page[] - categories: Category[] - } -} - -const ModalView: FC<{ modalView: string; closeModal(): any }> = ({ - modalView, - closeModal, -}) => { - return ( - - {modalView === 'LOGIN_VIEW' && } - {modalView === 'SIGNUP_VIEW' && } - {modalView === 'FORGOT_VIEW' && } - - ) -} - -const ModalUI: FC = () => { - const { displayModal, closeModal, modalView } = useUI() - return displayModal ? ( - - ) : null -} - -const SidebarView: FC<{ sidebarView: string; closeSidebar(): any }> = ({ - sidebarView, - closeSidebar, -}) => { - return ( - - {sidebarView === 'CART_VIEW' && } - {sidebarView === 'CHECKOUT_VIEW' && } - {sidebarView === 'PAYMENT_VIEW' && } - {sidebarView === 'SHIPPING_VIEW' && } - - ) -} - -const SidebarUI: FC = () => { - const { displaySidebar, closeSidebar, sidebarView } = useUI() - return displaySidebar ? ( - - ) : null -} - -const Layout: FC = ({ - children, - pageProps: { categories = [], ...pageProps }, -}) => { - const { acceptedCookies, onAcceptCookies } = useAcceptCookies() - const { locale = 'en-US' } = useRouter() - const navBarlinks = categories.slice(0, 2).map((c) => ({ - label: c.name, - href: `/search/${c.slug}`, - })) - - return ( - -
    - -
    {children}
    -
    - - - onAcceptCookies()}> - Accept cookies - - } - /> -
    -
    - ) -} - -export default Layout diff --git a/components/common/Layout/index.ts b/components/common/Layout/index.ts deleted file mode 100644 index 0e2737eee..000000000 --- a/components/common/Layout/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Layout' diff --git a/components/common/Navbar/Navbar.module.css b/components/common/Navbar/Navbar.module.css deleted file mode 100644 index faa86d156..000000000 --- a/components/common/Navbar/Navbar.module.css +++ /dev/null @@ -1,35 +0,0 @@ -.root { - @apply sticky top-0 bg-primary z-40 transition-all duration-150; - min-height: 74px; -} - -.nav { - @apply relative flex flex-row justify-between py-4 md:py-4; -} - -.navMenu { - @apply hidden ml-6 space-x-4 lg:block; -} - -.link { - @apply inline-flex items-center leading-6 - transition ease-in-out duration-75 cursor-pointer - text-accent-5; -} - -.link:hover { - @apply text-accent-9; -} - -.link:focus { - @apply outline-none text-accent-8; -} - -.logo { - @apply cursor-pointer rounded-full border transform duration-100 ease-in-out; - - &:hover { - @apply shadow-md; - transform: scale(1.05); - } -} diff --git a/components/common/Navbar/Navbar.tsx b/components/common/Navbar/Navbar.tsx deleted file mode 100644 index 2ce5f33b8..000000000 --- a/components/common/Navbar/Navbar.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { FC } from 'react' -import Link from 'next/link' -import s from './Navbar.module.css' -import NavbarRoot from './NavbarRoot' -import { Logo, Container } from '@components/ui' -import { Searchbar, UserNav } from '@components/common' - -interface Link { - href: string - label: string -} -interface NavbarProps { - links?: Link[] -} - -const Navbar: FC = ({ links }) => ( - - -
    -
    - - - - - - -
    - {process.env.COMMERCE_SEARCH_ENABLED && ( -
    - -
    - )} -
    - -
    -
    -
    - -
    -
    -
    -) - -export default Navbar diff --git a/components/common/Navbar/NavbarRoot.tsx b/components/common/Navbar/NavbarRoot.tsx deleted file mode 100644 index 2eb8c5429..000000000 --- a/components/common/Navbar/NavbarRoot.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { FC, useState, useEffect } from 'react' -import throttle from 'lodash.throttle' -import cn from 'classnames' -import s from './Navbar.module.css' - -const NavbarRoot: FC = ({ children }) => { - const [hasScrolled, setHasScrolled] = useState(false) - - useEffect(() => { - const handleScroll = throttle(() => { - const offset = 0 - const { scrollTop } = document.documentElement - const scrolled = scrollTop > offset - - if (hasScrolled !== scrolled) { - setHasScrolled(scrolled) - } - }, 200) - - document.addEventListener('scroll', handleScroll) - return () => { - document.removeEventListener('scroll', handleScroll) - } - }, [hasScrolled]) - - return ( -
    - {children} -
    - ) -} - -export default NavbarRoot diff --git a/components/common/Navbar/index.ts b/components/common/Navbar/index.ts deleted file mode 100644 index e6400ae40..000000000 --- a/components/common/Navbar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Navbar' diff --git a/components/common/Searchbar/Searchbar.module.css b/components/common/Searchbar/Searchbar.module.css deleted file mode 100644 index 7f20ed973..000000000 --- a/components/common/Searchbar/Searchbar.module.css +++ /dev/null @@ -1,29 +0,0 @@ -.root { - @apply relative text-sm bg-accent-0 text-base w-full transition-colors duration-150 border border-accent-2; -} - -.input { - @apply bg-transparent px-3 py-2 appearance-none w-full transition duration-150 ease-in-out pr-10; -} - -.input::placeholder { - @apply text-accent-3; -} - -.input:focus { - @apply outline-none shadow-outline-normal; -} - -.iconContainer { - @apply absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none; -} - -.icon { - @apply h-5 w-5; -} - -@screen sm { - .input { - min-width: 300px; - } -} diff --git a/components/common/Searchbar/Searchbar.tsx b/components/common/Searchbar/Searchbar.tsx deleted file mode 100644 index 0fc276d02..000000000 --- a/components/common/Searchbar/Searchbar.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { FC, InputHTMLAttributes, useEffect, useMemo } from 'react' -import cn from 'classnames' -import s from './Searchbar.module.css' -import { useRouter } from 'next/router' - -interface Props { - className?: string - id?: string -} - -const Searchbar: FC = ({ className, id = 'search' }) => { - const router = useRouter() - - useEffect(() => { - router.prefetch('/search') - }, []) - - const handleKeyUp = (e: React.KeyboardEvent) => { - e.preventDefault() - - if (e.key === 'Enter') { - const q = e.currentTarget.value - - router.push( - { - pathname: `/search`, - query: q ? { q } : {}, - }, - undefined, - { shallow: true } - ) - } - } - - return useMemo( - () => ( -
    - - -
    - - - -
    -
    - ), - [] - ) -} - -export default Searchbar diff --git a/components/common/Searchbar/index.ts b/components/common/Searchbar/index.ts deleted file mode 100644 index e6c0e36c8..000000000 --- a/components/common/Searchbar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Searchbar' diff --git a/components/common/SidebarLayout/SidebarLayout.module.css b/components/common/SidebarLayout/SidebarLayout.module.css deleted file mode 100644 index a8940dc52..000000000 --- a/components/common/SidebarLayout/SidebarLayout.module.css +++ /dev/null @@ -1,20 +0,0 @@ -.root { - @apply relative h-full flex flex-col; -} - -.header { - @apply sticky top-0 pl-4 py-4 pr-6 - flex items-center justify-between - bg-accent-0 box-border w-full z-10; - min-height: 66px; -} - -.container { - @apply flex flex-col flex-1 box-border; -} - -@screen lg { - .header { - min-height: 74px; - } -} diff --git a/components/common/SidebarLayout/SidebarLayout.tsx b/components/common/SidebarLayout/SidebarLayout.tsx deleted file mode 100644 index a4e60a758..000000000 --- a/components/common/SidebarLayout/SidebarLayout.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, { FC } from 'react' -import { Cross, ChevronLeft } from '@components/icons' -import { UserNav } from '@components/common' -import cn from 'classnames' -import s from './SidebarLayout.module.css' - -type ComponentProps = { className?: string } & ( - | { handleClose: () => any; handleBack?: never } - | { handleBack: () => any; handleClose?: never } -) - -const SidebarLayout: FC = ({ - children, - className, - handleClose, - handleBack, -}) => { - return ( -
    -
    - {handleClose && ( - - )} - {handleBack && ( - - )} - - - -
    -
    {children}
    -
    - ) -} - -export default SidebarLayout diff --git a/components/common/SidebarLayout/index.ts b/components/common/SidebarLayout/index.ts deleted file mode 100644 index 45ded0cf0..000000000 --- a/components/common/SidebarLayout/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SidebarLayout' diff --git a/components/common/UserNav/DropdownMenu.module.css b/components/common/UserNav/DropdownMenu.module.css deleted file mode 100644 index d6b13ecb5..000000000 --- a/components/common/UserNav/DropdownMenu.module.css +++ /dev/null @@ -1,24 +0,0 @@ -.dropdownMenu { - @apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full; - - @screen lg { - @apply absolute top-10 border border-accent-1 shadow-lg w-56 h-auto; - } -} - -.link { - @apply text-primary flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 leading-6 font-medium items-center; - text-transform: capitalize; -} - -.link:hover { - @apply bg-accent-1; -} - -.link.active { - @apply font-bold bg-accent-2; -} - -.off { - @apply hidden; -} diff --git a/components/common/UserNav/DropdownMenu.tsx b/components/common/UserNav/DropdownMenu.tsx deleted file mode 100644 index f79fd5821..000000000 --- a/components/common/UserNav/DropdownMenu.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import cn from 'classnames' -import Link from 'next/link' -import { FC, useRef, useState, useEffect } from 'react' -import { useTheme } from 'next-themes' -import { useRouter } from 'next/router' -import s from './DropdownMenu.module.css' -import { Avatar } from '@components/common' -import { Moon, Sun } from '@components/icons' -import { useUI } from '@components/ui/context' -import ClickOutside from '@lib/click-outside' -import useLogout from '@framework/auth/use-logout' - -import { - disableBodyScroll, - enableBodyScroll, - clearAllBodyScrollLocks, -} from 'body-scroll-lock' - -interface DropdownMenuProps { - open?: boolean -} - -const LINKS = [ - { - name: 'My Orders', - href: '/orders', - }, - { - name: 'My Profile', - href: '/profile', - }, - { - name: 'My Cart', - href: '/cart', - }, -] - -const DropdownMenu: FC = ({ open = false }) => { - const logout = useLogout() - const { pathname } = useRouter() - const { theme, setTheme } = useTheme() - const [display, setDisplay] = useState(false) - const { closeSidebarIfPresent } = useUI() - const ref = useRef() as React.MutableRefObject - - useEffect(() => { - if (ref.current) { - if (display) { - disableBodyScroll(ref.current) - } else { - enableBodyScroll(ref.current) - } - } - return () => { - clearAllBodyScrollLocks() - } - }, [display]) - - return ( - setDisplay(false)}> - - - ) -} - -export default DropdownMenu diff --git a/components/common/UserNav/UserNav.module.css b/components/common/UserNav/UserNav.module.css deleted file mode 100644 index 92f62c10d..000000000 --- a/components/common/UserNav/UserNav.module.css +++ /dev/null @@ -1,40 +0,0 @@ -.root { - @apply relative; -} - -.list { - @apply flex flex-row items-center justify-items-end h-full; -} - -.item { - @apply mr-6 cursor-pointer relative transition ease-in-out duration-100 flex items-center outline-none text-primary; - - &:hover { - @apply text-accent-6 transition scale-110 duration-100; - } - - &:last-child { - @apply mr-0; - } - - &:focus, - &:active { - @apply outline-none; - } -} - -.bagCount { - @apply border border-accent-1 bg-secondary text-secondary absolute rounded-full right-3 top-3 flex items-center justify-center font-bold text-xs; - padding-left: 2.5px; - padding-right: 2.5px; - min-width: 1.25rem; - min-height: 1.25rem; -} - -.avatarButton { - @apply inline-flex justify-center rounded-full; -} - -.avatarButton:focus { - @apply outline-none; -} diff --git a/components/common/UserNav/UserNav.tsx b/components/common/UserNav/UserNav.tsx deleted file mode 100644 index 5d7d28df3..000000000 --- a/components/common/UserNav/UserNav.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { FC } from 'react' -import Link from 'next/link' -import cn from 'classnames' -import type { LineItem } from '@commerce/types/cart' -import useCart from '@framework/cart/use-cart' -import useCustomer from '@framework/customer/use-customer' -import { Avatar } from '@components/common' -import { Heart, Bag } from '@components/icons' -import { useUI } from '@components/ui/context' -import DropdownMenu from './DropdownMenu' -import s from './UserNav.module.css' - -interface Props { - className?: string -} - -const countItem = (count: number, item: LineItem) => count + item.quantity - -const UserNav: FC = ({ className }) => { - const { data } = useCart() - const { data: customer } = useCustomer() - const { toggleSidebar, closeSidebarIfPresent, openModal } = useUI() - const itemsCount = data?.lineItems.reduce(countItem, 0) ?? 0 - - return ( - - ) -} - -export default UserNav diff --git a/components/common/UserNav/index.ts b/components/common/UserNav/index.ts deleted file mode 100644 index 9e35ac018..000000000 --- a/components/common/UserNav/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './UserNav' diff --git a/components/common/index.ts b/components/common/index.ts deleted file mode 100644 index 98dd3394b..000000000 --- a/components/common/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { default as Avatar } from './Avatar' -export { default as FeatureBar } from './FeatureBar' -export { default as Footer } from './Footer' -export { default as Layout } from './Layout' -export { default as Navbar } from './Navbar' -export { default as Searchbar } from './Searchbar' -export { default as UserNav } from './UserNav' -export { default as Head } from './Head' -export { default as I18nWidget } from './I18nWidget' diff --git a/components/icons/ArrowLeft.tsx b/components/icons/ArrowLeft.tsx deleted file mode 100644 index 8cc1e1294..000000000 --- a/components/icons/ArrowLeft.tsx +++ /dev/null @@ -1,27 +0,0 @@ -const ArrowLeft = ({ ...props }) => { - return ( - - - - - ) -} - -export default ArrowLeft diff --git a/components/icons/ArrowRight.tsx b/components/icons/ArrowRight.tsx deleted file mode 100644 index e644951d9..000000000 --- a/components/icons/ArrowRight.tsx +++ /dev/null @@ -1,28 +0,0 @@ -const ArrowRight = ({ ...props }) => { - return ( - - - - - ) -} - -export default ArrowRight diff --git a/components/icons/Bag.tsx b/components/icons/Bag.tsx deleted file mode 100644 index de2cde0d1..000000000 --- a/components/icons/Bag.tsx +++ /dev/null @@ -1,33 +0,0 @@ -const Bag = ({ ...props }) => { - return ( - - - - - - ) -} - -export default Bag diff --git a/components/icons/Check.tsx b/components/icons/Check.tsx deleted file mode 100644 index 89c91a1e3..000000000 --- a/components/icons/Check.tsx +++ /dev/null @@ -1,21 +0,0 @@ -const Check = ({ ...props }) => { - return ( - - - - ) -} - -export default Check diff --git a/components/icons/ChevronDown.tsx b/components/icons/ChevronDown.tsx deleted file mode 100644 index 542e8056d..000000000 --- a/components/icons/ChevronDown.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const ChevronDown = ({ ...props }) => { - return ( - - - - ) -} - -export default ChevronDown diff --git a/components/icons/ChevronLeft.tsx b/components/icons/ChevronLeft.tsx deleted file mode 100644 index 4efb6a522..000000000 --- a/components/icons/ChevronLeft.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const ChevronLeft = ({ ...props }) => { - return ( - - - - ) -} - -export default ChevronLeft diff --git a/components/icons/ChevronRight.tsx b/components/icons/ChevronRight.tsx deleted file mode 100644 index d72b77a32..000000000 --- a/components/icons/ChevronRight.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const ChevronUp = ({ ...props }) => { - return ( - - - - ) -} - -export default ChevronUp diff --git a/components/icons/ChevronUp.tsx b/components/icons/ChevronUp.tsx deleted file mode 100644 index 69b9959b8..000000000 --- a/components/icons/ChevronUp.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const ChevronUp = ({ ...props }) => { - return ( - - - - ) -} - -export default ChevronUp diff --git a/components/icons/CreditCard.tsx b/components/icons/CreditCard.tsx deleted file mode 100644 index 958c31193..000000000 --- a/components/icons/CreditCard.tsx +++ /dev/null @@ -1,21 +0,0 @@ -const CreditCard = ({ ...props }) => { - return ( - - - - - ) -} - -export default CreditCard diff --git a/components/icons/Cross.tsx b/components/icons/Cross.tsx deleted file mode 100644 index 12e115ac9..000000000 --- a/components/icons/Cross.tsx +++ /dev/null @@ -1,21 +0,0 @@ -const Cross = ({ ...props }) => { - return ( - - - - - ) -} - -export default Cross diff --git a/components/icons/DoubleChevron.tsx b/components/icons/DoubleChevron.tsx deleted file mode 100644 index 198c30464..000000000 --- a/components/icons/DoubleChevron.tsx +++ /dev/null @@ -1,22 +0,0 @@ -const DoubleChevron = ({ ...props }) => { - return ( - - - - ) -} - -export default DoubleChevron diff --git a/components/icons/Github.tsx b/components/icons/Github.tsx deleted file mode 100644 index 1195a3c3a..000000000 --- a/components/icons/Github.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const Github = ({ ...props }) => { - return ( - - - - ) -} - -export default Github diff --git a/components/icons/Heart.tsx b/components/icons/Heart.tsx deleted file mode 100644 index afa2f6aaa..000000000 --- a/components/icons/Heart.tsx +++ /dev/null @@ -1,22 +0,0 @@ -const Heart = ({ ...props }) => { - return ( - - - - ) -} - -export default Heart diff --git a/components/icons/Info.tsx b/components/icons/Info.tsx deleted file mode 100644 index 67c79cf27..000000000 --- a/components/icons/Info.tsx +++ /dev/null @@ -1,22 +0,0 @@ -const Info = ({ ...props }) => { - return ( - - - - - - ) -} - -export default Info diff --git a/components/icons/MapPin.tsx b/components/icons/MapPin.tsx deleted file mode 100644 index 6323b9c1c..000000000 --- a/components/icons/MapPin.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const MapPin = ({ ...props }) => { - return ( - - - - - ) -} - -export default MapPin diff --git a/components/icons/Minus.tsx b/components/icons/Minus.tsx deleted file mode 100644 index 1e9411dda..000000000 --- a/components/icons/Minus.tsx +++ /dev/null @@ -1,15 +0,0 @@ -const Minus = ({ ...props }) => { - return ( - - - - ) -} - -export default Minus diff --git a/components/icons/Moon.tsx b/components/icons/Moon.tsx deleted file mode 100644 index e02f2a30d..000000000 --- a/components/icons/Moon.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const Moon = ({ ...props }) => { - return ( - - - - ) -} - -export default Moon diff --git a/components/icons/Plus.tsx b/components/icons/Plus.tsx deleted file mode 100644 index ad030b92e..000000000 --- a/components/icons/Plus.tsx +++ /dev/null @@ -1,22 +0,0 @@ -const Plus = ({ ...props }) => { - return ( - - - - - ) -} - -export default Plus diff --git a/components/icons/Star.tsx b/components/icons/Star.tsx deleted file mode 100644 index d98f55e1d..000000000 --- a/components/icons/Star.tsx +++ /dev/null @@ -1,16 +0,0 @@ -const Star = ({ ...props }) => { - return ( - - - - ) -} - -export default Star diff --git a/components/icons/Sun.tsx b/components/icons/Sun.tsx deleted file mode 100644 index d3684bcb9..000000000 --- a/components/icons/Sun.tsx +++ /dev/null @@ -1,28 +0,0 @@ -const Sun = ({ ...props }) => { - return ( - - - - - - - - - - - - ) -} - -export default Sun diff --git a/components/icons/Trash.tsx b/components/icons/Trash.tsx deleted file mode 100644 index b005ea892..000000000 --- a/components/icons/Trash.tsx +++ /dev/null @@ -1,43 +0,0 @@ -const Trash = ({ ...props }) => { - return ( - - - - - - - ) -} - -export default Trash diff --git a/components/icons/Vercel.tsx b/components/icons/Vercel.tsx deleted file mode 100644 index 96e619fdf..000000000 --- a/components/icons/Vercel.tsx +++ /dev/null @@ -1,40 +0,0 @@ -const Vercel = ({ ...props }) => { - return ( - - - - - - - - - - ) -} - -export default Vercel diff --git a/components/icons/index.ts b/components/icons/index.ts deleted file mode 100644 index 97eef6d58..000000000 --- a/components/icons/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -export { default as Bag } from './Bag' -export { default as Heart } from './Heart' -export { default as Trash } from './Trash' -export { default as Cross } from './Cross' -export { default as Plus } from './Plus' -export { default as Minus } from './Minus' -export { default as Check } from './Check' -export { default as Sun } from './Sun' -export { default as Moon } from './Moon' -export { default as Github } from './Github' -export { default as Info } from './Info' -export { default as Vercel } from './Vercel' -export { default as MapPin } from './MapPin' -export { default as Star } from './Star' -export { default as ArrowLeft } from './ArrowLeft' -export { default as ArrowRight } from './ArrowRight' -export { default as CreditCard } from './CreditCard' -export { default as ChevronUp } from './ChevronUp' -export { default as ChevronLeft } from './ChevronLeft' -export { default as ChevronDown } from './ChevronDown' -export { default as ChevronRight } from './ChevronRight' -export { default as DoubleChevron } from './DoubleChevron' diff --git a/components/product/ProductCard/ProductCard.module.css b/components/product/ProductCard/ProductCard.module.css deleted file mode 100644 index d5d441fea..000000000 --- a/components/product/ProductCard/ProductCard.module.css +++ /dev/null @@ -1,114 +0,0 @@ -.root { - @apply relative max-h-full w-full box-border overflow-hidden - bg-no-repeat bg-center bg-cover transition-transform - ease-linear cursor-pointer inline-block bg-accent-1; - height: 100% !important; -} - -.root:hover { - & .productImage { - transform: scale(1.2625); - } - - & .header .name span, - & .header .price, - & .wishlistButton { - @apply bg-secondary text-secondary; - } - - &:nth-child(6n + 1) .header .name span, - &:nth-child(6n + 1) .header .price, - &:nth-child(6n + 1) .wishlistButton { - @apply bg-violet text-white; - } - - &:nth-child(6n + 5) .header .name span, - &:nth-child(6n + 5) .header .price, - &:nth-child(6n + 5) .wishlistButton { - @apply bg-blue text-white; - } - - &:nth-child(6n + 3) .header .name span, - &:nth-child(6n + 3) .header .price, - &:nth-child(6n + 3) .wishlistButton { - @apply bg-pink text-white; - } - - &:nth-child(6n + 6) .header .name span, - &:nth-child(6n + 6) .header .price, - &:nth-child(6n + 6) .wishlistButton { - @apply bg-cyan text-white; - } -} - -.header { - @apply transition-colors ease-in-out duration-500 - absolute top-0 left-0 z-20 pr-16; -} - -.header .name { - @apply pt-0 max-w-full w-full leading-extra-loose - transition-colors ease-in-out duration-500; - font-size: 2rem; - letter-spacing: 0.4px; -} - -.header .name span { - @apply py-4 px-6 bg-primary text-primary font-bold - transition-colors ease-in-out duration-500; - font-size: inherit; - letter-spacing: inherit; - box-decoration-break: clone; - -webkit-box-decoration-break: clone; -} - -.header .price { - @apply pt-2 px-6 pb-4 text-sm bg-primary text-accent-9 - font-semibold inline-block tracking-wide - transition-colors ease-in-out duration-500; -} - -.imageContainer { - @apply flex items-center justify-center overflow-hidden; -} - -.imageContainer > div { - min-width: 100%; -} - -.imageContainer .productImage { - @apply transform transition-transform duration-500 - object-cover scale-120; -} - -.root .wishlistButton { - @apply top-0 right-0 z-30 absolute; -} - -/* Variant Simple */ -.simple .header .name { - @apply pt-2 text-lg leading-10 -mt-1; -} - -.simple .header .price { - @apply text-sm; -} - -/* Variant Slim */ -.slim { - @apply bg-transparent relative overflow-hidden - box-border; -} - -.slim .header { - @apply absolute inset-0 flex items-center justify-end mr-8 z-20; -} - -.slim span { - @apply bg-accent-9 text-accent-0 inline-block p-3 - font-bold text-xl break-words; -} - -.root:global(.secondary) .header span { - @apply bg-accent-0 text-accent-9; -} diff --git a/components/product/ProductCard/ProductCard.tsx b/components/product/ProductCard/ProductCard.tsx deleted file mode 100644 index 39c19db00..000000000 --- a/components/product/ProductCard/ProductCard.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { FC } from 'react' -import cn from 'classnames' -import Link from 'next/link' -import type { Product } from '@commerce/types/product' -import s from './ProductCard.module.css' -import Image, { ImageProps } from 'next/image' -import WishlistButton from '@components/wishlist/WishlistButton' -import usePrice from '@framework/product/use-price' -import ProductTag from '../ProductTag' -interface Props { - className?: string - product: Product - noNameTag?: boolean - imgProps?: Omit - variant?: 'default' | 'slim' | 'simple' -} - -const placeholderImg = '/product-img-placeholder.svg' - -const ProductCard: FC = ({ - product, - imgProps, - className, - noNameTag = false, - variant = 'default', - ...props -}) => { - const { price } = usePrice({ - amount: product.price.value, - baseAmount: product.price.retailPrice, - currencyCode: product.price.currencyCode!, - }) - - const rootClassName = cn( - s.root, - { [s.slim]: variant === 'slim', [s.simple]: variant === 'simple' }, - className - ) - - return ( - - - {variant === 'slim' && ( - <> -
    - {product.name} -
    - {product?.images && ( - {product.name - )} - - )} - - {variant === 'simple' && ( - <> - {process.env.COMMERCE_WISHLIST_ENABLED && ( - - )} - {!noNameTag && ( -
    -

    - {product.name} -

    -
    - {`${price} ${product.price?.currencyCode}`} -
    -
    - )} -
    - {product?.images && ( - {product.name - )} -
    - - )} - - {variant === 'default' && ( - <> - {process.env.COMMERCE_WISHLIST_ENABLED && ( - - )} - -
    - {product?.images && ( - {product.name - )} -
    - - )} -
    - - ) -} - -export default ProductCard diff --git a/components/product/ProductCard/index.ts b/components/product/ProductCard/index.ts deleted file mode 100644 index 4559faa14..000000000 --- a/components/product/ProductCard/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProductCard' diff --git a/components/product/ProductOptions/ProductOptions.tsx b/components/product/ProductOptions/ProductOptions.tsx deleted file mode 100644 index 9261406bc..000000000 --- a/components/product/ProductOptions/ProductOptions.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Swatch } from '@components/product' -import type { ProductOption } from '@commerce/types/product' -import { SelectedOptions } from '../helpers' -import React from 'react' -interface ProductOptionsProps { - options: ProductOption[] - selectedOptions: SelectedOptions - setSelectedOptions: React.Dispatch> -} - -const ProductOptions: React.FC = React.memo( - ({ options, selectedOptions, setSelectedOptions }) => { - return ( -
    - {options.map((opt) => ( -
    -

    - {opt.displayName} -

    -
    - {opt.values.map((v, i: number) => { - const active = selectedOptions[opt.displayName.toLowerCase()] - return ( - { - setSelectedOptions((selectedOptions) => { - return { - ...selectedOptions, - [opt.displayName.toLowerCase()]: - v.label.toLowerCase(), - } - }) - }} - /> - ) - })} -
    -
    - ))} -
    - ) - } -) - -export default ProductOptions diff --git a/components/product/ProductOptions/index.ts b/components/product/ProductOptions/index.ts deleted file mode 100644 index 252415ab7..000000000 --- a/components/product/ProductOptions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProductOptions' diff --git a/components/product/ProductSidebar/ProductSidebar.module.css b/components/product/ProductSidebar/ProductSidebar.module.css deleted file mode 100644 index b6ecc2b77..000000000 --- a/components/product/ProductSidebar/ProductSidebar.module.css +++ /dev/null @@ -1,84 +0,0 @@ -.root { - @apply relative grid items-start gap-1 grid-cols-1 overflow-x-hidden; - min-height: auto; -} - -.main { - @apply relative px-0 pb-0 box-border flex flex-col col-span-1; - min-height: 500px; -} - -.header { - @apply transition-colors ease-in-out duration-500 - absolute top-0 left-0 z-20 pr-16; -} - -.header .name { - @apply pt-0 max-w-full w-full leading-extra-loose; - font-size: 2rem; - letter-spacing: 0.4px; -} - -.header .name span { - @apply py-4 px-6 bg-primary text-primary font-bold; - font-size: inherit; - letter-spacing: inherit; - box-decoration-break: clone; - -webkit-box-decoration-break: clone; -} - -.header .price { - @apply pt-2 px-6 pb-4 text-sm bg-primary text-accent-9 - font-semibold inline-block tracking-wide; -} - -.sidebar { - @apply flex flex-col col-span-1 mx-auto max-w-8xl px-6 py-6 w-full h-full; -} - -.sliderContainer { - @apply flex items-center justify-center overflow-x-hidden bg-violet; -} - -.imageContainer { - @apply text-center; -} - -.imageContainer > div, -.imageContainer > div > div { - @apply h-full; -} - -.sliderContainer .img { - @apply w-full h-auto max-h-full object-cover; -} - -.button { - width: 100%; -} - -.wishlistButton { - @apply absolute z-30 top-0 right-0; -} - -.relatedProductsGrid { - @apply grid grid-cols-2 py-2 gap-2 md:grid-cols-4 md:gap-7; -} - -@screen lg { - .root { - @apply grid-cols-12; - } - - .main { - @apply mx-0 col-span-8; - } - - .sidebar { - @apply col-span-4 py-6; - } - - .imageContainer { - max-height: 600px; - } -} diff --git a/components/product/ProductSidebar/ProductSidebar.tsx b/components/product/ProductSidebar/ProductSidebar.tsx deleted file mode 100644 index fe8a71aa5..000000000 --- a/components/product/ProductSidebar/ProductSidebar.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import s from './ProductSidebar.module.css' -import { useAddItem } from '@framework/cart' -import { FC, useEffect, useState } from 'react' -import { ProductOptions } from '@components/product' -import type { Product } from '@commerce/types/product' -import { Button, Text, Rating, Collapse, useUI } from '@components/ui' -import { - getProductVariant, - selectDefaultOptionFromProduct, - SelectedOptions, -} from '../helpers' - -interface ProductSidebarProps { - product: Product - className?: string -} - -const ProductSidebar: FC = ({ product, className }) => { - const addItem = useAddItem() - const { openSidebar } = useUI() - const [loading, setLoading] = useState(false) - const [selectedOptions, setSelectedOptions] = useState({}) - - useEffect(() => { - selectDefaultOptionFromProduct(product, setSelectedOptions) - }, []) - - const variant = getProductVariant(product, selectedOptions) - const addToCart = async () => { - setLoading(true) - try { - await addItem({ - productId: String(product.id), - variantId: String(variant ? variant.id : product.variants[0].id), - }) - openSidebar() - setLoading(false) - } catch (err) { - setLoading(false) - } - } - - return ( -
    - - -
    - -
    36 reviews
    -
    -
    - {process.env.COMMERCE_CART_ENABLED && ( - - )} -
    -
    - - This is a limited edition production run. Printing starts when the - drop ends. - - - This is a limited edition production run. Printing starts when the - drop ends. Reminder: Bad Boys For Life. Shipping may take 10+ days due - to COVID-19. - -
    -
    - ) -} - -export default ProductSidebar diff --git a/components/product/ProductSidebar/index.ts b/components/product/ProductSidebar/index.ts deleted file mode 100644 index 7e00359c4..000000000 --- a/components/product/ProductSidebar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProductSidebar' diff --git a/components/product/ProductSlider/ProductSlider.module.css b/components/product/ProductSlider/ProductSlider.module.css deleted file mode 100644 index 8d7265eb8..000000000 --- a/components/product/ProductSlider/ProductSlider.module.css +++ /dev/null @@ -1,64 +0,0 @@ -.root { - @apply relative w-full h-full select-none; - overflow: hidden; -} - -.slider { - @apply relative h-full transition-opacity duration-150; - opacity: 0; -} - -.slider.show { - opacity: 1; -} - -.thumb { - @apply transition-transform transition-colors - ease-linear duration-75 overflow-hidden inline-block - cursor-pointer h-full; - width: 125px; - width: calc(100% / 3); -} - -.thumb.selected { - @apply bg-white; -} - -.thumb img { - height: 85% !important; -} - -.album { - width: 100%; - height: 100%; - @apply bg-violet-dark; - box-sizing: content-box; - overflow-y: hidden; - overflow-x: auto; - white-space: nowrap; - height: 125px; - scrollbar-width: none; -} - -/* Hide scrollbar for Chrome, Safari and Opera */ -.album::-webkit-scrollbar { - display: none; -} - -@screen md { - .thumb:hover { - transform: scale(1.02); - background-color: rgba(255, 255, 255, 0.08); - } - - .thumb.selected { - @apply bg-white; - } - - .album { - height: 182px; - } - .thumb { - width: 235px; - } -} diff --git a/components/product/ProductSlider/ProductSlider.tsx b/components/product/ProductSlider/ProductSlider.tsx deleted file mode 100644 index 8c3441906..000000000 --- a/components/product/ProductSlider/ProductSlider.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { useKeenSlider } from 'keen-slider/react' -import React, { - Children, - FC, - isValidElement, - useState, - useRef, - useEffect, -} from 'react' -import cn from 'classnames' -import { a } from '@react-spring/web' -import s from './ProductSlider.module.css' -import ProductSliderControl from '../ProductSliderControl' - -interface ProductSliderProps { - children: React.ReactNode[] - className?: string -} - -const ProductSlider: React.FC = ({ - children, - className = '', -}) => { - const [currentSlide, setCurrentSlide] = useState(0) - const [isMounted, setIsMounted] = useState(false) - const sliderContainerRef = useRef(null) - const thumbsContainerRef = useRef(null) - - const [ref, slider] = useKeenSlider({ - loop: true, - slidesPerView: 1, - mounted: () => setIsMounted(true), - slideChanged(s) { - const slideNumber = s.details().relativeSlide - setCurrentSlide(slideNumber) - - if (thumbsContainerRef.current) { - const $el = document.getElementById( - `thumb-${s.details().relativeSlide}` - ) - if (slideNumber >= 3) { - thumbsContainerRef.current.scrollLeft = $el!.offsetLeft - } else { - thumbsContainerRef.current.scrollLeft = 0 - } - } - }, - }) - - // Stop the history navigation gesture on touch devices - useEffect(() => { - const preventNavigation = (event: TouchEvent) => { - // Center point of the touch area - const touchXPosition = event.touches[0].pageX - // Size of the touch area - const touchXRadius = event.touches[0].radiusX || 0 - - // We set a threshold (10px) on both sizes of the screen, - // if the touch area overlaps with the screen edges - // it's likely to trigger the navigation. We prevent the - // touchstart event in that case. - if ( - touchXPosition - touchXRadius < 10 || - touchXPosition + touchXRadius > window.innerWidth - 10 - ) - event.preventDefault() - } - - sliderContainerRef.current!.addEventListener( - 'touchstart', - preventNavigation - ) - - return () => { - if (sliderContainerRef.current) { - sliderContainerRef.current!.removeEventListener( - 'touchstart', - preventNavigation - ) - } - } - }, []) - - const onPrev = React.useCallback(() => slider.prev(), [slider]) - const onNext = React.useCallback(() => slider.next(), [slider]) - - return ( -
    -
    - {slider && } - {Children.map(children, (child) => { - // Add the keen-slider__slide className to children - if (isValidElement(child)) { - return { - ...child, - props: { - ...child.props, - className: `${ - child.props.className ? `${child.props.className} ` : '' - }keen-slider__slide`, - }, - } - } - return child - })} -
    - - - {slider && - Children.map(children, (child, idx) => { - if (isValidElement(child)) { - return { - ...child, - props: { - ...child.props, - className: cn(child.props.className, s.thumb, { - [s.selected]: currentSlide === idx, - }), - id: `thumb-${idx}`, - onClick: () => { - slider.moveToSlideRelative(idx) - }, - }, - } - } - return child - })} - -
    - ) -} - -export default ProductSlider diff --git a/components/product/ProductSlider/index.ts b/components/product/ProductSlider/index.ts deleted file mode 100644 index 504440410..000000000 --- a/components/product/ProductSlider/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProductSlider' diff --git a/components/product/ProductSliderControl/ProductSliderControl.module.css b/components/product/ProductSliderControl/ProductSliderControl.module.css deleted file mode 100644 index c744e7598..000000000 --- a/components/product/ProductSliderControl/ProductSliderControl.module.css +++ /dev/null @@ -1,29 +0,0 @@ -.control { - @apply bg-violet absolute bottom-10 right-10 flex flex-row - border-accent-0 border text-accent-0 z-30 shadow-xl select-none; - height: 48px; -} - -.leftControl, -.rightControl { - @apply px-9 cursor-pointer; - transition: background-color 0.2s ease; -} - -.leftControl:hover, -.rightControl:hover { - background-color: var(--violet-dark); -} - -.leftControl:focus, -.rightControl:focus { - @apply outline-none; -} - -.rightControl { - @apply border-l border-accent-0; -} - -.leftControl { - margin-right: -1px; -} diff --git a/components/product/ProductSliderControl/ProductSliderControl.tsx b/components/product/ProductSliderControl/ProductSliderControl.tsx deleted file mode 100644 index 4e767b5db..000000000 --- a/components/product/ProductSliderControl/ProductSliderControl.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import cn from 'classnames' -import React from 'react' -import s from './ProductSliderControl.module.css' -import { ArrowLeft, ArrowRight } from '@components/icons' - -interface ProductSliderControl { - onPrev: React.MouseEventHandler - onNext: React.MouseEventHandler -} - -const ProductSliderControl: React.FC = React.memo( - ({ onPrev, onNext }) => ( -
    - - -
    - ) -) -export default ProductSliderControl diff --git a/components/product/ProductSliderControl/index.ts b/components/product/ProductSliderControl/index.ts deleted file mode 100644 index 5b63c466f..000000000 --- a/components/product/ProductSliderControl/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProductSliderControl' diff --git a/components/product/ProductTag/ProductTag.module.css b/components/product/ProductTag/ProductTag.module.css deleted file mode 100644 index faf2fd97f..000000000 --- a/components/product/ProductTag/ProductTag.module.css +++ /dev/null @@ -1,30 +0,0 @@ -.root { - @apply transition-colors ease-in-out duration-500 - absolute top-0 left-0 z-20 pr-16; -} - -.root .name { - @apply pt-0 max-w-full w-full leading-extra-loose; - font-size: 2rem; - letter-spacing: 0.4px; - line-height: 2.2em; -} - -.root .name span { - @apply py-4 px-6 bg-primary text-primary font-bold; - min-height: 70px; - font-size: inherit; - letter-spacing: inherit; - box-decoration-break: clone; - -webkit-box-decoration-break: clone; -} - -.root .name span.fontsizing { - display: flex; - padding-top: 1.5rem; -} - -.root .price { - @apply pt-2 px-6 pb-4 text-sm bg-primary text-accent-9 - font-semibold inline-block tracking-wide; -} diff --git a/components/product/ProductTag/ProductTag.tsx b/components/product/ProductTag/ProductTag.tsx deleted file mode 100644 index 2bc80b878..000000000 --- a/components/product/ProductTag/ProductTag.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import cn from 'classnames' -import { inherits } from 'util' -import s from './ProductTag.module.css' - -interface ProductTagProps { - className?: string - name: string - price: string - fontSize?: number -} - -const ProductTag: React.FC = ({ - name, - price, - className = '', - fontSize = 32, -}) => { - return ( -
    -

    - - {name} - -

    -
    {price}
    -
    - ) -} - -export default ProductTag diff --git a/components/product/ProductTag/index.ts b/components/product/ProductTag/index.ts deleted file mode 100644 index cb345e8bd..000000000 --- a/components/product/ProductTag/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProductTag' diff --git a/components/product/ProductView/ProductView.module.css b/components/product/ProductView/ProductView.module.css deleted file mode 100644 index 0b3ebf564..000000000 --- a/components/product/ProductView/ProductView.module.css +++ /dev/null @@ -1,60 +0,0 @@ -.root { - @apply relative grid items-start gap-1 grid-cols-1 overflow-x-hidden; - min-height: auto; -} - -.main { - @apply relative px-0 pb-0 box-border flex flex-col col-span-1; - min-height: 500px; -} - -.sidebar { - @apply flex flex-col col-span-1 mx-auto max-w-8xl px-6 py-6 w-full h-full; -} - -.sliderContainer { - @apply flex items-center justify-center overflow-x-hidden bg-violet; -} - -.imageContainer { - @apply text-center; -} - -.imageContainer > div, -.imageContainer > div > div { - @apply h-full; -} - -.sliderContainer .img { - @apply w-full h-auto max-h-full object-cover; -} - -.button { - width: 100%; -} - -.wishlistButton { - @apply absolute z-30 top-0 right-0; -} - -.relatedProductsGrid { - @apply grid grid-cols-2 py-2 gap-2 md:grid-cols-4 md:gap-7; -} - -@screen lg { - .root { - @apply grid-cols-12; - } - - .main { - @apply mx-0 col-span-8; - } - - .sidebar { - @apply col-span-4 py-6; - } - - .imageContainer { - max-height: 600px; - } -} diff --git a/components/product/ProductView/ProductView.tsx b/components/product/ProductView/ProductView.tsx deleted file mode 100644 index cfe26983a..000000000 --- a/components/product/ProductView/ProductView.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import cn from 'classnames' -import Image from 'next/image' -import { NextSeo } from 'next-seo' -import s from './ProductView.module.css' -import { FC } from 'react' -import type { Product } from '@commerce/types/product' -import usePrice from '@framework/product/use-price' -import { ProductSlider, ProductCard } from '@components/product' -import { Container, Text } from '@components/ui' -import ProductSidebar from '../ProductSidebar' -import ProductTag from '../ProductTag' -import { WishlistButton } from '@components/wishlist' -interface ProductViewProps { - product: Product - relatedProducts: Product[] -} - -const ProductView: FC = ({ product, relatedProducts }) => { - const { price } = usePrice({ - amount: product.price.value, - baseAmount: product.price.retailPrice, - currencyCode: product.price.currencyCode!, - }) - - return ( - <> - -
    -
    - -
    - - {product.images.map((image, i) => ( -
    - {image.alt -
    - ))} -
    -
    - {process.env.COMMERCE_WISHLIST_ENABLED && ( - - )} -
    - - -
    -
    -
    - Related Products -
    - {relatedProducts.map((p) => ( -
    - -
    - ))} -
    -
    -
    - - - ) -} - -export default ProductView diff --git a/components/product/ProductView/index.ts b/components/product/ProductView/index.ts deleted file mode 100644 index 9ac144801..000000000 --- a/components/product/ProductView/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProductView' diff --git a/components/product/Swatch/Swatch.module.css b/components/product/Swatch/Swatch.module.css deleted file mode 100644 index 79a69e548..000000000 --- a/components/product/Swatch/Swatch.module.css +++ /dev/null @@ -1,54 +0,0 @@ -.swatch { - box-sizing: border-box; - composes: root from '@components/ui/Button/Button.module.css'; - @apply h-10 w-10 bg-primary text-primary rounded-full mr-3 inline-flex - items-center justify-center cursor-pointer transition duration-150 ease-in-out - p-0 shadow-none border-accent-3 border box-border select-none; - margin-right: calc(0.75rem - 1px); - overflow: hidden; - width: 48px; - height: 48px; -} - -.swatch::before, -.swatch::after { - box-sizing: border-box; -} - -.swatch:hover { - @apply transform scale-110 bg-hover; -} - -.swatch > span { - @apply absolute; -} - -.color { - @apply text-black transition duration-150 ease-in-out; -} - -.color :hover { - @apply text-black; -} - -.color.dark, -.color.dark:hover { - color: white !important; -} - -.active { - @apply border-accent-9 border-2; - padding-right: 1px; - padding-left: 1px; -} - -.textLabel { - @apply w-auto px-4; - min-width: 3rem; -} - -.active.textLabel { - @apply border-accent-9 border-2; - padding-right: calc(1rem - 1px); - padding-left: calc(1rem - 1px); -} diff --git a/components/product/Swatch/Swatch.tsx b/components/product/Swatch/Swatch.tsx deleted file mode 100644 index d04e77a78..000000000 --- a/components/product/Swatch/Swatch.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import cn from 'classnames' -import React from 'react' -import s from './Swatch.module.css' -import { Check } from '@components/icons' -import Button, { ButtonProps } from '@components/ui/Button' -import { isDark } from '@lib/colors' -interface SwatchProps { - active?: boolean - children?: any - className?: string - variant?: 'size' | 'color' | string - color?: string - label?: string | null -} - -const Swatch: React.FC & SwatchProps> = React.memo( - ({ - active, - className, - color = '', - label = null, - variant = 'size', - ...props - }) => { - variant = variant?.toLowerCase() - - if (label) { - label = label?.toLowerCase() - } - - const swatchClassName = cn( - s.swatch, - { - [s.color]: color, - [s.active]: active, - [s.size]: variant === 'size', - [s.dark]: color ? isDark(color) : false, - [s.textLabel]: !color && label && label.length > 3, - }, - className - ) - - return ( - - ) - } -) - -export default Swatch diff --git a/components/product/Swatch/index.ts b/components/product/Swatch/index.ts deleted file mode 100644 index c8a795498..000000000 --- a/components/product/Swatch/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Swatch' diff --git a/components/product/helpers.ts b/components/product/helpers.ts deleted file mode 100644 index d3fbd5ef5..000000000 --- a/components/product/helpers.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { Product } from '@commerce/types/product' -export type SelectedOptions = Record -import { Dispatch, SetStateAction } from 'react' - -export function getProductVariant(product: Product, opts: SelectedOptions) { - const variant = product.variants.find((variant) => { - return Object.entries(opts).every(([key, value]) => - variant.options.find((option) => { - if ( - option.__typename === 'MultipleChoiceOption' && - option.displayName.toLowerCase() === key.toLowerCase() - ) { - return option.values.find((v) => v.label.toLowerCase() === value) - } - }) - ) - }) - return variant -} - -export function selectDefaultOptionFromProduct( - product: Product, - updater: Dispatch> -) { - // Selects the default option - product.variants[0].options?.forEach((v) => { - updater((choices) => ({ - ...choices, - [v.displayName.toLowerCase()]: v.values[0].label.toLowerCase(), - })) - }) -} diff --git a/components/product/index.ts b/components/product/index.ts deleted file mode 100644 index 8b70f8e2e..000000000 --- a/components/product/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as Swatch } from './Swatch' -export { default as ProductView } from './ProductView' -export { default as ProductCard } from './ProductCard' -export { default as ProductSlider } from './ProductSlider' -export { default as ProductOptions } from './ProductOptions' diff --git a/components/ui/Button/Button.module.css b/components/ui/Button/Button.module.css deleted file mode 100644 index 2ac7544f7..000000000 --- a/components/ui/Button/Button.module.css +++ /dev/null @@ -1,48 +0,0 @@ -.root { - @apply bg-accent-9 text-accent-0 cursor-pointer inline-flex - px-10 py-5 leading-6 transition ease-in-out duration-150 - shadow-sm text-center justify-center uppercase - border border-transparent items-center text-sm font-semibold - tracking-wide; - max-height: 64px; -} - -.root:hover { - @apply border-accent-9 bg-accent-6; -} - -.root:focus { - @apply shadow-outline-normal outline-none; -} - -.root[data-active] { - @apply bg-accent-6; -} - -.loading { - @apply bg-accent-1 text-accent-3 border-accent-2 cursor-not-allowed; -} - -.slim { - @apply py-2 transform-none normal-case; -} - -.ghost { - @apply border border-accent-2 bg-accent-0 text-accent-9 text-sm; -} - -.ghost:hover { - @apply border-accent-9 bg-accent-9 text-accent-0; -} - -.disabled, -.disabled:hover { - @apply text-accent-4 border-accent-2 bg-accent-1 cursor-not-allowed; - filter: grayscale(1); - -webkit-transform: translateZ(0); - -webkit-perspective: 1000; - -webkit-backface-visibility: hidden; -} - -.progress { -} diff --git a/components/ui/Button/Button.tsx b/components/ui/Button/Button.tsx deleted file mode 100644 index b29fb432a..000000000 --- a/components/ui/Button/Button.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import cn from 'classnames' -import React, { - forwardRef, - ButtonHTMLAttributes, - JSXElementConstructor, - useRef, -} from 'react' -import mergeRefs from 'react-merge-refs' -import s from './Button.module.css' -import { LoadingDots } from '@components/ui' - -export interface ButtonProps extends ButtonHTMLAttributes { - href?: string - className?: string - variant?: 'flat' | 'slim' | 'ghost' - active?: boolean - type?: 'submit' | 'reset' | 'button' - Component?: string | JSXElementConstructor - width?: string | number - loading?: boolean - disabled?: boolean -} - -const Button: React.FC = forwardRef((props, buttonRef) => { - const { - className, - variant = 'flat', - children, - active, - width, - loading = false, - disabled = false, - style = {}, - Component = 'button', - ...rest - } = props - const ref = useRef(null) - - const rootClassName = cn( - s.root, - { - [s.ghost]: variant === 'ghost', - [s.slim]: variant === 'slim', - [s.loading]: loading, - [s.disabled]: disabled, - }, - className - ) - - return ( - - {children} - {loading && ( - - - - )} - - ) -}) - -export default Button diff --git a/components/ui/Button/index.ts b/components/ui/Button/index.ts deleted file mode 100644 index aa076c58e..000000000 --- a/components/ui/Button/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Button' -export * from './Button' diff --git a/components/ui/Collapse/Collapse.module.css b/components/ui/Collapse/Collapse.module.css deleted file mode 100644 index fb4a82a90..000000000 --- a/components/ui/Collapse/Collapse.module.css +++ /dev/null @@ -1,25 +0,0 @@ -.root { - @apply border-b border-accent-2 py-4 flex flex-col outline-none; -} - -.header { - @apply flex flex-row items-center; -} - -.header .label { - @apply text-base font-medium; -} - -.content { - @apply pt-3 overflow-hidden pl-8; -} - -.icon { - @apply mr-3 text-accent-6; - margin-left: -6px; - transition: transform 0.2s ease; -} - -.icon.open { - transform: rotate(90deg); -} diff --git a/components/ui/Collapse/Collapse.tsx b/components/ui/Collapse/Collapse.tsx deleted file mode 100644 index b2f9525ac..000000000 --- a/components/ui/Collapse/Collapse.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import cn from 'classnames' -import React, { FC, ReactNode, useState } from 'react' -import s from './Collapse.module.css' -import { ChevronRight } from '@components/icons' -import { useSpring, a } from '@react-spring/web' -import useMeasure from 'react-use-measure' - -export interface CollapseProps { - title: string - children: ReactNode -} - -const Collapse: FC = React.memo(({ title, children }) => { - const [isActive, setActive] = useState(false) - const [ref, { height: viewHeight }] = useMeasure() - - const animProps = useSpring({ - height: isActive ? viewHeight : 0, - config: { tension: 250, friction: 32, clamp: true, duration: 150 }, - opacity: isActive ? 1 : 0, - }) - - const toggle = () => setActive((x) => !x) - - return ( -
    -
    - - {title} -
    - -
    - {children} -
    -
    -
    - ) -}) - -export default Collapse diff --git a/components/ui/Collapse/index.ts b/components/ui/Collapse/index.ts deleted file mode 100644 index 1e584a53b..000000000 --- a/components/ui/Collapse/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Collapse' -export * from './Collapse' diff --git a/components/ui/Container/Container.tsx b/components/ui/Container/Container.tsx deleted file mode 100644 index 538b1cac7..000000000 --- a/components/ui/Container/Container.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import cn from 'classnames' -import React, { FC } from 'react' - -interface ContainerProps { - className?: string - children?: any - el?: HTMLElement - clean?: boolean -} - -const Container: FC = ({ - children, - className, - el = 'div', - clean, -}) => { - const rootClassName = cn(className, { - 'mx-auto max-w-8xl px-6': !clean, - }) - - let Component: React.ComponentType> = - el as any - - return {children} -} - -export default Container diff --git a/components/ui/Container/index.ts b/components/ui/Container/index.ts deleted file mode 100644 index 9dbd596a8..000000000 --- a/components/ui/Container/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Container' diff --git a/components/ui/Grid/Grid.module.css b/components/ui/Grid/Grid.module.css deleted file mode 100644 index 27e4c5b19..000000000 --- a/components/ui/Grid/Grid.module.css +++ /dev/null @@ -1,154 +0,0 @@ -.root { - @apply grid grid-cols-1 gap-0; - - @screen lg { - @apply grid-cols-3 grid-rows-2; - } - - & > * { - @apply row-span-1 bg-transparent box-border overflow-hidden; - height: 500px; - max-height: 800px; - - @screen lg { - @apply col-span-1; - height: inherit; - } - } -} - -.default { - & > * { - @apply bg-transparent; - } -} - -.layoutNormal { - @apply gap-3; -} - -@screen md { - .layoutNormal > * { - max-height: min-content !important; - } -} - -@screen lg { - .layoutNormal > * { - max-height: 400px; - } -} - -.layoutA { - & > *:nth-child(6n + 1), - & > *:nth-child(6n + 5) { - @apply row-span-2; - height: var(--row-height); - - @screen lg { - @apply col-span-2; - } - } - - &.filled { - & > *:nth-child(6n + 1) { - @apply bg-violet; - } - - & > *:nth-child(6n + 2) { - @apply bg-accent-8; - } - - & > *:nth-child(6n + 3) { - @apply bg-pink; - } - - & > *:nth-child(6n + 6) { - @apply bg-cyan; - } - } -} - -.layoutB { - & > *:nth-child(6n + 2), - & > *:nth-child(6n + 4) { - @apply row-span-2; - height: var(--row-height); - - @screen lg { - @apply col-span-2; - } - } - - &.filled { - & > *:nth-child(6n + 1) { - @apply bg-violet; - } - - & > *:nth-child(6n + 2) { - @apply bg-accent-8; - } - - & > *:nth-child(6n + 3) { - @apply bg-pink; - } - - & > *:nth-child(6n + 6) { - @apply bg-cyan; - } - } -} - -.layoutC { - & > *:nth-child(12n + 1), - & > *:nth-child(12n + 8) { - @apply row-span-2; - height: var(--row-height); - - @screen lg { - @apply col-span-2; - } - } - - &.filled { - & > *:nth-child(12n + 1) { - @apply bg-violet; - height: var(--row-height); - } - - & > *:nth-child(12n + 8) { - @apply bg-cyan; - height: var(--row-height); - } - - & > *:nth-child(6n + 3) { - @apply bg-pink; - } - } -} - -.layoutD { - & > *:nth-child(12n + 2), - & > *:nth-child(12n + 7) { - @apply row-span-2; - height: var(--row-height); - - @screen lg { - @apply col-span-2; - } - } - - &.filled { - & > *:nth-child(12n + 2) { - @apply bg-violet; - } - - & > *:nth-child(12n + 7) { - @apply bg-cyan; - } - - & > *:nth-child(6n + 3) { - @apply bg-pink; - } - } -} diff --git a/components/ui/Grid/Grid.tsx b/components/ui/Grid/Grid.tsx deleted file mode 100644 index 55ca78277..000000000 --- a/components/ui/Grid/Grid.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import cn from 'classnames' -import { FC, ReactNode, Component } from 'react' -import s from './Grid.module.css' - -interface GridProps { - className?: string - children?: ReactNode[] | Component[] | any[] - layout?: 'A' | 'B' | 'C' | 'D' | 'normal' - variant?: 'default' | 'filled' -} - -const Grid: FC = ({ - className, - layout = 'A', - children, - variant = 'default', -}) => { - const rootClassName = cn( - s.root, - { - [s.layoutA]: layout === 'A', - [s.layoutB]: layout === 'B', - [s.layoutC]: layout === 'C', - [s.layoutD]: layout === 'D', - [s.layoutNormal]: layout === 'normal', - [s.default]: variant === 'default', - [s.filled]: variant === 'filled', - }, - className - ) - return
    {children}
    -} - -export default Grid diff --git a/components/ui/Grid/index.ts b/components/ui/Grid/index.ts deleted file mode 100644 index ddb51299b..000000000 --- a/components/ui/Grid/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Grid' diff --git a/components/ui/Hero/Hero.module.css b/components/ui/Hero/Hero.module.css deleted file mode 100644 index a0f1798f5..000000000 --- a/components/ui/Hero/Hero.module.css +++ /dev/null @@ -1,30 +0,0 @@ -.root { - @apply flex flex-col py-16 mx-auto; -} - -.title { - @apply text-accent-0 font-extrabold text-4xl leading-none tracking-tight; -} - -.description { - @apply mt-4 text-xl leading-8 text-accent-2 mb-1 lg:max-w-4xl; -} - -@screen lg { - .root { - @apply flex-row items-start justify-center py-32; - } - .title { - @apply text-5xl max-w-xl text-right leading-10 -mt-3; - line-height: 3.5rem; - } - .description { - @apply mt-0 ml-6; - } -} - -@screen xl { - .title { - @apply text-6xl; - } -} diff --git a/components/ui/Hero/Hero.tsx b/components/ui/Hero/Hero.tsx deleted file mode 100644 index 58d13e5de..000000000 --- a/components/ui/Hero/Hero.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { FC } from 'react' -import { Container } from '@components/ui' -import { ArrowRight } from '@components/icons' -import s from './Hero.module.css' -import Link from 'next/link' -interface HeroProps { - className?: string - headline: string - description: string -} - -const Hero: FC = ({ headline, description }) => { - return ( -
    - -
    -

    {headline}

    -
    -

    {description}

    - - - Read it here - - - -
    -
    -
    -
    - ) -} - -export default Hero diff --git a/components/ui/Hero/index.ts b/components/ui/Hero/index.ts deleted file mode 100644 index b08fa5ac8..000000000 --- a/components/ui/Hero/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Hero' diff --git a/components/ui/Input/Input.module.css b/components/ui/Input/Input.module.css deleted file mode 100644 index 34507f445..000000000 --- a/components/ui/Input/Input.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.root { - @apply bg-primary py-2 px-6 w-full appearance-none transition duration-150 ease-in-out pr-10 border border-accent-3 text-accent-6; -} - -.root:focus { - @apply outline-none shadow-outline-normal; -} diff --git a/components/ui/Input/Input.tsx b/components/ui/Input/Input.tsx deleted file mode 100644 index e630728b2..000000000 --- a/components/ui/Input/Input.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import cn from 'classnames' -import s from './Input.module.css' -import React, { InputHTMLAttributes } from 'react' - -export interface InputProps extends InputHTMLAttributes { - className?: string - onChange?: (...args: any[]) => any -} - -const Input: React.FC = (props) => { - const { className, children, onChange, ...rest } = props - - const rootClassName = cn(s.root, {}, className) - - const handleOnChange = (e: any) => { - if (onChange) { - onChange(e.target.value) - } - return null - } - - return ( - - ) -} - -export default Input diff --git a/components/ui/Input/index.ts b/components/ui/Input/index.ts deleted file mode 100644 index aa97178e5..000000000 --- a/components/ui/Input/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Input' diff --git a/components/ui/Link/Link.tsx b/components/ui/Link/Link.tsx deleted file mode 100644 index 27f30e863..000000000 --- a/components/ui/Link/Link.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import NextLink, { LinkProps as NextLinkProps } from 'next/link' - -const Link: React.FC = ({ href, children, ...props }) => { - return ( - - {children} - - ) -} - -export default Link diff --git a/components/ui/Link/index.ts b/components/ui/Link/index.ts deleted file mode 100644 index 518d37298..000000000 --- a/components/ui/Link/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Link' diff --git a/components/ui/LoadingDots/LoadingDots.module.css b/components/ui/LoadingDots/LoadingDots.module.css deleted file mode 100644 index 6054de3c7..000000000 --- a/components/ui/LoadingDots/LoadingDots.module.css +++ /dev/null @@ -1,33 +0,0 @@ -.root { - @apply inline-flex text-center items-center leading-7; -} - -.root .dot { - @apply rounded-full h-2 w-2; - background-color: currentColor; - animation-name: blink; - animation-duration: 1.4s; - animation-iteration-count: infinite; - animation-fill-mode: both; - margin: 0 2px; -} - -.root .dot:nth-of-type(2) { - animation-delay: 0.2s; -} - -.root .dot::nth-of-type(3) { - animation-delay: 0.4s; -} - -@keyframes blink { - 0% { - opacity: 0.2; - } - 20% { - opacity: 1; - } - 100% { - opacity: 0.2; - } -} diff --git a/components/ui/LoadingDots/LoadingDots.tsx b/components/ui/LoadingDots/LoadingDots.tsx deleted file mode 100644 index 27ce9f25f..000000000 --- a/components/ui/LoadingDots/LoadingDots.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import s from './LoadingDots.module.css' - -const LoadingDots: React.FC = () => { - return ( - - - - - - ) -} - -export default LoadingDots diff --git a/components/ui/LoadingDots/index.ts b/components/ui/LoadingDots/index.ts deleted file mode 100644 index 63df282bf..000000000 --- a/components/ui/LoadingDots/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './LoadingDots' diff --git a/components/ui/Logo/Logo.tsx b/components/ui/Logo/Logo.tsx deleted file mode 100644 index f15bde40a..000000000 --- a/components/ui/Logo/Logo.tsx +++ /dev/null @@ -1,21 +0,0 @@ -const Logo = ({ className = '', ...props }) => ( - - - - -) - -export default Logo diff --git a/components/ui/Logo/index.ts b/components/ui/Logo/index.ts deleted file mode 100644 index 93dce23b4..000000000 --- a/components/ui/Logo/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Logo' diff --git a/components/ui/Marquee/Marquee.module.css b/components/ui/Marquee/Marquee.module.css deleted file mode 100644 index e5ecb16ef..000000000 --- a/components/ui/Marquee/Marquee.module.css +++ /dev/null @@ -1,22 +0,0 @@ -.root { - @apply w-full min-w-full relative flex flex-row items-center overflow-hidden py-0; - max-height: 320px; -} - -.root > div { - max-height: 320px; - padding: 0; - margin: 0; -} - -.root > div > * > *:nth-child(2) * { - max-height: 100%; -} - -.primary { - @apply bg-accent-0; -} - -.secondary { - @apply bg-accent-9; -} diff --git a/components/ui/Marquee/Marquee.tsx b/components/ui/Marquee/Marquee.tsx deleted file mode 100644 index ce5ec2338..000000000 --- a/components/ui/Marquee/Marquee.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import cn from 'classnames' -import s from './Marquee.module.css' -import { FC, ReactNode, Component, Children } from 'react' -import { default as FastMarquee } from 'react-fast-marquee' - -interface MarqueeProps { - className?: string - children?: ReactNode[] | Component[] | any[] - variant?: 'primary' | 'secondary' -} - -const Marquee: FC = ({ - className = '', - children, - variant = 'primary', -}) => { - const rootClassName = cn( - s.root, - { - [s.primary]: variant === 'primary', - [s.secondary]: variant === 'secondary', - }, - className - ) - - return ( - - {Children.map(children, (child) => ({ - ...child, - props: { - ...child.props, - className: cn(child.props.className, `${variant}`), - }, - }))} - - ) -} - -export default Marquee diff --git a/components/ui/Marquee/index.ts b/components/ui/Marquee/index.ts deleted file mode 100644 index b59b75568..000000000 --- a/components/ui/Marquee/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Marquee' diff --git a/components/ui/Modal/Modal.module.css b/components/ui/Modal/Modal.module.css deleted file mode 100644 index f30d7c90a..000000000 --- a/components/ui/Modal/Modal.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.root { - @apply fixed bg-black bg-opacity-40 flex items-center inset-0 z-50 justify-center; - backdrop-filter: blur(0.8px); - -webkit-backdrop-filter: blur(0.8px); -} - -.modal { - @apply bg-primary p-12 border border-accent-2 relative; -} - -.modal:focus { - @apply outline-none; -} - -.close { - @apply hover:text-accent-5 transition ease-in-out duration-150 focus:outline-none absolute right-0 top-0 m-6; -} diff --git a/components/ui/Modal/Modal.tsx b/components/ui/Modal/Modal.tsx deleted file mode 100644 index bb42b3d1b..000000000 --- a/components/ui/Modal/Modal.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { FC, useRef, useEffect, useCallback } from 'react' -import s from './Modal.module.css' -import FocusTrap from '@lib/focus-trap' -import { Cross } from '@components/icons' -import { - disableBodyScroll, - clearAllBodyScrollLocks, - enableBodyScroll, -} from 'body-scroll-lock' -interface ModalProps { - className?: string - children?: any - onClose: () => void - onEnter?: () => void | null -} - -const Modal: FC = ({ children, onClose }) => { - const ref = useRef() as React.MutableRefObject - - const handleKey = useCallback( - (e: KeyboardEvent) => { - if (e.key === 'Escape') { - return onClose() - } - }, - [onClose] - ) - - useEffect(() => { - if (ref.current) { - disableBodyScroll(ref.current, { reserveScrollBarGap: true }) - window.addEventListener('keydown', handleKey) - } - return () => { - if (ref && ref.current) { - enableBodyScroll(ref.current) - } - clearAllBodyScrollLocks() - window.removeEventListener('keydown', handleKey) - } - }, [handleKey]) - - return ( -
    -
    - - {children} -
    -
    - ) -} - -export default Modal diff --git a/components/ui/Modal/index.ts b/components/ui/Modal/index.ts deleted file mode 100644 index e24753a1e..000000000 --- a/components/ui/Modal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Modal' diff --git a/components/ui/Quantity/Quantity.module.css b/components/ui/Quantity/Quantity.module.css deleted file mode 100644 index fa60cc56e..000000000 --- a/components/ui/Quantity/Quantity.module.css +++ /dev/null @@ -1,27 +0,0 @@ -.actions { - @apply flex p-1 border-accent-2 border items-center justify-center - w-12 text-accent-7; - transition-property: border-color, background, color, transform, box-shadow; - - transition-duration: 0.15s; - transition-timing-function: ease; - user-select: none; -} - -.actions:hover { - @apply border bg-accent-1 border-accent-3 text-accent-9; - transition: border-color; - z-index: 10; -} - -.actions:focus { - @apply outline-none; -} - -.actions:disabled { - @apply cursor-not-allowed; -} - -.input { - @apply bg-transparent px-4 w-full h-full focus:outline-none select-none pointer-events-auto; -} diff --git a/components/ui/Quantity/Quantity.tsx b/components/ui/Quantity/Quantity.tsx deleted file mode 100644 index abde145aa..000000000 --- a/components/ui/Quantity/Quantity.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { FC } from 'react' -import s from './Quantity.module.css' -import { Cross, Plus, Minus } from '@components/icons' -import cn from 'classnames' -export interface QuantityProps { - value: number - increase: () => any - decrease: () => any - handleRemove: React.MouseEventHandler - handleChange: React.ChangeEventHandler - max?: number -} - -const Quantity: FC = ({ - value, - increase, - decrease, - handleChange, - handleRemove, - max = 6, -}) => { - return ( -
    - - - - -
    - ) -} - -export default Quantity diff --git a/components/ui/Quantity/index.ts b/components/ui/Quantity/index.ts deleted file mode 100644 index 5ee880cc9..000000000 --- a/components/ui/Quantity/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Quantity' -export * from './Quantity' diff --git a/components/ui/README.md b/components/ui/README.md deleted file mode 100644 index 5bf4fe510..000000000 --- a/components/ui/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# UI - -Building blocks to build a rich graphical interfaces. Components should be atomic and pure. Serve one purpose. diff --git a/components/ui/Rating/Rating.tsx b/components/ui/Rating/Rating.tsx deleted file mode 100644 index 259e642ea..000000000 --- a/components/ui/Rating/Rating.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React, { FC } from 'react' -import rangeMap from '@lib/range-map' -import { Star } from '@components/icons' -import cn from 'classnames' - -export interface RatingProps { - value: number -} - -const Quantity: React.FC = React.memo(({ value = 5 }) => { - return ( -
    - {rangeMap(5, (i) => ( - = Math.floor(value), - })} - > - - - ))} -
    - ) -}) - -export default Quantity diff --git a/components/ui/Rating/index.ts b/components/ui/Rating/index.ts deleted file mode 100644 index 1354efb25..000000000 --- a/components/ui/Rating/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Rating' -export * from './Rating' diff --git a/components/ui/Sidebar/Sidebar.module.css b/components/ui/Sidebar/Sidebar.module.css deleted file mode 100644 index f6a49387f..000000000 --- a/components/ui/Sidebar/Sidebar.module.css +++ /dev/null @@ -1,14 +0,0 @@ -.root { - @apply fixed inset-0 h-full z-50 box-border; -} - -.sidebar { - @apply h-full flex flex-col text-base bg-accent-0 shadow-xl overflow-y-auto overflow-x-hidden; - -webkit-overflow-scrolling: touch !important; -} - -.backdrop { - @apply absolute inset-0 bg-black bg-opacity-40 duration-100 ease-linear; - backdrop-filter: blur(0.8px); - -webkit-backdrop-filter: blur(0.8px); -} diff --git a/components/ui/Sidebar/Sidebar.tsx b/components/ui/Sidebar/Sidebar.tsx deleted file mode 100644 index ce0eeefe2..000000000 --- a/components/ui/Sidebar/Sidebar.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { FC, useEffect, useRef } from 'react' -import s from './Sidebar.module.css' -import cn from 'classnames' -import { - disableBodyScroll, - enableBodyScroll, - clearAllBodyScrollLocks, -} from 'body-scroll-lock' - -interface SidebarProps { - children: any - onClose: () => void -} - -const Sidebar: FC = ({ children, onClose }) => { - const ref = useRef() as React.MutableRefObject - - useEffect(() => { - if (ref.current) { - disableBodyScroll(ref.current, { reserveScrollBarGap: true }) - } - return () => { - if (ref && ref.current) { - enableBodyScroll(ref.current) - } - clearAllBodyScrollLocks() - } - }, []) - - return ( -
    -
    -
    -
    -
    -
    - {children} -
    -
    -
    -
    -
    - ) -} - -export default Sidebar diff --git a/components/ui/Sidebar/index.ts b/components/ui/Sidebar/index.ts deleted file mode 100644 index 877187ca3..000000000 --- a/components/ui/Sidebar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Sidebar' diff --git a/components/ui/Skeleton/Skeleton.module.css b/components/ui/Skeleton/Skeleton.module.css deleted file mode 100644 index 37c164de7..000000000 --- a/components/ui/Skeleton/Skeleton.module.css +++ /dev/null @@ -1,48 +0,0 @@ -.skeleton { - @apply block; - background-image: linear-gradient( - 270deg, - var(--accent-0), - var(--accent-2), - var(--accent-0), - var(--accent-1) - ); - background-size: 400% 100%; - animation: loading 8s ease-in-out infinite; -} - -.wrapper { - @apply block relative; - - &:not(.show)::before { - content: none; - } - - &::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 100; - background-image: linear-gradient( - 270deg, - var(--accent-0), - var(--accent-2), - var(--accent-0), - var(--accent-1) - ); - background-size: 400% 100%; - animation: loading 8s ease-in-out infinite; - } -} - -@keyframes loading { - 0% { - background-position: 200% 0; - } - 100% { - background-position: -200% 0; - } -} diff --git a/components/ui/Skeleton/Skeleton.tsx b/components/ui/Skeleton/Skeleton.tsx deleted file mode 100644 index 9cef2c1ac..000000000 --- a/components/ui/Skeleton/Skeleton.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, { CSSProperties } from 'react' -import cn from 'classnames' -import px from '@lib/to-pixels' -import s from './Skeleton.module.css' - -interface SkeletonProps { - show?: boolean - block?: boolean - className?: string - style?: CSSProperties - width?: string | number - height?: string | number - boxHeight?: string | number -} - -const Skeleton: React.FC = ({ - style, - width, - height, - children, - className, - show = true, - boxHeight = height, -}) => { - // Automatically calculate the size if there are children - // and no fixed sizes are specified - const shouldAutoSize = !!children && !(width || height) - - // Defaults - width = width || 24 - height = height || 24 - boxHeight = boxHeight || height - - return ( - - {children} - - ) -} - -export default Skeleton diff --git a/components/ui/Skeleton/index.ts b/components/ui/Skeleton/index.ts deleted file mode 100644 index 3ec6c0031..000000000 --- a/components/ui/Skeleton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Skeleton' diff --git a/components/ui/Text/Text.module.css b/components/ui/Text/Text.module.css deleted file mode 100644 index f572fdf18..000000000 --- a/components/ui/Text/Text.module.css +++ /dev/null @@ -1,15 +0,0 @@ -.body { - @apply text-base leading-7 max-w-6xl mx-auto; -} - -.heading { - @apply text-5xl pt-1 pb-2 font-semibold tracking-wide cursor-pointer mb-2; -} - -.pageHeading { - @apply pt-1 pb-4 text-2xl leading-7 font-bold tracking-wide; -} - -.sectionHeading { - @apply pt-1 pb-2 text-2xl font-bold tracking-wide cursor-pointer mb-2; -} diff --git a/components/ui/Text/Text.tsx b/components/ui/Text/Text.tsx deleted file mode 100644 index 6106c209a..000000000 --- a/components/ui/Text/Text.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React, { - FunctionComponent, - JSXElementConstructor, - CSSProperties, -} from 'react' -import cn from 'classnames' -import s from './Text.module.css' - -interface TextProps { - variant?: Variant - className?: string - style?: CSSProperties - children?: React.ReactNode | any - html?: string - onClick?: () => any -} - -type Variant = 'heading' | 'body' | 'pageHeading' | 'sectionHeading' - -const Text: FunctionComponent = ({ - style, - className = '', - variant = 'body', - children, - html, - onClick, -}) => { - const componentsMap: { - [P in Variant]: React.ComponentType | string - } = { - body: 'div', - heading: 'h1', - pageHeading: 'h1', - sectionHeading: 'h2', - } - - const Component: - | JSXElementConstructor - | React.ReactElement - | React.ComponentType - | string = componentsMap![variant!] - - const htmlContentProps = html - ? { - dangerouslySetInnerHTML: { __html: html }, - } - : {} - - return ( - - {children} - - ) -} - -export default Text diff --git a/components/ui/Text/index.ts b/components/ui/Text/index.ts deleted file mode 100644 index e1e5fa74e..000000000 --- a/components/ui/Text/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Text' diff --git a/components/ui/context.tsx b/components/ui/context.tsx deleted file mode 100644 index d2f5aebfd..000000000 --- a/components/ui/context.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import React, { FC, useCallback, useMemo } from 'react' -import { ThemeProvider } from 'next-themes' - -export interface State { - displaySidebar: boolean - displayDropdown: boolean - displayModal: boolean - sidebarView: string - modalView: string - userAvatar: string -} - -const initialState = { - displaySidebar: false, - displayDropdown: false, - displayModal: false, - modalView: 'LOGIN_VIEW', - sidebarView: 'CHECKOUT_VIEW', - userAvatar: '', -} - -type Action = - | { - type: 'OPEN_SIDEBAR' - } - | { - type: 'CLOSE_SIDEBAR' - } - | { - type: 'OPEN_DROPDOWN' - } - | { - type: 'CLOSE_DROPDOWN' - } - | { - type: 'OPEN_MODAL' - } - | { - type: 'CLOSE_MODAL' - } - | { - type: 'SET_MODAL_VIEW' - view: MODAL_VIEWS - } - | { - type: 'SET_SIDEBAR_VIEW' - view: SIDEBAR_VIEWS - } - | { - type: 'SET_USER_AVATAR' - value: string - } - -type MODAL_VIEWS = - | 'SIGNUP_VIEW' - | 'LOGIN_VIEW' - | 'FORGOT_VIEW' - | 'NEW_SHIPPING_ADDRESS' - | 'NEW_PAYMENT_METHOD' - -type SIDEBAR_VIEWS = 'CART_VIEW' | 'CHECKOUT_VIEW' | 'PAYMENT_METHOD_VIEW' - -export const UIContext = React.createContext(initialState) - -UIContext.displayName = 'UIContext' - -function uiReducer(state: State, action: Action) { - switch (action.type) { - case 'OPEN_SIDEBAR': { - return { - ...state, - displaySidebar: true, - } - } - case 'CLOSE_SIDEBAR': { - return { - ...state, - displaySidebar: false, - } - } - case 'OPEN_DROPDOWN': { - return { - ...state, - displayDropdown: true, - } - } - case 'CLOSE_DROPDOWN': { - return { - ...state, - displayDropdown: false, - } - } - case 'OPEN_MODAL': { - return { - ...state, - displayModal: true, - displaySidebar: false, - } - } - case 'CLOSE_MODAL': { - return { - ...state, - displayModal: false, - } - } - case 'SET_MODAL_VIEW': { - return { - ...state, - modalView: action.view, - } - } - case 'SET_SIDEBAR_VIEW': { - return { - ...state, - sidebarView: action.view, - } - } - case 'SET_USER_AVATAR': { - return { - ...state, - userAvatar: action.value, - } - } - } -} - -export const UIProvider: FC = (props) => { - const [state, dispatch] = React.useReducer(uiReducer, initialState) - - const openSidebar = useCallback( - () => dispatch({ type: 'OPEN_SIDEBAR' }), - [dispatch] - ) - const closeSidebar = useCallback( - () => dispatch({ type: 'CLOSE_SIDEBAR' }), - [dispatch] - ) - const toggleSidebar = useCallback( - () => - state.displaySidebar - ? dispatch({ type: 'CLOSE_SIDEBAR' }) - : dispatch({ type: 'OPEN_SIDEBAR' }), - [dispatch, state.displaySidebar] - ) - const closeSidebarIfPresent = useCallback( - () => state.displaySidebar && dispatch({ type: 'CLOSE_SIDEBAR' }), - [dispatch, state.displaySidebar] - ) - - const openDropdown = useCallback( - () => dispatch({ type: 'OPEN_DROPDOWN' }), - [dispatch] - ) - const closeDropdown = useCallback( - () => dispatch({ type: 'CLOSE_DROPDOWN' }), - [dispatch] - ) - - const openModal = useCallback( - () => dispatch({ type: 'OPEN_MODAL' }), - [dispatch] - ) - const closeModal = useCallback( - () => dispatch({ type: 'CLOSE_MODAL' }), - [dispatch] - ) - - const setUserAvatar = useCallback( - (value: string) => dispatch({ type: 'SET_USER_AVATAR', value }), - [dispatch] - ) - - const setModalView = useCallback( - (view: MODAL_VIEWS) => dispatch({ type: 'SET_MODAL_VIEW', view }), - [dispatch] - ) - - const setSidebarView = useCallback( - (view: SIDEBAR_VIEWS) => dispatch({ type: 'SET_SIDEBAR_VIEW', view }), - [dispatch] - ) - - const value = useMemo( - () => ({ - ...state, - openSidebar, - closeSidebar, - toggleSidebar, - closeSidebarIfPresent, - openDropdown, - closeDropdown, - openModal, - closeModal, - setModalView, - setSidebarView, - setUserAvatar, - }), - [state] - ) - - return -} - -export const useUI = () => { - const context = React.useContext(UIContext) - if (context === undefined) { - throw new Error(`useUI must be used within a UIProvider`) - } - return context -} - -export const ManagedUIContext: FC = ({ children }) => ( - - {children} - -) diff --git a/components/ui/index.ts b/components/ui/index.ts deleted file mode 100644 index 47bdbd9ff..000000000 --- a/components/ui/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export { default as Hero } from './Hero' -export { default as Logo } from './Logo' -export { default as Grid } from './Grid' -export { default as Button } from './Button' -export { default as Sidebar } from './Sidebar' -export { default as Marquee } from './Marquee' -export { default as Container } from './Container' -export { default as LoadingDots } from './LoadingDots' -export { default as Skeleton } from './Skeleton' -export { default as Modal } from './Modal' -export { default as Text } from './Text' -export { default as Input } from './Input' -export { default as Collapse } from './Collapse' -export { default as Quantity } from './Quantity' -export { default as Rating } from './Rating' -export { useUI } from './context' diff --git a/components/wishlist/WishlistButton/WishlistButton.module.css b/components/wishlist/WishlistButton/WishlistButton.module.css deleted file mode 100644 index 3bdf1e710..000000000 --- a/components/wishlist/WishlistButton/WishlistButton.module.css +++ /dev/null @@ -1,33 +0,0 @@ -.root { - transition-duration: 0.2s; - transition-timing-function: ease; - transition-property: color, background-color, opacity; - @apply p-3 text-accent-9 flex items-center - justify-center font-semibold cursor-pointer - bg-accent-0 text-sm; -} - -.root:focus { - @apply outline-none; -} - -.icon { - transition-duration: 0.2s; - transition-timing-function: ease; - transition-property: transform, fill; - color: currentColor; -} - -.icon.loading { - fill: var(--pink-light); -} - -.icon.inWishlist { - fill: var(--pink); -} - -@screen lg { - .root { - @apply p-4; - } -} diff --git a/components/wishlist/WishlistButton/WishlistButton.tsx b/components/wishlist/WishlistButton/WishlistButton.tsx deleted file mode 100644 index a48eac170..000000000 --- a/components/wishlist/WishlistButton/WishlistButton.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { FC, useState } from 'react' -import cn from 'classnames' -import { useUI } from '@components/ui' -import { Heart } from '@components/icons' -import useAddItem from '@framework/wishlist/use-add-item' -import useCustomer from '@framework/customer/use-customer' -import useWishlist from '@framework/wishlist/use-wishlist' -import useRemoveItem from '@framework/wishlist/use-remove-item' -import s from './WishlistButton.module.css' -import type { Product, ProductVariant } from '@commerce/types/product' - -type Props = { - productId: Product['id'] - variant: ProductVariant -} & React.ButtonHTMLAttributes - -const WishlistButton: FC = ({ - productId, - variant, - className, - ...props -}) => { - const { data } = useWishlist() - const addItem = useAddItem() - const removeItem = useRemoveItem() - const { data: customer } = useCustomer() - const { openModal, setModalView } = useUI() - const [loading, setLoading] = useState(false) - - // @ts-ignore Wishlist is not always enabled - const itemInWishlist = data?.items?.find( - // @ts-ignore Wishlist is not always enabled - (item) => - item.product_id === Number(productId) && - (item.variant_id as any) === Number(variant.id) - ) - - const handleWishlistChange = async (e: any) => { - e.preventDefault() - - if (loading) return - - // A login is required before adding an item to the wishlist - if (!customer) { - setModalView('LOGIN_VIEW') - return openModal() - } - - setLoading(true) - - try { - if (itemInWishlist) { - await removeItem({ id: itemInWishlist.id! }) - } else { - await addItem({ - productId, - variantId: variant?.id!, - }) - } - - setLoading(false) - } catch (err) { - setLoading(false) - } - } - - return ( - - ) -} - -export default WishlistButton diff --git a/components/wishlist/WishlistButton/index.ts b/components/wishlist/WishlistButton/index.ts deleted file mode 100644 index 66e88074b..000000000 --- a/components/wishlist/WishlistButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './WishlistButton' diff --git a/components/wishlist/index.ts b/components/wishlist/index.ts deleted file mode 100644 index 9fe0a3541..000000000 --- a/components/wishlist/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as WishlistButton } from './WishlistButton' diff --git a/grocery-vercel-commerce b/grocery-vercel-commerce deleted file mode 160000 index 3c7aa8e86..000000000 --- a/grocery-vercel-commerce +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3c7aa8e862bfd8d44719be44c6c0a31ab01524a3 diff --git a/next.config.js b/next.config.js index 515b2ae7c..d3ad64f4a 100644 --- a/next.config.js +++ b/next.config.js @@ -13,6 +13,10 @@ const isVendure = provider === 'vendure' module.exports = withCommerceConfig({ commerce, + images: { + // todo: replace domains for images + domains: ['user-images.githubusercontent.com'], + }, i18n: { locales: ['en-US', 'es'], defaultLocale: 'en-US', diff --git a/package.json b/package.json index 91a529d52..57df2ec3b 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,8 @@ "classnames": "^2.3.1", "cookie": "^0.4.1", "email-validator": "^2.0.4", + "eslint": "^7.32.0", + "eslint-config-next": "^11.1.2", "immutability-helper": "^3.1.1", "js-cookie": "^2.2.1", "keen-slider": "^5.5.1", @@ -66,6 +68,7 @@ "@types/node": "^15.12.4", "@types/react": "^17.0.8", "deepmerge": "^4.2.2", + "eslint-config-prettier": "^8.3.0", "graphql": "^15.5.1", "husky": "^6.0.0", "lint-staged": "^11.0.0", diff --git a/pages/404.tsx b/pages/404.tsx index 38a01bcc4..8a357fb51 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -1,24 +1,4 @@ -import type { GetStaticPropsContext } from 'next' -import commerce from '@lib/api/commerce' -import { Layout } from '@components/common' - -export async function getStaticProps({ - preview, - locale, - locales, -}: GetStaticPropsContext) { - const config = { locale, locales } - const { pages } = await commerce.getAllPages({ config, preview }) - const { categories, brands } = await commerce.getSiteInfo({ config, preview }) - return { - props: { - pages, - categories, - brands, - }, - revalidate: 200, - } -} +import { Layout } from "src/components/common" export default function NotFound() { return ( diff --git a/pages/[...pages].tsx b/pages/[...pages].tsx deleted file mode 100644 index a8a24b3aa..000000000 --- a/pages/[...pages].tsx +++ /dev/null @@ -1,86 +0,0 @@ -import type { - GetStaticPathsContext, - GetStaticPropsContext, - InferGetStaticPropsType, -} from 'next' -import commerce from '@lib/api/commerce' -import { Text } from '@components/ui' -import { Layout } from '@components/common' -import getSlug from '@lib/get-slug' -import { missingLocaleInPages } from '@lib/usage-warns' -import type { Page } from '@commerce/types/page' -import { useRouter } from 'next/router' - -export async function getStaticProps({ - preview, - params, - locale, - locales, -}: GetStaticPropsContext<{ pages: string[] }>) { - const config = { locale, locales } - const pagesPromise = commerce.getAllPages({ config, preview }) - const siteInfoPromise = commerce.getSiteInfo({ config, preview }) - const { pages } = await pagesPromise - const { categories } = await siteInfoPromise - const path = params?.pages.join('/') - const slug = locale ? `${locale}/${path}` : path - const pageItem = pages.find((p: Page) => - p.url ? getSlug(p.url) === slug : false - ) - const data = - pageItem && - (await commerce.getPage({ - variables: { id: pageItem.id! }, - config, - preview, - })) - - const page = data?.page - - if (!page) { - // We throw to make sure this fails at build time as this is never expected to happen - throw new Error(`Page with slug '${slug}' not found`) - } - - return { - props: { pages, page, categories }, - revalidate: 60 * 60, // Every hour - } -} - -export async function getStaticPaths({ locales }: GetStaticPathsContext) { - const config = { locales } - const { pages }: { pages: Page[] } = await commerce.getAllPages({ config }) - const [invalidPaths, log] = missingLocaleInPages() - const paths = pages - .map((page) => page.url) - .filter((url) => { - if (!url || !locales) return url - // If there are locales, only include the pages that include one of the available locales - if (locales.includes(getSlug(url).split('/')[0])) return url - - invalidPaths.push(url) - }) - log() - - return { - paths, - fallback: 'blocking', - } -} - -export default function Pages({ - page, -}: InferGetStaticPropsType) { - const router = useRouter() - - return router.isFallback ? ( -

    Loading...

    // TODO (BC) Add Skeleton Views - ) : ( -
    - {page?.body && } -
    - ) -} - -Pages.Layout = Layout diff --git a/pages/cart.tsx b/pages/cart.tsx deleted file mode 100644 index b9659d21b..000000000 --- a/pages/cart.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import type { GetStaticPropsContext } from 'next' -import commerce from '@lib/api/commerce' -import { Layout } from '@components/common' -// import useCart from '@framework/cart/use-cart' -// import usePrice from '@framework/product/use-price' -// import { Button, Text } from '@components/ui' -// import { Bag, Cross, Check, MapPin, CreditCard } from '@components/icons' -// import { CartItem } from '@components/cart' - -export async function getStaticProps({ - preview, - locale, - locales, -}: GetStaticPropsContext) { - const config = { locale, locales } - const pagesPromise = commerce.getAllPages({ config, preview }) - const siteInfoPromise = commerce.getSiteInfo({ config, preview }) - const { pages } = await pagesPromise - const { categories } = await siteInfoPromise - return { - props: { pages, categories }, - } -} - -export default function Cart() { - // const error = null - // const success = null - // const { data, isLoading, isEmpty } = useCart() - - // const { price: subTotal } = usePrice( - // data && { - // amount: Number(data.subtotalPrice), - // currencyCode: data.currency.code, - // } - // ) - // const { price: total } = usePrice( - // data && { - // amount: Number(data.totalPrice), - // currencyCode: data.currency.code, - // } - // ) - - return ( -
    - This is cart page -
    - ) -} - -Cart.Layout = Layout diff --git a/pages/demo.tsx b/pages/demo.tsx new file mode 100644 index 000000000..38f91037c --- /dev/null +++ b/pages/demo.tsx @@ -0,0 +1,13 @@ +import { Layout } from 'src/components/common'; + + + +export default function Demo() { + return <> + Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias possimus tempore, nulla voluptate sed iste unde qui. Natus, amet minus, fugiat unde optio iste perferendis ea quae iusto asperiores voluptates enim sunt ducimus? Perferendis velit maxime sint pariatur beatae, veniam nulla sed, impedit, consectetur minus est libero enim? Quia reiciendis dolor, porro nisi harum fuga ullam pariatur facilis quas, praesentium quae, eveniet officiis officia animi aspernatur ut sunt commodi vero totam! Rerum, placeat perferendis laborum itaque blanditiis natus aperiam, eum delectus enim architecto eos, et voluptates! Illo at sed, pariatur ullam suscipit rerum recusandae doloremque natus nihil. Et temporibus quae necessitatibus quam alias, repellat laudantium a perspiciatis dolorum accusamus officiis pariatur ipsum facilis, nobis magni molestiae accusantium assumenda tempora consequuntur natus nostrum? Id, mollitia alias quidem hic aperiam error, blanditiis vero distinctio sit neque assumenda odio praesentium, perspiciatis aspernatur exercitationem. Eveniet nostrum tempore saepe cupiditate totam fuga doloremque placeat natus beatae quibusdam labore tempora delectus alias architecto vel, recusandae facilis nam rerum dolores magni? Eaque fugiat ut dicta. Aperiam, excepturi ad molestias non corrupti, officia dolore sequi, provident laborum officiis praesentium beatae quos? Totam et consequatur atque fugit voluptate. Aliquam neque, ab hic suscipit obcaecati ut aut quos. Expedita, ipsam. + Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias possimus tempore, nulla voluptate sed iste unde qui. Natus, amet minus, fugiat unde optio iste perferendis ea quae iusto asperiores voluptates enim sunt ducimus? Perferendis velit maxime sint pariatur beatae, veniam nulla sed, impedit, consectetur minus est libero enim? Quia reiciendis dolor, porro nisi harum fuga ullam pariatur facilis quas, praesentium quae, eveniet officiis officia animi aspernatur ut sunt commodi vero totam! Rerum, placeat perferendis laborum itaque blanditiis natus aperiam, eum delectus enim architecto eos, et voluptates! Illo at sed, pariatur ullam suscipit rerum recusandae doloremque natus nihil. Et temporibus quae necessitatibus quam alias, repellat laudantium a perspiciatis dolorum accusamus officiis pariatur ipsum facilis, nobis magni molestiae accusantium assumenda tempora consequuntur natus nostrum? Id, mollitia alias quidem hic aperiam error, blanditiis vero distinctio sit neque assumenda odio praesentium, perspiciatis aspernatur exercitationem. Eveniet nostrum tempore saepe cupiditate totam fuga doloremque placeat natus beatae quibusdam labore tempora delectus alias architecto vel, recusandae facilis nam rerum dolores magni? Eaque fugiat ut dicta. Aperiam, excepturi ad molestias non corrupti, officia dolore sequi, provident laborum officiis praesentium beatae quos? Totam et consequatur atque fugit voluptate. Aliquam neque, ab hic suscipit obcaecati ut aut quos. Expedita, ipsam. + Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias possimus tempore, nulla voluptate sed iste unde qui. Natus, amet minus, fugiat unde optio iste perferendis ea quae iusto asperiores voluptates enim sunt ducimus? Perferendis velit maxime sint pariatur beatae, veniam nulla sed, impedit, consectetur minus est libero enim? Quia reiciendis dolor, porro nisi harum fuga ullam pariatur facilis quas, praesentium quae, eveniet officiis officia animi aspernatur ut sunt commodi vero totam! Rerum, placeat perferendis laborum itaque blanditiis natus aperiam, eum delectus enim architecto eos, et voluptates! Illo at sed, pariatur ullam suscipit rerum recusandae doloremque natus nihil. Et temporibus quae necessitatibus quam alias, repellat laudantium a perspiciatis dolorum accusamus officiis pariatur ipsum facilis, nobis magni molestiae accusantium assumenda tempora consequuntur natus nostrum? Id, mollitia alias quidem hic aperiam error, blanditiis vero distinctio sit neque assumenda odio praesentium, perspiciatis aspernatur exercitationem. Eveniet nostrum tempore saepe cupiditate totam fuga doloremque placeat natus beatae quibusdam labore tempora delectus alias architecto vel, recusandae facilis nam rerum dolores magni? Eaque fugiat ut dicta. Aperiam, excepturi ad molestias non corrupti, officia dolore sequi, provident laborum officiis praesentium beatae quos? Totam et consequatur atque fugit voluptate. Aliquam neque, ab hic suscipit obcaecati ut aut quos. Expedita, ipsam. + +} + +Demo.Layout = Layout diff --git a/pages/index.tsx b/pages/index.tsx index e428ff533..7d23ebadd 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,36 +1,19 @@ - import { Layout } from 'src/components/common'; import { HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home'; -import {SelectCommon} from 'src/components/common' - -const OPTION_SORT = [ - { - name: "By Name" - }, - { - name: "Price (High to Low)" - }, - { - name: "On Sale" - } -] export default function Home() { return ( <> - {/* - + - */} - Sort By - Sort By + - // todo: uncomment + {/* // todo: uncomment */} {/* */} ) diff --git a/pages/product/[slug].tsx b/pages/product/[slug].tsx index c5bcbdba1..c34394af5 100644 --- a/pages/product/[slug].tsx +++ b/pages/product/[slug].tsx @@ -1,76 +1,16 @@ -import { Layout } from '@components/common' -import commerce from '@lib/api/commerce' -import type { - GetStaticPathsContext, - GetStaticPropsContext, - InferGetStaticPropsType -} from 'next' -import { useRouter } from 'next/router' -export async function getStaticProps({ - params, - locale, - locales, - preview, -}: GetStaticPropsContext<{ slug: string }>) { - const config = { locale, locales } - const pagesPromise = commerce.getAllPages({ config, preview }) - const siteInfoPromise = commerce.getSiteInfo({ config, preview }) - const productPromise = commerce.getProduct({ - variables: { slug: params!.slug }, - config, - preview, - }) +import { Layout, RecipeDetail } from 'src/components/common' +import { ProductInfoDetail, RecommendedRecipes, ReleventProducts, ViewedProducts } from 'src/components/modules/product-detail' +import { INGREDIENT_DATA_TEST, RECIPE_DATA_TEST } from 'src/utils/demo-data' - const allProductsPromise = commerce.getAllProducts({ - variables: { first: 4 }, - config, - preview, - }) - const { pages } = await pagesPromise - const { categories } = await siteInfoPromise - const { product } = await productPromise - const { products: relatedProducts } = await allProductsPromise - - if (!product) { - throw new Error(`Product with slug '${params!.slug}' not found`) - } - - return { - props: { - pages, - product, - relatedProducts, - categories, - }, - revalidate: 200, - } -} - -export async function getStaticPaths({ locales }: GetStaticPathsContext) { - const { products } = await commerce.getAllProductPaths() - - return { - paths: locales - ? locales.reduce((arr, locale) => { - // Add a product path for every locale - products.forEach((product: any) => { - arr.push(`/${locale}/product${product.path}`) - }) - return arr - }, []) - : products.map((product: any) => `/product${product.path}`), - fallback: 'blocking', - } -} - -export default function Slug({ - product, - relatedProducts, -}: InferGetStaticPropsType) { - const router = useRouter() - - return
    This is product page
    +export default function Slug() { + return <> + + + + + + } Slug.Layout = Layout diff --git a/pages/test.tsx b/pages/test.tsx index a0d99978c..f9296f786 100644 --- a/pages/test.tsx +++ b/pages/test.tsx @@ -1,421 +1,46 @@ -import { useState } from 'react' import { - ButtonCommon, - Layout, - ModalCommon, - ModalConfirm, - ModalInfo, - ProductCarousel, - ProductList, + CollapseCommon, Layout, RelevantBlogPosts } from 'src/components/common' -import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon' -import image5 from '../public/assets/images/image5.png' -import image6 from '../public/assets/images/image6.png' -import image7 from '../public/assets/images/image7.png' -import image8 from '../public/assets/images/image8.png' -const dataTest = [ + +const COLLAPSE_DATA = [ { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, + title: "This is a subtitle", + content: [ + "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.", + "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.", + "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.", + ], }, { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, + title: "This is a subtitle", + content: [ + "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.", + "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.", + "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.", + ], }, { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, + title: "This is a subtitle", + content: [ + "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.", + "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.", + "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.", + ], }, { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Cucumber', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image6.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Cucumber', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image6.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Cucumber', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image6.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Carrot', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image7.src, - }, - { - name: 'Salad', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image8.src, - }, - { - name: 'Tomato', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image5.src, - }, - { - name: 'Cucumber', - weight: '250g', - category: 'VEGGIE', - price: 'Rp 27.500', - imageSrc: image6.src, + title: "This is a subtitle", + content: [ + "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.", + "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.", + "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.", + ], }, ] export default function Test() { - const [visible, setVisible] = useState(false) - const onClose = () => { - setVisible(false) - } - const onOpen = () => { - setVisible(true) - } return ( <> - open - - Lorem, ipsum dolor sit amet consectetur adipisicing elit. Nisi qui, esse eos nobis soluta suscipit aliquid nostrum corporis. Nihil eligendi similique recusandae minus mollitia aliquam, molestias fugit tenetur voluptatibus maiores et. Quaerat labore corporis inventore nostrum, amet autem exercitationem eligendi? - - - + + ) } diff --git a/public/assets/bannerrecipes.png b/public/assets/bannerrecipes.png new file mode 100644 index 000000000..91271cbd2 Binary files /dev/null and b/public/assets/bannerrecipes.png differ diff --git a/public/assets/images/image15.png b/public/assets/images/image15.png new file mode 100644 index 000000000..a4d0badbd Binary files /dev/null and b/public/assets/images/image15.png differ diff --git a/public/assets/images/image16.png b/public/assets/images/image16.png new file mode 100644 index 000000000..c5457090e Binary files /dev/null and b/public/assets/images/image16.png differ diff --git a/public/assets/images/image17.png b/public/assets/images/image17.png new file mode 100644 index 000000000..2dcb53d27 Binary files /dev/null and b/public/assets/images/image17.png differ diff --git a/public/bg-products.svg b/public/bg-products.svg index 2118c3277..1eaa1df8b 100644 --- a/public/bg-products.svg +++ b/public/bg-products.svg @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/src/components/common/BreadcrumbCommon/BreadcrumbCommon.module.scss b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.module.scss new file mode 100644 index 000000000..95c8526e1 --- /dev/null +++ b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.module.scss @@ -0,0 +1,11 @@ +@import '../../../styles/utilities'; + +.breadcrumbCommon { + color: var(--text-base); +<<<<<<< HEAD +======= + .currentItem { + cursor: default; + } +>>>>>>> a9f9f06eb9dee2a1ddefe907ff804237a78c5210 +} diff --git a/src/components/common/BreadcrumbCommon/BreadcrumbCommon.tsx b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.tsx new file mode 100644 index 000000000..6ad2e6817 --- /dev/null +++ b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.tsx @@ -0,0 +1,37 @@ +import React from 'react' +import { ROUTE } from 'src/utils/constanst.utils' +import s from './BreadcrumbCommon.module.scss' +import BreadcrumbItem from './components/BreadcrumbItem/BreadcrumbItem' +import BreadcrumbSeparator from './components/BreadcrumbSeparator/BreadcrumbSeparator' + +interface BreadcrumbCommonProps { + crumbs: { link: string, name: string }[]; + showHomePage?: boolean; +} + +const BreadcrumbCommon = ({ crumbs, showHomePage = true }: BreadcrumbCommonProps) => { + return ( +
    + { + + showHomePage && + } + { + crumbs.length > 0 && <> + + { + crumbs.slice(0, crumbs.length - 1).map((crumb) => ( + < BreadcrumbSeparator key={crumb.name}> + + + ))} + < BreadcrumbSeparator> + {crumbs[crumbs.length - 1].name} + + + } +
    + ) +} + +export default BreadcrumbCommon diff --git a/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.module.scss b/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.module.scss new file mode 100644 index 000000000..3a785f480 --- /dev/null +++ b/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.module.scss @@ -0,0 +1,5 @@ +.breadcrumbItem { + &:hover { + color: var(--primary); + } +} diff --git a/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.tsx b/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.tsx new file mode 100644 index 000000000..13f980ea9 --- /dev/null +++ b/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import Link from 'next/link' +import s from './BreadcrumbItem.module.scss' + +interface BreadcrumbItemProps { + text: string; + href: string; +} + +const BreadcrumbItem = ({ text, href }: BreadcrumbItemProps) => { + return ( + + {text} + + ) +} + +export default BreadcrumbItem diff --git a/src/components/common/BreadcrumbCommon/components/BreadcrumbSeparator/BreadcrumbSeparator.tsx b/src/components/common/BreadcrumbCommon/components/BreadcrumbSeparator/BreadcrumbSeparator.tsx new file mode 100644 index 000000000..370c342d8 --- /dev/null +++ b/src/components/common/BreadcrumbCommon/components/BreadcrumbSeparator/BreadcrumbSeparator.tsx @@ -0,0 +1,15 @@ +import React from 'react' + +interface BreadcrumbSeparatorProps { + children?: React.ReactNode +} + +const BreadcrumbSeparator = ({ children }: BreadcrumbSeparatorProps) => { + return ( + +  / {children} + + ) +} + +export default BreadcrumbSeparator diff --git a/src/components/common/ButtonCommon/ButtonCommon.module.scss b/src/components/common/ButtonCommon/ButtonCommon.module.scss index 4cfe737de..c7b9f1ffa 100644 --- a/src/components/common/ButtonCommon/ButtonCommon.module.scss +++ b/src/components/common/ButtonCommon/ButtonCommon.module.scss @@ -7,6 +7,9 @@ align-items: center; padding: 1rem 2rem; @screen md { + padding: 0.8rem 1.6rem; + } + @screen lg { padding: 0.8rem 3.2rem; } &:disabled { @@ -84,11 +87,14 @@ padding: 1rem; } @screen md { - padding: 1.6rem 4.8rem; + padding: 1.6rem 3.2rem; &.onlyIcon { padding: 1.6rem; } } + @screen lg { + padding: 1.6rem 4.8rem; + } &.loading { &::before { width: 2.4rem; diff --git a/src/components/common/CardBlog/CardBlog.module.scss b/src/components/common/CardBlog/CardBlog.module.scss new file mode 100644 index 000000000..f0dc00b3a --- /dev/null +++ b/src/components/common/CardBlog/CardBlog.module.scss @@ -0,0 +1,34 @@ +@import "../../../styles/utilities"; + +.cardBlogWarpper { + @apply inline-flex flex-col justify-start; + max-width: 39.2rem; + min-height: 34.4rem; + .image { + width: 100%; + max-height: 22rem; + border-radius: 2.4rem; + &:hover { + cursor: pointer; + } + } + .title { + padding: 1.6rem 0.8rem 0.4rem 0.8rem; + @apply font-bold; + font-size: 2rem; + line-height: 2.8rem; + letter-spacing: -0.01em; + color: var(--text-active); + &:hover { + cursor: pointer; + } + } + .description { + padding: 0 0.8rem; + @apply overflow-hidden overflow-ellipsis ; + color: var(--text-label); + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + } +} \ No newline at end of file diff --git a/src/components/common/CardBlog/CardBlog.tsx b/src/components/common/CardBlog/CardBlog.tsx new file mode 100644 index 000000000..314a6a1fd --- /dev/null +++ b/src/components/common/CardBlog/CardBlog.tsx @@ -0,0 +1,31 @@ +import Link from 'next/link' +import React from 'react' +import { ROUTE } from 'src/utils/constanst.utils' +import { BlogProps } from 'src/utils/types.utils' +import s from './CardBlog.module.scss' +export interface BlogCardProps extends BlogProps { + // todo: edit when intergrate API + +} + +const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => { + return ( +
    + + +
    + image cardblog +
    +
    + + + +
    {title}
    +
    + +
    {description}
    +
    + ) +} + +export default CardBlog diff --git a/src/components/common/CarouselCommon/CarouselCommon.module.scss b/src/components/common/CarouselCommon/CarouselCommon.module.scss index da306f38f..ef2671947 100644 --- a/src/components/common/CarouselCommon/CarouselCommon.module.scss +++ b/src/components/common/CarouselCommon/CarouselCommon.module.scss @@ -8,6 +8,7 @@ :global(.customArrow) { width: 64px; height: 64px; + border-radius: .8rem; &:focus { outline: none; } diff --git a/src/components/common/CarouselCommon/CarouselCommon.tsx b/src/components/common/CarouselCommon/CarouselCommon.tsx index 136c323f3..3b5854ed4 100644 --- a/src/components/common/CarouselCommon/CarouselCommon.tsx +++ b/src/components/common/CarouselCommon/CarouselCommon.tsx @@ -28,7 +28,6 @@ const CarouselCommon = ({ option: { slideChanged,slidesPerView, ...sliderOption }, }: CarouselCommonProps) => { const [currentSlide, setCurrentSlide] = React.useState(0) - // const [dotActive, setDotActive] = React.useState(0) const [dotArr, setDotArr] = React.useState([]) const [sliderRef, slider] = useKeenSlider({ ...sliderOption, diff --git a/src/components/common/CartDrawer/CartDrawer.module.scss b/src/components/common/CartDrawer/CartDrawer.module.scss new file mode 100644 index 000000000..126028d3c --- /dev/null +++ b/src/components/common/CartDrawer/CartDrawer.module.scss @@ -0,0 +1,12 @@ +@import '../../../styles/utilities'; + + +.cartDrawer { + @apply flex flex-col h-full; + .body { + @apply overflow-y-auto overflow-x-hidden h-full custom-scroll; + } + .bottom { + padding-top: 1.6rem; + } +} \ No newline at end of file diff --git a/src/components/common/CartDrawer/CartDrawer.tsx b/src/components/common/CartDrawer/CartDrawer.tsx new file mode 100644 index 000000000..0a432bb65 --- /dev/null +++ b/src/components/common/CartDrawer/CartDrawer.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { PRODUCT_CART_DATA_TEST } from 'src/utils/demo-data'; +import { DrawerCommon } from '..'; +import s from './CartDrawer.module.scss'; +import CartCheckoutButton from './components/CartCheckoutButton/CartCheckoutButton'; +import CartMessage from './components/CartMessage/CartMessage'; +import CartRecommendation from './components/CartRecommendation/CartRecommendation'; +import ProductsInCart from './components/ProductsInCart/ProductsInCart'; + +interface Props { + visible: boolean + onClose: () => void +} + +const CartDrawer = ({ visible, onClose }: Props) => { + return ( + +
    +
    + + +
    +
    + + +
    +
    +
    + ) +} + +export default CartDrawer; \ No newline at end of file diff --git a/src/components/common/CartDrawer/components/CartCheckoutButton/CartCheckoutButton.module.scss b/src/components/common/CartDrawer/components/CartCheckoutButton/CartCheckoutButton.module.scss new file mode 100644 index 000000000..3f90bffbd --- /dev/null +++ b/src/components/common/CartDrawer/components/CartCheckoutButton/CartCheckoutButton.module.scss @@ -0,0 +1,6 @@ +.cartCheckoutButton { + padding: 1.6rem; + button { + width: 100%; + } +} diff --git a/src/components/common/CartDrawer/components/CartCheckoutButton/CartCheckoutButton.tsx b/src/components/common/CartDrawer/components/CartCheckoutButton/CartCheckoutButton.tsx new file mode 100644 index 000000000..0cd7d00a2 --- /dev/null +++ b/src/components/common/CartDrawer/components/CartCheckoutButton/CartCheckoutButton.tsx @@ -0,0 +1,13 @@ +import React, { memo } from 'react'; +import { ButtonCommon } from 'src/components/common'; +import s from './CartCheckoutButton.module.scss'; + +const CartCheckoutButton = memo(() => { + return ( +
    + Check out - Rp 120.500 +
    + ) +}) + +export default CartCheckoutButton; \ No newline at end of file diff --git a/src/components/common/CartDrawer/components/CartMessage/CartMessage.module.scss b/src/components/common/CartDrawer/components/CartMessage/CartMessage.module.scss new file mode 100644 index 000000000..59d8e8ddc --- /dev/null +++ b/src/components/common/CartDrawer/components/CartMessage/CartMessage.module.scss @@ -0,0 +1,16 @@ +@import "../../../../../styles/utilities"; + +.cartMessage { + @apply flex bg-info; + padding: 1.2rem 1.6rem; + .text { + color: var(--white); + font-weight: bold; + margin-right: 0.8rem; + } + .icon { + svg path { + fill: var(--text-placeholder); + } + } +} diff --git a/src/components/common/CartDrawer/components/CartMessage/CartMessage.tsx b/src/components/common/CartDrawer/components/CartMessage/CartMessage.tsx new file mode 100644 index 000000000..2cc85fb49 --- /dev/null +++ b/src/components/common/CartDrawer/components/CartMessage/CartMessage.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; +import { IconInfo } from 'src/components/icons'; +import s from './CartMessage.module.scss'; + +const CartMessage = memo(() => { + return ( +
    +
    + You save - Rp 150 +
    +
    + +
    +
    + ) +}) + +export default CartMessage; \ No newline at end of file diff --git a/src/components/common/CartDrawer/components/CartRecommendation/CartRecommendation.module.scss b/src/components/common/CartDrawer/components/CartRecommendation/CartRecommendation.module.scss new file mode 100644 index 000000000..88664460c --- /dev/null +++ b/src/components/common/CartDrawer/components/CartRecommendation/CartRecommendation.module.scss @@ -0,0 +1,26 @@ +@import '../../../../../styles/utilities'; + +.cartRecommendation { + @apply w-full bg-background-gray; + .top { + @apply flex justify-between items-center; + padding: 1.6rem; + .heading { + @apply font-bold text-active sm-headline; + } + } + .productCardWarpper { + padding-left: 1.6rem; + :global(.customArrow) { + @apply bg-line; + @screen lg { + &:global(.leftArrow) { + left: calc(-6.4rem - 2rem); + } + &:global(.rightArrow) { + right: calc(-6.4rem - 2rem); + } + } + } + } +} diff --git a/src/components/common/CartDrawer/components/CartRecommendation/CartRecommendation.tsx b/src/components/common/CartDrawer/components/CartRecommendation/CartRecommendation.tsx new file mode 100644 index 000000000..bbc40647e --- /dev/null +++ b/src/components/common/CartDrawer/components/CartRecommendation/CartRecommendation.tsx @@ -0,0 +1,43 @@ +import { TOptionsEvents } from 'keen-slider'; +import React from 'react'; +import { CarouselCommon, ViewAllItem } from 'src/components/common'; +import ProductCard, { ProductCardProps } from 'src/components/common/ProductCard/ProductCard'; +import { ROUTE } from 'src/utils/constanst.utils'; +import { PRODUCT_DATA_TEST } from 'src/utils/demo-data'; +import s from './CartRecommendation.module.scss'; + +const option: TOptionsEvents = { + slidesPerView: 2, + mode: 'free', + breakpoints: { + '(min-width: 640px)': { + slidesPerView: 1, + }, + '(min-width: 768px)': { + slidesPerView: 2.5, + } + }, +} + +const CartRecommendation = () => { + return ( +
    +
    +
    + Recommendation +
    + +
    +
    + + data={PRODUCT_DATA_TEST} + Component={ProductCard} + itemKey="cart-recommendation" + option={option} + /> +
    +
    + ) +} + +export default CartRecommendation; diff --git a/src/components/common/CartDrawer/components/ProductCartItem/ProductCartItem.module.scss b/src/components/common/CartDrawer/components/ProductCartItem/ProductCartItem.module.scss new file mode 100644 index 000000000..4988d4a66 --- /dev/null +++ b/src/components/common/CartDrawer/components/ProductCartItem/ProductCartItem.module.scss @@ -0,0 +1,54 @@ +@import "../../../../../styles/utilities"; + +.productCartItem { + @apply grid; + grid-template-columns: 2fr 1fr; + padding-bottom: 1.6rem; + padding-top: 1.6rem; + .info { + @apply flex; + .imgWrap { + width: 11rem; + height: 7.5rem; + margin-right: 1.6rem; + img { + object-fit: contain; + } + } + .detail { + min-height: 9rem; + .name { + &:hover { + color: var(--primary); + } + } + .price { + margin-top: 0.8rem; + .old { + margin-bottom: 0.8rem; + .number { + margin-right: 0.8rem; + color: var(--text-label); + text-decoration: line-through; + } + } + .current { + @apply text-active font-bold sm-headline; + } + } + } + } + + .actions { + @apply flex flex-col justify-between items-end; + margin-left: 1.6rem; + .iconDelete { + @apply cursor-pointer; + &:hover { + svg path { + fill: var(--negative); + } + } + } + } +} diff --git a/src/components/common/CartDrawer/components/ProductCartItem/ProductCartItem.tsx b/src/components/common/CartDrawer/components/ProductCartItem/ProductCartItem.tsx new file mode 100644 index 000000000..7ec3ecbdb --- /dev/null +++ b/src/components/common/CartDrawer/components/ProductCartItem/ProductCartItem.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import Link from 'next/link' +import { QuanittyInput } from 'src/components/common'; +import { IconDelete } from 'src/components/icons'; +import { ROUTE } from 'src/utils/constanst.utils'; +import { ProductProps } from 'src/utils/types.utils'; +import ImgWithLink from '../../../ImgWithLink/ImgWithLink'; +import LabelCommon from '../../../LabelCommon/LabelCommon'; +import s from './ProductCartItem.module.scss'; + +export interface ProductCartItempProps extends ProductProps { + quantity: number, +} + +const ProductCartItem = ({ name, slug, weight, price, oldPrice, discount, imageSrc, quantity }: ProductCartItempProps) => { + return ( +
    +
    + + +
    + +
    +
    + +
    + + +
    + {name} {weight ? `(${weight})` : ''} +
    +
    + +
    + { + oldPrice && +
    + {oldPrice} + {discount} +
    + } +
    {price}
    +
    +
    +
    +
    +
    + +
    + +
    +
    + ) +} + +export default ProductCartItem; \ No newline at end of file diff --git a/src/components/common/CartDrawer/components/ProductsInCart/ProductsInCart.module.scss b/src/components/common/CartDrawer/components/ProductsInCart/ProductsInCart.module.scss new file mode 100644 index 000000000..61ef7421e --- /dev/null +++ b/src/components/common/CartDrawer/components/ProductsInCart/ProductsInCart.module.scss @@ -0,0 +1,9 @@ +.productsInCart { + padding: 1.6rem 1.6rem 0 1.6rem; + list-style: none; + li { + &:not(:last-child) { + border-bottom: 1px solid var(--border-line); + } + } +} diff --git a/src/components/common/CartDrawer/components/ProductsInCart/ProductsInCart.tsx b/src/components/common/CartDrawer/components/ProductsInCart/ProductsInCart.tsx new file mode 100644 index 000000000..b455d4d73 --- /dev/null +++ b/src/components/common/CartDrawer/components/ProductsInCart/ProductsInCart.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import ProductCartItem, { ProductCartItempProps } from '../ProductCartItem/ProductCartItem'; +import s from './ProductsInCart.module.scss'; + +interface Props { + data: ProductCartItempProps[] +} + +const ProductsInCart = ({ data }: Props) => { + return ( +
      + { + data.map(item =>
    • + +
    • ) + } +
    + ) +} + +export default ProductsInCart; \ No newline at end of file diff --git a/src/components/common/CollapseCommon/CollapseChild/CollapseChild.module.scss b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.module.scss new file mode 100644 index 000000000..e6a71e44e --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.module.scss @@ -0,0 +1,66 @@ +@import "../../../../styles/utilities"; + +.collapseWrapper { + @apply border-t border-b; + border-color: var(--border-line); + max-width: 80.4rem; + min-height: 4rem; + &.isActive { + .title { + @apply pb-0; + } + .contentContainer { + @apply block; + animation: ContentAnimationIn 0.5s ease-out; + } + .toggle { + &:before { + transform: rotate(180deg); + } + &:after { + transform: rotate(180deg); + } + } + } + &:hover { + cursor: pointer; + } +} +.title { + @apply outline-none flex justify-between font-heading items-center pt-16 pb-16; + font-size: 3.2rem; + line-height: 4rem; + letter-spacing: -0.01em; + .toggle { + height: 2.2rem; + width: 2.2rem; + position: relative; + &:before, + &:after { + @apply absolute h-2; + content: ""; + border-radius: 0.8rem; + background: var(--text-active); + top: 40%; + width: 2.2rem; + transition: transform 500ms ease; + } + &:before { + transform-origin: center; + transform: rotate(90deg); + } + } +} +.contentContainer { + @apply hidden pb-16; +} +@keyframes ContentAnimationIn { + 0% { + opacity: 0; + transform: translateY(-1.6rem); + } + 100% { + opacity: 1; + transform: none; + } +} \ No newline at end of file diff --git a/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx new file mode 100644 index 000000000..53cd70cf3 --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx @@ -0,0 +1,37 @@ +import s from './CollapseChild.module.scss' +import { useState } from 'react' +import classNames from 'classnames' +import CollapseContent from './CollapseContent/CollapseContent' + +interface CollapseProps{ + title?: string, + content: Array, + isToggle?: boolean, +} +const CollapseChild = ({title, content, isToggle=false}: CollapseProps) => { + const [isActive, changeActive] = useState(isToggle) + + const handleToggle = () => { + changeActive(!isActive) + } + return( +
    +
    +

    {title}

    +
    +
    +
    + { + content.map(item => ) + } +
    +
    + ) +} + +export default CollapseChild \ No newline at end of file diff --git a/src/components/common/CollapseCommon/CollapseChild/CollapseContent/CollapseContent.module.scss b/src/components/common/CollapseCommon/CollapseChild/CollapseContent/CollapseContent.module.scss new file mode 100644 index 000000000..9e5cfba30 --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseChild/CollapseContent/CollapseContent.module.scss @@ -0,0 +1,3 @@ +.content { + margin-top: 1.6rem; +} \ No newline at end of file diff --git a/src/components/common/CollapseCommon/CollapseChild/CollapseContent/CollapseContent.tsx b/src/components/common/CollapseCommon/CollapseChild/CollapseContent/CollapseContent.tsx new file mode 100644 index 000000000..e18e19c0a --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseChild/CollapseContent/CollapseContent.tsx @@ -0,0 +1,15 @@ +import s from './CollapseContent.module.scss' + +interface CollapseContentProps{ + content: string +} + +const CollapseContent = ({content}: CollapseContentProps) => { + return ( +
    + {content} +
    + ) +} + +export default CollapseContent \ No newline at end of file diff --git a/src/components/common/CollapseCommon/CollapseCommon.tsx b/src/components/common/CollapseCommon/CollapseCommon.tsx new file mode 100644 index 000000000..e695a6576 --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseCommon.tsx @@ -0,0 +1,19 @@ +import CollapseChild from './CollapseChild/CollapseChild' + +interface CollapseCommonProps{ + data: {title: string, content: Array}[], +} + +const CollapseCommon = ({data}: CollapseCommonProps) => { + return ( +
    + { + data.map(item => + + ) + } +
    + ) +} + +export default CollapseCommon diff --git a/src/components/common/DrawerCommon/DrawerCommon.module.scss b/src/components/common/DrawerCommon/DrawerCommon.module.scss new file mode 100644 index 000000000..3253eac50 --- /dev/null +++ b/src/components/common/DrawerCommon/DrawerCommon.module.scss @@ -0,0 +1,52 @@ +@import "../../../styles/utilities"; + +.drawerCommon { + @apply fixed flex justify-end transition-all duration-200; + overflow: hidden; + top: 0; + right: 0; + height: 100vh; + width: 90%; + box-shadow: -3px 0 10px rgba(0, 0, 0, 0.15); + z-index: 20000; + + .inner { + @apply flex flex-col bg-white; + width: fit-content; + height: 100vh; + width: 100%; + margin-right: 0; + @screen md { + max-width: 55rem; + } + .top { + @apply flex justify-between items-center; + padding: 1.6rem; + .heading { + @apply sm-headline; + } + .iconClose { + @apply cursor-pointer transition-all duration-200; + &:hover { + svg path { + fill: var(--primary); + } + } + } + } + } + .content { + overflow-y: auto; + height: 100%; + } + &.hide { + transform: translateX(110%); + } + + @screen md { + width: unset; + .inner { + min-width: 48rem; + } + } +} diff --git a/src/components/common/DrawerCommon/DrawerCommon.tsx b/src/components/common/DrawerCommon/DrawerCommon.tsx new file mode 100644 index 000000000..deb1af3eb --- /dev/null +++ b/src/components/common/DrawerCommon/DrawerCommon.tsx @@ -0,0 +1,36 @@ +import React, { useRef } from 'react'; +import s from './DrawerCommon.module.scss'; +import classNames from 'classnames'; +import { IconClose } from 'src/components/icons'; + +interface Props { + visible: boolean + title?: string + children?: React.ReactNode + onClose: () => void +} + +const DrawerCommon = ({ title, visible, children, onClose }: Props) => { + return ( +
    +
    +
    +

    + {title} +

    +
    + +
    +
    +
    + {children} +
    +
    +
    + ) +} + +export default DrawerCommon; \ No newline at end of file diff --git a/src/components/common/Header/Header.tsx b/src/components/common/Header/Header.tsx index e9a06b9a8..a9926f765 100644 --- a/src/components/common/Header/Header.tsx +++ b/src/components/common/Header/Header.tsx @@ -1,6 +1,6 @@ import classNames from 'classnames' import React, { memo, useEffect, useState } from 'react' -import { useModalCommon } from 'src/components/hooks/useModalCommon' +import { useModalCommon } from 'src/components/hooks' import { isMobile } from 'src/utils/funtion.utils' import ModalAuthenticate from '../ModalAuthenticate/ModalAuthenticate' import ModalCreateUserInfo from '../ModalCreateUserInfo/ModalCreateUserInfo' diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss index a61c059e6..eaaabca70 100644 --- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss +++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss @@ -42,7 +42,7 @@ @apply hidden; @screen md { @apply flex items-center list-none; - li { + > li { @apply flex justify-center items-center w-full; &:not(:last-child) { margin-right: 4.8rem; @@ -52,13 +52,23 @@ } a { @appy no-underline; - &.iconFovourite { + &:hover { + opacity: 0.8; + } + &.iconFavourite { svg path { fill: var(--negative); } } } - + .btnCart { + &:hover { + svg path { + fill: var(--primary); + opacity: 0.8; + } + } + } } } } diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx index 969964608..05e0b38fa 100644 --- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx +++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx @@ -5,6 +5,7 @@ import InputSearch from 'src/components/common/InputSearch/InputSearch' import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown' import { IconBuy, IconHeart, IconHistory, IconUser } from 'src/components/icons' import { ACCOUNT_TAB, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils' +import Logo from '../../../Logo/Logo' import s from './HeaderMenu.module.scss' interface Props { @@ -39,7 +40,7 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
    -
    Online Grocery
    + @@ -51,14 +52,14 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
    • - +
    • - + @@ -67,7 +68,7 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
    • -
    • diff --git a/src/components/common/ImgWithLink/ImgWithLink.module.scss b/src/components/common/ImgWithLink/ImgWithLink.module.scss new file mode 100644 index 000000000..413f96cdb --- /dev/null +++ b/src/components/common/ImgWithLink/ImgWithLink.module.scss @@ -0,0 +1,9 @@ +.imgWithLink { + position: relative; + min-width: 5rem; + width: 100%; + height: 100%; + img { + object-fit: cover; + } +} diff --git a/src/components/common/ImgWithLink/ImgWithLink.tsx b/src/components/common/ImgWithLink/ImgWithLink.tsx new file mode 100644 index 000000000..092322085 --- /dev/null +++ b/src/components/common/ImgWithLink/ImgWithLink.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import s from './ImgWithLink.module.scss' +import Image from 'next/image' + +export interface ImgWithLinkProps { + src: string, + alt?: string, +} + +const ImgWithLink = ({ src, alt }: ImgWithLinkProps) => { + return ( +
      + {alt} +
      + ) +} + +export default ImgWithLink \ No newline at end of file diff --git a/src/components/common/Layout/Layout.tsx b/src/components/common/Layout/Layout.tsx index aa5da11e1..17f520185 100644 --- a/src/components/common/Layout/Layout.tsx +++ b/src/components/common/Layout/Layout.tsx @@ -1,6 +1,8 @@ import { CommerceProvider } from '@framework' import { useRouter } from 'next/router' import { FC } from 'react' +import { useModalCommon } from 'src/components/hooks' +import { CartDrawer } from '..' import Footer from '../Footer/Footer' import Header from '../Header/Header' import s from './Layout.module.scss' @@ -13,12 +15,24 @@ interface Props { // note: demo code const Layout: FC = ({ children }) => { const { locale = 'en-US' } = useRouter() + const { visible: visibleCartDrawer, openModal, closeModal: closeCartDrawer } = useModalCommon({ initialValue: false }) + const toggle = () => { + if (visibleCartDrawer) { + closeCartDrawer() + } else { + openModal() + } + } return (
      {children}
      + +
      diff --git a/src/components/common/ListProductWithInfo/InfoProducts/InfoProducts.module.scss b/src/components/common/ListProductWithInfo/InfoProducts/InfoProducts.module.scss new file mode 100644 index 000000000..c1cd9966e --- /dev/null +++ b/src/components/common/ListProductWithInfo/InfoProducts/InfoProducts.module.scss @@ -0,0 +1,23 @@ +@import "../../../../styles/utilities"; + +.infoProducts { + @apply flex justify-between items-center spacing-horizontal; + + .top { + .sub { + display: none; + } + } + @screen lg { + @apply block; + margin-right: 4rem; + padding: 0; + .top { + margin-bottom: 3.2rem; + .sub { + display: block; + margin-top: 0.4rem; + } + } + } +} diff --git a/src/components/common/ListProductWithInfo/InfoProducts/InfoProducts.tsx b/src/components/common/ListProductWithInfo/InfoProducts/InfoProducts.tsx new file mode 100644 index 000000000..25e18252c --- /dev/null +++ b/src/components/common/ListProductWithInfo/InfoProducts/InfoProducts.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { ROUTE } from 'src/utils/constanst.utils'; +import HeadingCommon from '../../HeadingCommon/HeadingCommon'; +import ViewAllItem from '../../ViewAllItem/ViewAllItem'; +import s from './InfoProducts.module.scss' +interface Props { + title: string, + subtitle?: string, +} + +const InfoProducts = ({ title, subtitle }: Props) => { + return ( +
      +
      + {title} +
      + {subtitle} +
      +
      + + +
      + ); +}; + +export default InfoProducts; \ No newline at end of file diff --git a/src/components/common/ListProductWithInfo/ListProductWithInfo.module.scss b/src/components/common/ListProductWithInfo/ListProductWithInfo.module.scss new file mode 100644 index 000000000..ddd8ed901 --- /dev/null +++ b/src/components/common/ListProductWithInfo/ListProductWithInfo.module.scss @@ -0,0 +1,48 @@ +@import "../../../styles/utilities"; + +.listProductWithInfo { + background-color: var(--background); + border-top: 1rem solid var(--gray); + border-bottom: 1rem solid var(--gray); + padding-top: 6rem; + padding-bottom: 6rem; + @screen lg { + @apply flex spacing-horizontal-left; + padding-top: 5.6rem; + padding-bottom: 5.6rem; + border: none; + background-color: var(--background-gray); + } + .productsWrap { + @apply spacing-horizontal-left; + @screen lg { + max-width: 75%; + @apply custom-border-radius-lg bg-white; + padding: 4rem .8rem; + :global(.customArrow) { + @screen lg { + &:global(.leftArrow) { + left: calc(-6.4rem + 3rem); + } + &:global(.rightArrow) { + right: calc(-6.4rem + 3rem); + } + } + } + } + @screen xl { + padding: 4rem 2.4rem; + max-width: 80%; + :global(.customArrow) { + @screen lg { + &:global(.leftArrow) { + left: calc(-6.4rem + 1rem); + } + &:global(.rightArrow) { + right: calc(-6.4rem + 1rem); + } + } + } + } + } +} diff --git a/src/components/common/ListProductWithInfo/ListProductWithInfo.tsx b/src/components/common/ListProductWithInfo/ListProductWithInfo.tsx new file mode 100644 index 000000000..66b8253d1 --- /dev/null +++ b/src/components/common/ListProductWithInfo/ListProductWithInfo.tsx @@ -0,0 +1,51 @@ +import { TOptionsEvents } from 'keen-slider'; +import React from 'react'; +import CarouselCommon from '../CarouselCommon/CarouselCommon'; +import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard'; +import InfoProducts from './InfoProducts/InfoProducts'; +import s from './ListProductWithInfo.module.scss'; + +interface Props { + data: ProductCardProps[], + title: string, + subtitle?: string, +} +const OPTION_DEFAULT: TOptionsEvents = { + slidesPerView: 2, + mode: 'free', + breakpoints: { + '(min-width: 640px)': { + slidesPerView: 3, + }, + '(min-width: 768px)': { + slidesPerView: 4, + }, + '(min-width: 1024px)': { + slidesPerView: 3, + }, + '(min-width: 1280px)': { + slidesPerView: 4.5, + }, + }, +} + +const ListProductWithInfo = ({ data, title, subtitle }: Props) => { + return ( +
      + +
      + + data={data} + Component={ProductCard} + itemKey={title} + option={OPTION_DEFAULT} + /> +
      +
      + ); +}; + +export default ListProductWithInfo; \ No newline at end of file diff --git a/src/components/common/Logo/Logo.module.scss b/src/components/common/Logo/Logo.module.scss index 2660c4880..da6bfc49f 100644 --- a/src/components/common/Logo/Logo.module.scss +++ b/src/components/common/Logo/Logo.module.scss @@ -1,7 +1,7 @@ -@import '../../../styles/utilities'; +@import "../../../styles/utilities"; .logo { - display: flex; + @apply flex justify-center items-center; .eclipse { width: 3.2rem; height: 3.2rem; @@ -10,9 +10,9 @@ margin-right: 1.2rem; } .content { - @apply font-logo; + @apply font-logo font-bold; font-size: 16px; line-height: 32px; letter-spacing: -0.02em; } -} \ No newline at end of file +} diff --git a/src/components/common/Logo/Logo.tsx b/src/components/common/Logo/Logo.tsx index 96d1820e0..58a0ea5de 100644 --- a/src/components/common/Logo/Logo.tsx +++ b/src/components/common/Logo/Logo.tsx @@ -1,14 +1,18 @@ import s from './Logo.module.scss' +import Link from 'next/link' +import { ROUTE } from 'src/utils/constanst.utils' const Logo = () => { - return( -
      -
      -
      -
      - ONLINE GROCERY -
      -
      + return ( + + +
      +
      +
      + ONLINE GROCERY +
      +
      + ) } diff --git a/src/components/common/MenuDropdown/MenuDropdown.module.scss b/src/components/common/MenuDropdown/MenuDropdown.module.scss index 8fc270b2a..5332794ff 100644 --- a/src/components/common/MenuDropdown/MenuDropdown.module.scss +++ b/src/components/common/MenuDropdown/MenuDropdown.module.scss @@ -17,10 +17,21 @@ } .label { + all: unset; @apply flex justify-end items-center transition-all duration-200; svg path { width: fit-content; } + &:focus, + &:active { + color: var(--primary); + svg path { + fill: currentColor; + } + } + &:focus-visible { + outline: 2px solid #000; + } } &.arrow { @@ -63,8 +74,9 @@ @apply rounded list-none bg-white; border: 1px solid var(--text-active); margin-top: 0.4rem; - li { + > li { @apply block w-full transition-all duration-200 cursor-pointer text-active; + white-space: nowrap; button { all: unset; color: currentColor; diff --git a/src/components/common/MenuDropdown/MenuDropdown.tsx b/src/components/common/MenuDropdown/MenuDropdown.tsx index bd3f0c851..ca25f22f8 100644 --- a/src/components/common/MenuDropdown/MenuDropdown.tsx +++ b/src/components/common/MenuDropdown/MenuDropdown.tsx @@ -16,9 +16,9 @@ const MenuDropdown = ({ options, children, isHasArrow = true, align }: Props) => [s.menuDropdown]: true, [s.arrow]: isHasArrow, })}> - +
      void +} + +const MenuFilter = ({heading,categories,type,onChangeValue}:Props)=> { + const [active, setActive] = useState(''); + + function handleClick(link:string){ + setActive(link); + + if(active === link){ + setActive(''); + } + } + + useEffect(()=>{ + + let href = active?.split("="); + const linkValue = href[1]; + + onChangeValue && onChangeValue({[type]:linkValue}); + },[active]) + + return ( +
      +

      {heading}

      +
        + { + categories.map(item =>
      • +
        handleClick(item.link)} className={classNames({ [s.active]: item.link === active? true: false })}> + {item.name} +
        +
      • ) + } +
      +
      + ) +} + +export default MenuFilter diff --git a/src/components/common/MenuNavigation/MenuNavigation.module.scss b/src/components/common/MenuNavigation/MenuNavigation.module.scss new file mode 100644 index 000000000..7535df707 --- /dev/null +++ b/src/components/common/MenuNavigation/MenuNavigation.module.scss @@ -0,0 +1,29 @@ +@import "../../../styles/utilities"; +.menuNavigationWrapper{ + .menuNavigationHeading{ + @screen md { + @apply sub-headline font-bold ; + color: var(--text-active); + font-feature-settings: 'salt' on; + margin: 1.6rem 0; + } + } + .menuNavigationList{ + @screen md { + li{ + margin: 0.8rem 0; + a{ + display:block; + width:100%; + color:var(--text-base); + &:hover { + @apply text-primary; + } + &.active { + @apply text-primary; + } + } + } + } + } +} diff --git a/src/components/common/MenuNavigation/MenuNavigation.tsx b/src/components/common/MenuNavigation/MenuNavigation.tsx new file mode 100644 index 000000000..4a8943051 --- /dev/null +++ b/src/components/common/MenuNavigation/MenuNavigation.tsx @@ -0,0 +1,34 @@ +import classNames from 'classnames' +import Link from 'next/link' +import { useRouter } from 'next/router' +import s from './MenuNavigation.module.scss' + +interface Props { + children?: any, + heading:string, + categories:{name:string,link:string}[] +} + +const MenuNavigation = ({heading,categories}:Props)=> { + const router = useRouter() + + return ( +
      +

      {heading}({categories.length})

      + +
      + ) +} + +export default MenuNavigation diff --git a/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss new file mode 100644 index 000000000..aa3f5e6c3 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss @@ -0,0 +1,45 @@ +@import "../../../styles/utilities"; +.menuNavigationProductListDesktop{ + @screen sm-only { + @apply hidden; + } +} +.menuNavigationProductListMobile{ + @apply hidden; + &.isShow{ + @apply block; + @screen md { + @apply hidden; + } + } + .menuNavigationProductModal{ + background: rgba(0, 0, 0, 0.5); + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + z-index: 10000; + .content{ + @apply spacing-horizontal; + margin-top: 3rem; + padding-top: 2rem ; + padding-bottom: 5rem; + background-color: white; + overflow: auto; + height: 100%; + border-radius: 2.4rem 2.4rem 0 0; + .head{ + @apply flex justify-between; + h3{ + @apply heading-3 font-bold; + color:var(--text-base); + } + } + button{ + margin-top: 2rem; + width: 100%; + } + } + } +} \ No newline at end of file diff --git a/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx new file mode 100644 index 000000000..d9ac2aa26 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx @@ -0,0 +1,60 @@ +import React, { useState } from 'react'; +import {ButtonCommon} from 'src/components/common'; +import s from './MenuNavigationProductList.module.scss'; +import MenuSort from './MenuSort/MenuSort'; +import {LANGUAGE} from 'src/utils/language.utils'; +import classNames from 'classnames' +import MenuFilter from '../MenuFilter/MenuFilter'; +import MenuNavigation from '../MenuNavigation/MenuNavigation'; +import IconHide from 'src/components/icons/IconHide'; + +interface Props{ + categories:{name:string,link:string}[], + brands:{name:string,link:string}[], + featured:{name:string,link:string}[], +} + +const MenuNavigationProductList = ({categories,brands,featured}:Props)=>{ + + const [dataSort,setDataSort] = useState({}); + const [isShow,setIsShow] = useState(true); + + function handleValue(value:Object){ + setDataSort({...dataSort,...value}); + } + function filter(){ + console.log(dataSort) + } + + function hideMenu(){ + if(isShow === true){ + setIsShow(false); + } + } + return( + <> +
      + + + +
      +
      +
      +
      +
      +

      FILTER

      +
      +
      + + + + + {LANGUAGE.BUTTON_LABEL.CONFIRM} +
      +
      +
      + + ) +} + +export default MenuNavigationProductList \ No newline at end of file diff --git a/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss new file mode 100644 index 000000000..a25752901 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss @@ -0,0 +1,46 @@ +@import "../../../../styles/utilities"; +.menuSortWrapper{ + + @screen md { + @apply hidden; + } + .menuSortHeading{ + @apply sub-headline font-bold ; + color: var(--text-active); + font-feature-settings: 'salt' on; + margin: 0.8rem 0; + } + .menuSortList{ + box-sizing: border-box; + &::after{ + @apply absolute; + top: 110%; + content: ""; + width: 100%; + border-bottom: 1px solid var(--border-line); + } + li{ + div{ + height: 4.8rem; + line-height: 4.8rem; + padding: 0 1.6rem; + margin-right: 0.8rem; + border-radius: 0.8rem; + &.active { + @apply font-bold relative; + color:var(--text-active); + background-color: var(--primary-lightest); + &::after{ + @apply absolute; + content:""; + background-image: url('/assets/svg/check.svg'); + right: 1.6rem; + top: calc(50% - 24px/2); + width: 2.4rem; + height: 2.4rem; + } + } + } + } + } +} diff --git a/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx new file mode 100644 index 000000000..2e66dfc83 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx @@ -0,0 +1,67 @@ +import classNames from 'classnames'; +import { useEffect, useState } from 'react'; +import { QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'; +import s from './MenuSort.module.scss'; + +interface Props { + children?: any, + heading:string, + type:string, + onChangeValue?: (value: Object) => void +} +const SORT = [ + { + name: 'By Name', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=by-name`, + }, + { + name: 'Price(High to Low)', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=high-to-low`, + }, + { + name: 'Price (Low to High)', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=low-to-high`, + }, + { + name: 'On Sale', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=on-sale`, + }, + ]; + + +const MenuSort = ({heading,type,onChangeValue}:Props)=> { + const [active, setActive] = useState(''); + + function handleClick(link:string){ + setActive(link); + + if(active === link){ + setActive(''); + } + } + + useEffect(()=>{ + + let href = active?.split("="); + const linkValue = href[1]; + + onChangeValue && onChangeValue({[type]:linkValue}); + },[active]) + + return ( +
      +

      {heading}

      +
        + { + SORT.map(item =>
      • +
        handleClick(item.link)} className={classNames({ [s.active]: item.link === active? true: false })}> + {item.name} +
        +
      • ) + } +
      +
      + ) +} + +export default MenuSort diff --git a/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx b/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx index bedb993f4..b1059a441 100644 --- a/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx +++ b/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx @@ -1,7 +1,6 @@ import Link from 'next/link' import React, { useEffect, useRef } from 'react' -import { ButtonCommon, Inputcommon } from 'src/components/common' -import InputPassword from 'src/components/common/InputPassword/InputPassword' +import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common' import { ROUTE } from 'src/utils/constanst.utils' import { CustomInputCommon } from 'src/utils/type.utils' import s from '../FormAuthen.module.scss' diff --git a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx index d03dbc39e..66ec1f8a4 100644 --- a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx +++ b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef } from 'react' -import { ButtonCommon, Inputcommon } from 'src/components/common' +import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common' import s from '../FormAuthen.module.scss' import styles from './FormRegister.module.scss' import SocialAuthen from '../SocialAuthen/SocialAuthen' diff --git a/src/components/common/PaginationCommon/PaginationCommon.tsx b/src/components/common/PaginationCommon/PaginationCommon.tsx index d0df5efe7..540771729 100644 --- a/src/components/common/PaginationCommon/PaginationCommon.tsx +++ b/src/components/common/PaginationCommon/PaginationCommon.tsx @@ -1,18 +1,19 @@ import classNames from 'classnames' import React, { useEffect, useState } from 'react' import { ArrowLeftSmall, ArrowRightSmall } from 'src/components/icons' +import { DEFAULT_PAGE_SIZE } from 'src/utils/constanst.utils' import PaginationItem from './components/PaginationItem' import s from './PaginationCommon.module.scss' interface PaginationCommonProps { defaultCurrent?: number - pageSize: number + pageSize?: number total: number onChange?: (page: number, pageSize: number) => void } const PaginationCommon = ({ total, - pageSize, + pageSize=DEFAULT_PAGE_SIZE, defaultCurrent, onChange, }: PaginationCommonProps) => { diff --git a/src/components/common/ProductCard/ProductCard.module.scss b/src/components/common/ProductCard/ProductCard.module.scss index 65e81c811..cffbe063b 100644 --- a/src/components/common/ProductCard/ProductCard.module.scss +++ b/src/components/common/ProductCard/ProductCard.module.scss @@ -2,8 +2,12 @@ max-width: 20.8rem; min-height: 31.8rem; padding: 1.2rem 1.2rem 0 1.2rem; + margin: auto; margin-bottom: 1px; @apply flex flex-col justify-between; + &.notSell { + @apply justify-center; + } .cardTop{ @apply relative; height: 13.8rem; @@ -29,8 +33,6 @@ .cardMidTop{ .productname{ font-weight: bold; - line-height: 2.4rem; - font-size: 1.6rem; color: var(--text-active); &:hover{ cursor: pointer; diff --git a/src/components/common/ProductCard/ProductCard.tsx b/src/components/common/ProductCard/ProductCard.tsx index 7d94be6bc..4f1e3b329 100644 --- a/src/components/common/ProductCard/ProductCard.tsx +++ b/src/components/common/ProductCard/ProductCard.tsx @@ -6,6 +6,7 @@ import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy' import ItemWishList from '../ItemWishList/ItemWishList' import LabelCommon from '../LabelCommon/LabelCommon' import s from './ProductCard.module.scss' +import ProductNotSell from './ProductNotSell/ProductNotSell' export interface ProductCardProps extends ProductProps { buttonText?: string @@ -18,7 +19,15 @@ const ProductCard = ({ price, buttonText = 'Buy Now', imageSrc, + isNotSell, }: ProductCardProps) => { + if (isNotSell) { + return
      + +
      + + } + return (
      diff --git a/src/components/common/ProductCard/ProductNotSell/ProductNotSell.module.scss b/src/components/common/ProductCard/ProductNotSell/ProductNotSell.module.scss new file mode 100644 index 000000000..4945220a9 --- /dev/null +++ b/src/components/common/ProductCard/ProductNotSell/ProductNotSell.module.scss @@ -0,0 +1,27 @@ +@import "../../../../styles/utilities"; + +.imgWrap { + img { + opacity: 0.5; + } +} + +.name { + @apply text-label cursor-default font-bold; +} + +.info { + @apply flex justify-center items-center custom-border-radius bg-info-light text-center; + padding: .8rem 1.6rem; + margin-top: 1.6rem; + color: var(--info); + svg { + @apply u-icon; + path { + fill: currentColor; + } + } + .text { + margin-left: 0.8rem; + } +} diff --git a/src/components/common/ProductCard/ProductNotSell/ProductNotSell.tsx b/src/components/common/ProductCard/ProductNotSell/ProductNotSell.tsx new file mode 100644 index 000000000..f87d87c43 --- /dev/null +++ b/src/components/common/ProductCard/ProductNotSell/ProductNotSell.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { IconInfo } from 'src/components/icons'; +import ImgWithLink from '../../ImgWithLink/ImgWithLink'; +import s from './ProductNotSell.module.scss'; + +export interface Props { + name: string, + imageSrc: string, +} + +const ProductNotSell = ({ name, imageSrc }: Props) => { + return ( + <> +
      + +
      +
      {name}
      +
      + +
      + Not Sell +
      +
      + + ); +}; + +export default ProductNotSell; \ No newline at end of file diff --git a/src/components/common/QuanittyInput/QuanittyInput.tsx b/src/components/common/QuanittyInput/QuanittyInput.tsx index a01f16fe7..20baba9ea 100644 --- a/src/components/common/QuanittyInput/QuanittyInput.tsx +++ b/src/components/common/QuanittyInput/QuanittyInput.tsx @@ -1,7 +1,7 @@ import React, { ChangeEvent, useEffect, useState } from 'react' import s from './QuanittyInput.module.scss' import classNames from 'classnames' -import { Minus, Plus } from '@components/icons' +import { IconMinus, IconPlus } from '../../icons' interface QuanittyInputProps extends Omit< React.InputHTMLAttributes, @@ -64,7 +64,7 @@ const QuanittyInput = ({ return (
      - +
      - +
      ) diff --git a/src/components/common/RecipeCard/RecipeCard.module.scss b/src/components/common/RecipeCard/RecipeCard.module.scss index 1fd6fd65e..19f3eb76a 100644 --- a/src/components/common/RecipeCard/RecipeCard.module.scss +++ b/src/components/common/RecipeCard/RecipeCard.module.scss @@ -6,6 +6,9 @@ width: 100%; max-height: 22rem; border-radius: 2.4rem; + img { + border-radius: 2.4rem; + } &:hover{ cursor: pointer; } diff --git a/components/ui/Rating/Rating.module.css b/src/components/common/RecipeDetail/RecipeDetail.module.scss similarity index 100% rename from components/ui/Rating/Rating.module.css rename to src/components/common/RecipeDetail/RecipeDetail.module.scss diff --git a/src/components/common/RecipeDetail/RecipeDetail.tsx b/src/components/common/RecipeDetail/RecipeDetail.tsx new file mode 100644 index 000000000..cdec99994 --- /dev/null +++ b/src/components/common/RecipeDetail/RecipeDetail.tsx @@ -0,0 +1,23 @@ +import React from 'react' +import { ProductCardProps } from '../ProductCard/ProductCard' +import RecipeDetailInfo from './components/RecipeDetailInfo/RecipeDetailInfo' +import RecipeIngredient from './components/RecipeIngredient/RecipeIngredient' +import s from './RecipeDetail.module.scss' + + +interface Props { + className?: string + children?: any, + ingredients: ProductCardProps[], +} + +const RecipeDetail = ({ ingredients }: Props) => { + return ( +
      + + +
      + ) +} + +export default RecipeDetail diff --git a/src/components/common/RecipeDetail/components/RecipeBriefInfo/RecipeBriefInfo.module.scss b/src/components/common/RecipeDetail/components/RecipeBriefInfo/RecipeBriefInfo.module.scss new file mode 100644 index 000000000..56f1e6500 --- /dev/null +++ b/src/components/common/RecipeDetail/components/RecipeBriefInfo/RecipeBriefInfo.module.scss @@ -0,0 +1,19 @@ +.recipeBriefInfo { + @apply flex; + .item { + @apply flex; + &:not(:last-child) { + margin-right: 2.4rem; + } + svg { + width: 2rem; + height: 2rem; + path { + fill: var(--text-label); + } + } + .content { + margin-left: 0.8rem; + } + } +} diff --git a/src/components/common/RecipeDetail/components/RecipeBriefInfo/RecipeBriefInfo.tsx b/src/components/common/RecipeDetail/components/RecipeBriefInfo/RecipeBriefInfo.tsx new file mode 100644 index 000000000..d06387914 --- /dev/null +++ b/src/components/common/RecipeDetail/components/RecipeBriefInfo/RecipeBriefInfo.tsx @@ -0,0 +1,29 @@ +import React from 'react' +import { IconLocation, IconPeople, IconTime } from 'src/components/icons' +import s from './RecipeBriefInfo.module.scss' + +interface Props { + className?: string + children?: any, +} + +const RecipeBriefInfo = ({ }: Props) => { + return ( +
      +
      + +
      15 minutes
      +
      +
      + +
      4 People
      +
      +
      + +
      15 minutes
      +
      +
      + ) +} + +export default RecipeBriefInfo diff --git a/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.module.scss b/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.module.scss new file mode 100644 index 000000000..86b525083 --- /dev/null +++ b/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.module.scss @@ -0,0 +1,61 @@ +@import "../../../../../styles/utilities"; + +.recipeDetailInfo { + @apply spacing-horizontal; + margin: 5.6rem auto; + @screen md { + @apply flex; + } + .img { + width: fit-content; + margin-top: 0; + + @screen sm-only { + margin-bottom: 2rem; + } + @screen lg { + max-width: 60rem; + } + img { + @apply w-full; + object-fit: contain; + max-height: 64rem; + border-radius: 2.4rem; + @screen md { + max-height: 90rem; + } + } + } + + .recipeInfo { + @screen md { + max-width: 39rem; + margin-left: 4.8rem; + } + @screen lg { + margin-left: 11.2rem; + } + .top { + margin-bottom: 4.8rem; + .name { + @apply heading-1 font-heading; + margin-bottom: 1.6rem; + } + } + .detail { + .item { + &:not(:last-child) { + margin-bottom: 2.4rem; + } + .heading { + @apply heading-3 font-heading; + margin-bottom: 0.8rem; + } + .content { + list-style: disc; + margin-left: 2rem; + } + } + } + } +} diff --git a/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.tsx b/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.tsx new file mode 100644 index 000000000..4d212e10a --- /dev/null +++ b/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import RecipeBriefInfo from '../RecipeBriefInfo/RecipeBriefInfo' +import s from './RecipeDetailInfo.module.scss' + + +interface Props { + className?: string + children?: any +} + +const RecipeDetailInfo = ({ }: Props) => { + return ( +
      +
      + Recipe +
      +
      +
      +

      + Crispy Fried Calamari +

      + +
      +
      +
      +

      Ingredients

      +
        +
      • Canola oil for frying
      • +
      • 1 pound clean squid bodies cut in 1/4 inch rings and dried with a paper towel
      • +
      • 2 cups flour
      • +
      • 1/2 teaspoon kosher salt
      • +
      • 1/2 teaspoon garlic powder
      • +
      • 1/8 teaspoon coarse ground black pepper
      • +
      • 1 lemon cut into wedges
      • +
      +
      + +
      +

      Preparation

      +
        +
      • 1In a large pot or dutch oven add three inches of oil and bring to 350 degrees.
      • +
      • Add the flour, salt, garlic powder and pepper to a large bowl and stir to combine.
      • +
      • Toss the squid pieces in the flour then into the hot oil.
      • +
      • Fry the squid for 1-2 minutes. You want the color to stay pale like in the pictures.
      • +
      • Remove to a cookie sheet to drain (do not add paper towels as it will steam the calamari and make it soft.)
      • +
      • Serve with lemon wedges.
      • +
      +
      + +
      +
      +
      + ) +} + +export default RecipeDetailInfo diff --git a/src/components/common/RecipeDetail/components/RecipeIngredient/RecipeIngredient.module.scss b/src/components/common/RecipeDetail/components/RecipeIngredient/RecipeIngredient.module.scss new file mode 100644 index 000000000..b1419699d --- /dev/null +++ b/src/components/common/RecipeDetail/components/RecipeIngredient/RecipeIngredient.module.scss @@ -0,0 +1,21 @@ +@import "../../../../../styles/utilities"; + +.recipeIngredient { + padding: 6rem 0; + @screen md { + padding: 5.6rem 0; + } + .top { + @apply flex justify-between items-center spacing-horizontal; + } + .bottom { + @apply flex justify-center items-center spacing-horizontal; + margin-top: 4rem; + button { + width: 100%; + @screen md { + width: 39rem; + } + } + } +} diff --git a/src/components/common/RecipeDetail/components/RecipeIngredient/RecipeIngredient.tsx b/src/components/common/RecipeDetail/components/RecipeIngredient/RecipeIngredient.tsx new file mode 100644 index 000000000..a879f0b72 --- /dev/null +++ b/src/components/common/RecipeDetail/components/RecipeIngredient/RecipeIngredient.tsx @@ -0,0 +1,33 @@ +import React from 'react' +import ButtonCommon from 'src/components/common/ButtonCommon/ButtonCommon' +import HeadingCommon from 'src/components/common/HeadingCommon/HeadingCommon' +import { ProductCardProps } from 'src/components/common/ProductCard/ProductCard' +import ProductCarousel from 'src/components/common/ProductCarousel/ProductCarousel' +import ViewAllItem from 'src/components/common/ViewAllItem/ViewAllItem' +import { ROUTE } from 'src/utils/constanst.utils' +import s from './RecipeIngredient.module.scss' + +interface Props { + className?: string + children?: any, + data: ProductCardProps[], +} + +const RecipeIngredient = ({ data }: Props) => { + return ( +
      +
      + Ingredients +
      + +
      +
      + +
      + Buy all +
      +
      + ) +} + +export default RecipeIngredient diff --git a/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.module.scss b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.module.scss new file mode 100644 index 000000000..6179a6aed --- /dev/null +++ b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.module.scss @@ -0,0 +1,16 @@ +@import '../../../../styles/utilities'; +.blogCardWarpper { + @apply spacing-horizontal; + @screen xl { + :global(.customArrow) { + @screen lg { + &:global(.leftArrow) { + left: calc(-6.4rem - 2rem); + } + &:global(.rightArrow) { + right: calc(-6.4rem - 2rem); + } + } + } + } +} diff --git a/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.tsx b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.tsx new file mode 100644 index 000000000..396d42d07 --- /dev/null +++ b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.tsx @@ -0,0 +1,46 @@ +import { TOptionsEvents } from 'keen-slider' +import React from 'react' +import CarouselCommon, { + CarouselCommonProps, +} from '../../CarouselCommon/CarouselCommon' +import BlogCard, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog' +import s from "./BlogPostCarousel.module.scss" + +interface BlogPostCarouselProps + extends Omit, 'Component'|"option"> { + option?:TOptionsEvents + } + +const OPTION_DEFAULT: TOptionsEvents = { + slidesPerView: 1.25, + mode: 'free', + spacing:24, + breakpoints: { + '(min-width: 640px)': { + slidesPerView: 2, + }, + '(min-width: 1024px)': { + slidesPerView: 2.5, + }, + '(min-width: 1440px)': { + slidesPerView: 3, + }, + '(min-width: 1536px)': { + slidesPerView: 3.5, + }, + }, +} +const BlogPostCarousel = ({ option, data, ...props }: BlogPostCarouselProps) => { + return ( +
      + + data={data} + Component={BlogCard} + {...props} + option={{ ...OPTION_DEFAULT, ...option }} + /> +
      + ) +} + +export default BlogPostCarousel diff --git a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss new file mode 100644 index 000000000..ed232830f --- /dev/null +++ b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss @@ -0,0 +1,19 @@ +@import '../../../styles/utilities'; + +.blogPostWarpper { + &.cream{ + background-color: #F5F4F2; + } + padding-top: 5.6rem; + padding-bottom: 5.2rem; + @apply flex flex-col; + .top { + @apply spacing-horizontal flex w-full justify-between; + padding-bottom: 3.2rem; + @screen xl { + .right { + margin-right: 2.476rem; + } + } + } +} diff --git a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx new file mode 100644 index 000000000..1d71a6ca1 --- /dev/null +++ b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx @@ -0,0 +1,75 @@ +import image15 from '../../../../public/assets/images/image15.png' +import image16 from '../../../../public/assets/images/image16.png' +import image17 from '../../../../public/assets/images/image17.png' +import classNames from 'classnames' +import React from 'react' +import { HeadingCommon, ViewAllItem } from 'src/components/common' +import { BlogCardProps } from 'src/components/common/CardBlog/CardBlog' +import BlogPostCarousel from './BlogPostCarousel/BlogPostCarousel' +import s from './RelevantBlogPosts.module.scss' +import { ROUTE } from 'src/utils/constanst.utils'; + +interface RelevantProps { + data?: BlogCardProps[], + itemKey?: string, + title?: string, + viewAllLink?: string, + bgcolor?: "default" | "cream" +} + +const recipe:BlogCardProps[] = [ +{ + title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners", + slug: 'have-a-nice-lunch', + description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...", + imageSrc: image15.src, +},{ + title: "9 Ways to Make an Aloe Vera Mask at Home", + slug: 'have-a-nice-lunch', + description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + imageSrc: image16.src, +},{ + title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit", + slug: 'have-a-nice-lunch', + description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + imageSrc: image17.src, +},{ + title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners", + slug: 'have-a-nice-lunch', + description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...", + imageSrc: image15.src, +},{ + title: "9 Ways to Make an Aloe Vera Mask at Home", + slug: 'have-a-nice-lunch', + description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + imageSrc: image16.src, +},{ + title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit", + slug: 'have-a-nice-lunch', + description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + imageSrc: image17.src, +}] + + const RelevantBlogPosts = ({ data = recipe, itemKey="detail-relevant", title="Relevant Blog Posts", bgcolor = "default" }: RelevantProps) => { + return ( +
      +
      +
      + {title} +
      +
      + +
      +
      +
      + +
      +
      + ) + } + + export default RelevantBlogPosts \ No newline at end of file diff --git a/src/components/common/ScrollToTop/ScrollTarget.tsx b/src/components/common/ScrollToTop/ScrollTarget.tsx deleted file mode 100644 index 50a839c83..000000000 --- a/src/components/common/ScrollToTop/ScrollTarget.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { MutableRefObject } from 'react' - -interface ScrollTargetProps { - refScrollUp: MutableRefObject; -} - -const ScrollTarget = ({ refScrollUp } : ScrollTargetProps) => { - - return ( -
      - ) - -} - -export default ScrollTarget diff --git a/src/components/common/ScrollToTop/ScrollToTop.tsx b/src/components/common/ScrollToTop/ScrollToTop.tsx index 98e16168d..d148c8937 100644 --- a/src/components/common/ScrollToTop/ScrollToTop.tsx +++ b/src/components/common/ScrollToTop/ScrollToTop.tsx @@ -5,11 +5,10 @@ import s from './ScrollToTop.module.scss' import ArrowUp from '../../icons/IconArrowUp' interface ScrollToTopProps { - target: MutableRefObject; visibilityHeight?: number; } -const ScrollToTop = ({ target, visibilityHeight=450 }: ScrollToTopProps) => { +const ScrollToTop = ({ visibilityHeight=450 }: ScrollToTopProps) => { const [scrollPosition, setSrollPosition] = useState(0); const [showScrollToTop, setShowScrollToTop] = useState("hide"); @@ -26,7 +25,7 @@ const ScrollToTop = ({ target, visibilityHeight=450 }: ScrollToTopProps) => { }; function handleScrollUp() { - target.current.scrollIntoView({ behavior: "smooth" }); + window.scrollTo(0, 0); } function addEventScroll() { @@ -34,7 +33,7 @@ const ScrollToTop = ({ target, visibilityHeight=450 }: ScrollToTopProps) => { } useEffect(() => { - addEventScroll() + addEventScroll(); }); return ( diff --git a/src/components/common/SelectCommon/SelectCommon.module.scss b/src/components/common/SelectCommon/SelectCommon.module.scss index d91b1831e..4809a46bb 100644 --- a/src/components/common/SelectCommon/SelectCommon.module.scss +++ b/src/components/common/SelectCommon/SelectCommon.module.scss @@ -1,69 +1,90 @@ @import "../../../styles/utilities"; -.select{ +.select { background-color: var(--white); - &.base{ + .selectTrigger { + svg { + @apply transition-all duration-200; + } + } + &.base { width: 20.6rem; - .selectTrigger{ + .selectTrigger { width: 20.6rem; padding: 1.2rem 1.6rem; } } - &.large{ + &.large { width: 34.25rem; - .selectTrigger{ + .selectTrigger { width: 34.25rem; padding: 1.6rem 1.6rem; } } - &.default{ - .selectTrigger{ + &.default { + .selectTrigger { @apply border-solid border border-current; - } + } } - &.custom{ - .selectTrigger{ + &.custom { + .selectTrigger { @apply border-2; border-color: var(--border-line); color: var(--text-label); } } - &.isActive{ - .selectOptionWrapper{ + &:hover { + cursor: pointer; + .hoverWrapper { @apply block; + animation: SelectAnimation 0.2s ease-out; + } + .selectTrigger { + svg { + transform: rotate(180deg); + } } } } -.selectTrigger{ +.selectTrigger { @apply outline-none flex justify-between; color: var(--text-active); border-radius: 0.8rem; - } -.selectOptionWrapper{ - @apply outline-none hidden z-10 absolute; - border-radius: 0.8rem; - background-color: var(--white); - padding: 0.4rem 0rem 0.4rem 0rem; - margin-top: 0.6rem; - &.base{ - width: 20.6rem; +.hoverWrapper { + @apply hidden outline-none absolute z-10; + padding-top: 0.6rem; + .selectOptionWrapper { + border-radius: 0.8rem; + background-color: var(--white); + padding: 0.4rem 0rem 0.4rem 0rem; + &.base { + width: 20.6rem; + } + &.large { + width: 34.25rem; + } + &.default { + @apply border-solid border border-current; + } + &.custom { + @apply border-2; + border-color: var(--border-line); + color: var(--text-label); + } } - &.large{ - width: 34.25rem; - } - &.default{ - @apply border-solid border border-current; - } - &.custom{ - @apply border-2; - border-color: var(--border-line); - color: var(--text-label); - } - &.active{ - @apply hidden; + &:hover { + @apply block; } } - - +@keyframes SelectAnimation { + 0% { + opacity: 0; + transform: translateY(1.6rem); + } + 100% { + opacity: 1; + transform: none; + } +} diff --git a/src/components/common/SelectCommon/SelectCommon.tsx b/src/components/common/SelectCommon/SelectCommon.tsx index 5bb3d15d6..9b8c88e24 100644 --- a/src/components/common/SelectCommon/SelectCommon.tsx +++ b/src/components/common/SelectCommon/SelectCommon.tsx @@ -1,43 +1,25 @@ import s from './SelectCommon.module.scss' import classNames from 'classnames' -import { useState, useRef, useEffect } from 'react' +import { useState } from 'react' import { IconVectorDown } from 'src/components/icons' import SelectOption from './SelectOption/SelectOption' interface Props { - children? : React.ReactNode, + placeholder? : string, size?: 'base' | 'large', type?: 'default' | 'custom', - option: {name: string}[], + option: {name: string, value: string}[], + onChange?: (value: string) => void, } -const SelectCommon = ({ type = 'default', size = 'base', option, children }: Props) => { - const [isActive, setActive] = useState(false) - const [selectedName, setSelectedName] = useState(children) - const ref = useRef(null) - - useEffect(() => { - const handleClick = (event: MouseEvent) => { - const { target } = event; - if (!ref?.current || ref?.current.contains(target as Node)) { - return - } - else{ - setActive(false) - } - } - document.addEventListener('click', handleClick) - return () => { - document.removeEventListener('click', handleClick) - } - }, [ref]) +const SelectCommon = ({ type = 'default', size = 'base', option, placeholder, onChange}: Props) => { + const [selectedName, setSelectedName] = useState(placeholder) + const [selectedValue, setSelectedValue] = useState('') - const changeActiveStatus = () => { - setActive(!isActive) - } - - const changeSelectedName = (item:string) => { + const changeSelectedName = (item:string, value: string) => { + setSelectedValue(value) setSelectedName(item) + onChange && onChange(value) } return( <> @@ -45,29 +27,29 @@ const SelectCommon = ({ type = 'default', size = 'base', option, children }: Pro [s.select] : true, [s[size]] : !!size, [s[type]] : !!type, - [s.isActive] : isActive, })} - onClick = { changeActiveStatus } - ref = {ref} >
      {selectedName}
      - -
      - { - option.map(item => - - ) - } + +
      +
      + { + option.map(item => + + ) + } +
      +
      ) diff --git a/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss b/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss index 5448f9879..ef504c112 100644 --- a/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss +++ b/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss @@ -13,5 +13,9 @@ } &:hover{ background-color: var(--gray); + color: var(--primary); + } + &.isChoose{ + background-color: var(--gray); } } \ No newline at end of file diff --git a/src/components/common/SelectCommon/SelectOption/SelectOption.tsx b/src/components/common/SelectCommon/SelectOption/SelectOption.tsx index 54877d5fe..7e1968f9e 100644 --- a/src/components/common/SelectCommon/SelectOption/SelectOption.tsx +++ b/src/components/common/SelectCommon/SelectOption/SelectOption.tsx @@ -2,20 +2,22 @@ import s from './SelectOption.module.scss' import classNames from 'classnames' interface Props{ - onClick: (value: string) => void, + onClick: (name: string, value: string) => void, itemName: string, size: 'base' | 'large', + value: string, + selected?: boolean, } -const SelectOption = ({onClick, itemName, size}: Props) => { - +const SelectOption = ({onClick, itemName, size, value, selected} : Props) => { const changeName = () => { - onClick(itemName) + onClick(itemName, value) } return(
      {itemName}
      diff --git a/src/components/common/ViewAllItem/ViewAllItem.module.scss b/src/components/common/ViewAllItem/ViewAllItem.module.scss index 4b8b6fe6d..b4ec26872 100644 --- a/src/components/common/ViewAllItem/ViewAllItem.module.scss +++ b/src/components/common/ViewAllItem/ViewAllItem.module.scss @@ -4,7 +4,7 @@ display: flex; .content { color: var(--primary); - margin: 0.8rem 0.8rem 0.8rem 1.6rem; + margin: 0.8rem 0.8rem 0.8rem 0; font-weight: bold; } .vector { diff --git a/src/components/common/index.ts b/src/components/common/index.ts index f3d73ad96..56896f790 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -19,7 +19,6 @@ export { default as DateTime} from './DateTime/DateTime' export { default as HeadingCommon } from './HeadingCommon/HeadingCommon' export { default as CollectionHeading } from './CollectionHeading/CollectionHeading' export { default as ScrollToTop } from './ScrollToTop/ScrollToTop' -export { default as ScrollTarget } from './ScrollToTop/ScrollTarget' export { default as InputSearch} from './InputSearch/InputSearch' export { default as ButtonIconBuy} from './ButtonIconBuy/ButtonIconBuy' export { default as Banner} from './Banner/Banner' @@ -33,3 +32,10 @@ export { default as ModalConfirm} from "./ModalConfirm/ModalConfirm" export { default as ModalInfo} from "./ModalInfo/ModalInfo" export { default as ProductList} from "./ProductList/ProductList" export { default as ModalCreateUserInfo} from './ModalCreateUserInfo/ModalCreateUserInfo' +export { default as CardBlog} from './CardBlog/CardBlog' +export { default as RelevantBlogPosts} from './RelevantBlogPosts/RelevantBlogPosts' +export { default as CollapseCommon} from './CollapseCommon/CollapseCommon' +export { default as ImgWithLink} from './ImgWithLink/ImgWithLink' +export { default as RecipeDetail} from './RecipeDetail/RecipeDetail' +export { default as DrawerCommon} from './DrawerCommon/DrawerCommon' +export { default as CartDrawer} from './CartDrawer/CartDrawer' diff --git a/src/components/hooks/index.ts b/src/components/hooks/index.ts new file mode 100644 index 000000000..cf83feb42 --- /dev/null +++ b/src/components/hooks/index.ts @@ -0,0 +1 @@ +export { default as useModalCommon } from './useModalCommon' diff --git a/src/components/hooks/useModalCommon.tsx b/src/components/hooks/useModalCommon.tsx index 02626ce94..41aed648f 100644 --- a/src/components/hooks/useModalCommon.tsx +++ b/src/components/hooks/useModalCommon.tsx @@ -4,7 +4,7 @@ interface Props { initialValue?: boolean, } -export const useModalCommon = ({ initialValue = false }: Props) => { +const useModalCommon = ({ initialValue = false }: Props) => { const [visible, setVisible] = useState(initialValue) const openModal = (e?: any) => { @@ -21,3 +21,5 @@ export const useModalCommon = ({ initialValue = false }: Props) => { visible, openModal, closeModal } }; + +export default useModalCommon \ No newline at end of file diff --git a/src/components/icons/IconArrowUp.tsx b/src/components/icons/IconArrowUp.tsx index 3eac6391b..1f518d612 100644 --- a/src/components/icons/IconArrowUp.tsx +++ b/src/components/icons/IconArrowUp.tsx @@ -2,7 +2,7 @@ const ArrowUp = () => { return ( - + ) } diff --git a/src/components/icons/IconClose.tsx b/src/components/icons/IconClose.tsx new file mode 100644 index 000000000..018ee8cd6 --- /dev/null +++ b/src/components/icons/IconClose.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +const IconClose = () => { + return ( + + + + ) +} + +export default IconClose diff --git a/src/components/icons/IconDelete.tsx b/src/components/icons/IconDelete.tsx new file mode 100644 index 000000000..4daff3f80 --- /dev/null +++ b/src/components/icons/IconDelete.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconDelete = () => { + return ( + + + + ) +} + +export default IconDelete diff --git a/src/components/icons/IconHide.tsx b/src/components/icons/IconHide.tsx new file mode 100644 index 000000000..a977aff84 --- /dev/null +++ b/src/components/icons/IconHide.tsx @@ -0,0 +1,12 @@ +import React from 'react' + +const IconHide = () => { + return ( + + + + + ) +} + +export default IconHide diff --git a/src/components/icons/IconLocation.tsx b/src/components/icons/IconLocation.tsx new file mode 100644 index 000000000..3dc0a81b9 --- /dev/null +++ b/src/components/icons/IconLocation.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconLocation = () => { + return ( + + + + ) +} + +export default IconLocation diff --git a/src/components/icons/Minus.tsx b/src/components/icons/IconMinus.tsx similarity index 94% rename from src/components/icons/Minus.tsx rename to src/components/icons/IconMinus.tsx index 7c3b97d30..abf3a2907 100644 --- a/src/components/icons/Minus.tsx +++ b/src/components/icons/IconMinus.tsx @@ -1,4 +1,4 @@ -const ArrowRight = ({ ...props }) => { +const IconMinus = ({ ...props }) => { return ( { ) } -export default ArrowRight +export default IconMinus diff --git a/src/components/icons/IconPeople.tsx b/src/components/icons/IconPeople.tsx new file mode 100644 index 000000000..0075b0f75 --- /dev/null +++ b/src/components/icons/IconPeople.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconPeople = () => { + return ( + + + + ) +} + +export default IconPeople diff --git a/src/components/icons/Plus.tsx b/src/components/icons/IconPlus.tsx similarity index 91% rename from src/components/icons/Plus.tsx rename to src/components/icons/IconPlus.tsx index c8b2fcca3..63d6d2dd4 100644 --- a/src/components/icons/Plus.tsx +++ b/src/components/icons/IconPlus.tsx @@ -1,4 +1,4 @@ -const ArrowLeft = ({ ...props }) => { +const IconPlus = ({ ...props }) => { return ( { ) } -export default ArrowLeft +export default IconPlus diff --git a/src/components/icons/IconTime.tsx b/src/components/icons/IconTime.tsx new file mode 100644 index 000000000..81064df9d --- /dev/null +++ b/src/components/icons/IconTime.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconTime = () => { + return ( + + + + ) +} + +export default IconTime diff --git a/src/components/icons/IconVectorDown.tsx b/src/components/icons/IconVectorDown.tsx index 019fc2806..0bb1cb8c1 100644 --- a/src/components/icons/IconVectorDown.tsx +++ b/src/components/icons/IconVectorDown.tsx @@ -1,5 +1,3 @@ - - const IconVectorDown = ({ ...props }) => { return ( div { + @apply w-full h-full custom-border-radius-lg; + } + img { + object-fit: cover; + } + } .text { @apply relative font-heading text-center; diff --git a/src/components/modules/home/HomeBanner/HomeBanner.tsx b/src/components/modules/home/HomeBanner/HomeBanner.tsx index 2a3a632fb..18432ec82 100644 --- a/src/components/modules/home/HomeBanner/HomeBanner.tsx +++ b/src/components/modules/home/HomeBanner/HomeBanner.tsx @@ -1,8 +1,9 @@ import React from 'react' import { Banner } from 'src/components/common' -import s from './HomeBanner.module.scss' import BannerImgRight from './assets/banner_full.png' -import BannerImgRight2 from './assets/banner_product.png' +import HomeBannerImg from './assets/home_banner.png' +import s from './HomeBanner.module.scss' +import Image from 'next/image' interface Props { className?: string @@ -13,6 +14,9 @@ const HomeBanner = ({ }: Props) => { return (
      +
      + +
      Freshness
      guaranteed
      @@ -28,10 +32,10 @@ const HomeBanner = ({ }: Props) => { { title: "Save 15% on your first order 2", subtitle: "Last call! Shop deep deals on 100+ bulk picks while you can.", - imgLink: BannerImgRight2.src, + imgLink: BannerImgRight.src, size: "small", } - ] + ] } />
      diff --git a/src/components/modules/home/HomeBanner/assets/banner_product.png b/src/components/modules/home/HomeBanner/assets/banner_product.png deleted file mode 100644 index 82f1b7fee..000000000 Binary files a/src/components/modules/home/HomeBanner/assets/banner_product.png and /dev/null differ diff --git a/src/components/modules/home/HomeVideo/assets/bg_left.svg b/src/components/modules/home/HomeVideo/assets/bg_left.svg index d730f777d..74b215ae0 100644 --- a/src/components/modules/home/HomeVideo/assets/bg_left.svg +++ b/src/components/modules/home/HomeVideo/assets/bg_left.svg @@ -1,19 +1,19 @@ - - + + - - + + - - + + diff --git a/src/components/modules/home/HomeVideo/assets/bg_right.svg b/src/components/modules/home/HomeVideo/assets/bg_right.svg index e89652a3a..346d14e31 100644 --- a/src/components/modules/home/HomeVideo/assets/bg_right.svg +++ b/src/components/modules/home/HomeVideo/assets/bg_right.svg @@ -1,21 +1,21 @@ - - + + - - + + - - + + diff --git a/src/components/modules/product-detail/ProductInfoDetail/ProductInfoDetail.module.scss b/src/components/modules/product-detail/ProductInfoDetail/ProductInfoDetail.module.scss new file mode 100644 index 000000000..645ff7259 --- /dev/null +++ b/src/components/modules/product-detail/ProductInfoDetail/ProductInfoDetail.module.scss @@ -0,0 +1,10 @@ +@import '../../../../styles/utilities'; + +.productInfoDetail { + @apply spacing-horizontal; + padding-bottom: 4rem; + @screen md { + @apply flex; + padding-bottom: 5.6rem; + } +} \ No newline at end of file diff --git a/src/components/modules/product-detail/ProductInfoDetail/ProductInfoDetail.tsx b/src/components/modules/product-detail/ProductInfoDetail/ProductInfoDetail.tsx new file mode 100644 index 000000000..d1047bd3a --- /dev/null +++ b/src/components/modules/product-detail/ProductInfoDetail/ProductInfoDetail.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import ProductImgs from './components/ProductImgs/ProductImgs' +import ProductInfo from './components/ProductInfo/ProductInfo' +import s from './ProductInfoDetail.module.scss' + +interface Props { + className?: string + children?: any +} + +const ProductInfoDetail = ({ }: Props) => { + return ( +
      + + +
      + ) +} + +export default ProductInfoDetail diff --git a/src/components/modules/product-detail/ProductInfoDetail/components/ProductImgs/ProductImgs.module.scss b/src/components/modules/product-detail/ProductInfoDetail/components/ProductImgs/ProductImgs.module.scss new file mode 100644 index 000000000..a10eb5865 --- /dev/null +++ b/src/components/modules/product-detail/ProductInfoDetail/components/ProductImgs/ProductImgs.module.scss @@ -0,0 +1,9 @@ +.productImgs { + @apply w-full flex justify-between items-center; + @screen sm-only { + margin-bottom: 2rem; + } + @screen lg { + max-width: 60rem; + } +} diff --git a/src/components/modules/product-detail/ProductInfoDetail/components/ProductImgs/ProductImgs.tsx b/src/components/modules/product-detail/ProductInfoDetail/components/ProductImgs/ProductImgs.tsx new file mode 100644 index 000000000..325c6b453 --- /dev/null +++ b/src/components/modules/product-detail/ProductInfoDetail/components/ProductImgs/ProductImgs.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import { CarouselCommon, ImgWithLink } from 'src/components/common' +import { ImgWithLinkProps } from 'src/components/common/ImgWithLink/ImgWithLink' +import s from './ProductImgs.module.scss' + +interface Props { + className?: string + children?: any, +} + +const DATA = [ + { + src: 'https://user-images.githubusercontent.com/76729908/130574371-3b75fa72-9552-4605-aba9-a4b31cd9dce7.png', + alt: 'Broccoli', + }, + { + src: 'https://user-images.githubusercontent.com/76729908/130574371-3b75fa72-9552-4605-aba9-a4b31cd9dce7.png', + alt: 'Broccoli', + } +] + +const option = { + slidesPerView: 1, +} + +const ProductImgs = ({ }: Props) => { + return ( +
      + + data={DATA} + itemKey="product-detail-img" + Component={ImgWithLink} + option={option} + isDot={true} + /> +
      + ) +} + +export default ProductImgs diff --git a/src/components/modules/product-detail/ProductInfoDetail/components/ProductInfo/ProductInfo.module.scss b/src/components/modules/product-detail/ProductInfoDetail/components/ProductInfo/ProductInfo.module.scss new file mode 100644 index 000000000..403782c51 --- /dev/null +++ b/src/components/modules/product-detail/ProductInfoDetail/components/ProductInfo/ProductInfo.module.scss @@ -0,0 +1,81 @@ +@import "../../../../../../styles/utilities"; + +.productInfo { + @screen md { + max-width: 39rem; + margin-left: 4.8rem; + } + @screen lg { + margin-left: 11.2rem; + } + .info { + margin-bottom: 3.2rem; + .heading { + @apply heading-2 font-heading; + margin-top: 0.8rem; + } + .price { + margin-top: 0.8rem; + .old { + margin-bottom: 0.8rem; + .number { + margin-right: 0.8rem; + color: var(--text-label); + text-decoration: line-through; + } + } + .current { + @apply text-active font-bold sm-headline; + } + } + .description { + margin-top: 0.8rem; + } + } + .actions { + @screen sm-only { + @apply fixed flex justify-between items-center bg-white w-full; + z-index: 10000; + bottom: 0; + left: 0; + padding: 2rem; + } + } + .bottom { + @screen sm-only { + @apply flex justify-between items-center flex-row-reverse; + margin-left: 1rem; + flex: 1; + button { + &:first-child { + min-width: 13rem; + } + &:nth-child(n + 1) { + margin-left: 0.8rem; + } + } + } + .buttonWithIcon { + @apply flex items-center; + .label { + @apply hidden; + @screen md { + @apply inline-block; + margin-left: 0.8rem; + } + } + } + button { + @apply w-full; + } + + @screen md { + margin-top: 2.4rem; + button { + &:first-child { + margin-bottom: 0.8rem; + } + } + } + } +} diff --git a/src/components/modules/product-detail/ProductInfoDetail/components/ProductInfo/ProductInfo.tsx b/src/components/modules/product-detail/ProductInfoDetail/components/ProductInfo/ProductInfo.tsx new file mode 100644 index 000000000..4abb62568 --- /dev/null +++ b/src/components/modules/product-detail/ProductInfoDetail/components/ProductInfo/ProductInfo.tsx @@ -0,0 +1,46 @@ +import React from 'react' +import { ButtonCommon, LabelCommon, QuanittyInput } from 'src/components/common' +import { IconBuy } from 'src/components/icons' +import { LANGUAGE } from 'src/utils/language.utils' +import s from './ProductInfo.module.scss' + +interface Props { + className?: string + children?: any, +} + +const ProductInfo = ({ }: Props) => { + return ( +
      +
      + SEAFOOD +

      SeaPAk

      +
      +
      + Rp 32.000 + -15% +
      +
      Rp 27.500
      +
      +
      + In a large non-reactive dish, mix together the orange juice, soy sauce, olive oil, lemon juice, parsley +
      +
      +
      + +
      + {/* {LANGUAGE.BUTTON_LABEL.PREORDER} */} + {LANGUAGE.BUTTON_LABEL.BUY_NOW} + + + + {LANGUAGE.BUTTON_LABEL.ADD_TO_CARD} + + +
      +
      +
      + ) +} + +export default ProductInfo diff --git a/src/components/modules/product-detail/RecommendedRecipes/RecommendedRecipes.module.scss b/src/components/modules/product-detail/RecommendedRecipes/RecommendedRecipes.module.scss new file mode 100644 index 000000000..d43e2d58c --- /dev/null +++ b/src/components/modules/product-detail/RecommendedRecipes/RecommendedRecipes.module.scss @@ -0,0 +1,27 @@ +@import "../../../../styles/utilities"; + +.recommendedRecipes { + margin: 6rem auto; + @screen md { + margin: 5.6rem auto; + } + .infoProducts { + @apply flex justify-between items-center spacing-horizontal; + margin-bottom: 3.2rem; + } + .productsWrap { + @apply spacing-horizontal-left; + @screen xl { + :global(.customArrow) { + @screen lg { + &:global(.leftArrow) { + left: calc(-6.4rem - 2rem); + } + &:global(.rightArrow) { + right: calc(-6.4rem - 2rem); + } + } + } + } + } +} diff --git a/src/components/modules/product-detail/RecommendedRecipes/RecommendedRecipes.tsx b/src/components/modules/product-detail/RecommendedRecipes/RecommendedRecipes.tsx new file mode 100644 index 000000000..34950fbab --- /dev/null +++ b/src/components/modules/product-detail/RecommendedRecipes/RecommendedRecipes.tsx @@ -0,0 +1,51 @@ +import { TOptionsEvents } from 'keen-slider'; +import React from 'react'; +import { CarouselCommon, HeadingCommon, RecipeCard, ViewAllItem } from 'src/components/common'; +import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard'; +import { ROUTE } from 'src/utils/constanst.utils'; +import s from './RecommendedRecipes.module.scss'; + +const OPTION_DEFAULT: TOptionsEvents = { + slidesPerView: 1.25, + mode: 'free', + spacing: 24, + breakpoints: { + '(min-width: 640px)': { + slidesPerView: 2, + }, + '(min-width: 1024px)': { + slidesPerView: 2.5, + }, + '(min-width: 1440px)': { + slidesPerView: 3, + }, + '(min-width: 1536px)': { + slidesPerView: 3.5, + }, + }, +} + +interface Props { + data: RecipeCardProps[], +} + +const RecommendedRecipes = ({ data }: Props) => { + return ( +
      +
      + Recommended Recipes + +
      +
      + + data={data} + Component={RecipeCard} + itemKey="Recommended Recipes" + option={OPTION_DEFAULT} + /> +
      +
      + ); +}; + +export default RecommendedRecipes; \ No newline at end of file diff --git a/src/components/modules/product-detail/ReleventProducts/ReleventProducts.tsx b/src/components/modules/product-detail/ReleventProducts/ReleventProducts.tsx new file mode 100644 index 000000000..e11d31065 --- /dev/null +++ b/src/components/modules/product-detail/ReleventProducts/ReleventProducts.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import ListProductWithInfo from 'src/components/common/ListProductWithInfo/ListProductWithInfo'; +import { PRODUCT_DATA_TEST } from 'src/utils/demo-data'; + +const ReleventProducts = () => { + return ( + + ); +}; + +export default ReleventProducts; \ No newline at end of file diff --git a/src/components/modules/product-detail/ViewedProducts/ViewedProducts.tsx b/src/components/modules/product-detail/ViewedProducts/ViewedProducts.tsx new file mode 100644 index 000000000..820af402f --- /dev/null +++ b/src/components/modules/product-detail/ViewedProducts/ViewedProducts.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import ListProductWithInfo from 'src/components/common/ListProductWithInfo/ListProductWithInfo'; +import { PRODUCT_DATA_TEST } from 'src/utils/demo-data'; + +const ViewedProducts = () => { + return ( + + ); +}; + +export default ViewedProducts; \ No newline at end of file diff --git a/src/components/modules/product-detail/index.ts b/src/components/modules/product-detail/index.ts new file mode 100644 index 000000000..ef4461432 --- /dev/null +++ b/src/components/modules/product-detail/index.ts @@ -0,0 +1,4 @@ +export { default as ProductInfoDetail } from './ProductInfoDetail/ProductInfoDetail' +export { default as ViewedProducts } from './ViewedProducts/ViewedProducts' +export { default as ReleventProducts } from './ReleventProducts/ReleventProducts' +export { default as RecommendedRecipes } from './RecommendedRecipes/RecommendedRecipes' diff --git a/src/styles/_base.scss b/src/styles/_base.scss index 67eb96726..e8719581f 100644 --- a/src/styles/_base.scss +++ b/src/styles/_base.scss @@ -6,7 +6,7 @@ --primary-lightest: #effaf4; --info-dark: #00317a; - --info: #297fff; + --info: #3468B7; --info-border-line: #d6e7ff; --info-light: #ebf3ff; @@ -21,7 +21,7 @@ --warning-light: #fef8eb; --negative-dark: #741a06; - --negative: #f34f2b; + --negative: #D1644D; --negative-border-line: #fddfd8; --negative-light: #feefec; @@ -33,6 +33,7 @@ --disabled: #cccccc; --border-line: #ebebeb; --background: #fff; + --background-gray: #F5F4F2; --gray: #f8f8f8; --white: #fff; --background-arrow:rgba(20, 20, 20, 0.05); @@ -79,5 +80,5 @@ html { } a { - -webkit-tap-highlight-color: var(--text-active); + -webkit-tap-highlight-color: var(--primary); } diff --git a/src/styles/_utilities.scss b/src/styles/_utilities.scss index 26cea17c0..6b919de76 100644 --- a/src/styles/_utilities.scss +++ b/src/styles/_utilities.scss @@ -120,6 +120,25 @@ font-family: var(--font-logo); } + .custom-scroll { + overflow-y: auto; + &::-webkit-scrollbar-track { + background-color: var(--background-gray); + border-radius: 10px; + } + + &::-webkit-scrollbar { + border-radius: 10px; + width: 6px; + background-color: var(--background-gray); + } + + &::-webkit-scrollbar-thumb { + border-radius: 10px; + background-color: var(--primary) + } + } + .u-form { .body { > div { @@ -130,6 +149,7 @@ .line { @apply flex justify-between items-center; > div { + flex: 1; &:not(:last-child) { margin-right: 1.6rem; } @@ -137,4 +157,9 @@ } } } + + .u-icon { + width: 2rem; + height: 2rem; + } } diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index c7002a730..1522e477f 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -8,9 +8,11 @@ export const SOCIAL_LINKS = { export const ROUTE = { HOME: '/', PRODUCTS: '/products', + PRODUCT_DETAIL: '/product', ABOUT: '/about', + BLOG_DETAIL: '/blog', ACCOUNT: '/account', - + RECIPES: '/recipes', BUSSINESS: '/bussiness', CONTACT: '/contact', FAQ: '/faq', @@ -31,7 +33,9 @@ export const QUERY_KEY = { TAB: 'tab', CATEGORY: 'category', BRAND: 'brand', - FEATURED: 'feature' + FEATURED: 'feature', + SORTBY:'sortby', + RECIPES:'recipes' } export enum ProductFeature { @@ -39,10 +43,11 @@ export enum ProductFeature { Sales = 'Sales', NewItem = 'New Item', Viewed = 'Viewed', - } export const KEY = { ENTER: 'Enter', } +export const OPTION_ALL = 'all'; +export const DEFAULT_PAGE_SIZE=20 \ No newline at end of file diff --git a/src/utils/demo-data.ts b/src/utils/demo-data.ts new file mode 100644 index 000000000..64c8128ae --- /dev/null +++ b/src/utils/demo-data.ts @@ -0,0 +1,215 @@ +import { RecipeCardProps } from "src/components/common/RecipeCard/RecipeCard" + +export const PRODUCT_DATA_TEST = [ + { + name: 'Tomato', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646211-d56b77ac-83f1-4dd2-b55c-e3f1e0ba4e49.png", + }, + { + name: 'Cucumber', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646211-d56b77ac-83f1-4dd2-b55c-e3f1e0ba4e49.png", + }, + { + name: 'Carrot', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646217-23b86160-45c9-4845-8dcc-b3e1a4483edd.png", + }, + { + name: 'Salad', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646221-aaa1d48d-bb80-470f-9400-ae2aa47285b6.png", + }, + { + name: 'Tomato', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646224-d22dc2e4-6ae8-4bbe-adcf-491ce191f09b.png", + }, + { + name: 'Cucumber', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646225-2728f192-481b-4142-99b0-dde92f53c6c6.png", + }, + { + name: 'Tomato', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646227-b5705e64-3b45-47a3-9433-9f4b5ee8d40c.png", + }, + { + name: 'Cucumber', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646231-2d1c3ad1-4f5b-4a8e-9874-ca731f4ce128.png", + }, +] + +export const PRODUCT_CART_DATA_TEST = [ + { + name: 'Tomato', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646211-d56b77ac-83f1-4dd2-b55c-e3f1e0ba4e49.png", + oldPrice: 'Rp 32.000', + discount: '15%', + quantity: 1, + }, + { + name: 'Cucumber', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646211-d56b77ac-83f1-4dd2-b55c-e3f1e0ba4e49.png", + oldPrice: 'Rp 32.000', + discount: '15%', + quantity: 2, + }, + { + name: 'Carrot', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646217-23b86160-45c9-4845-8dcc-b3e1a4483edd.png", + oldPrice: 'Rp 32.000', + discount: '20%', + quantity: 3, + }, + { + name: 'Salad', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646221-aaa1d48d-bb80-470f-9400-ae2aa47285b6.png", + quantity: 1, + }, +] + +export const INGREDIENT_DATA_TEST = [ + { + name: 'Tomato', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646211-d56b77ac-83f1-4dd2-b55c-e3f1e0ba4e49.png", + }, + { + name: 'Cucumber', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646211-d56b77ac-83f1-4dd2-b55c-e3f1e0ba4e49.png", + isNotSell: true, + }, + { + name: 'Carrot', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646217-23b86160-45c9-4845-8dcc-b3e1a4483edd.png", + }, + { + name: 'Salad', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646221-aaa1d48d-bb80-470f-9400-ae2aa47285b6.png", + isNotSell: true, + }, + { + name: 'Tomato', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646224-d22dc2e4-6ae8-4bbe-adcf-491ce191f09b.png", + }, + { + name: 'Cucumber', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646225-2728f192-481b-4142-99b0-dde92f53c6c6.png", + }, + { + name: 'Tomato', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646227-b5705e64-3b45-47a3-9433-9f4b5ee8d40c.png", + }, + { + name: 'Cucumber', + slug: 'tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646231-2d1c3ad1-4f5b-4a8e-9874-ca731f4ce128.png", + }, +] + +export const RECIPE_DATA_TEST: RecipeCardProps[] = [ + { + title: "Special Recipe of Vietnamese Phở", + description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png' + }, + { + title: "Original Recipe of Curry", + description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png' + }, + { + title: "The Best Recipe of Beef Noodle Soup", + description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png' + }, + { + title: "Special Recipe of Vietnamese Phở", + description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png' + }, + { + title: "Original Recipe of Curry", + description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png' + }, + { + title: "The Best Recipe of Beef Noodle Soup", + description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png' + }, +] \ No newline at end of file diff --git a/src/utils/language.utils.ts b/src/utils/language.utils.ts index 3f8d61926..8b3d8f8d5 100644 --- a/src/utils/language.utils.ts +++ b/src/utils/language.utils.ts @@ -2,6 +2,9 @@ export const LANGUAGE = { BUTTON_LABEL: { BUY_NOW: 'Buy now', SHOP_NOW: 'Shop now', + CONFIRM:'Confirm', + ADD_TO_CARD: 'Add to Cart', + PREORDER: 'Pre-Order Now', }, PLACE_HOLDER: { SEARCH: 'Search', diff --git a/src/utils/types.utils.ts b/src/utils/types.utils.ts index 2c99df73a..d6f1b47ad 100644 --- a/src/utils/types.utils.ts +++ b/src/utils/types.utils.ts @@ -1,9 +1,13 @@ export interface ProductProps { - category: string + category?: string name: string + slug: string weight: string price: string + oldPrice?: string + discount?: string imageSrc: string + isNotSell?: boolean } export interface FeaturedProductProps { @@ -16,7 +20,14 @@ export interface FeaturedProductProps { export interface RecipeProps { title: string - description:string + description: string + imageSrc: string +} + +export interface BlogProps { + title: string + slug: string + description: string imageSrc: string } diff --git a/tailwind.config.js b/tailwind.config.js index 028e78f05..69ab1ade5 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -47,19 +47,20 @@ module.exports = { 'line': 'var(--border-line)', 'background': 'var(--background)', + 'background-gray': 'var(--background-gray)', 'white': 'var(--white)', - 'background-arrow':'var(--background-arrow)', + 'background-arrow': 'var(--background-arrow)', + - 'disabled': 'var(--text-disabled)', line: 'var(--border-line)', background: 'var(--background)', white: 'var(--white)', gray: 'var(--gray)', disabled: 'var(--text-disabled)', - 'background-arrow':'var(--background-arrow)', - + 'background-arrow': 'var(--background-arrow)', + // @deprecated (NOT use these variables) 'primary-2': 'var(--primary-2)', secondary: 'var(--secondary)', @@ -93,7 +94,7 @@ module.exports = { label: 'var(--text-label)', placeholder: 'var(--text-placeholder)', primary: 'var(--primary)', - + // @deprecated (NOT use these variables) secondary: 'var(--text-secondary)', }, @@ -112,9 +113,11 @@ module.exports = { 'sm-only': {'min': '0', 'max': '767px'}, 'sm': '640px', // => @media (min-width: 640px) { ... } + 'md-only': {'min': '768px', 'max': '1023px'}, 'md': '768px', // => @media (min-width: 768px) { ... } + 'lg-only': {'min': '1024px', 'max': '1279px'}, 'lg': '1024px', // => @media (min-width: 1024px) { ... } @@ -125,8 +128,8 @@ module.exports = { '2xl': '1536px', // => @media (min-width: 1536px) { ... } }, - caroucel:{ - "arrow-height":"64px" + caroucel: { + "arrow-height": "64px" }, }, },