Skip to content

Commit

Permalink
Merge pull request #440 from EasyBrizy/27154-addToCart
Browse files Browse the repository at this point in the history
add to cart element
  • Loading branch information
maxval1 authored Oct 29, 2024
2 parents b77d9bd + 4636279 commit 458b6ff
Show file tree
Hide file tree
Showing 23 changed files with 904 additions and 131 deletions.
9 changes: 9 additions & 0 deletions packages/demo-nextjs/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ const nextConfig = {
},
],
},
{
source: "/api/(.*)",
headers: [
{
key: "Access-Control-Allow-Origin",
value: "*",
},
],
},
];
},
images: {
Expand Down
13 changes: 13 additions & 0 deletions packages/demo-nextjs/src/app/api/products/all/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { getAllProducts } from "@/lib/db/shopify/getProducts";
import { NextResponse } from "next/server";

export async function GET() {
try {
const { products } = await getAllProducts();

return NextResponse.json({ products }, { status: 200 });
} catch (e) {
console.error(e);
return NextResponse.json({ error: "Failed to get products", e }, { status: 400 });
}
}
6 changes: 3 additions & 3 deletions packages/demo-nextjs/src/placeholders/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Reference } from "@/components/Editor/contexts/types";
import { BuilderPlaceholder } from "@/placeholders/types/BuilderPlaceholder";
import { CollectionItemPlaceholder } from "@/placeholders/types/CollectionItem";
import { CompareAtPricePlaceholder } from "@/placeholders/types/CompareAtPrice";
import { DescriptionPlaceholder } from "@/placeholders/types/Description";
import { FeaturedImagePlaceholder } from "@/placeholders/types/FeaturedImage";
Expand All @@ -12,8 +13,7 @@ import { VariantOptionValuePlaceholder } from "@/placeholders/types/VariantOptio
import { VariantOptionValuesPlaceholder } from "@/placeholders/types/VariantOptionValues";
import { VariantOptionsPlaceholder } from "@/placeholders/types/VariantOptions";
import { VariantTitlePlaceholder } from "@/placeholders/types/VariantTitle";
import { CollectionItemPlaceholder } from "@/placeholders/types/Vendor";
import { EmptyContext, Registry, Replacer } from "@brizy/content-placeholder";
import { Registry, Replacer } from "@brizy/content-placeholder";
import { CollectionContext } from "./context/CollectionContext";

const PlaceholderInstances = [
Expand Down Expand Up @@ -64,7 +64,7 @@ export const replacePlaceholders = async ({

// The first replacePlaceholders call is to transform the placeholder
// `{{ placeholder content='base64encode(placeholderName)' attr1='val1' }}` to `{{ placeholderName attr1='val1'}}`
const result = await replacer.replacePlaceholders(value, new EmptyContext());
const result = await replacer.replacePlaceholders(value, context);

return replacer.replacePlaceholders(result, context);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AlphaButton } from "@brizy/builder-ui/lib/components/AlphaButton";
import { ThemeIconEditor, ThemeIconPreview } from "@brizy/core";
import { Props as BaseProps } from "./types";

type Props = BaseProps & {
ThemeIcon: typeof ThemeIconEditor | typeof ThemeIconPreview;
};

export const AddToCart = (props: Props) => {
const { iconType, iconName, itemId, title, ThemeIcon } = props;

const cartIcon = <ThemeIcon name={iconName} type={iconType} />;

const productId = !itemId || itemId === "auto" ? "{{ brizy_dc_collection_item_field }}" : itemId;

return (
<div data-product-id={productId} className="add-to-cart-third-party-wrapper">
<AlphaButton className="add-to-cart-third-party" icon={cartIcon}>
{title}
<ThemeIcon name="circle-02" type="glyph" className="brz-icon-spinner brz-hidden" />
</AlphaButton>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Props } from "./types";
import { ThemeIconEditor } from "@brizy/core";
import { AddToCart } from "./AddToCart";

export const AddToCartEditor = ({ iconType, iconName, itemId, title }: Props) => (
<AddToCart iconType={iconType} iconName={iconName} title={title} itemId={itemId} ThemeIcon={ThemeIconEditor} />
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ThemeIconPreview } from "@brizy/core";
import { AddToCart } from "./AddToCart";
import { Props } from "./types";

export const AddToCartView = ({ iconType, iconName, itemId, title }: Props) => (
<AddToCart iconType={iconType} iconName={iconName} title={title} itemId={itemId} ThemeIcon={ThemeIconPreview} />
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Props {
iconName: string;
iconType: string;
itemId: string;
title: string;
}
25 changes: 25 additions & 0 deletions packages/demo-nextjs/src/widgets/AddToCart/export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { handleAddToCart, loadProductData, onChangeVariant } from "./utils";

document.addEventListener("DOMContentLoaded", () => {
const addToCarts = document.querySelectorAll<HTMLElement>(".add-to-cart-third-party-wrapper");
const variants = document.querySelectorAll<HTMLElement>(".brz-shopify-variant-container");

addToCarts.forEach((item) => {
const { productId } = item.dataset;
const button = item.querySelector<HTMLButtonElement>(".add-to-cart-third-party");

if (productId && button) {
button.addEventListener("click", () => {
handleAddToCart(button, productId);
});
}
});

variants.forEach((variant) => {
variant
.querySelectorAll(".brz-shopify-variant-radio-block, .brz-shopify-variant-items li")
.forEach((item) => item.addEventListener("click", () => onChangeVariant(variant)));
});

loadProductData();
});
26 changes: 26 additions & 0 deletions packages/demo-nextjs/src/widgets/AddToCart/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.add-to-cart-third-party {
&.brz-ui-ed-btn {
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
height: auto;

.brz-ui-ed-btn-icon{
display: flex;
}
}

svg.brz-icon-spinner {
position: absolute;
left: 50%;
color: #ffffff;
animation: spin 1s linear infinite;
}
}

@keyframes spin {
100% {
transform: rotate(360deg)
}
}
17 changes: 17 additions & 0 deletions packages/demo-nextjs/src/widgets/AddToCart/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Brizy as BrizyCore } from "@brizy/core";
import { AddToCartEditor } from "./components/Editor";
import { AddToCartView } from "./components/View";
import "./index.scss";
import { getToolbar } from "./toolbar";

BrizyCore.registerComponent({
id: "Brizy.ThirdParty.AddToCart",
component: {
editor: AddToCartEditor,
view: AddToCartView,
},
title: "Add to cart",
icon: "nc-woo-add-to-cart",
category: "Ecommerce",
options: getToolbar,
});
25 changes: 25 additions & 0 deletions packages/demo-nextjs/src/widgets/AddToCart/requests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Variant } from "@/lib/db/shopify/types";
import axios from "axios";

export const addItemToCart = ({
quantity,
variants,
productId,
cartId,
}: {
quantity: number;
variants?: Variant[];
cartId: string;
productId: string;
}) =>
axios.post("/api/products/cart", {
quantity,
variants,
cartId,
productId,
});

export const getProductsWithVariants = (productIds: string) =>
axios.get(`/api/products/cart/withVariants?productIds=${productIds}`);

export const getAllProducts = (origin: string) => axios.get(`${origin}/api/products/all`);
Loading

0 comments on commit 458b6ff

Please sign in to comment.