🛍️
Shopify Polaris Admin Extensions — Extensión generada
Admin Action · Modal de aprobación de pedido · Validado con scripts/validate.mjs
✓ Validación pasada · revision 2
Model: claude-sonnet-4-6
Client: claude-code
Artifact ID: admin-ext-order-approval-7f3a
Revision: 2
Framework: polaris-admin-extensions v3.2.1
Paso 1
search_docs.mjs
✓ 4 resultados
Paso 2
Código escrito
✓ AdminAction
Paso 3a
validate.mjs r1
✗ Error: prop
Paso 3b
Search + fix
⚡ Corregido
Paso 4
validate.mjs r2
✓ Pasado
polaris-admin-extensions/docs/admin-action.md · línea 42
Un AdminAction se monta en el menú contextual del recurso. Requiere target (p. ej. admin.order-details.action.render) y un componente React que recibe api.data con el contexto del recurso actual.
polaris-admin-extensions/docs/components/Modal.md · línea 8
Usa <Modal> de @shopify/admin-ui-extensions-react. La prop es open (boolean), no isOpen. Cierre con onClose.
polaris-admin-extensions/docs/api/resource-context.md · línea 19
Acceso al ID del pedido actual: api.data.orderId (string). Disponible solo en targets admin.order-*.
polaris-admin-extensions/examples/action-with-modal.tsx · línea 1
Ejemplo completo de AdminAction con Modal confirmatorio. Usa useAppBridge para dispatch y Redirect para navegar tras acción.
ValidationError: Invalid prop `isOpen` on component `Modal`. Expected prop `open` (boolean). Received `isOpen` (boolean). at AdminExtension → OrderApprovalModal Artifact: admin-ext-order-approval-7f3a · revision 1 Hint: search_docs.mjs "Modal props" for correct API signature.
Fix aplicado: Renombrado isOpen={showModal}open={showModal} según la documentación encontrada en el Paso 3b (search: "Modal props"). Revision incrementada a 2.
📄 extensions/order-approval/src/index.tsx ✓ Validado
import React, { useState } from 'react'; import { extend, AdminAction } from '@shopify/admin-ui-extensions'; import { Button, Modal, Stack, Text, Badge, Banner } from '@shopify/admin-ui-extensions-react'; // Target: aparece en el menú de acción de cada pedido extend('admin.order-details.action.render', (root, api) => { const app = render(<OrderApprovalAction api={api} />, root); }); function OrderApprovalAction({ api }) { const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); const [done, setDone] = useState(false); const orderId = api.data.orderId; // ej. "gid://shopify/Order/5512384299" async function handleApprove() { setLoading(true); await fetch(`/apps/approvals/orders/${orderId}/approve`, { method: 'POST', }); setLoading(false); setDone(true); setOpen(false); } return ( <> <AdminAction primaryAction={<Button onClick={() => setOpen(true)}>Aprobar pedido</Button>} > {done && <Banner status="success">Pedido aprobado</Banner>} </AdminAction> <Modal open={open} title="Confirmar aprobación" onClose={() => setOpen(false)} primaryAction={{ content: loading ? "Aprobando…" : "Confirmar", onAction: handleApprove, loading: loading, }} secondaryActions={[{ content: "Cancelar", onAction: () => setOpen(false), }]} > <Stack vertical spacing="base"> <Text>¿Confirmas la aprobación manual del pedido</Text> <Badge status="info">{orderId}</Badge> <Text color="subdued">Esta acción no se puede deshacer.</Text> </Stack> </Modal> </> ); }
✓ scripts/validate.mjs — Resultado (revision 2)
--model claude-sonnet-4-6
--client-name claude-code
--artifact-id admin-ext-order-approval-7f3a
--revision 2
target válido admin.order-details.action.render ✓
props Modal open (boolean) ✓
api.data.orderId acceso correcto ✓
imports @shopify/admin-ui-extensions-react ✓
resultado PASS — listo para entregar
Ubicación
Admin → Pedidos → Detalle del pedido
target: admin.order-details.action.render
Comportamiento
El botón "Aprobar pedido" aparece en el menú de acciones contextuales. Al pulsar, abre un Modal de confirmación con el ID del pedido. Tras confirmar, llama a tu endpoint backend y muestra un Banner de éxito.
Próximos pasos
1. shopify app deploy para subir la extensión
2. Configurar el endpoint /apps/approvals/orders/:id/approve
3. Solicitar permiso write_orders en scopes