243 lines
7.4 KiB
JavaScript
243 lines
7.4 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
||
import { json } from "@remix-run/node";
|
||
import { useLoaderData, useActionData, useSubmit } from "@remix-run/react";
|
||
import {
|
||
Page,
|
||
Layout,
|
||
Card,
|
||
BlockStack,
|
||
Text,
|
||
Badge,
|
||
InlineStack,
|
||
Image,
|
||
Divider,
|
||
Button,
|
||
Modal,
|
||
TextField,
|
||
} from "@shopify/polaris";
|
||
import { TitleBar } from "@shopify/app-bridge-react";
|
||
import data4autosLogo from "../assets/data4autos_logo.png"; // make sure this exists
|
||
import { authenticate } from "../shopify.server"; // Shopify server authentication
|
||
|
||
import { Form } from "@remix-run/react";
|
||
|
||
|
||
|
||
// Loader to check subscription status
|
||
export const loader = async ({ request }) => {
|
||
const { admin } = await authenticate.admin(request);
|
||
|
||
// Query the current subscription status
|
||
const resp = await admin.graphql(`
|
||
query {
|
||
currentAppInstallation {
|
||
activeSubscriptions {
|
||
id
|
||
status
|
||
trialDays
|
||
createdAt
|
||
currentPeriodEnd
|
||
}
|
||
}
|
||
}
|
||
`);
|
||
|
||
const result = await resp.json();
|
||
const subscription = result.data.currentAppInstallation.activeSubscriptions[0] || null;
|
||
|
||
// For new users, there's no subscription. We will show a "Not subscribed" message.
|
||
if (!subscription) {
|
||
return json({ redirectToBilling: true, subscription: null });
|
||
}
|
||
|
||
// If no active or trial subscription, return redirect signal
|
||
if (subscription.status !== "ACTIVE" && subscription.status !== "TRIAL") {
|
||
return json({ redirectToBilling: true, subscription });
|
||
}
|
||
|
||
return json({ redirectToBilling: false, subscription });
|
||
};
|
||
|
||
// Action to create subscription
|
||
export const action = async ({ request }) => {
|
||
console.log("Creating subscription...");
|
||
const { admin } = await authenticate.admin(request);
|
||
|
||
const createRes = await admin.graphql(`
|
||
mutation {
|
||
appSubscriptionCreate(
|
||
name: "Pro Plan",
|
||
returnUrl: "https://your-app.com/after-billing",
|
||
lineItems: [
|
||
{
|
||
plan: {
|
||
appRecurringPricingDetails: {
|
||
price: { amount: 19.99, currencyCode: USD },
|
||
interval: EVERY_30_DAYS
|
||
}
|
||
}
|
||
}
|
||
],
|
||
trialDays: 7, # ✅ trialDays is a top-level argument!
|
||
test: true
|
||
) {
|
||
confirmationUrl
|
||
appSubscription {
|
||
id
|
||
status
|
||
trialDays
|
||
}
|
||
userErrors {
|
||
field
|
||
message
|
||
}
|
||
}
|
||
}
|
||
`);
|
||
|
||
const data = await createRes.json();
|
||
console.log("Subscription creation response:", data);
|
||
if (data.errors || !data.data.appSubscriptionCreate.confirmationUrl) {
|
||
return json({ errors: ["Failed to create subscription."] }, { status: 400 });
|
||
}
|
||
console.log("Subscription created successfully:", data.data.appSubscriptionCreate.confirmationUrl);
|
||
return json({
|
||
confirmationUrl: data.data.appSubscriptionCreate.confirmationUrl
|
||
});
|
||
};
|
||
|
||
export default function Index() {
|
||
const actionData = useActionData();
|
||
const loaderData = useLoaderData();
|
||
const submit = useSubmit(); // Use submit to trigger the action
|
||
const [activeModal, setActiveModal] = useState(false);
|
||
|
||
const subscription = loaderData?.subscription;
|
||
|
||
// useEffect(() => {
|
||
// console.log("Action data:", actionData);
|
||
// // If we have a confirmation URL, redirect to it
|
||
// if (actionData?.confirmationUrl) {
|
||
// window.location.href = actionData.confirmationUrl; // Redirect to Shopify's billing confirmation page
|
||
// }
|
||
// }, [actionData]);
|
||
|
||
|
||
useEffect(() => {
|
||
if (actionData?.confirmationUrl) {
|
||
window.open(actionData.confirmationUrl, "_blank", "noopener,noreferrer");
|
||
setActiveModal(false); // close the modal
|
||
}
|
||
}, [actionData]);
|
||
const openModal = () => setActiveModal(true);
|
||
const closeModal = () => setActiveModal(false);
|
||
|
||
return (
|
||
<Page>
|
||
<TitleBar title="Data4Autos Turn14 Integration" />
|
||
<Layout>
|
||
<Layout.Section>
|
||
<Card padding="500">
|
||
<BlockStack gap="400">
|
||
<InlineStack gap="200" align="center">
|
||
<Image
|
||
source={data4autosLogo}
|
||
alt="Data4Autos Logo"
|
||
width={120}
|
||
/>
|
||
<Text variant="headingLg" as="h1">
|
||
Welcome to your Turn14 Dashboard
|
||
</Text>
|
||
</InlineStack>
|
||
|
||
<Divider />
|
||
|
||
<BlockStack gap="200">
|
||
<Text variant="bodyMd">
|
||
🚀 <b>Data4Autos Turn14 Integration</b> gives you the power to sync
|
||
product brands, manage collections, and automate catalog setup directly from
|
||
Turn14 to your Shopify store.
|
||
</Text>
|
||
|
||
<Text variant="bodyMd">
|
||
🔧 Use the left sidebar to:
|
||
</Text>
|
||
<BlockStack gap="100">
|
||
<Text as="span">⚙️ Manage API settings</Text>
|
||
<Text as="span">🏷️ Browse and import available brands</Text>
|
||
<Text as="span">📦 Sync brand collections to Shopify</Text>
|
||
<Text as="span">🔐 Handle secure Turn14 login credentials</Text>
|
||
</BlockStack>
|
||
|
||
<Divider />
|
||
|
||
<InlineStack align="center">
|
||
<Badge tone="success">Status: Connected</Badge>
|
||
<Text tone="subdued">Shopify x Turn14</Text>
|
||
</InlineStack>
|
||
|
||
<Text tone="subdued" alignment="center">
|
||
Need help? Contact us at{" "}
|
||
<a href="mailto:support@data4autos.com">support@data4autos.com</a>
|
||
</Text>
|
||
|
||
<Button onClick={openModal}>
|
||
{loaderData?.redirectToBilling ? "Proceed to Billing" : "View Subscription Details"}
|
||
</Button>
|
||
</BlockStack>
|
||
</BlockStack>
|
||
</Card>
|
||
</Layout.Section>
|
||
</Layout>
|
||
|
||
{/* Modal for Subscription Info */}
|
||
<Modal
|
||
open={activeModal}
|
||
onClose={closeModal}
|
||
title="Subscription Details"
|
||
// primaryAction={{
|
||
// content: "Proceed to Billing",
|
||
// onAction: () => {
|
||
// submit(null, { method: "post", form: document.getElementById("billing-form") });
|
||
// },
|
||
// }}
|
||
primaryAction={{
|
||
content: "Proceed to Billing",
|
||
onAction: () => {
|
||
submit(null, { method: "post", form: document.getElementById("billing-form") });
|
||
},
|
||
}}
|
||
secondaryActions={[{ content: "Close", onAction: closeModal }]}
|
||
>
|
||
<Form id="billing-form" method="post">
|
||
<Modal.Section>
|
||
|
||
<BlockStack gap="100">
|
||
<TextField
|
||
label="Subscription Status"
|
||
value={subscription ? subscription.status : "No active subscription"}
|
||
disabled
|
||
/>
|
||
<TextField
|
||
label="Trial Days Left"
|
||
value={subscription?.trialDays ? `${subscription.trialDays} days left` : "No trial available"}
|
||
disabled
|
||
/>
|
||
<TextField
|
||
label="Subscription Plan"
|
||
value={subscription?.id ? "Pro Plan" : "Not subscribed"}
|
||
disabled
|
||
/>
|
||
<TextField
|
||
label="Trial Expiration Date"
|
||
value={subscription?.currentPeriodEnd ? new Date(subscription.currentPeriodEnd).toLocaleDateString() : "N/A"}
|
||
disabled
|
||
/>
|
||
</BlockStack>
|
||
</Modal.Section>
|
||
</Form>
|
||
</Modal>
|
||
</Page>
|
||
);
|
||
}
|