import {
getRecommendation,
recordActivity,
} from '@recommendations/utils/record-activity';
import { recordPluginActivity } from '@shared/api/DataApi';
import { activatePlugin, installPlugin } from '@shared/api/wp';
import { retryOperation, sleep } from '@shared/lib/utils';
import { Button } from '@wordpress/components';
import { useCallback, useEffect, useState } from '@wordpress/element';
import { decodeEntities } from '@wordpress/html-entities';
import { __, _x, sprintf } from '@wordpress/i18n';
import { caution, check, external, Icon } from '@wordpress/icons';
export const RecommendationCard = ({
slug: product,
title,
description,
ctaContent,
provider,
image,
ctaType,
ctaPluginSlug,
ctaExternalLink,
ctaInternalLink,
priceTag,
}) => {
useEffect(() => {
recordActivity({ slot: 'plugin-search', event: 'view', product });
}, [product]);
return (
{sprintf(
// translators: %s is a name
_x(
'By %s',
'Preposition for "By Author Name"',
'extendify-local',
),
provider,
)}
{decodeEntities(description)}
{priceTag && (
)}
{ctaType === 'plugin' && (
)}
{ctaType === 'external-link' && (
)}
{ctaType === 'internal-link' && (
)}
);
};
const InstallPluginAction = ({ product, ctaContent, ctaPluginSlug }) => {
const [status, setStatus] = useState('idle');
const [error, setError] = useState(null);
const handleInstall = useCallback(async () => {
recordActivity({
slot: 'plugin-search',
event: 'click-install',
product,
});
try {
setStatus('installing');
await Promise.all([
retryOperation(() => installPlugin(ctaPluginSlug), { maxAttempts: 2 }),
// Sleep makes sure the installing UI is displayed for at least 1 second.
sleep(1000),
]);
} catch (_) {
setError(__('Failed to install the plugin', 'extendify-local'));
setStatus('error');
return;
}
const recommendation = getRecommendation({ product });
recordPluginActivity({
slug: recommendation || product,
source: 'search-recommendation-card',
});
try {
setStatus('activating');
await Promise.all([
retryOperation(() => activatePlugin(ctaPluginSlug), { maxAttempts: 2 }),
// Sleep makes sure the activating UI is displayed for at least 1 second.
sleep(1000),
]);
} catch (_) {
setError(__('Failed to activate the plugin', 'extendify-local'));
setStatus('error');
return;
}
setStatus('activated');
}, [product, ctaPluginSlug]);
const actionText = {
idle: ctaContent,
installing: _x(
'Installing...',
'Plugin installation status',
'extendify-local',
),
activating: _x(
'Activating...',
'Plugin activation status',
'extendify-local',
),
activated: _x('Activated', 'Plugin activation status', 'extendify-local'),
error,
};
if (status === 'error') {
return (
{actionText[status]}
);
}
if (status === 'activated') {
return (
{actionText[status]}
);
}
return (
);
};
const ExternalLinkAction = ({ product, ctaContent, ctaExternalLink }) => {
const ctaExternalLinkWithPartner = decodeEntities(ctaExternalLink).replace(
'{PARTNERID}',
window.extSharedData?.partnerId,
);
return (
recordActivity({
slot: 'plugin-search',
event: 'click-link-external',
product,
})
}
href={ctaExternalLinkWithPartner}
target="_blank"
className="relative flex min-h-8 min-w-24 cursor-pointer items-center justify-center whitespace-normal wrap-break-word rounded-xs bg-wp-theme-main fill-design-text py-1.5 pl-3 pr-9 text-center text-sm leading-tight text-design-text no-underline hover:opacity-90 focus:shadow-none"
>
{ctaContent}
);
};
const InternalLinkAction = ({ product, ctaContent, ctaInternalLink }) => {
return (
recordActivity({
slot: 'plugin-search',
event: 'click-link-internal',
product,
})
}
href={ctaInternalLink}
className="relative flex min-h-8 min-w-24 cursor-pointer items-center justify-center whitespace-normal break-words rounded-xs bg-wp-theme-main fill-design-text px-3 py-[6px] text-center text-sm leading-tight text-design-text no-underline hover:opacity-90 focus:shadow-none"
>
{ctaContent}
);
};