import React, { useEffect, useMemo, useRef, useState } from 'react'; import { __ } from '@wordpress/i18n'; import apiFetch from '@wordpress/api-fetch'; import { useWizardStore } from '@/store/reports/useWizardStore'; import { useTheme } from '@/hooks/useTheme'; import { AdminWysiwygField } from '@/components/Fields/Wysiwyg/WysiwygField'; import WysiwygPreview from '@/components/Common/WysiwygPreview'; import { BlockComponentProps } from '@/store/reports/types'; import useSettingsData from '@/hooks/useSettingsData'; import { useAttachmentUrl } from '@/hooks/useAttachmentUrl'; const HERO_BLOCK_SETTING = { id: 'hero' }; const LABEL_STYLE = 'margin:0 0 2px;font-size:10px;text-transform:uppercase;letter-spacing:0.08em;'; const DEFAULT_HERO_TEMPLATE = [ `

${ __( 'Created by', 'burst-statistics' ) }

`, '

{created_by}

', `

${ __( 'Created on', 'burst-statistics' ) }

`, '

{created_at}

' ].join( '' ); const HeroBlock: React.FC = ({ reportBlockIndex = 0 }) => { const isEditingMode = useWizardStore( ( state ) => state.isEditingMode ); const content = useWizardStore( ( state ) => state.wizard.content[ reportBlockIndex ]?.content ?? '' ); const updateComment = useWizardStore( ( state ) => state.updateComment ); const { isDarkTheme } = useTheme(); const { getValue } = useSettingsData(); const logoId = getValue( 'logo_attachment_id' ); const rawBgImageId = getValue( 'hero_background_image_attachment_id' ); const brandColor: string = getValue( 'brand_color' ); const colorOverlayEnabled: boolean = getValue( 'hero_color_overlay_enabled' ); const heroBgDefaultUrl = ( window as any ).burst_settings.plugin_url + 'assets/img/burst-report-hero-bg.jpg'; // eslint-disable-line @typescript-eslint/no-explicit-any const logoQuery = useAttachmentUrl( logoId ); const bgImageQuery = useAttachmentUrl( rawBgImageId ?? 0, heroBgDefaultUrl ); const logoUrl = logoQuery.data?.attachmentUrl ?? ''; const bgImageUrl = bgImageQuery.data?.attachmentUrl ?? ''; // eslint-disable-next-line @typescript-eslint/no-explicit-any const [ displayName, setDisplayName ] = useState( () => ( window as any ).wp?.data?.select( 'core' )?.getCurrentUser()?.name ?? '' ); useEffect( () => { if ( displayName ) { return; } apiFetch<{ name: string }>({ path: '/wp/v2/users/me' }) .then( ( user ) => setDisplayName( user?.name ?? '' ) ) .catch( () => {}); }, []); // eslint-disable-line react-hooks/exhaustive-deps const dateStr = new Intl.DateTimeFormat( 'en-GB', { day: 'numeric', month: 'long', year: 'numeric' }).format( new Date() ); // Strip full burst wrapper, keeping only the raw shortcode. const stripBurstComments = ( html: string ) => html .replace( /[\s\S]*?(\{[^}]+\})/g, '$1' ); // Wrap each shortcode: value{shortcode} const injectValues = ( html: string ) => { const clean = stripBurstComments( html ); return clean .replace( /\{created_by\}/g, `${displayName}{created_by}` ) .replace( /\{created_at\}/g, `${dateStr}{created_at}` ); }; // Editor sees raw shortcodes — strip comments and values. const stripValues = ( html: string ) => stripBurstComments( html ); // Preview/story: extract value from between opening comment and shortcode. const resolveFromComments = ( html: string ) => html .replace( /([\s\S]*?)\{[^}]+\}/g, '$2' ); // Seed default template once when hero block is first added (empty content, editing mode). // Wait for displayName so the resolved value is stored immediately. const didSeedTemplate = useRef( false ); useEffect( () => { if ( didSeedTemplate.current || ! isEditingMode || content || ! displayName ) { return; } didSeedTemplate.current = true; updateComment( reportBlockIndex, injectValues( DEFAULT_HERO_TEMPLATE ) ); }, [ isEditingMode, content, reportBlockIndex, updateComment, displayName ]); // eslint-disable-line react-hooks/exhaustive-deps const field = useMemo( () => ({ value: stripValues( content ), onChange: ( value: string ) => updateComment( reportBlockIndex, injectValues( value ) ), name: `hero_${ reportBlockIndex }` }), [ content, reportBlockIndex, updateComment, displayName ]); // eslint-disable-line react-hooks/exhaustive-deps const previewContent = resolveFromComments( content || injectValues( DEFAULT_HERO_TEMPLATE ) ); const leftColClass = bgImageUrl ? 'md:col-span-7' : 'md:col-span-12'; return (
{ logoUrl && (
logo
) }
{ isEditingMode ? ( ) : ( ) }
{ bgImageUrl && (
{ !! brandColor && !! colorOverlayEnabled && (
) }
); }; HeroBlock.displayName = 'HeroBlock'; export default HeroBlock;