diff --git a/app/routes/app._index.jsx b/app/routes/app._index.jsx
index c14752a..b8f875c 100644
--- a/app/routes/app._index.jsx
+++ b/app/routes/app._index.jsx
@@ -90,7 +90,7 @@ export const action = async ({ request }) => {
}
],
trialDays: 7, # ✅ trialDays is a top-level argument!
- test: false
+ test: true
) {
confirmationUrl
appSubscription {
diff --git a/app/routes/app.brands.jsx b/app/routes/app.brands.jsx
index 54c7138..203105e 100644
--- a/app/routes/app.brands.jsx
+++ b/app/routes/app.brands.jsx
@@ -38,36 +38,36 @@ async function checkShopExists(shop) {
}
export const loader = async ({ request }) => {
- const accessToken = await getTurn14AccessTokenFromMetafield(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 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) || [];
+ // // 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) || [];
@@ -75,23 +75,23 @@ export const loader = async ({ 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;
+ // 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);
+ // let brands = [];
+ // try {
+ // brands = JSON.parse(rawValue);
- } catch (err) {
- console.error("❌ Failed to parse metafield value:", err);
- }
+ // } catch (err) {
+ // console.error("❌ Failed to parse metafield value:", err);
+ // }
@@ -99,7 +99,7 @@ export const loader = async ({ request }) => {
const { session } = await authenticate.admin(request);
const shop = session.shop;
- return json({ brands: brandJson.data, collections, selectedBrandsFromShopify: brands || [], shop });
+ return json({ brands: [], collections : [], selectedBrandsFromShopify: [], shop });
};
export const action = async ({ request }) => {
@@ -340,7 +340,7 @@ if (Turn14Enabled === false) {
-
+ {/*
Turn 14 Status:{" "}
{Turn14Enabled === true
@@ -349,7 +349,7 @@ if (Turn14Enabled === false) {
? "❌ Turn14 x Shopify Connection Doesn't Exists"
: "Checking..."}
-
+
*/}
diff --git a/app/routes/app.brands_2808.jsx b/app/routes/app.brands_2808.jsx
new file mode 100644
index 0000000..e95979e
--- /dev/null
+++ b/app/routes/app.brands_2808.jsx
@@ -0,0 +1,457 @@
+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,
+ Text,
+} 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";
+
+
+
+
+
+
+
+async function checkShopExists(shop) {
+ try {
+ const resp = await fetch(
+ `https://backend.data4autos.com/checkisshopdataexists/${shop}`
+ );
+ const data = await resp.json();
+ return data.status === 1; // ✅ true if shop exists, false otherwise
+ } catch (err) {
+ console.error("Error checking shop:", err);
+ return false; // default to false if error
+ }
+}
+
+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) || [];
+
+
+
+
+
+
+
+ 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);
+ }
+
+
+
+
+ const { session } = await authenticate.admin(request);
+ const shop = session.shop;
+
+ return json({ brands: brandJson.data, collections, selectedBrandsFromShopify: brands || [], shop });
+};
+
+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, selectedBrandsFromShopify, shop } = useLoaderData();
+ // console.log(`selectedBrandsFromShopify: ${JSON.stringify(selectedBrandsFromShopify)}`);
+ 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 [selectedIds, setSelectedIds] = useState(() => {
+ return selectedBrandsFromShopify.map(b => b.id);
+ });
+ // console.log("Selected IDS : ", selectedIds)
+ 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 || "");
+
+
+
+
+
+
+
+ const [Turn14Enabled, setTurn14Enabled] = useState(null); // null | true | false
+
+ useEffect(() => {
+ if (!shop) {
+ console.log("⚠️ shop is undefined or empty");
+ return;
+ }
+
+ (async () => {
+ const result = await checkShopExists(shop);
+ console.log("✅ API status result:", result, "| shop:", shop);
+ setTurn14Enabled(result);
+ })();
+ }, [shop]);
+
+
+
+
+
+ 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));
+
+
+
+ const shopDomain = (shop || "").split(".")[0];
+
+ const items = [
+ { icon: "⚙️", text: "Manage API settings", link: `https://admin.shopify.com/store/${shopDomain}/apps/d4a-turn14/app/settings` },
+ { icon: "🏷️", text: "Browse and import available brands", link: `https://admin.shopify.com/store/${shopDomain}/apps/d4a-turn14/app/brands` },
+ { icon: "📦", text: "Sync brand collections to Shopify", link: `https://admin.shopify.com/store/${shopDomain}/apps/d4a-turn14/app/managebrand` },
+ { icon: "🔐", text: "Handle secure Turn14 login credentials", link: `https://admin.shopify.com/store/${shopDomain}/apps/d4a-turn14/app/help` },
+ ];
+
+ // If Turn14 is explicitly NOT connected, show a lightweight call-to-action screen
+if (Turn14Enabled === false) {
+ return (
+
+
+
+
+
+
+
+
+ Turn14 isn’t connected yet
+
+
+
+ This shop hasn’t been configured with Turn14 / Data4Autos. To get started, open Settings and complete the connection.
+
+
+
+ {/* Primary actions */}
+
+
+
+
+ Once connected, you’ll be able to browse brands and sync collections.
+
+
+
+ {/* Secondary links */}
+
+
+
+
+
+
+
+ );
+}
+
+
+
+
+ // console.log("Selected Brands:", selectedBrands)
+ return (
+
+
+
+
+
+ Data4Autos Turn14 Brands List
+
+
+
+
+ {/*
+
+ Turn 14 Status:{" "}
+ {Turn14Enabled === true
+ ? "✅ Turn14 x Shopify Connected!"
+ : Turn14Enabled === false
+ ? "❌ Turn14 x Shopify Connection Doesn't Exists"
+ : "Checking..."}
+
+
*/}
+
+
+
+
+
+
+
+ {/* Left side - Search + Select All */}
+
+ {(actionData?.processId || false) && (
+
+
+ Process ID: {actionData.processId}
+
+
+ Status: {status || "—"}
+
+
+
+ )}
+
+
+
+
+ {/* Right side - Save Button */}
+
+
+
+
+
+
+ {filteredBrands.map((brand) => (
+
+
+ {/* Checkbox in top-right corner */}
+
+ toggleSelect(brand.id)}
+ />
+
+
+ {/* Brand image */}
+
+
+
+ {/* Brand name */}
+
+ {brand.name}
+
+
+
+ ))}
+
+
+
+
+ {toastMarkup}
+
+
+ );
+}
diff --git a/app/routes/app.managebrand.jsx b/app/routes/app.managebrand.jsx
index 612df03..4622fd0 100644
--- a/app/routes/app.managebrand.jsx
+++ b/app/routes/app.managebrand.jsx
@@ -532,14 +532,14 @@ export default function ManageBrandProducts() {
-
+ {/*
Turn 14 Status:{" "}
{Turn14Enabled === true
? "✅ Turn14 x Shopify Connected!"
: Turn14Enabled === false
? "❌ Turn14 x Shopify Connection Doesn't Exists"
: "Checking..."}
-
+ */}
{brands.length === 0 ? (