File "site-selector-popup.js"
Full Path: /home/fresvfqn/waterdamagerestorationandrepairsmithtown.com/wp-content/plugins/surerank/src/apps/admin-dashboard/site-selector-popup.js
File size: 10.13 KB
MIME-type: text/x-java
Charset: utf-8
import apiFetch from '@wordpress/api-fetch';
import {
Button,
toast,
Loader,
Skeleton,
Container,
Alert,
Text,
} from '@bsf/force-ui';
import { useDispatch, useSuspenseSelect, useSelect } from '@wordpress/data';
import { STORE_NAME } from '@/admin-store/constants';
import { __ } from '@wordpress/i18n';
import { useState, Suspense } from '@wordpress/element';
import { handleDisconnectConfirm } from '../admin-components/user-dropdown';
import { X } from 'lucide-react';
import ModalWrapper from '@AdminComponents/modal-wrapper';
import useSiteVerificationStatus, {
normalizeUrl,
} from './use-site-verification-status';
import SiteSelector from './site-selector';
const SiteSelectorPopup = () => {
const { toggleSiteSelectorModal } = useDispatch( STORE_NAME );
const searchConsole = useSelect(
( select ) => select( STORE_NAME ).getSearchConsole(),
[]
);
const isSiteSelected = () => {
return !! searchConsole?.hasSiteSelected;
};
return (
<ModalWrapper
maxWidth="max-w-[480px]"
isOpen={ toggleSiteSelectorModal }
>
<Container
className="relative bg-white rounded-lg shadow-lg max-w-md w-full"
direction="column"
gap="xs"
>
{ /* Header */ }
<Container
className="border-b border-gray-200 p-5 pb-2"
justify="between"
align="start"
gap="xs"
direction="column"
>
<Container
justify="between"
align="start"
gap="xs"
className="w-full"
>
<Text className="text-lg font-semibold">
{ __( 'Search Console Account', 'surerank' ) }
</Text>
{ isSiteSelected() && (
<Button
icon={ <X /> }
onClick={ toggleSiteSelectorModal }
variant="ghost"
className="p-0"
/>
) }
</Container>
<Container direction="column" gap="xs">
<Text className="text-sm text-gray-600">
{ __(
'Please select a site below to view its data.',
'surerank'
) }
</Text>
</Container>
</Container>
{ /* Body */ }
<Suspense
fallback={
<Container direction="column" className="gap-5">
<Container
direction="column"
className="gap-1.5 px-5 pt-2"
>
<Skeleton className="h-5 w-1/4" />
<Skeleton className="h-10 w-full" />
</Container>
<Container justify="end" className="p-4 gap-3">
<Skeleton className="h-10 w-20" />
<Skeleton className="h-10 w-20" />
</Container>
</Container>
}
>
<SiteSelectorInputs />
</Suspense>
</Container>
</ModalWrapper>
);
};
const SiteSelectorInputs = () => {
const searchConsole = useSuspenseSelect(
( select ) => select( STORE_NAME ).getSearchConsole(),
[]
);
const { toggleSiteSelectorModal, setSearchConsole, setConfirmationModal } =
useDispatch( STORE_NAME );
const [ isLoading, setIsLoading ] = useState( false );
const [ isCreatingProperty, setIsCreatingProperty ] = useState( false );
// Check if current site is in the available sites list
const getCurrentSiteUrl = () => {
// Get current site URL from window location or WordPress localized data
return window.location.origin;
};
const currentSiteUrl = getCurrentSiteUrl();
// Set default selected site - if current site is not in list, use current site URL
const [ selectedSite, setSelectedSite ] = useState( () => {
const isCurrentSiteInList = searchConsole?.sites?.some(
( site ) =>
site.siteUrl === currentSiteUrl ||
site.siteUrl === `${ currentSiteUrl }/` ||
normalizeUrl( site.siteUrl ) === normalizeUrl( currentSiteUrl )
);
return ! isCurrentSiteInList
? currentSiteUrl
: searchConsole?.selectedSite ||
searchConsole?.tempSelectedSite ||
currentSiteUrl;
} );
// Use the custom hook for site verification status
const {
isSelectedSiteVerified,
currentSiteInListButNotVerified,
shouldShowConnectAlert,
} = useSiteVerificationStatus(
selectedSite,
currentSiteUrl,
searchConsole
);
const handleSelectSite = ( site ) => {
setSelectedSite( site );
};
const handleDisconnect = () => {
setConfirmationModal( {
open: true,
title: __( 'Disconnect Search Console Account', 'surerank' ),
description: __(
'Are you sure you want to disconnect your Search Console account from SureRank?',
'surerank'
),
onConfirm: handleDisconnectConfirm,
confirmButtonText: __( 'Disconnect', 'surerank' ),
} );
};
const handleCreateProperty = async () => {
if ( isCreatingProperty ) {
return;
}
setIsCreatingProperty( true );
try {
// Use different endpoints based on whether site exists or not
const endpoint = currentSiteInListButNotVerified
? '/surerank/v1/google-search-console/verify-site'
: '/surerank/v1/google-search-console/add-site';
const response = await apiFetch( {
path: endpoint,
method: 'POST',
} );
if ( ! response.success ) {
throw new Error(
response.message ??
__( 'Failed to create property', 'surerank' )
);
}
// Handle pending verification case
if ( response.pending ) {
toast.success(
currentSiteInListButNotVerified
? __( 'Verification started successfully!', 'surerank' )
: __( 'Property created successfully!', 'surerank' ),
{
description: __(
'Verification is pending and may take 1-2 hours or up to 2 days. Your site has been added to Search Console. Reloading in 2 seconds…',
'surerank'
),
}
);
} else {
toast.success(
currentSiteInListButNotVerified
? __( 'Property verified successfully!', 'surerank' )
: __(
'Property created and verified successfully!',
'surerank'
),
{
description: __(
'The changes will take effect after a page refresh. Reloading in 2 seconds…',
'surerank'
),
}
);
}
// Reload page after 2 seconds
setTimeout( () => {
window.location.reload();
}, 2000 );
} catch ( error ) {
toast.error( error.message );
} finally {
setIsCreatingProperty( false );
}
};
const handleProceed = async () => {
if ( isLoading ) {
return;
}
// Proceed with site selection only
if ( ! selectedSite ) {
toast.error( __( 'Please select a site', 'surerank' ) );
return;
}
setIsLoading( true );
try {
const response = await apiFetch( {
path: '/surerank/v1/google-search-console/site',
method: 'PUT',
data: { url: selectedSite },
} );
if ( ! response.success ) {
throw new Error(
response.message ?? __( 'Failed to proceed', 'surerank' )
);
}
toast.success( __( 'Site selected successfully', 'surerank' ) );
toggleSiteSelectorModal();
setSearchConsole( {
selectedSite,
hasSiteSelected: true,
} );
} catch ( error ) {
toast.error( error.message );
} finally {
setIsLoading( false );
}
};
return (
<>
<Container direction="column" gap="xs" className="p-5 pt-2 pb-3">
<SiteSelector
sites={ searchConsole?.sites || [] }
currentSiteUrl={ currentSiteUrl }
selectedSite={ selectedSite }
onSiteSelect={ handleSelectSite }
placeholder={ __( 'Select a site', 'surerank' ) }
/>
{ shouldShowConnectAlert && (
<Container className="mt-4">
<div>
<Alert
variant="info"
className="shadow-none m-0 [&>div>p]:mr-0"
content={
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-1">
<span className="text-text-primary text-sm font-semibold">
{ __(
"Let's Get Your Site Connected",
'surerank'
) }
</span>
<p className="text-text-primary text-sm">
{ __(
'Connect it now to see SureRank insights. Your site will usually be verified instantly, though Google may take up to 1-2 days in some situations.',
'surerank'
) }{ ' ' }
<a
href="https://support.google.com/webmasters/answer/34592?hl=en"
target="_blank"
rel="noopener noreferrer"
className="text-text-secondary"
>
{ __(
'Learn more',
'surerank'
) }
</a>
</p>
</div>
</div>
}
/>
</div>
</Container>
) }
</Container>
{ /* Footer */ }
<SiteSelectorFooter
currentSiteUrl={ currentSiteUrl }
isLoading={ isLoading }
isCreatingProperty={ isCreatingProperty }
selectedSite={ selectedSite }
isSelectedSiteVerified={ isSelectedSiteVerified }
handleDisconnect={ handleDisconnect }
handleProceed={ handleProceed }
handleCreateProperty={ handleCreateProperty }
/>
</>
);
};
const SiteSelectorFooter = ( {
currentSiteUrl,
isLoading,
isCreatingProperty,
selectedSite,
isSelectedSiteVerified,
handleDisconnect,
handleProceed,
handleCreateProperty,
} ) => {
// Check if current site is selected and not verified
const isCurrentSiteSelectedAndUnverified =
normalizeUrl( selectedSite ) === normalizeUrl( currentSiteUrl ) &&
! isSelectedSiteVerified;
return (
<Container
className="border-0 border-solid border-t border-gray-200 gap-3 p-4"
justify="between"
>
<Button
destructive
iconPosition="left"
size="md"
tag="button"
type="button"
variant="link"
onClick={ handleDisconnect }
>
{ __( 'Disconnect', 'surerank' ) }
</Button>
{ isCurrentSiteSelectedAndUnverified ? (
<Button
variant="primary"
size="md"
onClick={ handleCreateProperty }
icon={
isCreatingProperty && <Loader variant="secondary" />
}
iconPosition="left"
disabled={ isCreatingProperty || isLoading }
>
{ isCreatingProperty
? __( 'Connecting your site…', 'surerank' )
: __( 'Connect Site', 'surerank' ) }
</Button>
) : (
<Button
variant="primary"
size="md"
onClick={ handleProceed }
icon={ isLoading && <Loader variant="secondary" /> }
iconPosition="left"
disabled={
isLoading ||
isCreatingProperty ||
! selectedSite ||
! isSelectedSiteVerified
}
>
{ __( 'Select Site', 'surerank' ) }
</Button>
) }
</Container>
);
};
export default SiteSelectorPopup;