import { __ } from '@wordpress/i18n';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
Alert,
Card,
ChoiceGroup,
Input,
Page,
Spinner,
Toggle,
} from './UI/index.jsx';
import { api } from '../api/index.js';
import { ShoppingCart } from 'lucide-react';
import { decodeHtmlEntities } from '../lib/utils.js';
const PREVIEW_THEMES = [
{
value: 'light',
label: __( 'Light Surface', 'arrayfunnel' ),
},
{
value: 'graphite',
label: __( 'Graphite Surface', 'arrayfunnel' ),
},
];
const PREVIEW_RADIUS = [
{
value: 'soft',
label: __( 'Soft', 'arrayfunnel' ),
},
{
value: 'balanced',
label: __( 'Balanced', 'arrayfunnel' ),
},
{
value: 'expressive',
label: __( 'Expressive', 'arrayfunnel' ),
},
];
const PREVIEW_ACCENTS = [
{
value: 'emerald',
label: __( 'Emerald', 'arrayfunnel' ),
swatch: '#059669',
previewClass: 'bg-emerald-600',
},
{
value: 'black',
label: __( 'Black', 'arrayfunnel' ),
swatch: '#0f172a',
previewClass: 'bg-slate-900',
},
{
value: 'sky',
label: __( 'Sky', 'arrayfunnel' ),
swatch: '#0284c7',
previewClass: 'bg-sky-600',
},
];
const currencySymbol = decodeHtmlEntities(
window.arrayfunnelAdmin?.currency?.symbol || '$'
);
const DEFAULT_PRESETS = {
arrayfunnel_side_cart_theme: 'light',
arrayfunnel_side_cart_radius: 'balanced',
arrayfunnel_side_cart_accent: 'emerald',
arrayfunnel_side_cart_open_mode: 'always',
};
function normalizeSettings( settings = {} ) {
const theme = PREVIEW_THEMES.some(
( item ) => item.value === settings.arrayfunnel_side_cart_theme
)
? settings.arrayfunnel_side_cart_theme
: DEFAULT_PRESETS.arrayfunnel_side_cart_theme;
const radius = PREVIEW_RADIUS.some(
( item ) => item.value === settings.arrayfunnel_side_cart_radius
)
? settings.arrayfunnel_side_cart_radius
: DEFAULT_PRESETS.arrayfunnel_side_cart_radius;
const accent = PREVIEW_ACCENTS.some(
( item ) => item.value === settings.arrayfunnel_side_cart_accent
)
? settings.arrayfunnel_side_cart_accent
: DEFAULT_PRESETS.arrayfunnel_side_cart_accent;
const openMode =
settings.arrayfunnel_side_cart_open_mode === 'smart'
? 'smart'
: DEFAULT_PRESETS.arrayfunnel_side_cart_open_mode;
return {
...settings,
arrayfunnel_side_cart_theme: theme,
arrayfunnel_side_cart_radius: radius,
arrayfunnel_side_cart_accent: accent,
arrayfunnel_side_cart_open_mode: openMode,
};
}
export default function SideCartEditor() {
const pageHeader = {
title: __( 'Side Cart', 'arrayfunnel' ),
subtitle: __(
'Visual customization + behavior controls with real-time preview',
'arrayfunnel'
),
};
const qc = useQueryClient();
const [ settings, setSettings ] = useState( null );
const [ original, setOriginal ] = useState( null );
const { data: settingsData, isLoading } = useQuery( {
queryKey: [ 'settings' ],
queryFn: api.getSettings,
staleTime: 30_000,
gcTime: 5 * 60_000,
} );
useEffect( () => {
if ( ! settingsData ) {
return;
}
const normalized = normalizeSettings( settingsData );
setSettings( normalized );
setOriginal( JSON.stringify( normalized ) );
}, [ settingsData ] );
const { mutateAsync: save, isPending: savingSettings } = useMutation( {
mutationFn: ( { changes } ) => api.saveSettings( changes ),
onSuccess( response, { changes, snapshot } ) {
const saved = { ...snapshot, ...( response?.saved || {} ) };
setOriginal( JSON.stringify( saved ) );
qc.setQueryData( [ 'settings' ], ( current ) => ( {
...current,
...changes,
...( response?.saved || {} ),
} ) );
},
} );
const hasChanges = settings && JSON.stringify( settings ) !== original;
useEffect( () => {
if ( typeof window === 'undefined' ) {
return;
}
window.dispatchEvent(
new window.CustomEvent( 'arrayfunnel:dirty-state', {
detail: {
dirty: Boolean( hasChanges ),
},
} )
);
return () => {
window.dispatchEvent(
new window.CustomEvent( 'arrayfunnel:dirty-state', {
detail: {
dirty: false,
},
} )
);
};
}, [ hasChanges ] );
const set = ( key, val ) =>
setSettings( ( s ) => ( {
...s,
[ key ]: val,
} ) );
useEffect( () => {
const handleDiscard = () => {
if ( ! savingSettings && original !== null ) {
setSettings( JSON.parse( original ) );
}
};
window.addEventListener(
'arrayfunnel:discard-current-page',
handleDiscard
);
return () =>
window.removeEventListener(
'arrayfunnel:discard-current-page',
handleDiscard
);
}, [ original, savingSettings ] );
const saveCurrentPage = useCallback( async () => {
if ( ! hasChanges || savingSettings ) {
return;
}
const baseline = JSON.parse( original );
const changes = Object.fromEntries(
Object.entries( settings ).filter(
( [ key, value ] ) =>
JSON.stringify( value ) !==
JSON.stringify( baseline[ key ] )
)
);
await save( { changes, snapshot: settings } );
}, [ hasChanges, original, save, savingSettings, settings ] );
useEffect( () => {
const handleHeaderSave = ( event ) => {
if ( ! hasChanges ) {
return;
}
const task = saveCurrentPage();
event?.detail?.register?.( task );
};
window.addEventListener(
'arrayfunnel:save-current-page',
handleHeaderSave
);
return () =>
window.removeEventListener(
'arrayfunnel:save-current-page',
handleHeaderSave
);
}, [ hasChanges, saveCurrentPage ] );
const theme =
settings?.arrayfunnel_side_cart_theme ||
DEFAULT_PRESETS.arrayfunnel_side_cart_theme;
const radius =
settings?.arrayfunnel_side_cart_radius ||
DEFAULT_PRESETS.arrayfunnel_side_cart_radius;
const accent =
settings?.arrayfunnel_side_cart_accent ||
DEFAULT_PRESETS.arrayfunnel_side_cart_accent;
const previewTone = useMemo( () => {
return theme === 'graphite'
? 'bg-slate-900 text-slate-100 ring-slate-700'
: 'bg-white text-slate-900 ring-slate-200';
}, [ theme ] );
const previewRadius = useMemo( () => {
const classes = {
soft: 'rounded-md',
balanced: 'rounded-xl',
expressive: 'rounded-2xl',
};
return classes[ radius ] || classes.balanced;
}, [ radius ] );
const previewAccent = useMemo( () => {
const found = PREVIEW_ACCENTS.find( ( item ) => item.value === accent );
return found ? found.previewClass : 'bg-emerald-600';
}, [ accent ] );
if ( isLoading || ! settings ) {
return (
{ title }
{ price }