File "dashboard.js"

Full Path: /home/fresvfqn/waterdamagerestorationandrepairsmithtown.com/wp-content/plugins/surerank/src/apps/admin-dashboard/dashboard.js
File size: 7.86 KB
MIME-type: text/html
Charset: utf-8

import { Container, Label, toast } from '@bsf/force-ui';
import { __ } from '@wordpress/i18n';
import { useEffect, useCallback } from '@wordpress/element';
import { usePluginsAndThemes } from './use-plugins-and-themes';
import { PluginCard } from './plugin-card';
import {
	themesAndPlugins,
	dashboard_plugins_sequence,
} from './dashboard-constants';
import { Ticket, MessageSquare, Star, Info } from 'lucide-react';
import { SureRankMonoLogo } from '@/global/components/icons';
import { SiteSeoChecksSummary } from './site-seo-checks';
import { useNavigate } from '@tanstack/react-router';
const quickLinks = [
	{
		label: __( 'Open Support Ticket', 'surerank' ),
		icon: <Ticket className="size-4" />,
		link: surerank_globals.support_link,
		external: true,
	},
	{
		label: __( 'Help Center', 'surerank' ),
		icon: <Info className="size-4" />,
		link: surerank_globals.help_link,
		external: true,
	},
	{
		label: __( 'Join our Community on Facebook', 'surerank' ),
		icon: <MessageSquare className="size-4" />,
		link: surerank_globals.community_link,
		external: true,
	},
	{
		label: __( 'Leave Us a Review', 'surerank' ),
		icon: <Star className="size-4" />,
		link: surerank_globals.rating_link,
		external: true,
	},
];

const onboardingSetup = [
	{
		label: __( 'Launch Setup Wizard', 'surerank' ),
		icon: <SureRankMonoLogo className="size-4" />,
		link: surerank_globals.wp_dashboard_url + '?page=surerank_onboarding',
		external: false,
	},
];

const quickAccessLinks =
	'yes' !== surerank_admin_common?.onboarding_complete_status
		? [ ...onboardingSetup, ...quickLinks ]
		: [ ...quickLinks ];

const SequencedThemesAndPlugins = dashboard_plugins_sequence
	.map( ( slug ) => themesAndPlugins.find( ( item ) => item.slug === slug ) )
	.filter( Boolean );

