Auto-publish on AI finish and add custom save button

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Rami Bitar
2026-05-05 10:59:16 -04:00
parent 2a397da576
commit 4cada5b2b5
2 changed files with 49 additions and 25 deletions

View File

@@ -106,12 +106,6 @@ export const ShopifyProvider: React.FC<{
token: string; token: string;
children: React.ReactNode; children: React.ReactNode;
}> = ({ domain, token, children }) => { }> = ({ domain, token, children }) => {
console.log('[ShopifyProvider] creds', {
domain,
hasToken: !!token,
tokenPreview: token ? `${token.slice(0, 4)}${token.slice(-4)}` : null,
});
// Sync creds into the module-level store synchronously so any render-time // Sync creds into the module-level store synchronously so any render-time
// call (incl. SSR) reads the right domain/token. // call (incl. SSR) reads the right domain/token.
setShopifyCredentials({ domain, token }); setShopifyCredentials({ domain, token });

View File

@@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { import {
App as ReactEditorApp, App as ReactEditorApp,
blocksPlugin, blocksPlugin,
@@ -36,6 +36,11 @@ export default function App() {
const pages = schemaJson as Pages; const pages = schemaJson as Pages;
const [currentPath, setCurrentPath] = useState<string>(readPathname); const [currentPath, setCurrentPath] = useState<string>(readPathname);
const [isPublishing, setIsPublishing] = useState(false); const [isPublishing, setIsPublishing] = useState(false);
const latestDataRef = useRef<any>(null);
const handleChange = useCallback((data: any) => {
latestDataRef.current = data;
}, []);
useEffect(() => { useEffect(() => {
const onPop = () => setCurrentPath(readPathname()); const onPop = () => setCurrentPath(readPathname());
@@ -52,25 +57,8 @@ export default function App() {
[], [],
); );
const plugins = useMemo(
() => [
aiPlugin({
api: "https://www.frontend-ai.com/cloud/api/chat",
headers: { "X-Api-Key": AI_API_KEY },
getCurrentRoute: () => ({ path: window.location.pathname }),
}),
createTailwindCdnPlugin(),
blocksPlugin(),
outlinePlugin(),
mediaPlugin({
adapter: frontendAiMediaAdapter,
showSearch: true,
}),
],
[],
);
const handlePublish = useCallback((data: any, route?: string) => { const handlePublish = useCallback((data: any, route?: string) => {
console.log(data);
setIsPublishing(true); setIsPublishing(true);
if (typeof window !== "undefined" && window.parent !== window) { if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage( window.parent.postMessage(
@@ -81,6 +69,30 @@ export default function App() {
setTimeout(() => setIsPublishing(false), 1000); setTimeout(() => setIsPublishing(false), 1000);
}, []); }, []);
const plugins = useMemo(
() => [
aiPlugin({
api: "https://www.frontend-ai.com/cloud/api/chat",
headers: { "X-Api-Key": AI_API_KEY },
getCurrentRoute: () => ({ path: window.location.pathname }),
onFinish: (output: any) => {
if (output?.finishReason === "stop") {
console.log(output);
handlePublish(latestDataRef.current, currentPath);
}
},
}),
createTailwindCdnPlugin(),
blocksPlugin(),
outlinePlugin(),
mediaPlugin({
adapter: frontendAiMediaAdapter,
showSearch: true,
}),
],
[pages, currentPath, handlePublish],
);
return ( return (
<div className="h-screen w-screen"> <div className="h-screen w-screen">
<ShopifyProvider domain={SHOPIFY_DOMAIN} token={STOREFRONT_TOKEN}> <ShopifyProvider domain={SHOPIFY_DOMAIN} token={STOREFRONT_TOKEN}>
@@ -91,6 +103,24 @@ export default function App() {
plugins={plugins} plugins={plugins}
iframe={{ enabled: true }} iframe={{ enabled: true }}
onPublish={handlePublish} onPublish={handlePublish}
onChange={handleChange}
overrides={{
header: ({ children }: any) => (
<div className="flex items-center justify-between gap-2 border-b border-gray-200 bg-white px-4 py-2">
<div className="flex flex-1 items-center gap-2">{children}</div>
<button
type="button"
disabled={isPublishing}
onClick={() => {
handlePublish(latestDataRef.current, currentPath);
}}
className="inline-flex items-center justify-center rounded-md bg-black px-4 py-1.5 text-sm font-medium text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-60"
>
{isPublishing ? "Saving..." : "Save"}
</button>
</div>
),
}}
/> />
</ShopifyProvider> </ShopifyProvider>
{isPublishing && ( {isPublishing && (