Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Free Listings + Paid Ads: Use merchant's data to composite the ad previews #1692

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 50 additions & 5 deletions js/src/components/paid-ads/campaign-preview/campaign-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
import { _x } from '@wordpress/i18n';
import { useState, useCallback, useEffect } from '@wordpress/element';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import CurrencyFactory from '@woocommerce/currency';
import { getSetting } from '@woocommerce/settings'; // eslint-disable-line import/no-unresolved

/**
* Internal dependencies
*/
import useCountdown from '.~/hooks/useCountdown';
import useAppSelectDispatch from '.~/hooks/useAppSelectDispatch';
import AppSpinner from '.~/components/app-spinner';
import MockupShopping from './mockup-shopping';
import MockupYouTube from './mockup-youtube';
import MockupSearch from './mockup-search';
Expand All @@ -17,6 +21,7 @@ import MockupDisplay from './mockup-display';
import MockupMap from './mockup-map';
import productSampleImageURL from './images/product-sample-image.jpg';
import shopSampleLogoURL from './images/shop-sample-logo.png';
import { glaData } from '.~/constants';
import './campaign-preview.scss';

/**
Expand Down Expand Up @@ -47,6 +52,13 @@ const fallbackProduct = {
shopUrl: 'colleensteestore.com',
};

const bestsellingQuery = {
page: 1,
per_page: 1,
orderby: 'total_sales',
order: 'desc',
};

const mockups = [
MockupShopping,
MockupYouTube,
Expand All @@ -56,12 +68,36 @@ const mockups = [
MockupGmail,
];

function resolvePreviewProduct( products = [] ) {
const currencyFactory = CurrencyFactory( getSetting( 'currency' ) );
const [ product = {} ] = products;
const { title, price, image_url: coverUrl } = product;
const previewProduct = {
title,
coverUrl,
price: currencyFactory.formatAmount( price ),
shopName: getSetting( 'siteTitle' ),
shopUrl: new URL( getSetting( 'homeUrl' ) ).host,
shopLogoUrl: glaData.siteLogoUrl,
};

Object.entries( previewProduct ).forEach( ( [ key, val ] ) => {
// All possible values won't be number 0, so here simply use falsy condition to do fallback.
if ( ! val ) {
previewProduct[ key ] = fallbackProduct[ key ];
}
} );

return previewProduct;
}

export default function CampaignPreview() {
const [ index, setIndex ] = useState( 0 );
const { second, callCount, startCountdown } = useCountdown();

// TODO: Fetch required data from API.
const product = fallbackProduct;
const { hasFinishedResolution, data } = useAppSelectDispatch(
'getMCProductFeed',
bestsellingQuery
);

const moveBy = useCallback( ( step ) => {
setIndex( ( currentIndex ) => {
Expand All @@ -70,15 +106,24 @@ export default function CampaignPreview() {
}, [] );

useEffect( () => {
if ( second === 0 ) {
if ( hasFinishedResolution && second === 0 ) {
if ( callCount > 0 ) {
moveBy( 1 );
}
startCountdown( 5 );
}
}, [ second, callCount, startCountdown, moveBy ] );
}, [ hasFinishedResolution, second, callCount, startCountdown, moveBy ] );

if ( ! hasFinishedResolution ) {
return (
<div className="gla-ads-mockup">
<AppSpinner />
</div>
);
}

const Mockup = mockups[ index ];
const product = resolvePreviewProduct( data?.products );

return (
<TransitionGroup className="gla-campaign-preview">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ $gla-campaign-preview-height: 270px;
overflow: hidden;
background-color: $white;

.app-spinner {
align-items: center;
height: 100%;
}

// === Shared components within ad previews ===
&__placeholder {
height: 3px;
Expand Down Expand Up @@ -89,14 +94,15 @@ $gla-campaign-preview-height: 270px;

// Display smaller font sizes than browsers' limitations.
&__scaled-text {
height: 1em;
transform: scale(0.5);
transform-origin: top left;
margin-right: -100%; // Inner shrinkage for offsetting the outer horizontal gap caused by 0.5 times scaling.
margin-bottom: -0.5em; // Inner shrinkage for offsetting the outer vertical gap caused by 0.5 times scaling.
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1;
line-height: 0.9; // With 1em height, it prevents the font descender from getting cropped out.
font-size: 20px;

&--smaller {
Expand All @@ -120,6 +126,10 @@ $gla-campaign-preview-height: 270px;
}

&--ad-badge {
// Reset height and line-height because ad badge holds enough height for font descender.
height: auto;
line-height: 1;

// The same vertical inner shrinkage as above.
// A: Height of badge = &--ad-badge font-size + vertical padding
// B: Height of text after badge = &--smaller font-size
Expand Down