Fixade Appstle-planhämtning
X-Lovable-Edit-ID: edt-e68f2cf5-b9ca-4973-80a8-3b2692d2eee6 Co-authored-by: wolfoftyreso-debug <250630591+wolfoftyreso-debug@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import { useState, useMemo } from "react";
|
import { useState, useMemo } from "react";
|
||||||
import { Loader2, CreditCard, FileText } from "lucide-react";
|
import { Loader2, CreditCard, FileText } from "lucide-react";
|
||||||
import { useShopifyProducts } from "@/hooks/useShopifyProducts";
|
|
||||||
import {
|
import {
|
||||||
storefrontApiRequest,
|
storefrontApiRequest,
|
||||||
CART_CREATE_MUTATION,
|
CART_CREATE_MUTATION,
|
||||||
@@ -11,7 +10,6 @@ import { toast } from "sonner";
|
|||||||
const PRICE_PER_KG = 325;
|
const PRICE_PER_KG = 325;
|
||||||
const KG_PER_EMPLOYEE = 0.3;
|
const KG_PER_EMPLOYEE = 0.3;
|
||||||
|
|
||||||
// Map recommended kg to the closest available Shopify subscription plan
|
|
||||||
const availablePlans = [
|
const availablePlans = [
|
||||||
{ kg: 3, handle: "liten-kakabonnemang-3-kg-vecka", name: "Liten" },
|
{ kg: 3, handle: "liten-kakabonnemang-3-kg-vecka", name: "Liten" },
|
||||||
{ kg: 5, handle: "mellan-kakabonnemang-5-kg-vecka", name: "Mellan" },
|
{ kg: 5, handle: "mellan-kakabonnemang-5-kg-vecka", name: "Mellan" },
|
||||||
@@ -23,6 +21,39 @@ const pickPlan = (kg: number) => {
|
|||||||
return match || availablePlans[availablePlans.length - 1];
|
return match || availablePlans[availablePlans.length - 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PRODUCT_BY_HANDLE_QUERY = `
|
||||||
|
query ProductByHandle($handle: String!) {
|
||||||
|
productByHandle(handle: $handle) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
handle
|
||||||
|
variants(first: 1) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
availableForSale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sellingPlanGroups(first: 5) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
name
|
||||||
|
sellingPlans(first: 10) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
type PaymentMethod = "card" | "invoice";
|
type PaymentMethod = "card" | "invoice";
|
||||||
|
|
||||||
const PlansSection = () => {
|
const PlansSection = () => {
|
||||||
@@ -30,10 +61,6 @@ const PlansSection = () => {
|
|||||||
const [loadingMethod, setLoadingMethod] = useState<PaymentMethod | null>(null);
|
const [loadingMethod, setLoadingMethod] = useState<PaymentMethod | null>(null);
|
||||||
const [showPaymentOptions, setShowPaymentOptions] = useState(false);
|
const [showPaymentOptions, setShowPaymentOptions] = useState(false);
|
||||||
|
|
||||||
const { products, isLoading: productsLoading } = useShopifyProducts(
|
|
||||||
"product_type:Abonnemang"
|
|
||||||
);
|
|
||||||
|
|
||||||
const recommendedKg = useMemo(
|
const recommendedKg = useMemo(
|
||||||
() => Math.max(1, Math.round(employees * KG_PER_EMPLOYEE)),
|
() => Math.max(1, Math.round(employees * KG_PER_EMPLOYEE)),
|
||||||
[employees]
|
[employees]
|
||||||
@@ -42,30 +69,36 @@ const PlansSection = () => {
|
|||||||
|
|
||||||
const handleStart = async (method: PaymentMethod) => {
|
const handleStart = async (method: PaymentMethod) => {
|
||||||
const plan = pickPlan(recommendedKg);
|
const plan = pickPlan(recommendedKg);
|
||||||
const shopifyProduct = products.find((p) => p.node.handle === plan.handle);
|
setLoadingMethod(method);
|
||||||
|
|
||||||
if (!shopifyProduct) {
|
try {
|
||||||
toast.error("Kunde inte hitta produkten");
|
const productData = await storefrontApiRequest(PRODUCT_BY_HANDLE_QUERY, {
|
||||||
|
handle: plan.handle,
|
||||||
|
});
|
||||||
|
|
||||||
|
const product = productData?.data?.productByHandle;
|
||||||
|
if (!product) {
|
||||||
|
toast.error(`Kunde inte hitta produkten "${plan.handle}" i Shopify.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const variant = shopifyProduct.node.variants.edges[0]?.node;
|
|
||||||
if (!variant) {
|
const variant = product.variants?.edges?.[0]?.node;
|
||||||
toast.error("Ingen variant tillgänglig");
|
if (!variant?.id) {
|
||||||
|
toast.error("Ingen variant tillgänglig på produkten.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sellingPlanId =
|
const sellingPlanId =
|
||||||
shopifyProduct.node.sellingPlanGroups?.edges?.[0]?.node?.sellingPlans?.edges?.[0]?.node?.id;
|
product.sellingPlanGroups?.edges?.[0]?.node?.sellingPlans?.edges?.[0]?.node?.id;
|
||||||
|
|
||||||
if (!sellingPlanId) {
|
if (!sellingPlanId) {
|
||||||
toast.error(
|
toast.error(
|
||||||
"Ingen abonnemangsplan hittades i Shopify. Kontrollera att Appstle-planen är kopplad till produkten."
|
"Ingen Appstle-abonnemangsplan hittades. Aktivera Storefront-behörigheten 'unauthenticated_read_selling_plans' och koppla en Appstle-plan till produkten.",
|
||||||
|
{ duration: 10000 }
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoadingMethod(method);
|
|
||||||
try {
|
|
||||||
const data = await storefrontApiRequest(CART_CREATE_MUTATION, {
|
const data = await storefrontApiRequest(CART_CREATE_MUTATION, {
|
||||||
input: {
|
input: {
|
||||||
lines: [
|
lines: [
|
||||||
@@ -90,7 +123,7 @@ const PlansSection = () => {
|
|||||||
const errors = data?.data?.cartCreate?.userErrors || [];
|
const errors = data?.data?.cartCreate?.userErrors || [];
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
console.error("Cart creation failed:", errors);
|
console.error("Cart creation failed:", errors);
|
||||||
toast.error("Kunde inte skapa checkout");
|
toast.error("Kunde inte skapa checkout: " + errors[0].message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,13 +136,14 @@ const PlansSection = () => {
|
|||||||
window.open(formatCheckoutUrl(checkoutUrl), "_blank");
|
window.open(formatCheckoutUrl(checkoutUrl), "_blank");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
toast.error("Något gick fel");
|
toast.error("Något gick fel vid checkout");
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingMethod(null);
|
setLoadingMethod(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isBusy = productsLoading || loadingMethod !== null;
|
|
||||||
|
const isBusy = loadingMethod !== null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="abonnemang" className="py-16 md:py-28 px-6 bg-background">
|
<section id="abonnemang" className="py-16 md:py-28 px-6 bg-background">
|
||||||
|
|||||||
Reference in New Issue
Block a user