import { json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Page, Layout, Card, Thumbnail, TextContainer, Spinner, Button, Text, TextField, } from "@shopify/polaris"; import { useState } from "react"; import { authenticate } from "../shopify.server"; 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 { brands, accessToken } = useLoaderData(); const [expandedBrand, setExpandedBrand] = useState(null); const [itemsMap, setItemsMap] = useState({}); const [loadingMap, setLoadingMap] = useState({}); const [productCount, setProductCount] = useState("10"); const [adding, setAdding] = useState(false); 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`, { headers: { Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json", }, }); const data = await res.json(); setItemsMap((prev) => ({ ...prev, [brandId]: data })); } catch (err) { console.error("Error fetching items:", err); } setLoadingMap((prev) => ({ ...prev, [brandId]: false })); } } }; const handleAddProducts = async (brandId) => { const count = parseInt(productCount || "10"); const items = (itemsMap[brandId] || []).slice(0, count); if (!items.length) return alert("No products to add."); setAdding(true); for (const item of items) { const attr = item.attributes; // Step 1: Create Product (only allowed fields) const productInput = { title: attr.product_name, descriptionHtml: `
${attr.part_description}
`, vendor: attr.brand, productType: attr.category, tags: [attr.subcategory, attr.brand].filter(Boolean).join(", "), }; const createProductRes = await fetch("/admin/api/2023-04/graphql.json", { method: "POST", headers: { "Content-Type": "application/json", "X-Shopify-Access-Token": accessToken, }, body: JSON.stringify({ query: ` mutation productCreate($input: ProductInput!) { productCreate(input: $input) { product { id title } userErrors { field message } } }`, variables: { input: productInput }, }), }); const createProductResult = await createProductRes.json(); const product = createProductResult?.data?.productCreate?.product; const productErrors = createProductResult?.data?.productCreate?.userErrors; if (productErrors?.length || !product?.id) { console.error("❌ Product create error:", productErrors); continue; } const productId = product.id; // Step 2: Create Variant const variantInput = { productId, sku: attr.part_number, barcode: attr.barcode || undefined, price: "0.00", weight: attr.dimensions?.[0]?.weight || 0, weightUnit: "KILOGRAMS", inventoryManagement: "SHOPIFY", }; await fetch("/admin/api/2023-04/graphql.json", { method: "POST", headers: { "Content-Type": "application/json", "X-Shopify-Access-Token": accessToken, }, body: JSON.stringify({ query: ` mutation productVariantCreate($input: ProductVariantInput!) { productVariantCreate(input: $input) { productVariant { id } userErrors { field message } } }`, variables: { input: variantInput }, }), }); // Step 3: Add Image if (attr.thumbnail) { await fetch("/admin/api/2023-04/graphql.json", { method: "POST", headers: { "Content-Type": "application/json", "X-Shopify-Access-Token": accessToken, }, body: JSON.stringify({ query: ` mutation productImageCreate($productId: ID!, $image: ImageInput!) { productImageCreate(productId: $productId, image: $image) { image { id src } userErrors { field message } } }`, variables: { productId, image: { src: attr.thumbnail, }, }, }), }); } console.log("✅ Added:", attr.product_name); } setAdding(false); alert(`${items.length} products added.`); }; return (No brands selected yet.
Brand: {brand.name}
ID: {brand.id}
Part Number: {item.attributes.part_number}
Brand: {item.attributes.brand}
Category: {item.attributes.category} > {item.attributes.subcategory}
Dimensions: {item.attributes.dimensions?.[0]?.length} x {item.attributes.dimensions?.[0]?.width} x {item.attributes.dimensions?.[0]?.height} in