// Editor entry (ESNext) for Swiss Football blocks.
// This registers blocks and the shortcode insertion toolbar button.
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { InspectorControls, useBlockProps, RawHTML } from '@wordpress/block-editor';
import { PanelBody, SelectControl, ToggleControl, RangeControl, Spinner } from '@wordpress/components';
import { useState, useEffect, createElement } from '@wordpress/element';
import { registerFormatType, applyFormat } from '@wordpress/rich-text';
import './format-shortcode';
function makeAjaxCall(action, data = {}) {
const root = swiFootEditorData.rest_url.replace(/\/$/, '');
let url = root;
const opts = { credentials: 'same-origin', headers: { 'X-WP-Nonce': swiFootEditorData.rest_nonce } };
if (action === 'swi_foot_get_teams_for_editor') {
url += '/teams'; opts.method = 'GET';
} else if (action === 'swi_foot_get_matches_for_team') {
url += '/matches?team_id=' + encodeURIComponent(data.team_id || ''); opts.method = 'GET';
} else if (action === 'swi_foot_get_commons_ids') {
url += '/commons-ids'; opts.method = 'GET';
} else {
return Promise.reject({ error: 'Unknown action' });
}
return fetch(url, opts)
.then(r => { if (!r.ok) return r.json().then(j => Promise.reject(j)); return r.json(); })
.then(data => {
// Transform API response into expected format for editor blocks
if (action === 'swi_foot_get_teams_for_editor') {
return {
success: true,
data: Array.isArray(data) ? data.map(team => ({
value: team.teamId,
label: team.teamName
})) : []
};
} else if (action === 'swi_foot_get_matches_for_team') {
return {
success: true,
data: Array.isArray(data) ? data.map(match => ({
value: match.matchId,
label: `${match.teamNameA} vs ${match.teamNameB} (${match.matchDate})`
})) : []
};
}
return { success: true, data: data };
});
}
function checkBlockStatus(matchId, endpoint) {
if (!matchId) return Promise.resolve(null);
const root = swiFootEditorData.rest_url.replace(/\/$/, '');
const url = `${root}/block-status/${matchId}/${endpoint}`;
const opts = { credentials: 'same-origin', headers: { 'X-WP-Nonce': swiFootEditorData.rest_nonce } };
return fetch(url, opts)
.then(r => r.json())
.catch(() => null);
}
// Standings block (editor UI only, server renders)
// Gets team from container context, no user selection needed
registerBlockType('swi-foot/standings', {
apiVersion: 3,
title: __('Swiss Football Standings', 'swi_foot_matchdata'),
category: 'swi-football',
supports: { align: true, anchor: true },
edit: ({ attributes, setAttributes, isSelected }) => {
const blockProps = useBlockProps({ style: isSelected ? {outline: '2px solid #0073aa'} : {} });
return (
{__('Team is inherited from the container context.', 'swi_foot_matchdata')}
{__('Standings', 'swi_foot_matchdata')}
{__('League standings inherited from team context. ✓ Data will render on the front-end.', 'swi_foot_matchdata')}
);
},
save: () => null
});
// Schedule block (editor UI only, server renders)
// Gets team from container context, only allows limiting results
registerBlockType('swi-foot/schedule', {
apiVersion: 3,
title: __('Swiss Football Schedule', 'swi_foot_matchdata'),
category: 'swi-football',
supports: { align: true, anchor: true },
attributes: {
limit: { type: 'number', default: 10 },
matchFilter: { type: 'string', default: 'all' }
},
edit: ({ attributes, setAttributes, isSelected }) => {
const blockProps = useBlockProps({ style: isSelected ? {outline: '2px solid #0073aa'} : {} });
const { limit, matchFilter } = attributes;
return (
{__('Team is inherited from the container context.', 'swi_foot_matchdata')}
setAttributes({ limit: val })} min={1} max={20} />
setAttributes({ matchFilter: val })}
/>
{__('Schedule', 'swi_foot_matchdata')}
{__('Team and match schedule inherited from context. ✓ Data will render on the front-end.', 'swi_foot_matchdata')}
);
},
save: ({ attributes }) => null
});
// Match Roster
// Gets match and team from container context, only allows selecting which side (home/away) and bench option
registerBlockType('swi-foot/match-roster', {
apiVersion: 3,
title: __('Swiss Football Match Roster', 'swi_foot_matchdata'),
category: 'swi-football',
supports: { align: true, anchor: true },
attributes: {
side: { type: 'string', default: 'home' },
showStartingSquad: { type: 'boolean', default: true },
showBench: { type: 'boolean', default: false }
},
edit: ({ attributes, setAttributes, isSelected }) => {
const blockProps = useBlockProps({ style: isSelected ? {outline: '2px solid #0073aa'} : {} });
const { side, showStartingSquad, showBench } = attributes;
return (
{__('Match and team are inherited from the container context.', 'swi_foot_matchdata')}
setAttributes({side:v})}
__next40pxDefaultSize={true}
__nextHasNoMarginBottom={true}
/>
setAttributes({showStartingSquad:v})}
__nextHasNoMarginBottom={true}
/>
setAttributes({showBench:v})}
__nextHasNoMarginBottom={true}
/>
{__('Match Roster', 'swi_foot_matchdata')}
{__('Team and match are inherited from the container context. ✓ Data will render on the front-end.', 'swi_foot_matchdata')}
);
},
save: ({ attributes }) => {
const { side, showStartingSquad, showBench } = attributes;
let shortcode = '[swi_foot_roster side="' + side + '"';
if (showStartingSquad) shortcode += ' starting_squad="true"';
if (showBench) shortcode += ' bench="true"';
shortcode += ']';
return createElement(RawHTML, null, shortcode);
}
});
// Match Events
// Gets match and team from container context, only allows setting refresh interval
registerBlockType('swi-foot/match-events', {
apiVersion: 3,
title: __('Swiss Football Match Events', 'swi_foot_matchdata'),
category: 'swi-football',
supports: { align: true, anchor: true },
attributes: {
refreshInterval: { type: 'number', default: 30 },
eventOrder: { type: 'string', default: 'dynamic' }
},
edit: ({ attributes, setAttributes, isSelected }) => {
const blockProps = useBlockProps({ style: isSelected ? {outline: '2px solid #0073aa'} : {} });
const { refreshInterval, eventOrder } = attributes;
return (
{__('Match and team are inherited from the container context.', 'swi_foot_matchdata')}
setAttributes({refreshInterval:v})}
min={10}
max={300}
step={10}
/>
setAttributes({eventOrder:v})}
options={[
{ label: __('Dynamic (Newest first while live, chronological after)', 'swi_foot_matchdata'), value: 'dynamic' },
{ label: __('Newest First', 'swi_foot_matchdata'), value: 'newest_first' },
{ label: __('Oldest First', 'swi_foot_matchdata'), value: 'oldest_first' }
]}
help={__('Dynamic: newest events at top while match is ongoing, chronological (oldest first) after match ends', 'swi_foot_matchdata')}
__next40pxDefaultSize={true}
__nextHasNoMarginBottom={true}
/>
{__('Match Events', 'swi_foot_matchdata')}
{__('Live match events inherited from context. ✓ Will update during match.', 'swi_foot_matchdata')}
);
},
save: ({ attributes }) => {
const { refreshInterval, eventOrder } = attributes;
let shortcode = '[swi_foot_events refresh_interval="' + (refreshInterval || 30) + '"';
if (eventOrder && eventOrder !== 'dynamic') {
shortcode += ' event_order="' + eventOrder + '"';
}
shortcode += ']';
return createElement(RawHTML, null, shortcode);
}
});
// Match Bench
// Gets match from container context, displays team staff and bench players
registerBlockType('swi-foot/match-bench', {
apiVersion: 3,
title: __('Swiss Football Match Bench', 'swi_foot_matchdata'),
icon: 'clipboard-user',
category: 'swi-football',
supports: { align: true, anchor: true },
attributes: {
side: { type: 'string', default: 'home' }
},
edit: ({ attributes, setAttributes, isSelected }) => {
const blockProps = useBlockProps({ style: isSelected ? {outline: '2px solid #0073aa'} : {} });
const { side } = attributes;
return (
{__('Match is inherited from the container context.', 'swi_foot_matchdata')}
setAttributes({side:v})}
__next40pxDefaultSize={true}
__nextHasNoMarginBottom={true}
/>
{__('Match Bench', 'swi_foot_matchdata')}
{__('Team bench and substitutes inherited from context. ✓ Data will render on the front-end.', 'swi_foot_matchdata')}
);
},
save: ({ attributes }) => {
const { side } = attributes;
let shortcode = '[swi_foot_bench side="' + side + '"]';
return createElement(RawHTML, null, shortcode);
}
});
// Match Referees
// Gets match from container context, displays match officials and referees
registerBlockType('swi-foot/match-referees', {
apiVersion: 3,
title: __('Swiss Football Match Referees', 'swi_foot_matchdata'),
icon: 'whistle',
category: 'swi-football',
supports: { align: true, anchor: true },
edit: ({ attributes, isSelected }) => {
const blockProps = useBlockProps({ style: isSelected ? {outline: '2px solid #0073aa'} : {} });
return (
{__('Match is inherited from the container context.', 'swi_foot_matchdata')}
{__('Match Referees', 'swi_foot_matchdata')}
{__('Match officials and referees inherited from context. ✓ Data will render on the front-end.', 'swi_foot_matchdata')}
);
},
save: () => null
});