const Dashboard = () => {
	const navigate = useNavigate();
	const {
		fetchStatus,
		fetchInstalledPluginsAndThemes,
		handleInstallThemeOrPlugin,
		getProgressStatus,
		getPluginStatus,
	} = usePluginsAndThemes();

	useEffect( () => {
		checkForGCError();
		fetchInstalledPluginsAndThemes();
	}, [] );

	const getErrorMessages = ( errorCode ) => {
		switch ( String( errorCode ) ) {
			case '400':
				return __(
					'The request is malformed or invalid. Please check the request parameters and try again.',
					'surerank'
				);
			case '401':
				return __(
					'Authentication failed. Please provide valid credentials or re-authenticate.',
					'surerank'
				);
			case '403':
				return __(
					'Access is denied. You lack the necessary permissions to perform this action.',
					'surerank'
				);
			case '404':
				return __(
					'The requested resource was not found. Please verify the URL or resource ID.',
					'surerank'
				);
			case '429':
				return __(
					'You have exceeded your API quota. Please wait or upgrade your plan.',
					'surerank'
				);
			case '500':
				return __(
					`A server error occurred on Google's end. Please try again later.`,
					'surerank'
				);
			default:
				return __( 'An error occurred. Please try again.', 'surerank' );
		}
	};

	const checkForGCError = () => {
		const link = 'https://developers.google.com/webmaster-tools/v1/errors';

		const params = new URLSearchParams( window.location.search );
		const errorCode = params.get( 'gcp_error_code' );
		if ( ! errorCode ) {
			return;
		}
		const errorMessage = getErrorMessages( errorCode );

		const content = (
			<div>
				<p>{ errorMessage }</p>
				<p>
					{ __( 'Error code: ', 'surerank' ) }
					{ errorCode }
				</p>
				<a
					href={ link }
					target="_blank"
					rel="noopener noreferrer"
					className="text-link-primary no-underline"
				>
					{ __( 'Learn more', 'surerank' ) }
				</a>
			</div>
		);

		if ( errorMessage ) {
			toast.error( content, {
				dangerouslySetInnerHTML: true,
				autoDismiss: false,
			} );
		}

		//remove error code parameter and navigate directly to search-console
		const url = new URL( window.location.href );
		url.searchParams.delete( 'gcp_error_code' );
		url.searchParams.delete( 'action' );
		url.searchParams.delete( 'nonce' );
		url.searchParams.delete( 'status' );
		window.history.replaceState( {}, '', url.toString() );
		navigate( { to: '/search-console' } );
	};

	const renderInstallButtonText = useCallback(
		( item ) => {
			const status = getPluginStatus( item );
			switch ( status ) {
				case 'active':
					return __( 'Activated', 'surerank' );
				case 'activate':
					return __( 'Activate', 'surerank' );
				default:
					return __( 'Install & Activate', 'surerank' );
			}
		},
		[ getPluginStatus ]
	);

	return (
		<>
			<Container
				className="h-full p-5 pb-8 xl:p-8 max-[1920px]:max-w-full mx-auto box-content bg-background-secondary gap-6"
				cols={ 12 }
				containerType="grid"
				gap="2xl"
			>
				<Container.Item className="col-span-8">
					<Container direction="column" className="gap-8 relative">
						<SiteSeoChecksSummary
							limit={ 10 }
							showViewAll={ true }
						/>
					</Container>
				</Container.Item>
				<Container.Item className="col-span-4 flex flex-col gap-6">
					{ /* Plugins and Themes */ }
					<Container
						className="w-full h-fit bg-background-primary border-0.5 border-solid rounded-xl border-border-subtle p-3 shadow-sm"
						containerType="flex"
						direction="column"
						gap="xs"
					>
						<Container.Item className="md:w-full lg:w-full">
							<Container
								align="center"
								className="p-1"
								gap="xs"
								justify="between"
							>
								<Label className="font-semibold text-text-primary">
									{ __( 'Extend Your Website', 'surerank' ) }
								</Label>
							</Container>
						</Container.Item>
						<Container.Item className="md:w-full lg:w-full bg-field-primary-background rounded-lg">
							<Container
								containerType="grid"
								className="p-1 gap-1 grid-cols-1 min-[425px]:grid-cols-2 md:grid-cols-2 xl:grid-cols-2"
							>
								{ SequencedThemesAndPlugins.map( ( item ) => (
									<PluginCard
										key={ item.name }
										item={ item }
										onInstall={ handleInstallThemeOrPlugin }
										fetchStatus={ fetchStatus }
										getPluginStatus={ getPluginStatus }
										getProgressStatus={ getProgressStatus }
										renderInstallButtonText={
											renderInstallButtonText
										}
									/>
								) ) }
							</Container>
						</Container.Item>
					</Container>

					{ /* Quick Access */ }
					<Container
						className="w-full h-fit bg-background-primary border-0.5 border-solid rounded-xl border-border-subtle p-3 shadow-sm"
						containerType="flex"
						direction="column"
						gap="xs"
					>
						<Container.Item className="md:w-full lg:w-full p-1">
							<Label className="font-semibold text-text-primary">
								{ __( 'Quick Access', 'surerank' ) }
							</Label>
						</Container.Item>
						<Container.Item className="flex flex-col md:w-full lg:w-full bg-field-primary-background gap-1 p-1 rounded-lg">
							{ quickAccessLinks.map( ( link ) => (
								<div
									key={ link.label }
									className="p-2 gap-1 items-center bg-background-primary rounded-md shadow-sm cursor-pointer"
									onClick={ () => {
										if ( link.external ) {
											window.open(
												link.link,
												'_blank',
												'noopener,noreferrer'
											);
										} else {
											window.location.href = link.link;
										}
									} }
								>
									<Container
										align="center"
										className="gap-1 p-1"
										containerType="flex"
										direction="row"
									>
										<Container.Item className="flex">
											{ link.icon }
										</Container.Item>
										<Container.Item className="flex">
											<Label className="py-0 px-1 font-normal cursor-pointer hover:text-link-primary">
												{ link.label }
											</Label>
										</Container.Item>
									</Container>
								</div>
							) ) }
						</Container.Item>
					</Container>
				</Container.Item>
			</Container>
		</>
	);
};

export default Dashboard;