import { __ } from '@wordpress/i18n';
import { useState, useMemo, useCallback } from '@wordpress/element';
import { useSuspenseSelect, useDispatch } from '@wordpress/data';
import { STORE_NAME } from '@AdminStore/constants';
import { Label, Button } from '@bsf/force-ui';
import { Plus } from 'lucide-react';
import apiFetch from '@wordpress/api-fetch';
import ConditionSelect from './condition-select';
import { GET_POSTS_BY_QUERY_URL } from '@Global/constants/api';
const DisplayConditions = ( { schemaId } ) => {
const { setMetaSetting } = useDispatch( STORE_NAME );
const { metaSettings } = useSuspenseSelect( ( select ) => {
const { getMetaSettings } = select( STORE_NAME );
return { metaSettings: getMetaSettings() };
}, [] );
const displayRules = surerank_globals?.schema_rules || {};
const schemaSettings = metaSettings.schemas?.[ schemaId ] || {};
const groupedOptions = useMemo( () => {
return Object.entries( displayRules ).map( ( [ key, rule ] ) => ( {
label: rule.label,
options: Object.entries( rule.value ).map(
( [ valueKey, label ] ) => ( {
value: valueKey,
label,
key,
} )
),
} ) );
}, [ displayRules ] );
const initialShowOn = schemaSettings.show_on?.rules?.length
? Array.from( new Set( schemaSettings.show_on?.rules ) ).map(
( rule ) => ( {
condition: rule,
specificPosts:
rule === 'specifics'
? schemaSettings?.show_on?.specificText || []
: [],
searchOptions: [],
} )
)
: [ { condition: '', specificPosts: [], searchOptions: [] } ];
const initialNotShowOn = schemaSettings.not_show_on?.rules?.length
? Array.from( new Set( schemaSettings.not_show_on?.rules ) ).map(
( rule ) => ( {
condition: rule,
specificPosts:
rule === 'specifics'
? schemaSettings?.not_show_on?.specificText || []
: [],
searchOptions: [],
} )
)
: [ { condition: '', specificPosts: [], searchOptions: [] } ];
// Flattened state
const [ conditionsState, setConditionsState ] = useState( {
show_on: initialShowOn,
not_show_on: initialNotShowOn,
} );
// Function to update specific conditions
const setConditionsByType = ( type, updatedConditions ) => {
setConditionsState( ( prevState ) => ( {
...prevState,
[ type ]: updatedConditions,
} ) );
};
const fetchSpecificPosts = useCallback(
async ( query, index, type ) => {
try {
const response = await apiFetch( {
path: GET_POSTS_BY_QUERY_URL,
method: 'POST',
data: { q: query },
} );
if ( response?.success && Array.isArray( response?.results ) ) {
const groupedOptionsData = response.results.map(
( group ) => ( {
label: group.text,
options: group.children.map( ( child ) => ( {
value: child.id,
label: child.text,
} ) ),
} )
);
setConditionsState( ( prevState ) => {
const updatedConditions = [ ...prevState[ type ] ];
updatedConditions[ index ].searchOptions =
groupedOptionsData;
return {
...prevState,
[ type ]: updatedConditions,
};
} );
}
} catch ( error ) {
// return error;
}
},
[] // No dependencies because it doesn't rely on external state or props
);
const updateSchema = useCallback(
( key, updatedRules, updatedSpecific = null ) => {
const deduplicatedSpecific = Array.from(
new Set( updatedSpecific?.map( ( item ) => item.value ) )
);
const updatedSpecificText =
updatedSpecific?.filter( ( item ) =>
deduplicatedSpecific.includes( item.value )
) || [];
const updatedSchema = {
...schemaSettings,
[ key ]: {
rules: updatedRules,
specific: deduplicatedSpecific,
specificText: updatedSpecificText,
},
};
setMetaSetting( 'schemas', {
...metaSettings.schemas,
[ schemaId ]: updatedSchema,
} );
},
[ schemaSettings, schemaId, metaSettings.schemas, setMetaSetting ]
);
const addCondition = ( type ) => {
setConditionsState( ( prevState ) => {
const updatedConditions = [ ...prevState[ type ] ];
updatedConditions.push( {
condition: '',
specificPosts: [],
searchOptions: [],
} );
updateSchema(
type,
updatedConditions.map( ( cond ) => cond.condition ),
updatedConditions
.filter( ( cond ) => cond.condition === 'specifics' )
.flatMap( ( cond ) => cond.specificPosts )
);
return {
...prevState,
[ type ]: updatedConditions,
};
} );
};
return (
<>
<div className="space-y-2 p-2">
<Label required>{ __( 'Display On', 'surerank' ) }</Label>
<ConditionSelect
conditionsList={ conditionsState.show_on }
setConditionsList={ ( updatedConditions ) =>
setConditionsByType( 'show_on', updatedConditions )
}
groupedOptions={ groupedOptions }
viewKey="show_on"
updateSchema={ updateSchema }
fetchSpecificPosts={ fetchSpecificPosts }
/>
<Button
variant="ghost"
size="xs"
onClick={ () => addCondition( 'show_on' ) }
className="flex items-center gap-1"
icon={ <Plus className="size-4" /> }
>
{ __( 'Add Condition', 'surerank' ) }
</Button>
</div>
<div className="space-y-2 p-2">
<Label>{ __( 'Do Not Display On', 'surerank' ) }</Label>
<ConditionSelect
conditionsList={ conditionsState.not_show_on }
setConditionsList={ ( updatedConditions ) =>
setConditionsByType( 'not_show_on', updatedConditions )
}
groupedOptions={ groupedOptions }
viewKey="not_show_on"
updateSchema={ updateSchema }
fetchSpecificPosts={ fetchSpecificPosts }
/>
<Button
variant="ghost"
size="xs"
onClick={ () => addCondition( 'not_show_on' ) }
className="flex items-center gap-1"
icon={ <Plus className="size-4" /> }
>
{ __( 'Add Condition', 'surerank' ) }
</Button>
</div>
</>
);
};
export default DisplayConditions;