backend_shopify_data4autos/app/routes/app.managebrand copy.jsx
2025-07-12 17:20:28 +00:00

232 lines
8.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from "react";
import { json } from "@remix-run/node";
import { useLoaderData, Form, useActionData } from "@remix-run/react";
import {
Page,
Layout,
IndexTable,
Card,
Thumbnail,
TextContainer,
Spinner,
Button,
TextField,
Banner,
} from "@shopify/polaris";
import { authenticate } from "../shopify.server";
import { TitleBar } from "@shopify/app-bridge-react";
export const loader = async ({ request }) => {
const { admin } = await authenticate.admin(request);
const { getTurn14AccessTokenFromMetafield } = await import("../utils/turn14Token.server");
const accessToken = await getTurn14AccessTokenFromMetafield(request);
const res = await admin.graphql(`{
shop {
metafield(namespace: "turn14", key: "selected_brands") {
value
}
}
}`);
const data = await res.json();
const rawValue = data?.data?.shop?.metafield?.value;
let brands = [];
try {
brands = JSON.parse(rawValue);
} catch (err) {
console.error("❌ Failed to parse metafield value:", err);
}
return json({ brands, accessToken });
};
export default function ManageBrandProducts() {
const actionData = useActionData();
const { brands, accessToken } = useLoaderData();
const [expandedBrand, setExpandedBrand] = useState(null);
const [itemsMap, setItemsMap] = useState({});
const [loadingMap, setLoadingMap] = useState({});
const [productCount, setProductCount] = useState("0");
const [initialLoad, setInitialLoad] = useState(true);
// Function to toggle all brands
const toggleAllBrands = async () => {
for (const brand of brands) {
await toggleBrandItems(brand.id);
}
};
// Run on initial load
useEffect(() => {
if (initialLoad && brands.length > 0) {
toggleAllBrands();
setInitialLoad(false);
}
}, [brands, initialLoad]);
const toggleBrandItems = async (brandId) => {
const isExpanded = expandedBrand === brandId;
if (isExpanded) {
setExpandedBrand(null);
} else {
setExpandedBrand(brandId);
if (!itemsMap[brandId]) {
setLoadingMap((prev) => ({ ...prev, [brandId]: true }));
try {
// const res = await fetch(`https://turn14.data4autos.com/v1/items/brand/${brandId}?page=1`, {
const res = await fetch(`https://turn14.data4autos.com/v1/items/brandallitems/${brandId}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
const data = await res.json();
setProductCount(data.length)
setItemsMap((prev) => ({ ...prev, [brandId]: data }));
} catch (err) {
console.error("Error fetching items:", err);
}
setLoadingMap((prev) => ({ ...prev, [brandId]: false }));
} else {
setProductCount(itemsMap[brandId].length)
}
}
};
return (
<Page title="Data4Autos Turn14 Manage Brand Products">
<TitleBar title="Data4Autos Turn14 Integration" />
<Layout>
{brands.length === 0 ? (
<Layout.Section>
<Card sectioned>
<p>No brands selected yet.</p>
</Card>
</Layout.Section>
) : (
<Layout.Section>
<Card>
<IndexTable
resourceName={{ singular: "brand", plural: "brands" }}
itemCount={brands.length}
headings={[
{ title: "Brand ID" },
{ title: "Logo" },
{ title: "Action" },
{ title: "Products Count" },
]}
selectable={false}
>
{brands.map((brand, index) => (
<IndexTable.Row id={brand.id.toString()} key={brand.id} position={index}>
<IndexTable.Cell>{brand.id}</IndexTable.Cell>
<IndexTable.Cell>
<Thumbnail
source={
brand.logo ||
"https://cdn.shopify.com/s/files/1/0757/9955/files/no-image_280x@2x.png"
}
alt={brand.name}
size="small"
/>
</IndexTable.Cell>
<IndexTable.Cell>
<Button onClick={() => toggleBrandItems(brand.id)}>
{expandedBrand === brand.id ? "Hide Products" : "Show Products"}
</Button>
</IndexTable.Cell>
<IndexTable.Cell>{itemsMap[brand.id]?.length || 0}</IndexTable.Cell>
</IndexTable.Row>
))}
</IndexTable>
</Card>
</Layout.Section>
)}
{brands.map(
(brand) =>
expandedBrand === brand.id && (
<Layout.Section fullWidth key={brand.id + "-expanded"}>
<Card sectioned>
{actionData?.success && (
<Banner title="✅ Product created!" status="success">
<p>
{actionData.results.map((r) => (
<span key={r.variant.id}>
Product {r.productId} Variant {r.variant.id} @ ${r.variant.price} (SKU: {r.variant.sku})<br />
</span>
))}
</p>
</Banner>
)}
</Card>
<Card title={`Items from ${brand.name}`} sectioned>
{loadingMap[brand.id] ? (
<Spinner accessibilityLabel="Loading items" size="small" />
) : (
<div style={{ paddingTop: "1rem" }}>
<Form method="post">
<input type="hidden" name="brandId" value={brand.id} />
<TextField
label="Number of products to add"
type="number"
name="productCount"
value={productCount}
onChange={setProductCount}
autoComplete="off"
/>
<Button submit primary style={{ marginTop: "1rem" }}>
Add First {productCount} Products to Store
</Button>
</Form>
Total Products Count : {(itemsMap[brand.id] || []).length}
{(
itemsMap[brand.id] && itemsMap[brand.id].length > 0
? itemsMap[brand.id]
: []
).map((item) => (
<Card key={item?.id} title={item?.attributes.product_name} sectioned>
<Layout>
<Layout.Section oneThird>
<Thumbnail
source={
item?.attributes.thumbnail ||
"https://cdn.shopify.com/s/files/1/0757/9955/files/no-image_280x@2x.png"
}
alt={item?.attributes.product_name}
size="large"
/>
</Layout.Section>
<Layout.Section>
<TextContainer spacing="tight">
<p><strong>Part Number:</strong> {item?.attributes.part_number}</p>
<p><strong>Category:</strong> {item?.attributes.category} &gt; {item?.attributes.subcategory}</p>
</TextContainer>
</Layout.Section>
</Layout>
</Card>
))}
</div>
)}
</Card>
</Layout.Section>
)
)}
</Layout>
</Page>
);
}