import { json } from "@remix-run/node"; import { useLoaderData, Form, useActionData } from "@remix-run/react"; import { Page, Layout, Card, TextField, Checkbox, Button, Thumbnail, Spinner, Toast, Frame, } from "@shopify/polaris"; import { useEffect, useState } from "react"; import { TitleBar } from "@shopify/app-bridge-react"; import { getTurn14AccessTokenFromMetafield } from "../utils/turn14Token.server"; import { authenticate } from "../shopify.server"; export const loader = async ({ request }) => { const accessToken = await getTurn14AccessTokenFromMetafield(request); const { admin } = await authenticate.admin(request); // fetch brands const brandRes = await fetch("https://turn14.data4autos.com/v1/brands", { headers: { Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json", }, }); const brandJson = await brandRes.json(); if (!brandRes.ok) { return json({ error: brandJson.error || "Failed to fetch brands" }, { status: 500 }); } // fetch Shopify collections const gqlRaw = await admin.graphql(` { collections(first: 100) { edges { node { id title } } } } `); const gql = await gqlRaw.json(); const collections = gql?.data?.collections?.edges.map(e => e.node) || []; return json({ brands: brandJson.data, collections }); }; export const action = async ({ request }) => { const formData = await request.formData(); const selectedBrands = JSON.parse(formData.get("selectedBrands") || "[]"); const selectedOldBrands = JSON.parse(formData.get("selectedOldBrands") || "[]"); const { session } = await authenticate.admin(request); const shop = session.shop; // "veloxautomotive.myshopify.com" selectedBrands.forEach(brand => { delete brand.pricegroups; }); selectedOldBrands.forEach(brand => { delete brand.pricegroups; }); const resp = await fetch("https://backend.data4autos.com/managebrands", { method: "POST", headers: { "Content-Type": "application/json", "shop-domain": shop, }, body: JSON.stringify({ shop, selectedBrands, selectedOldBrands }), }); if (!resp.ok) { const err = await resp.text(); return json({ error: err }, { status: resp.status }); } const { processId, status } = await resp.json(); return json({ processId, status }); }; export default function BrandsPage() { const { brands, collections } = useLoaderData(); const actionData = useActionData() || {}; const [selectedIdsold, setSelectedIdsold] = useState([]) const [selectedIds, setSelectedIds] = useState(() => { const titles = new Set(collections.map(c => c.title.toLowerCase())); return brands .filter(b => titles.has(b.name.toLowerCase())) .map(b => b.id); }); const [search, setSearch] = useState(""); const [filteredBrands, setFilteredBrands] = useState(brands); const [toastActive, setToastActive] = useState(false); const [polling, setPolling] = useState(false); const [status, setStatus] = useState(actionData.status || ""); useEffect(() => { const selids = selectedIds console.log("Selected IDS : ", selids) setSelectedIdsold(selids) }, [toastActive]); useEffect(() => { const term = search.toLowerCase(); setFilteredBrands(brands.filter(b => b.name.toLowerCase().includes(term))); }, [search, brands]); useEffect(() => { if (actionData.status) { setStatus(actionData.status); setToastActive(true); } }, [actionData.status]); const checkStatus = async () => { if (!actionData.processId) return; setPolling(true); const resp = await fetch( `https://backend.data4autos.com/managebrands/status/${actionData.processId}`, { headers: { "shop-domain": window.shopify.shop || "" } } ); const jsonBody = await resp.json(); setStatus( jsonBody.status + (jsonBody.detail ? ` (${jsonBody.detail})` : "") ); setPolling(false); }; const toggleSelect = id => setSelectedIds(prev => prev.includes(id) ? prev.filter(i => i !== id) : [...prev, id] ); const allFilteredSelected = filteredBrands.length > 0 && filteredBrands.every(b => selectedIds.includes(b.id)); const toggleSelectAll = () => { const ids = filteredBrands.map(b => b.id); if (allFilteredSelected) { setSelectedIds(prev => prev.filter(id => !ids.includes(id))); } else { setSelectedIds(prev => Array.from(new Set([...prev, ...ids]))); } }; var isSubmitting; console.log("actionData", actionData); if (actionData.status) { isSubmitting = !actionData.status && !actionData.error && !actionData.processId; } else { isSubmitting = false; } console.log("isSubmitting", isSubmitting); const toastMarkup = toastActive ? ( setToastActive(false)} /> ) : null; const selectedBrands = brands.filter(b => selectedIds.includes(b.id)); const selectedOldBrands = brands.filter(b => selectedIdsold.includes(b.id)); console.log("123456", selectedOldBrands) return (
{(actionData.processId || false) && (

Process ID: {actionData.processId}

Status: {status || "—"}

)}
{filteredBrands.map(brand => (
toggleSelect(brand.id)} /> {brand.name}
))}
{toastMarkup}
); }