File "social.js"
Full Path: /home/fresvfqn/waterdamagerestorationandrepairsmithtown.com/wp-content/plugins/surerank/src/apps/admin-general/general/home-page/social.js
File size: 9.44 KB
MIME-type: text/x-java
Charset: utf-8
import { __, sprintf } from '@wordpress/i18n';
import { motion } from 'framer-motion';
import {
Tabs,
Label,
Input,
EditorInput,
Switch,
Container,
Text,
} from '@bsf/force-ui';
import { useCallback, useRef, useState } from '@wordpress/element';
import { Facebook } from 'lucide-react';
import SocialPreview from '@GlobalComponents/social-preview';
import {
INPUT_VARIABLE_SUGGESTIONS as variableSuggestions,
MAX_EDITOR_INPUT_LENGTH,
} from '@Global/constants';
import {
editorValueToString,
stringValueToFormatJSON,
truncateText,
} from '@Functions/utils';
import replacement from '@Functions/replacement';
import GeneratePageContent from '@Functions/page-content-generator';
import useSettings from '@/global/hooks/use-admin-settings';
import { InfoTooltip } from '@AdminComponents/tooltip';
import { XSocialIcon } from '@/global/components/icons';
import MediaPreview from '@/apps/admin-components/media-preview';
import { createMediaFrame } from '@/global/utils/utils';
const socialMedia = [
{
label: 'Facebook',
icon: Facebook,
tabSlug: 'facebook',
},
{
label: 'X',
icon: XSocialIcon,
tabSlug: 'twitter',
},
];
const renderIf = ( condition, content, fallbackContent ) => {
if ( condition ) {
return typeof content === 'function' ? content() : content;
}
return typeof fallbackContent === 'function'
? fallbackContent()
: fallbackContent;
};
const SocialSettings = () => {
const { metaSettings, siteSettings, setMetaSetting, setSiteSettings } =
useSettings();
const [ activeSocialTab, setActiveSocialTab ] = useState( 'facebook' );
const handleTabChange = useCallback( ( { value } ) => {
setActiveSocialTab( value.slug );
}, [] );
const handleClickInput = ( event ) => {
event.preventDefault();
const mediaUploader = createMediaFrame( {
title: 'Select Image',
button: {
text: 'Use this image',
},
multiple: false,
} );
mediaUploader.on( 'select', () => {
const attachment = mediaUploader
.state()
.get( 'selection' )
.first()
.toJSON();
setMetaSetting(
`home_page_${ activeSocialTab }_image_url`,
attachment.url
);
setSiteSettings( {
...siteSettings,
home_page_featured_image: attachment.url,
} );
} );
mediaUploader.open();
};
const getPreviewData = useCallback(
( key, fallbackValue ) => {
let mainKey = `home_page_${ activeSocialTab }`;
// If the active tab is Twitter and it's set to use Facebook data
if (
activeSocialTab === 'twitter' &&
!! metaSettings?.twitter_same_as_facebook
) {
mainKey = 'home_page_facebook'; // Use Facebook's data
}
// Fetch the data from metaSettings or fallback value
return (
metaSettings?.[ `${ mainKey }_${ key }` ] ||
fallbackValue?.[ `${ mainKey }_${ key }` ]
);
},
[ activeSocialTab, metaSettings ]
);
const { home_page_title: title, home_page_description: description } =
metaSettings;
const titlePreview = truncateText(
replacement(
getPreviewData( 'title', metaSettings ) || title,
siteSettings?.site
),
null
);
const descriptionPreview = truncateText(
replacement(
getPreviewData( 'description', metaSettings ) || description,
siteSettings?.site
),
78
);
const defaultTitleValue =
metaSettings[ `home_page_${ activeSocialTab }_title` ] || title;
const defaultDescriptionValue =
metaSettings[ `home_page_${ activeSocialTab }_description` ] ||
description;
const titleEditor = useRef( null );
const descriptionEditor = useRef( null );
const handleUpdatePostMetaData = ( key, value ) => {
setMetaSetting( key, value );
};
const removeImage = useCallback( () => {
setMetaSetting( `home_page_${ activeSocialTab }_image_url`, '' );
setSiteSettings( {
...siteSettings,
home_page_featured_image: '',
} );
}, [ setMetaSetting, activeSocialTab ] );
return (
<Container direction="column" className="w-full gap-6">
<div>
<Tabs.Group
activeItem={ activeSocialTab }
variant="rounded"
width="full"
onChange={ handleTabChange }
>
{ socialMedia.map( ( { label, icon: Icon, tabSlug } ) => (
<Tabs.Tab
key={ tabSlug }
slug={ tabSlug }
text={ label }
icon={ <Icon /> }
/>
) ) }
</Tabs.Group>
</div>
<motion.div
key={ activeSocialTab }
className="flex-1 flex flex-col gap-6"
initial={ { opacity: 0 } }
animate={ { opacity: 1 } }
exit={ { opacity: 0 } }
transition={ { duration: 0.2 } }
>
{ /* Use data from Facebook tab toggle button */ }
{ activeSocialTab === 'twitter' && (
<div className="flex items-center gap-3">
<Switch
id="facebook_same_as_twitter"
name="facebook_same_as_twitter"
size="sm"
defaultValue={
!! metaSettings?.twitter_same_as_facebook
}
onChange={ ( value ) => {
setMetaSetting(
'twitter_same_as_facebook',
value ? '1' : ''
);
} }
/>
<Label htmlFor="facebook_same_as_twitter" size="sm">
{ __( 'Use data from Facebook Tab', 'surerank' ) }
</Label>
</div>
) }
{ renderIf(
activeSocialTab === 'twitter' &&
!! metaSettings?.twitter_same_as_facebook,
null,
<>
{ /* Social Title */ }
<div className="space-y-1.5">
{ /* Label & Limit */ }
<div className="flex items-center justify-between gap-1">
<Label
tag="span"
size="sm"
className="space-x-0.5"
>
<span>
{ __( 'Social Title', 'surerank' ) }
</span>
</Label>
</div>
{ /* Input */ }
<EditorInput
ref={ titleEditor }
by="label"
trigger="@"
defaultValue={ stringValueToFormatJSON(
defaultTitleValue,
variableSuggestions,
'value'
) }
options={ variableSuggestions }
onChange={ ( editorState ) => {
handleUpdatePostMetaData(
`home_page_${ activeSocialTab }_title`,
editorValueToString(
editorState.toJSON()
)
);
} }
placeholder={ '' }
/>
{ /* Hint text */ }
<Text size={ 14 } weight={ 400 } color="help">
{ __(
'Type @ to view variable suggestions',
'surerank'
) }
</Text>
</div>
{ /* Social description */ }
<div className="space-y-1.5">
{ /* Label & Limit */ }
<div className="flex items-center justify-between gap-1">
<Label
tag="span"
size="sm"
className="space-x-0.5"
>
<span>
{ __(
'Social Description',
'surerank'
) }
</span>
</Label>
</div>
{ /* Input */ }
<EditorInput
ref={ descriptionEditor }
className="[&+div]:items-start [&+div]:pt-1"
by="label"
trigger="@"
defaultValue={ stringValueToFormatJSON(
defaultDescriptionValue,
variableSuggestions,
'value'
) }
options={ variableSuggestions }
onChange={ ( editorState ) => {
handleUpdatePostMetaData(
`home_page_${ activeSocialTab }_description`,
editorValueToString(
editorState.toJSON()
)
);
} }
placeholder={ '' }
maxLength={ MAX_EDITOR_INPUT_LENGTH }
/>
{ /* Hint text */ }
<Text size={ 14 } weight={ 400 } color="help">
{ __(
'Type @ to view variable suggestions',
'surerank'
) }
</Text>
</div>
<div className="space-y-1.5">
{ /* Label */ }
<div className="flex items-center justify-start gap-1">
<Label tag="span" size="sm">
{ __( 'Social Image', 'surerank' ) }
</Label>
<InfoTooltip
content={ __(
'Set a default image that will be used for social sharing when no featured or social-specific image is available. This ensures your content always has a visual when shared on platforms like Facebook or X (Twitter).',
'surerank'
) }
/>
</div>
{ /* Input */ }
<Input
className="m-0 [&>input]:m-0 [&>input]:transition-colors [&>input]:duration-150 [&>input]:ease-in-out"
type="file"
size="md"
onClick={ handleClickInput }
/>
<MediaPreview
imageUrl={ getPreviewData(
`image_url`,
siteSettings
) }
onRemove={ removeImage }
/>
</div>
</>
) }
<div className="space-y-2">
{ /* Label */ }
<Label tag="span" size="sm">
{ sprintf(
// Translators: %s: Facebook or Twitter
__( '%s Preview', 'surerank' ),
activeSocialTab === 'facebook' ? 'Facebook' : 'X'
) }
</Label>
{ /* Preview */ }
<SocialPreview
type={ activeSocialTab }
title={ titlePreview }
description={ descriptionPreview }
twitterLargePreview={
metaSettings?.twitter_card_type ===
'summary_large_image'
}
imageURL={ getPreviewData( `image_url`, siteSettings ) }
siteURL={ siteSettings?.site?.site_url?.replace(
/(^\w+:|^)\/\//,
''
) }
hideRemoveButton
/>
</div>
</motion.div>
</Container>
);
};
const PAGE_CONTENT = [
{
container: null,
content: [
{
id: 'homepage-social-settings',
type: 'custom',
component: <SocialSettings />,
},
],
},
];
const SocialTab = () => {
return <GeneratePageContent json={ PAGE_CONTENT } />;
};
export default SocialTab;