fix: resolve container width issues, spa redirects, and appearance settings overwrite. feat: enhance order/sub details and newsletter layout
This commit is contained in:
@@ -52,7 +52,9 @@ interface CanvasRendererProps {
|
||||
onDuplicateSection: (id: string) => void;
|
||||
onMoveSection: (id: string, direction: 'up' | 'down') => void;
|
||||
onReorderSections: (sections: Section[]) => void;
|
||||
|
||||
onDeviceModeChange: (mode: 'desktop' | 'mobile') => void;
|
||||
containerWidth?: 'boxed' | 'fullwidth' | 'default';
|
||||
}
|
||||
|
||||
const SECTION_TYPES = [
|
||||
@@ -84,7 +86,9 @@ export function CanvasRenderer({
|
||||
onDuplicateSection,
|
||||
onMoveSection,
|
||||
onReorderSections,
|
||||
|
||||
onDeviceModeChange,
|
||||
containerWidth = 'default',
|
||||
}: CanvasRendererProps) {
|
||||
const [hoveredSectionId, setHoveredSectionId] = useState<string | null>(null);
|
||||
|
||||
@@ -149,7 +153,9 @@ export function CanvasRenderer({
|
||||
<div
|
||||
className={cn(
|
||||
'mx-auto bg-white shadow-xl rounded-lg transition-all duration-300 min-h-[500px]',
|
||||
deviceMode === 'desktop' ? 'max-w-4xl' : 'max-w-sm'
|
||||
deviceMode === 'mobile' ? 'max-w-sm' : (
|
||||
containerWidth === 'fullwidth' ? 'max-w-full mx-4' : 'max-w-6xl'
|
||||
)
|
||||
)}
|
||||
>
|
||||
{sections.length === 0 ? (
|
||||
|
||||
@@ -173,7 +173,7 @@ export function CanvasSection({
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent className="z-[60]">
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{__('Delete this section?')}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from '@/components/ui/accordion';
|
||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Slider } from '@/components/ui/slider';
|
||||
import {
|
||||
@@ -51,6 +52,7 @@ interface PageItem {
|
||||
title: string;
|
||||
url?: string;
|
||||
isSpaLanding?: boolean;
|
||||
containerWidth?: 'boxed' | 'fullwidth';
|
||||
}
|
||||
|
||||
interface InspectorPanelProps {
|
||||
@@ -69,6 +71,7 @@ interface InspectorPanelProps {
|
||||
onSetAsSpaLanding?: () => void;
|
||||
onUnsetSpaLanding?: () => void;
|
||||
onDeletePage?: () => void;
|
||||
onContainerWidthChange?: (width: 'boxed' | 'fullwidth') => void;
|
||||
}
|
||||
|
||||
// Section field configurations
|
||||
@@ -191,6 +194,7 @@ export function InspectorPanel({
|
||||
onSetAsSpaLanding,
|
||||
onUnsetSpaLanding,
|
||||
onDeletePage,
|
||||
onContainerWidthChange,
|
||||
}: InspectorPanelProps) {
|
||||
if (isCollapsed) {
|
||||
return (
|
||||
@@ -273,6 +277,31 @@ export function InspectorPanel({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Container Width */}
|
||||
{!isTemplate && page && onContainerWidthChange && (
|
||||
<div className="pt-2 border-t mt-2">
|
||||
<Label className="text-xs text-gray-500 uppercase tracking-wider block mb-2">{__('Container Width')}</Label>
|
||||
<RadioGroup
|
||||
value={page.containerWidth || 'boxed'}
|
||||
onValueChange={(val: any) => onContainerWidthChange(val)}
|
||||
className="gap-2"
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="boxed" id="cw-boxed" />
|
||||
<Label htmlFor="cw-boxed" className="text-sm font-normal cursor-pointer">{__('Boxed')}</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="fullwidth" id="cw-full" />
|
||||
<Label htmlFor="cw-full" className="text-sm font-normal cursor-pointer">{__('Full Width')}</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="default" id="cw-default" />
|
||||
<Label htmlFor="cw-default" className="text-sm font-normal cursor-pointer text-gray-500">{__('Default (SPA Settings)')}</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Danger Zone */}
|
||||
{!isTemplate && page && onDeletePage && (
|
||||
<div className="pt-2 border-t mt-2">
|
||||
|
||||
@@ -93,6 +93,12 @@ export default function AppearancePages() {
|
||||
enabled: !!currentPage,
|
||||
});
|
||||
|
||||
// Fetch global settings for defaults
|
||||
const { data: globalSettings } = useQuery({
|
||||
queryKey: ['appearance-settings'],
|
||||
queryFn: async () => api.get('/appearance/settings'),
|
||||
});
|
||||
|
||||
// Update store when page data loads
|
||||
useEffect(() => {
|
||||
if (pageData?.structure?.sections) {
|
||||
@@ -106,6 +112,10 @@ export default function AppearancePages() {
|
||||
if (pageData?.is_front_page !== undefined && currentPage) {
|
||||
setCurrentPage({ ...currentPage, isFrontPage: !!pageData.is_front_page });
|
||||
}
|
||||
// Sync containerWidth
|
||||
if (pageData?.container_width && currentPage) {
|
||||
setCurrentPage({ ...currentPage, containerWidth: pageData.container_width });
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [pageData, setSections, markAsSaved, setAvailableSources]); // Removed currentPage from dependency to avoid loop
|
||||
|
||||
@@ -296,7 +306,13 @@ export default function AppearancePages() {
|
||||
onDuplicateSection={duplicateSection}
|
||||
onMoveSection={moveSection}
|
||||
onReorderSections={reorderSections}
|
||||
|
||||
onDeviceModeChange={setDeviceMode}
|
||||
containerWidth={
|
||||
currentPage?.containerWidth && currentPage.containerWidth !== 'default'
|
||||
? currentPage.containerWidth
|
||||
: ((globalSettings as any)?.data?.general?.container_width || 'boxed')
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex-1 bg-gray-100 flex items-center justify-center text-gray-400">
|
||||
@@ -356,6 +372,12 @@ export default function AppearancePages() {
|
||||
}}
|
||||
onUnsetSpaLanding={() => unsetSpaLandingMutation.mutate()}
|
||||
onDeletePage={handleDeletePage}
|
||||
onContainerWidthChange={(width) => {
|
||||
if (currentPage) {
|
||||
setCurrentPage({ ...currentPage, containerWidth: width });
|
||||
markAsSaved(); // Mark as changed so save button enables
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ export interface PageItem {
|
||||
url?: string;
|
||||
isFrontPage?: boolean;
|
||||
isSpaLanding?: boolean;
|
||||
containerWidth?: 'boxed' | 'fullwidth';
|
||||
}
|
||||
|
||||
interface PageEditorState {
|
||||
@@ -422,7 +423,10 @@ export const usePageEditorStore = create<PageEditorState>((set, get) => ({
|
||||
'X-WP-Nonce': (window as any).WNW_API.nonce,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ sections })
|
||||
body: JSON.stringify({
|
||||
sections,
|
||||
container_width: currentPage.containerWidth
|
||||
})
|
||||
});
|
||||
|
||||
set({
|
||||
|
||||
Reference in New Issue
Block a user