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:
gpt-engineer-app[bot]
2026-07-11 11:39:35 +00:00
+53 -19
View File
@@ -1,6 +1,5 @@
import { useState, useMemo } from "react";
import { Loader2, CreditCard, FileText } from "lucide-react";
import { useShopifyProducts } from "@/hooks/useShopifyProducts";
import {
storefrontApiRequest,
CART_CREATE_MUTATION,
@@ -11,7 +10,6 @@ import { toast } from "sonner";
const PRICE_PER_KG = 325;
const KG_PER_EMPLOYEE = 0.3;
// Map recommended kg to the closest available Shopify subscription plan
const availablePlans = [
{ kg: 3, handle: "liten-kakabonnemang-3-kg-vecka", name: "Liten" },
{ kg: 5, handle: "mellan-kakabonnemang-5-kg-vecka", name: "Mellan" },
@@ -23,6 +21,39 @@ const pickPlan = (kg: number) => {
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";
const PlansSection = () => {
@@ -30,10 +61,6 @@ const PlansSection = () => {
const [loadingMethod, setLoadingMethod] = useState<PaymentMethod | null>(null);
const [showPaymentOptions, setShowPaymentOptions] = useState(false);
const { products, isLoading: productsLoading } = useShopifyProducts(
"product_type:Abonnemang"
);
const recommendedKg = useMemo(
() => Math.max(1, Math.round(employees * KG_PER_EMPLOYEE)),
[employees]
@@ -42,30 +69,36 @@ const PlansSection = () => {
const handleStart = async (method: PaymentMethod) => {
const plan = pickPlan(recommendedKg);
const shopifyProduct = products.find((p) => p.node.handle === plan.handle);
setLoadingMethod(method);
if (!shopifyProduct) {
toast.error("Kunde inte hitta produkten");
try {
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;
}
const variant = shopifyProduct.node.variants.edges[0]?.node;
if (!variant) {
toast.error("Ingen variant tillgänglig");
const variant = product.variants?.edges?.[0]?.node;
if (!variant?.id) {
toast.error("Ingen variant tillgänglig på produkten.");
return;
}
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) {
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;
}
setLoadingMethod(method);
try {
const data = await storefrontApiRequest(CART_CREATE_MUTATION, {
input: {
lines: [
@@ -90,7 +123,7 @@ const PlansSection = () => {
const errors = data?.data?.cartCreate?.userErrors || [];
if (errors.length > 0) {
console.error("Cart creation failed:", errors);
toast.error("Kunde inte skapa checkout");
toast.error("Kunde inte skapa checkout: " + errors[0].message);
return;
}
@@ -103,13 +136,14 @@ const PlansSection = () => {
window.open(formatCheckoutUrl(checkoutUrl), "_blank");
} catch (e) {
console.error(e);
toast.error("Något gick fel");
toast.error("Något gick fel vid checkout");
} finally {
setLoadingMethod(null);
}
};
const isBusy = productsLoading || loadingMethod !== null;
const isBusy = loadingMethod !== null;
return (
<section id="abonnemang" className="py-16 md:py-28 px-6 bg-background">