feat: implement header/footer visibility controls for checkout and thankyou pages
- Created LayoutWrapper component to conditionally render header/footer based on route - Created MinimalHeader component (logo only) - Created MinimalFooter component (trust badges + policy links) - Created usePageVisibility hook to get visibility settings per page - Wrapped ClassicLayout with LayoutWrapper for conditional rendering - Header/footer visibility now controlled directly in React SPA - Settings: show/minimal/hide for both header and footer - Background color support for checkout and thankyou pages
This commit is contained in:
296
customer-spa/src/hooks/useAppearanceSettings.ts
Normal file
296
customer-spa/src/hooks/useAppearanceSettings.ts
Normal file
@@ -0,0 +1,296 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
interface AppearanceSettings {
|
||||
general: {
|
||||
spa_mode: string;
|
||||
typography: any;
|
||||
colors: any;
|
||||
};
|
||||
header: any;
|
||||
footer: any;
|
||||
pages: {
|
||||
shop: {
|
||||
layout: {
|
||||
grid_columns: string;
|
||||
card_style: string;
|
||||
aspect_ratio: string;
|
||||
};
|
||||
elements: {
|
||||
category_filter: boolean;
|
||||
search_bar: boolean;
|
||||
sort_dropdown: boolean;
|
||||
sale_badges: boolean;
|
||||
quick_view: boolean;
|
||||
};
|
||||
sale_badge: {
|
||||
color: string;
|
||||
};
|
||||
add_to_cart: {
|
||||
position: 'below' | 'hover' | 'overlay';
|
||||
style: 'solid' | 'outline' | 'ghost';
|
||||
show_icon: boolean;
|
||||
};
|
||||
};
|
||||
product: any;
|
||||
cart: any;
|
||||
checkout: any;
|
||||
thankyou: any;
|
||||
account: any;
|
||||
};
|
||||
}
|
||||
|
||||
export function useAppearanceSettings() {
|
||||
const apiRoot = (window as any).woonoowCustomer?.apiRoot || '/wp-json/woonoow/v1';
|
||||
|
||||
// Get preloaded settings from window object
|
||||
const preloadedSettings = (window as any).woonoowCustomer?.appearanceSettings;
|
||||
|
||||
return useQuery<AppearanceSettings>({
|
||||
queryKey: ['appearance-settings'],
|
||||
queryFn: async () => {
|
||||
const response = await fetch(`${apiRoot}/appearance/settings`, {
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch appearance settings');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data.data;
|
||||
},
|
||||
initialData: preloadedSettings,
|
||||
staleTime: 1000 * 60 * 5,
|
||||
refetchOnMount: false,
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function useShopSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
const defaultSettings = {
|
||||
layout: {
|
||||
grid_columns: '3' as string,
|
||||
grid_style: 'standard' as string,
|
||||
card_style: 'card' as string,
|
||||
aspect_ratio: 'square' as string,
|
||||
card_text_align: 'left' as string,
|
||||
},
|
||||
elements: {
|
||||
category_filter: true,
|
||||
search_bar: true,
|
||||
sort_dropdown: true,
|
||||
sale_badges: true,
|
||||
quick_view: false,
|
||||
},
|
||||
saleBadge: {
|
||||
color: '#ef4444' as string,
|
||||
},
|
||||
addToCart: {
|
||||
position: 'below' as string,
|
||||
style: 'solid' as string,
|
||||
show_icon: true,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
layout: { ...defaultSettings.layout, ...(data?.pages?.shop?.layout || {}) },
|
||||
elements: { ...defaultSettings.elements, ...(data?.pages?.shop?.elements || {}) },
|
||||
saleBadge: { ...defaultSettings.saleBadge, ...(data?.pages?.shop?.sale_badge || {}) } as { color: string },
|
||||
addToCart: { ...defaultSettings.addToCart, ...(data?.pages?.shop?.add_to_cart || {}) } as { position: string; style: string; show_icon: boolean },
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useProductSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
const defaultSettings = {
|
||||
layout: {
|
||||
image_position: 'left' as string,
|
||||
gallery_style: 'thumbnails' as string,
|
||||
sticky_add_to_cart: false,
|
||||
},
|
||||
elements: {
|
||||
breadcrumbs: true,
|
||||
related_products: true,
|
||||
reviews: true,
|
||||
share_buttons: false,
|
||||
product_meta: true,
|
||||
},
|
||||
related_products: {
|
||||
title: 'You May Also Like' as string,
|
||||
},
|
||||
reviews: {
|
||||
placement: 'product_page' as string,
|
||||
hide_if_empty: true,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
layout: { ...defaultSettings.layout, ...(data?.pages?.product?.layout || {}) },
|
||||
elements: { ...defaultSettings.elements, ...(data?.pages?.product?.elements || {}) },
|
||||
related_products: { ...defaultSettings.related_products, ...(data?.pages?.product?.related_products || {}) },
|
||||
reviews: { ...defaultSettings.reviews, ...(data?.pages?.product?.reviews || {}) },
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useCartSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
const defaultSettings = {
|
||||
layout: {
|
||||
style: 'fullwidth' as string,
|
||||
summary_position: 'right' as string,
|
||||
},
|
||||
elements: {
|
||||
product_images: true,
|
||||
continue_shopping_button: true,
|
||||
coupon_field: true,
|
||||
shipping_calculator: false,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
layout: { ...defaultSettings.layout, ...(data?.pages?.cart?.layout || {}) },
|
||||
elements: { ...defaultSettings.elements, ...(data?.pages?.cart?.elements || {}) },
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useCheckoutSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
const defaultSettings = {
|
||||
layout: {
|
||||
style: 'two-column' as string,
|
||||
order_summary: 'sidebar' as string,
|
||||
header_visibility: 'minimal' as string,
|
||||
footer_visibility: 'minimal' as string,
|
||||
background_color: '#f9fafb' as string,
|
||||
},
|
||||
elements: {
|
||||
order_notes: true,
|
||||
coupon_field: true,
|
||||
shipping_options: true,
|
||||
payment_icons: true,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
layout: { ...defaultSettings.layout, ...(data?.pages?.checkout?.layout || {}) },
|
||||
elements: { ...defaultSettings.elements, ...(data?.pages?.checkout?.elements || {}) },
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useThankYouSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
const defaultSettings = {
|
||||
template: 'basic',
|
||||
header_visibility: 'show',
|
||||
footer_visibility: 'minimal',
|
||||
background_color: '#f9fafb',
|
||||
custom_message: 'Thank you for your order! We\'ll send you a confirmation email shortly.',
|
||||
elements: {
|
||||
order_details: true,
|
||||
continue_shopping_button: true,
|
||||
related_products: false,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
template: data?.pages?.thankyou?.template || defaultSettings.template,
|
||||
headerVisibility: data?.pages?.thankyou?.header_visibility || defaultSettings.header_visibility,
|
||||
footerVisibility: data?.pages?.thankyou?.footer_visibility || defaultSettings.footer_visibility,
|
||||
backgroundColor: data?.pages?.thankyou?.background_color || defaultSettings.background_color,
|
||||
customMessage: data?.pages?.thankyou?.custom_message || defaultSettings.custom_message,
|
||||
elements: { ...defaultSettings.elements, ...(data?.pages?.thankyou?.elements || {}) },
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useAccountSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
const defaultSettings = {
|
||||
layout: {
|
||||
navigation_style: 'sidebar' as string,
|
||||
},
|
||||
elements: {
|
||||
dashboard: true,
|
||||
orders: true,
|
||||
downloads: false,
|
||||
addresses: true,
|
||||
account_details: true,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
layout: { ...defaultSettings.layout, ...(data?.pages?.account?.layout || {}) },
|
||||
elements: { ...defaultSettings.elements, ...(data?.pages?.account?.elements || {}) },
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useHeaderSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
return {
|
||||
style: data?.header?.style ?? 'classic',
|
||||
sticky: data?.header?.sticky ?? true,
|
||||
height: data?.header?.height ?? 'normal',
|
||||
mobile_menu: data?.header?.mobile_menu ?? 'hamburger',
|
||||
mobile_logo: data?.header?.mobile_logo ?? 'left',
|
||||
logo_width: data?.header?.logo_width ?? 'auto',
|
||||
logo_height: data?.header?.logo_height ?? '40px',
|
||||
elements: {
|
||||
logo: data?.header?.elements?.logo ?? true,
|
||||
navigation: data?.header?.elements?.navigation ?? true,
|
||||
search: data?.header?.elements?.search ?? true,
|
||||
account: data?.header?.elements?.account ?? true,
|
||||
cart: data?.header?.elements?.cart ?? true,
|
||||
wishlist: data?.header?.elements?.wishlist ?? false,
|
||||
},
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useFooterSettings() {
|
||||
const { data, isLoading } = useAppearanceSettings();
|
||||
|
||||
return {
|
||||
columns: data?.footer?.columns ?? '4',
|
||||
style: data?.footer?.style ?? 'detailed',
|
||||
copyright_text: data?.footer?.copyright_text ?? '© 2024 WooNooW. All rights reserved.',
|
||||
elements: {
|
||||
newsletter: data?.footer?.elements?.newsletter ?? true,
|
||||
social: data?.footer?.elements?.social ?? true,
|
||||
payment: data?.footer?.elements?.payment ?? true,
|
||||
copyright: data?.footer?.elements?.copyright ?? true,
|
||||
menu: data?.footer?.elements?.menu ?? true,
|
||||
contact: data?.footer?.elements?.contact ?? true,
|
||||
},
|
||||
social_links: data?.footer?.social_links ?? [],
|
||||
sections: data?.footer?.sections ?? [],
|
||||
contact_data: {
|
||||
email: data?.footer?.contact_data?.email ?? '',
|
||||
phone: data?.footer?.contact_data?.phone ?? '',
|
||||
address: data?.footer?.contact_data?.address ?? '',
|
||||
show_email: data?.footer?.contact_data?.show_email ?? true,
|
||||
show_phone: data?.footer?.contact_data?.show_phone ?? true,
|
||||
show_address: data?.footer?.contact_data?.show_address ?? true,
|
||||
},
|
||||
labels: {
|
||||
contact_title: data?.footer?.labels?.contact_title ?? 'Contact',
|
||||
menu_title: data?.footer?.labels?.menu_title ?? 'Quick Links',
|
||||
social_title: data?.footer?.labels?.social_title ?? 'Follow Us',
|
||||
newsletter_title: data?.footer?.labels?.newsletter_title ?? 'Newsletter',
|
||||
newsletter_description: data?.footer?.labels?.newsletter_description ?? 'Subscribe to get updates',
|
||||
},
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
34
customer-spa/src/hooks/usePageVisibility.ts
Normal file
34
customer-spa/src/hooks/usePageVisibility.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useCheckoutSettings, useThankYouSettings } from './useAppearanceSettings';
|
||||
|
||||
export function usePageVisibility() {
|
||||
const location = useLocation();
|
||||
const checkoutSettings = useCheckoutSettings();
|
||||
const thankYouSettings = useThankYouSettings();
|
||||
|
||||
// Default visibility
|
||||
let headerVisibility = 'show';
|
||||
let footerVisibility = 'show';
|
||||
let backgroundColor = '';
|
||||
|
||||
// Check current route and get visibility settings
|
||||
if (location.pathname === '/checkout') {
|
||||
headerVisibility = checkoutSettings.layout.header_visibility || 'minimal';
|
||||
footerVisibility = checkoutSettings.layout.footer_visibility || 'minimal';
|
||||
backgroundColor = checkoutSettings.layout.background_color || '';
|
||||
} else if (location.pathname.startsWith('/order-received/')) {
|
||||
headerVisibility = thankYouSettings.headerVisibility || 'show';
|
||||
footerVisibility = thankYouSettings.footerVisibility || 'minimal';
|
||||
backgroundColor = thankYouSettings.backgroundColor || '';
|
||||
}
|
||||
|
||||
return {
|
||||
headerVisibility,
|
||||
footerVisibility,
|
||||
backgroundColor,
|
||||
shouldShowHeader: headerVisibility !== 'hide',
|
||||
shouldShowFooter: footerVisibility !== 'hide',
|
||||
isMinimalHeader: headerVisibility === 'minimal',
|
||||
isMinimalFooter: footerVisibility === 'minimal',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user