File "display-conditions.js"

Full Path: /home/fresvfqn/waterdamagerestorationandrepairsmithtown.com/wp-content/plugins/surerank/src/apps/admin-general/schema/edit/display-conditions.js
File size: 5.8 KB
MIME-type: text/x-java
Charset: utf-8

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;