import { useState, useEffect } from "react"; import { useActionData, useLoaderData, useSubmit, useNavigation, useNavigate, useParams, } from "react-router"; import { authenticate } from "../shopify.server"; import { boundary } from "@shopify/shopify-app-react-router/server"; import db from "../db.server"; import { getQRCode, validateQRCode } from "../models/QRCode.server"; export async function loader({ request, params }) { const { admin } = await authenticate.admin(request); if (params.id === "new") { return { destination: "product", title: "", }; } return await getQRCode(Number(params.id), admin.graphql); } export async function action({ request, params }) { const { session, redirect } = await authenticate.admin(request); const { shop } = session; /** @type {any} */ const data = { ...Object.fromEntries(await request.formData()), shop, }; if (data.action === "delete") { await db.qRCode.delete({ where: { id: Number(params.id) } }); return redirect("/app"); } const errors = validateQRCode(data); if (errors) { return new Response(JSON.stringify({ errors }), { status: 422, headers: { "Content-Type": "application/json", }, }); } const qrCode = params.id === "new" ? await db.qRCode.create({ data }) : await db.qRCode.update({ where: { id: Number(params.id) }, data }); return redirect(`/app/qrcodes/${qrCode.id}`); } export default function QRCodeForm() { const navigate = useNavigate(); const { id } = useParams(); const qrCode = useLoaderData(); const [initialFormState, setInitialFormState] = useState(qrCode); const [formState, setFormState] = useState(qrCode); const errors = useActionData()?.errors || {}; const isSaving = useNavigation().state === "submitting"; const isDirty = JSON.stringify(formState) !== JSON.stringify(initialFormState); async function selectProduct() { const products = await window.shopify.resourcePicker({ type: "product", action: "select", // customized action verb, either 'select' or 'add', }); if (products) { const { images, id, variants, title, handle } = products[0]; setFormState({ ...formState, productId: id, productVariantId: variants[0].id, productTitle: title, productHandle: handle, productAlt: images[0]?.altText, productImage: images[0]?.originalSrc, }); } } function removeProduct() { setFormState({ title: formState.title, destination: formState.destination, }); } const productUrl = formState.productId ? `shopify://admin/products/${formState.productId.split("/").at(-1)}` : ""; const submit = useSubmit(); function handleSave(e) { e.preventDefault(); const data = { title: formState.title, productId: formState.productId || "", productVariantId: formState.productVariantId || "", productHandle: formState.productHandle || "", destination: formState.destination, }; submit(data, { method: "post" }); } function handleDelete(e) { e.preventDefault(); submit({ action: "delete" }, { method: "post" }); } function handleReset() { setFormState(initialFormState); window.shopify.saveBar.hide("qr-code-form"); } useEffect(() => { if (isDirty) { window.shopify.saveBar.show("qr-code-form"); } else { window.shopify.saveBar.hide("qr-code-form"); } return () => { window.shopify.saveBar.hide("qr-code-form"); }; }, [isDirty]); useEffect(() => { setInitialFormState(qrCode); setFormState(qrCode); }, [id, qrCode]); return ( <>
(isDirty ? e.preventDefault() : navigate("/app/"))} > QR Codes {initialFormState.id && Delete} setFormState({ ...formState, title: e.target.value }) } > setFormState({ ...formState, destination: e.target.value }) } > Link to product page Link to checkout page with product in the cart {initialFormState.destinationUrl ? ( Go to destination URL ) : null} Product {formState.productId ? ( Clear ) : null} {formState.productId ? ( {formState.productImage ? ( ) : ( )} {formState.productTitle} Change ) : ( Select product )} {initialFormState.image ? ( ) : ( See a preview once you save )} Go to public URL Download
); } export const headers = (headersArgs) => { return boundary.headers(headersArgs); };