-
Order summary
- {/* ПОМЕНЯТЬ ВСЕ ЦЕН НА ЗНАЧЕНИЯ ФОРМЫ, тк иначе сложно обновлять значения независимо из разных мест */}
-
-
-
subtotal:
-
{orderData?.subtotal?.value}
+
+
remember me
+
-
-
shipping price:
- {/* to-do pass shipping price */}
-
- {orderData?.promo?.freeShipping
- ? 0
- : dictionary?.shipmentCarriers?.find(
- (c) => c.id + "" === shipmentCarrierId,
- )?.shipmentCarrier?.price?.value || 0}
+
+
+
+
Order summary
+ {/* ПОМЕНЯТЬ ВСЕ ЦЕН НА ЗНАЧЕНИЯ ФОРМЫ, тк иначе сложно обновлять значения независимо из разных мест */}
+
+
+
subtotal:
+
{orderData?.subtotal?.value}
-
- {!!orderData?.promo?.discount?.value && (
-
discount:
-
{orderData?.promo?.discount?.value}%
+
shipping price:
+ {/* to-do pass shipping price */}
+
+ {orderData?.promo?.freeShipping
+ ? 0
+ : dictionary?.shipmentCarriers?.find(
+ (c) => c.id + "" === shipmentCarrierId,
+ )?.shipmentCarrier?.price?.value || 0}
+
+
+ {!!orderData?.promo?.discount?.value && (
+
+
discount:
+
{orderData?.promo?.discount?.value}%
+
+ )}
+
+
+
grand total:
+
{orderData?.totalSale?.value}
- )}
-
-
-
grand total:
-
{orderData?.totalSale?.value}
-
-
+
+ {newOrderStripeToken && (
+ <>
+
{newOrderStripeToken}
+
+ >
+ )}
+ >
);
}
diff --git a/src/components/forms/NewOrderForm/schema.ts b/src/components/forms/NewOrderForm/schema.ts
index 78a2c722..06ed7882 100644
--- a/src/components/forms/NewOrderForm/schema.ts
+++ b/src/components/forms/NewOrderForm/schema.ts
@@ -12,6 +12,13 @@ const addressFields = {
postalCode: z.string().min(2),
};
+// const creditCardFields = {
+// number: z.string().length(19),
+// fullName: z.string().min(3),
+// expirationDate: z.string().length(5),
+// cvc: z.string().length(3),
+// };
+
const baseCheckoutSchema = z.object({
email: z.string().email(),
phone: z.string().min(5),
@@ -27,30 +34,16 @@ const baseCheckoutSchema = z.object({
billingAddress: z.object(addressFields).optional(),
rememberMe: z.boolean().optional(),
+ paymentMethod: z.union([
+ z.literal("PAYMENT_METHOD_NAME_ENUM_ETH"),
+ z.literal("PAYMENT_METHOD_NAME_ENUM_USDT_TRON"),
+ z.literal("PAYMENT_METHOD_NAME_ENUM_USDT_SHASTA"),
+ z.literal("PAYMENT_METHOD_NAME_ENUM_CARD_TEST"),
+ z.literal("PAYMENT_METHOD_NAME_ENUM_CARD"),
+ ]),
});
-export const checkoutSchema = z.discriminatedUnion("paymentMethod", [
- baseCheckoutSchema.extend({
- paymentMethod: z.literal("PAYMENT_METHOD_NAME_ENUM_ETH"),
- }),
- baseCheckoutSchema.extend({
- paymentMethod: z.literal("PAYMENT_METHOD_NAME_ENUM_USDT_TRON"),
- }),
- baseCheckoutSchema.extend({
- paymentMethod: z.literal("PAYMENT_METHOD_NAME_ENUM_USDT_SHASTA"),
- }),
- baseCheckoutSchema.extend({
- paymentMethod: z.literal("PAYMENT_METHOD_NAME_ENUM_CARD"),
- creditCard: z.object({
- // todo: add validation of the mask
- // reuse same mask constant for inout and for schema
- number: z.string().length(19),
- fullName: z.string().min(3),
- expirationDate: z.string().length(5),
- cvc: z.string().length(3),
- }),
- }),
-]);
+export const checkoutSchema = baseCheckoutSchema;
export const defaultData: z.infer
= {
email: "",
@@ -69,13 +62,13 @@ export const defaultData: z.infer = {
subscribe: false,
billingAddressIsSameAsAddress: true,
billingAddress: undefined,
- paymentMethod: "PAYMENT_METHOD_NAME_ENUM_CARD",
- creditCard: {
- number: "",
- fullName: "",
- expirationDate: "",
- cvc: "",
- },
+ paymentMethod: "PAYMENT_METHOD_NAME_ENUM_CARD_TEST",
+ // creditCard: {
+ // number: "4242424242424242",
+ // fullName: "wdwd wdwd",
+ // expirationDate: "11/30",
+ // cvc: "122",
+ // },
rememberMe: false, // todo: groom the feature
promoCode: "",
};
diff --git a/src/components/forms/NewOrderForm/utils.tsx b/src/components/forms/NewOrderForm/utils.tsx
index aab00e40..5b55db05 100644
--- a/src/components/forms/NewOrderForm/utils.tsx
+++ b/src/components/forms/NewOrderForm/utils.tsx
@@ -16,7 +16,8 @@ export function mapFormFieldToOrderDataFormat(
company: data.company,
city: data.city,
state: data.state,
- country: data.country,
+ // country: data.country,
+ country: "US",
postalCode: data.postalCode,
};
@@ -30,7 +31,8 @@ export function mapFormFieldToOrderDataFormat(
company: data.billingAddress.company,
city: data.billingAddress.city,
state: data.billingAddress.state,
- country: data.billingAddress.country,
+ country: "US",
+ // country: data.billingAddress.country,
postalCode: data.billingAddress.postalCode,
}
: undefined;
diff --git a/src/components/forms/NewslatterForm.tsx b/src/components/forms/NewslatterForm.tsx
index 0025d6b6..51618692 100644
--- a/src/components/forms/NewslatterForm.tsx
+++ b/src/components/forms/NewslatterForm.tsx
@@ -33,7 +33,7 @@ export default function NewslatterForm({ formSubmitClick }: FooterFormProps) {
name="email"
/>
-
+
);
}
diff --git a/src/components/forms/StripeSecureCardForm/CheckoutForm.tsx b/src/components/forms/StripeSecureCardForm/CheckoutForm.tsx
new file mode 100644
index 00000000..b8b03b45
--- /dev/null
+++ b/src/components/forms/StripeSecureCardForm/CheckoutForm.tsx
@@ -0,0 +1,55 @@
+import {
+ useStripe,
+ useElements,
+ CardNumberElement,
+ CardExpiryElement,
+ CardCvcElement,
+ CardElement,
+} from "@stripe/react-stripe-js";
+
+export default function CheckoutForm({
+ clientSecret,
+}: {
+ clientSecret: string;
+}) {
+ const stripe = useStripe();
+ const elements = useElements();
+
+ const handleSubmit = async (event: any) => {
+ // We don't want to let default form submission happen here,
+ // which would refresh the page.
+ event.preventDefault();
+
+ if (!stripe || !elements) {
+ // Stripe.js hasn't yet loaded.
+ // Make sure to disable form submission until Stripe.js has loaded.
+ return;
+ }
+
+ const { error, paymentIntent } = await stripe.confirmCardPayment(
+ clientSecret,
+ {
+ payment_method: {
+ card: elements.getElement(CardElement) as any,
+ billing_details: {
+ name: "Customer Name",
+ email: "customer@example.com",
+ },
+ },
+ },
+ );
+
+ console.log(`stripe response:-0--0`);
+ console.log({ error, paymentIntent });
+ };
+
+ return (
+
+ );
+}
diff --git a/src/components/forms/StripeSecureCardForm/index.tsx b/src/components/forms/StripeSecureCardForm/index.tsx
new file mode 100644
index 00000000..1a2378c2
--- /dev/null
+++ b/src/components/forms/StripeSecureCardForm/index.tsx
@@ -0,0 +1,28 @@
+"use client";
+
+import { Elements } from "@stripe/react-stripe-js";
+import { loadStripe } from "@stripe/stripe-js";
+
+import CheckoutForm from "./CheckoutForm";
+// Make sure to call `loadStripe` outside of a component’s render to avoid
+// recreating the `Stripe` object on every render.
+const stripePromise = loadStripe(
+ "pk_test_51PQqJsP97IsmiR4DHmNimxWDeAAMhzOww6NNyrvYKyqW0nsRPKbfivB8M2gzeSJSgJktys1EWbHNfaqvvqDv5Mlq00rjie9vDF",
+);
+
+export default function StripeSecureCardForm({
+ clientSecret,
+}: {
+ clientSecret: string;
+}) {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/forms/SubmitButton.tsx b/src/components/forms/SubmitButton.tsx
index abdae93f..b420f765 100644
--- a/src/components/forms/SubmitButton.tsx
+++ b/src/components/forms/SubmitButton.tsx
@@ -2,22 +2,23 @@
// @ts-ignore
import { useFormStatus } from "react-dom";
-import Button from "@/components/ui/Button";
-import { ButtonStyle } from "@/components/ui/Button/styles";
+import { Button } from "@/components/ui/Button";
type Props = {
text: string;
disabled?: boolean;
};
-export function SubmitButton({ text, disabled }: Props) {
+export function SubmitButton({ text, disabled = false }: Props) {
const { pending } = useFormStatus();
return (
diff --git a/src/components/layouts/CheckoutLayout.tsx b/src/components/layouts/CheckoutLayout.tsx
new file mode 100644
index 00000000..de5297fb
--- /dev/null
+++ b/src/components/layouts/CheckoutLayout.tsx
@@ -0,0 +1,27 @@
+import { Elements } from "@stripe/react-stripe-js";
+import CheckoutForm from "../forms/StripeSecureCardForm/CheckoutForm";
+import { loadStripe } from "@stripe/stripe-js";
+
+// recreating the `Stripe` object on every render.
+const stripePromise = loadStripe(
+ "pk_test_51PQqJsP97IsmiR4DHmNimxWDeAAMhzOww6NNyrvYKyqW0nsRPKbfivB8M2gzeSJSgJktys1EWbHNfaqvvqDv5Mlq00rjie9vDF",
+);
+
+export default function CheckoutLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/components/layouts/HeroContextLayout.tsx b/src/components/layouts/CommonLayout.tsx
similarity index 50%
rename from src/components/layouts/HeroContextLayout.tsx
rename to src/components/layouts/CommonLayout.tsx
index 707c7732..2e397862 100644
--- a/src/components/layouts/HeroContextLayout.tsx
+++ b/src/components/layouts/CommonLayout.tsx
@@ -1,12 +1,16 @@
-import { serviceClient } from "@/lib/api";
-import { HeroContextProvider } from "@/components/contexts/HeroContext";
-
type Props = {
children: React.ReactNode;
};
-export default async function Layout({ children }: Props) {
+import { serviceClient } from "@/lib/api";
+import { HeroContextProvider } from "@/components/contexts/HeroContext";
+
+export async function CommonLayout({ children }: Props) {
const heroData = await serviceClient.GetHero({});
- return
{children};
+ return (
+
+ {children}
+
+ );
}
diff --git a/src/components/layouts/CoreLayout.tsx b/src/components/layouts/NavigationLayout.tsx
similarity index 55%
rename from src/components/layouts/CoreLayout.tsx
rename to src/components/layouts/NavigationLayout.tsx
index 0f41386a..1f956aa3 100644
--- a/src/components/layouts/CoreLayout.tsx
+++ b/src/components/layouts/NavigationLayout.tsx
@@ -3,25 +3,22 @@ import CartProductsList from "@/components/sections/Cart/CartProductsList";
import TotalPrice from "@/components/sections/Cart/TotalPrice";
import Footer from "@/components/sections/Footer";
import Header from "@/components/sections/Header";
-import Button from "@/components/ui/Button";
-import { ButtonStyle } from "@/components/ui/Button/styles";
+import { Button } from "@/components/ui/Button";
import { getCookieCart } from "@/lib/utils/cart";
import Link from "next/link";
import { Suspense } from "react";
-export default function CoreLayout({
+export default function NavigationLayout({
children,
hideForm,
- hidePopupCart,
}: Readonly<{
children: React.ReactNode;
hideForm?: boolean;
- hidePopupCart?: boolean;
}>) {
const cartData = getCookieCart();
const hasCartProducts =
cartData?.products && Object.keys(cartData?.products).length > 0;
- const productsNumber = Object.keys(cartData?.products || {}).length;
+ const itemsQuantity = Object.keys(cartData?.products || {}).length;
return (
@@ -30,13 +27,13 @@ export default function CoreLayout({
@@ -49,30 +46,19 @@ export default function CoreLayout({
diff --git a/src/components/layouts/RootLayout.tsx b/src/components/layouts/RootLayout.tsx
deleted file mode 100644
index 14d0fe40..00000000
--- a/src/components/layouts/RootLayout.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Toaster } from "sonner";
-
-type Props = {
- children: React.ReactNode;
-};
-
-export default function RootLayout({ children }: Props) {
- // add header to this layout (invoices page)
- return (
-
-
- {children}
-
- );
-}
diff --git a/src/components/sections/Cart/CartItemRow.tsx b/src/components/sections/Cart/CartItemRow.tsx
index b12c1e5d..4bb33d8a 100644
--- a/src/components/sections/Cart/CartItemRow.tsx
+++ b/src/components/sections/Cart/CartItemRow.tsx
@@ -1,52 +1,55 @@
import { changeCartProductQuantity, removeCartProduct } from "@/actions/cart";
import type { common_OrderItem } from "@/api/proto-http/frontend";
import Image from "@/components/ui/Image";
-import Size from "../Common/Size";
import ProductAmountButtons from "./ProductAmountButtons";
+import { cn } from "@/lib/utils";
+import ProductRemoveButton from "./ProductRemoveButton";
+import CartItemSize from "./CartItemSize";
export default function CartItemRow({
product,
+ className,
}: {
product?: common_OrderItem;
+ className?: string;
}) {
if (!product) return null;
return (
-
-
-
-
-
-
-
{product.productName}
-
{product.color}
-
- {product.orderItem?.sizeId && (
-
- )}
-
-
+
+
+
-
+
+
+
{product.productName}
+
+
{product.orderItem?.productId !== undefined && (
+ >
+ {product.orderItem?.quantity || 0}
+
)}
-
quantity: {product.orderItem?.quantity}
-
-
BTC {product.productPrice}
-
BTC {product.productPrice}
+
+
+
BTC {product.productPrice}
);
diff --git a/src/components/sections/Cart/CartItemSize.tsx b/src/components/sections/Cart/CartItemSize.tsx
new file mode 100644
index 00000000..2bf19c04
--- /dev/null
+++ b/src/components/sections/Cart/CartItemSize.tsx
@@ -0,0 +1,14 @@
+"use client";
+
+import { useHeroContext } from "@/components/contexts/HeroContext";
+
+export default function CartItemSize({ sizeId }: { sizeId: string }) {
+ const { dictionary } = useHeroContext();
+
+ const sizeName =
+ dictionary?.sizes?.find((size) => size.id === Number(sizeId))?.name || "";
+
+ if (!sizeName) return null;
+
+ return
{sizeName}
;
+}
diff --git a/src/components/sections/Cart/CartPopup.tsx b/src/components/sections/Cart/CartPopup.tsx
index 68c21810..b8e51c09 100644
--- a/src/components/sections/Cart/CartPopup.tsx
+++ b/src/components/sections/Cart/CartPopup.tsx
@@ -1,22 +1,19 @@
"use client";
-import Button from "@/components/ui/Button";
+import { Button } from "@/components/ui/Button";
import { cn } from "@/lib/utils";
import { useClickAway } from "@uidotdev/usehooks";
import Link from "next/link";
import { useState } from "react";
-import { ButtonStyle } from "@/components/ui/Button/styles";
export default function CartPopup({
children,
itemsQuantity,
hasCartProducts,
- hidePopupCart,
}: {
children: React.ReactNode;
itemsQuantity?: number;
hasCartProducts?: boolean;
- hidePopupCart?: boolean;
}) {
const [open, setOpenStatus] = useState(false);
@@ -27,32 +24,37 @@ export default function CartPopup({
return (
setOpenStatus(!open)}
- style={ButtonStyle.underlinedHightlightButton}
+ onClick={() => setOpenStatus((v) => !v)}
+ variant="underlineWithColors"
>
cart {itemsQuantity ? `(${itemsQuantity})` : ""}
-
added to cart {"[06]"}
- {children}
-
-
- cart
-
- {hasCartProducts && (
-
- checkout
-
- )}
+
+
+
SHOPPING CART
+
[{itemsQuantity?.toString().padStart(2, "0")}]
+
+
setOpenStatus((v) => !v)}>[X]
+ {children}
+
+ PROCEED TO CHECKOUT
+
diff --git a/src/components/sections/Cart/CartProductsList/HACK__UpdateCookieCart.tsx b/src/components/sections/Cart/CartProductsList/HACK__UpdateCookieCart.tsx
index afa4b2c7..cbfd4403 100644
--- a/src/components/sections/Cart/CartProductsList/HACK__UpdateCookieCart.tsx
+++ b/src/components/sections/Cart/CartProductsList/HACK__UpdateCookieCart.tsx
@@ -1,7 +1,6 @@
"use client";
import { useEffect } from "react";
-import { toast } from "sonner";
export default function HACK__UpdateCookieCart({
updateCookieCart,
@@ -10,8 +9,6 @@ export default function HACK__UpdateCookieCart({
}) {
useEffect(() => {
updateCookieCart();
-
- toast.info("Cart items have been updated!");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
diff --git a/src/components/sections/Cart/CartProductsList/index.tsx b/src/components/sections/Cart/CartProductsList/index.tsx
index 6935f52b..ea599e02 100644
--- a/src/components/sections/Cart/CartProductsList/index.tsx
+++ b/src/components/sections/Cart/CartProductsList/index.tsx
@@ -1,13 +1,18 @@
import { addCartProduct, clearCartProducts } from "@/actions/cart";
-import Button from "@/components/ui/Button";
+import { Button } from "@/components/ui/Button";
import { serviceClient } from "@/lib/api";
import { getValidateOrderItemsInsertItems } from "@/lib/utils/cart";
import Link from "next/link";
import CartItemRow from "../CartItemRow";
import SelectedCurrency from "../TotalPrice/SelectedCurrency";
import HACK__UpdateCookieCart from "./HACK__UpdateCookieCart";
+import { cn } from "@/lib/utils";
-export default async function CartProductsList() {
+export default async function CartProductsList({
+ className,
+}: {
+ className?: string;
+}) {
const items = getValidateOrderItemsInsertItems();
if (items.length === 0) return null;
@@ -41,19 +46,18 @@ export default async function CartProductsList() {
};
return (
-
- {response.hasChanged && (
-
- )}
+
{response?.validItems?.map((p, i) => (
-
-
-
-
-
+
))}
-
total:
+ {response.hasChanged && (
+
+ )}
);
}
diff --git a/src/components/sections/Cart/ProductAmountButtons.tsx b/src/components/sections/Cart/ProductAmountButtons.tsx
index de1d6991..2e29c1f7 100644
--- a/src/components/sections/Cart/ProductAmountButtons.tsx
+++ b/src/components/sections/Cart/ProductAmountButtons.tsx
@@ -1,7 +1,6 @@
"use client";
-import Button from "@/components/ui/Button";
-import { ButtonStyle } from "@/components/ui/Button/styles";
+import { Button } from "@/components/ui/Button";
type Props = {
changeProductAmount: ({
@@ -13,53 +12,34 @@ type Props = {
size: string;
operation: "increase" | "decrease";
}) => void;
- removeProduct: ({ id, size }: { id: number; size: string }) => void;
id: number;
size: string;
+ children: React.ReactNode;
};
export default function ProductAmountButtons({
- changeProductAmount,
- removeProduct,
id,
size,
+ children,
+ changeProductAmount,
}: Props) {
- // todo: check if product is in stock
-
return (
-
-
- ) => {
- e.preventDefault();
-
- changeProductAmount({ id, size, operation: "increase" });
- }}
- >
- [+]
-
- ) => {
- e.preventDefault();
-
- changeProductAmount({ id, size, operation: "decrease" });
- }}
- >
- [-]
-
- ) => {
- e.preventDefault();
-
- removeProduct({ id, size });
- }}
- >
- [x]
-
-
+
+ ) => {
+ changeProductAmount({ id, size, operation: "increase" });
+ }}
+ >
+ +
+
+ {children}
+ ) => {
+ changeProductAmount({ id, size, operation: "decrease" });
+ }}
+ >
+ -
+
);
}
diff --git a/src/components/sections/Cart/ProductRemoveButton.tsx b/src/components/sections/Cart/ProductRemoveButton.tsx
new file mode 100644
index 00000000..49dff94a
--- /dev/null
+++ b/src/components/sections/Cart/ProductRemoveButton.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import { Button } from "@/components/ui/Button";
+
+type Props = {
+ removeProduct: ({ id, size }: { id: number; size: string }) => void;
+ id: number;
+ size: string;
+};
+
+export default function ProductRemoveButton({
+ id,
+ size,
+ removeProduct,
+}: Props) {
+ return (
+
) => {
+ removeProduct({ id, size });
+ }}
+ variant="underline"
+ >
+ remove
+
+ );
+}
diff --git a/src/components/sections/Cart/TotalPrice/SelectedCurrency.tsx b/src/components/sections/Cart/TotalPrice/SelectedCurrency.tsx
index 94684953..3b5c1f5c 100644
--- a/src/components/sections/Cart/TotalPrice/SelectedCurrency.tsx
+++ b/src/components/sections/Cart/TotalPrice/SelectedCurrency.tsx
@@ -10,12 +10,11 @@ export default function SelectedCurrency({
const { selectedCurrency } = useHeroContext();
return (
-
-
total
-
base currency: {baseCurrencyTotal}
-
- todo: convert to {selectedCurrency}: {baseCurrencyTotal}
-
+
+ SUBTOTAL:
+
+ {selectedCurrency} {baseCurrencyTotal}
+
);
}
diff --git a/src/components/sections/Cart/TotalPrice/index.tsx b/src/components/sections/Cart/TotalPrice/index.tsx
index 1be25f4d..a1c7b230 100644
--- a/src/components/sections/Cart/TotalPrice/index.tsx
+++ b/src/components/sections/Cart/TotalPrice/index.tsx
@@ -12,9 +12,5 @@ export default function TotalPrice() {
0,
);
- return (
-
-
-
- );
+ return
;
}
diff --git a/src/components/sections/Footer/index.tsx b/src/components/sections/Footer/index.tsx
index d73fb23d..9dbdaf01 100644
--- a/src/components/sections/Footer/index.tsx
+++ b/src/components/sections/Footer/index.tsx
@@ -2,7 +2,7 @@ import Link from "next/link";
import { FOOTER_LINKS as links, FOOTER_YEAR as year } from "@/constants";
import { serviceClient } from "@/lib/api";
import { cn } from "@/lib/utils";
-import Button from "@/components/ui/Button";
+import { Button } from "@/components/ui/Button";
import FooterForm from "../../forms/NewslatterForm";
import CurrencyPopover from "./CurrencyPopover";
diff --git a/src/components/sections/Header/useMobileMenu.tsx b/src/components/sections/Header/useMobileMenu.tsx
index 1e9c8052..b79d642c 100644
--- a/src/components/sections/Header/useMobileMenu.tsx
+++ b/src/components/sections/Header/useMobileMenu.tsx
@@ -3,8 +3,7 @@
import { useClickAway } from "@uidotdev/usehooks";
import { Dispatch, SetStateAction, useState } from "react";
-import Button from "@/components/ui/Button";
-import { ButtonStyle } from "@/components/ui/Button/styles";
+import { Button } from "@/components/ui/Button";
import Link from "next/link";
export default function useMovileMenu() {
@@ -29,9 +28,13 @@ function MobileMenuTrigger({
setOpenStatus: Dispatch
>;
}) {
return (
- setOpenStatus(true)}>
+ setOpenStatus(true)}
+ >
menu
-
+
);
}
@@ -49,19 +52,19 @@ function MobileMenuDropdown({
{"[x]"}
diff --git a/src/components/sections/MeasurementsModal/index.tsx b/src/components/sections/MeasurementsModal/index.tsx
index b8b54f72..12767ae1 100644
--- a/src/components/sections/MeasurementsModal/index.tsx
+++ b/src/components/sections/MeasurementsModal/index.tsx
@@ -1,5 +1,4 @@
-import Button from "@/components/ui/Button";
-import { ButtonStyle } from "@/components/ui/Button/styles";
+import { Button } from "@/components/ui/Button";
import Modal from "@/components/ui/Modal";
import MeasurementsModalContent from "./MeasurementsModalContent";
import { common_ProductSize } from "@/api/proto-http/frontend";
@@ -29,7 +28,7 @@ export default function MeasurementsModal({
return (
+
measurements
}
diff --git a/src/components/sections/ProductsGridSection/ProductItem.tsx b/src/components/sections/ProductsGridSection/ProductItem.tsx
index 97931c82..0f933ad7 100644
--- a/src/components/sections/ProductsGridSection/ProductItem.tsx
+++ b/src/components/sections/ProductsGridSection/ProductItem.tsx
@@ -1,5 +1,5 @@
import type { common_Product } from "@/api/proto-http/frontend";
-import Button from "@/components/ui/Button";
+import { Button } from "@/components/ui/Button";
import Image from "@/components/ui/Image";
import { CURRENCY_MAP } from "@/constants";
import { cn } from "@/lib/utils";
@@ -41,7 +41,7 @@ export default function ProductItem({
{/* todo: change to css variable */}
-
+
{product.productDisplay?.productBody?.brand}
{product.productDisplay?.productBody?.name}
diff --git a/src/components/ui/Button.tsx b/src/components/ui/Button.tsx
new file mode 100644
index 00000000..148c6ac4
--- /dev/null
+++ b/src/components/ui/Button.tsx
@@ -0,0 +1,93 @@
+import { Slot } from "@radix-ui/react-slot";
+import { cva, VariantProps } from "class-variance-authority";
+
+const buttonVariants = cva("disabled:cursor-not-allowed", {
+ variants: {
+ variant: {
+ default: ["text-textBaseSize"],
+ simple: ["text-bgColor", "bg-textColor"],
+ main: [
+ "border",
+ "border-textColor",
+ "text-textBaseSize",
+ "text-bgColor",
+ "disabled:bg-textInactiveColor",
+ "bg-textColor",
+ "hover:bg-bgColor",
+ "hover:text-textColor",
+ "focus:outline-none",
+ "focus:ring-2",
+ "focus:ring-offset-2",
+ "focus:ring-textColor",
+ "disabled:bg-textInactiveColor",
+ "disabled:text-bgColor",
+ "disabled:border-textInactiveColor",
+ "leading-4",
+ "text-center",
+ ],
+ underline: [
+ "text-textBaseSize",
+ "border-textColor",
+ "underline",
+ "disabled:text-textInactiveColor",
+ ],
+ underlineWithColors: [
+ "underline",
+ "text-textBaseSize",
+ "text-highlightColor",
+ "disabled:text-textInactiveColor",
+ "visited:text-visitedLinkColor",
+ ],
+ },
+ size: {
+ sm: ["text-textSmallSize"],
+ default: ["text-textBaseSize"],
+ lg: ["py-2.5", "px-16", "text-textBaseSize"],
+ giant: [
+ "py-10",
+ "px-16",
+ "text-textGiantSmallSize",
+ "lg:text-textGiantSize",
+ ],
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+});
+
+interface Props extends VariantProps
{
+ asChild?: boolean;
+ children: React.ReactNode;
+ loading?: boolean;
+ className?: string;
+ [k: string]: unknown;
+}
+
+export function Button({
+ asChild,
+ children,
+ loading,
+ size,
+ variant,
+ className,
+ ...props
+}: Props) {
+ const Component = asChild ? Slot : "button";
+
+ return (
+
+
+ {children}
+
+
+ );
+}
diff --git a/src/components/ui/Button/button.stories.ts b/src/components/ui/Button/button.stories.ts
deleted file mode 100644
index 5152c0f0..00000000
--- a/src/components/ui/Button/button.stories.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import Button from "@/components/ui/Button";
-import { ButtonStyle } from "@/components/ui/Button/styles";
-import type { Meta, StoryObj } from "@storybook/react";
-
-const meta = {
- title: "UI/Button",
- component: Button,
- parameters: {
- layout: "centered",
- },
- args: {
- style: ButtonStyle.default,
- },
- tags: ["autodocs"],
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {
- children: "default button",
- },
-};
-
-export const BigButton: Story = {
- args: {
- style: ButtonStyle.bigButton,
- children: "big button",
- },
-};
-
-export const UnderlinedButton: Story = {
- args: {
- style: ButtonStyle.underlinedButton,
- children: "underlined button",
- },
-};
-
-export const UnderlinedHightlightButton: Story = {
- args: {
- style: ButtonStyle.underlinedHightlightButton,
- children: "underlined hightlight button",
- },
-};
-
-export const SimpleButton: Story = {
- args: {
- style: ButtonStyle.simpleButton,
- children: "simple button",
- },
-};
diff --git a/src/components/ui/Button/index.tsx b/src/components/ui/Button/index.tsx
deleted file mode 100644
index 5adb01a5..00000000
--- a/src/components/ui/Button/index.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Slot } from "@radix-ui/react-slot";
-import { getComponentByStyle, ButtonStyle } from "./styles";
-
-export default function Button({
- style = ButtonStyle.default,
- asChild,
- children,
- ...props
-}: {
- style?: ButtonStyle;
- asChild?: boolean;
- children: React.ReactNode;
- [k: string]: unknown;
-}) {
- const Component = asChild ? Slot : "button";
- const ComponentStyle = getComponentByStyle(style);
-
- return (
-
-
- {children}
-
-
- );
-}
diff --git a/src/components/ui/Button/styles.tsx b/src/components/ui/Button/styles.tsx
deleted file mode 100644
index 91caddab..00000000
--- a/src/components/ui/Button/styles.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-export enum ButtonStyle {
- default = "default",
- bigButton = "bigButton",
- underlinedButton = "underlinedButton",
- underlinedHightlightButton = "underlinedHightlightButton",
- simpleButton = "simpleButton",
-}
-
-type StyleComponentType = {
- children: React.ReactNode;
-};
-
-function DefaultStyleComponent({ children }: StyleComponentType) {
- return children;
-}
-
-function UnderlinedButtonStyleComponent({ children }: StyleComponentType) {
- return (
-
- {children}
-
- );
-}
-
-function UnderlinedHightlightButtonStyleComponent({
- children,
-}: StyleComponentType) {
- return (
-
- {children}
-
- );
-}
-
-function BigButtonStyleComponent({ children }: StyleComponentType) {
- return (
-
- {children}
-
- );
-}
-
-function SimpleButtonStyleComponent({ children }: StyleComponentType) {
- return (
-
- {children}
-
- );
-}
-
-const componentsStyleMap: Record = {
- [ButtonStyle.underlinedButton]: UnderlinedButtonStyleComponent,
- [ButtonStyle.underlinedHightlightButton]:
- UnderlinedHightlightButtonStyleComponent,
- [ButtonStyle.bigButton]: BigButtonStyleComponent,
- [ButtonStyle.default]: DefaultStyleComponent,
- [ButtonStyle.simpleButton]: SimpleButtonStyleComponent,
-};
-
-export function getComponentByStyle(style: ButtonStyle) {
- return componentsStyleMap[style] || DefaultStyleComponent;
-}
diff --git a/src/components/ui/Form/FormContainer.tsx b/src/components/ui/Form/FormContainer.tsx
index 767e2e72..3f893dda 100644
--- a/src/components/ui/Form/FormContainer.tsx
+++ b/src/components/ui/Form/FormContainer.tsx
@@ -5,36 +5,26 @@ import { SubmitButton } from "@/components/forms/SubmitButton";
type Props = {
form: UseFormReturn;
- initialData: any;
+ submitButton?: React.ReactNode;
onSubmit: (data: any) => void;
- loading?: boolean;
children: React.ReactNode;
className?: string;
- ctaLabel: string;
footerSide?: "left" | "right";
};
export const FormContainer = ({
form,
- initialData,
onSubmit,
- loading,
children,
className,
- ctaLabel,
footerSide,
+ submitButton,
}: Props) => {
return (
);
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
index df444cef..fb7d1d44 100644
--- a/tailwind.config.cjs
+++ b/tailwind.config.cjs
@@ -4,11 +4,19 @@ const config = {
theme: {
extend: {
colors: {
- bgColor: "var(--background)",
textColor: "var(--text)",
- buttonTextColor: "var(--button-text)",
- highlightTextColor: "var(--highlight-text)",
+ textInactiveColor: "var(--inactive)",
+ bgColor: "var(--background)",
+ highlightColor: "var(--highlight)",
errorColor: "var(--error)",
+ buttonTextColor: "var(--button-text)",
+ visitedLinkColor: "var(--visited-link)",
+ },
+ fontSize: {
+ textGiantSize: "var(--text-giant)",
+ textGiantSmallSize: "var(--text-giant-small)",
+ textBaseSize: "var(--text-base)",
+ textSmallSize: "var(--text-small)",
},
},
},