diff --git a/assets/stylesheets/_components.scss b/assets/stylesheets/_components.scss index 117601c7dc8a2..2fc1266ef5c72 100644 --- a/assets/stylesheets/_components.scss +++ b/assets/stylesheets/_components.scss @@ -28,7 +28,6 @@ @import 'blocks/image-editor/style'; @import 'blocks/like-button/style'; @import 'blocks/plan-storage/style'; -@import 'blocks/plan-thank-you-card/style'; @import 'blocks/post-edit-button/style'; @import 'blocks/post-item/style'; @import 'blocks/post-likes/style'; @@ -154,6 +153,7 @@ @import 'components/sticky-panel/style'; @import 'components/suggestions/style'; @import 'components/textarea-autosize/style'; +@import 'components/thank-you-card/style'; @import 'components/theme/style'; @import 'components/themes-list/style'; @import 'components/tinymce/style'; diff --git a/client/blocks/plan-thank-you-card/index.jsx b/client/blocks/plan-thank-you-card/index.jsx index 9ec39984e4740..a34ab0119664d 100644 --- a/client/blocks/plan-thank-you-card/index.jsx +++ b/client/blocks/plan-thank-you-card/index.jsx @@ -1,11 +1,9 @@ /** * External dependencies */ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import { localize } from 'i18n-calypso'; import { connect } from 'react-redux'; -import classnames from 'classnames'; -import Gridicon from 'gridicons'; /** * Internal dependencies @@ -16,76 +14,42 @@ import QuerySites from 'components/data/query-sites'; import QuerySitePlans from 'components/data/query-site-plans'; import { getPlan } from 'lib/plans'; import formatCurrency from 'lib/format-currency'; +import ThankYouCard from 'components/thank-you-card'; -class PlanThankYouCard extends Component { - static propTypes = { - siteId: PropTypes.number.isRequired - }; +const PlanThankYouCard = ( { + plan, + translate, + siteId, + siteUrl, +} ) => { + const name = plan && translate( '%(planName)s Plan', { + args: { planName: getPlan( plan.productSlug ).getTitle() } + } ); + const price = plan && formatCurrency( plan.rawPrice, plan.currencyCode ); + + return ( +
+ + + + +
+ ); +}; - render() { - const { - plan, - translate, - siteId, - siteURL, - } = this.props; - // Non standard gridicon sizes are used here because we use them as background pattern with various sizes and rotation - /* eslint-disable wpcalypso/jsx-gridicon-size */ - return ( -
- - -
- - { ! plan - ?
-
-
-
- :
-
- { translate( '%(planName)s Plan', { - args: { planName: getPlan( plan.productSlug ).getTitle() } - } ) } -
-
- { formatCurrency( plan.rawPrice, plan.currencyCode ) } -
-
- } -
- - - - - - - - - - - - -
-
-
-
- { translate( 'Thank you for your purchase!' ) } -
-
- { translate( "Now that we've taken care of the plan, it's time to see your new site." ) } -
- - { translate( 'Visit Your Site' ) } - -
-
- ); - /* eslint-enable wpcalypso/jsx-gridicon-size */ - } -} +PlanThankYouCard.propTypes = { + plan: PropTypes.object, + siteId: PropTypes.number.isRequired, + siteUrl: PropTypes.string, + translate: PropTypes.func.isRequired, +}; export default connect( ( state, ownProps ) => { const site = getRawSite( state, ownProps.siteId ); @@ -93,6 +57,6 @@ export default connect( ( state, ownProps ) => { return { plan, - siteURL: site && site.URL + siteUrl: site && site.URL }; } )( localize( PlanThankYouCard ) ); diff --git a/client/components/thank-you-card/index.jsx b/client/components/thank-you-card/index.jsx new file mode 100644 index 0000000000000..0d0b5bf827850 --- /dev/null +++ b/client/components/thank-you-card/index.jsx @@ -0,0 +1,65 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; +import Gridicon from 'gridicons'; +import React, { PropTypes } from 'react'; + +// Non standard gridicon sizes are used here because we use them as background pattern with various sizes and rotation +/* eslint-disable wpcalypso/jsx-gridicon-size */ +const ThankYouCard = ( { heading, description, buttonUrl, buttonText, price, name } ) => ( +
+
+ + +
+
+ { name } +
+
+ { price } +
+
+ +
+ + + + + + + + + + + + +
+
+
+
+ { heading } +
+
+ { description } +
+ + { buttonText } + +
+
+); +/* eslint-enable wpcalypso/jsx-gridicon-size */ + +ThankYouCard.propTypes = { + buttonText: PropTypes.string, + buttonUrl: PropTypes.string, + description: PropTypes.string, + heading: PropTypes.string, + name: PropTypes.string, + price: PropTypes.string, +}; + +export default ThankYouCard; diff --git a/client/blocks/plan-thank-you-card/style.scss b/client/components/thank-you-card/style.scss similarity index 86% rename from client/blocks/plan-thank-you-card/style.scss rename to client/components/thank-you-card/style.scss index 88ffd7a1a4b12..b95c3ebd35a6f 100644 --- a/client/blocks/plan-thank-you-card/style.scss +++ b/client/components/thank-you-card/style.scss @@ -1,4 +1,4 @@ -.plan-thank-you-card { +.thank-you-card { position: relative; width: 100%; max-width: 500px; @@ -15,7 +15,7 @@ } } -.plan-thank-you-card__header { +.thank-you-card__header { background-color: $alert-green; padding: 12px 0; position: relative; @@ -28,7 +28,7 @@ } } -.plan-thank-you-card__body { +.thank-you-card__body { padding: 24px; @include breakpoint( ">480px" ) { @@ -36,7 +36,47 @@ } } -.plan-thank-you-card__heading { +.thank-you-card__main-icon { + width: 72px; + height: 72px; + + @include breakpoint( ">480px" ) { + width: 96px; + height: 96px; + } +} + +.thank-you-card__name { + font-size: 18px; + font-weight: 500; + margin-bottom: 5px; + + &.is-placeholder { + @include placeholder(); + + background-color: lighten( $alert-green, 40 ); + margin-left: auto; + margin-right: auto; + width: 35%; + } +} + +.thank-you-card__price { + font-size: 15px; + font-weight: 500; + color: lighten( $alert-green, 40 ); + + &.is-placeholder { + @include placeholder(); + + background-color: lighten( $alert-green, 40 ); + margin-left: auto; + margin-right: auto; + width: 10%; + } +} + +.thank-you-card__heading { font-size: 18px; font-weight: 600; margin-bottom: 8px; @@ -46,7 +86,7 @@ } } -.plan-thank-you-card__description { +.thank-you-card__description { font-size: 13px; font-weight: 400; width: 280px; @@ -59,8 +99,8 @@ } } -.plan-thank-you-card__button, -.plan-thank-you-card__button:visited { +.thank-you-card__button, +.thank-you-card__button:visited { display: inline-block; border-radius: 4px; background-color: $white; @@ -77,8 +117,8 @@ border-width: 1px 1px 2px; } -.plan-thank-you-card__button.is-placeholder, -.plan-thank-you-card__button.is-placeholder:visited { +.thank-you-card__button.is-placeholder, +.thank-you-card__button.is-placeholder:visited { @include placeholder(); pointer-events: none; background-color: lighten( $alert-green, 40 ); @@ -86,51 +126,21 @@ border-radius: 0; } -.plan-thank-you-card__button:hover { +.thank-you-card__button:hover { border-color: darken( $alert-green, 30 ); color: darken( $alert-green, 10 ); } -.plan-thank-you-card__button:focus { +.thank-you-card__button:focus { color: darken( $alert-green, 10 ); outline: 1px dotted $white; } -.plan-thank-you-card__button:active { +.thank-you-card__button:active { border-width: 2px 1px 1px; color: darken( $alert-green, 30 ); } -.plan-thank-you-card__plan-name { - font-size: 18px; - font-weight: 500; - margin-bottom: 5px; - - &.is-placeholder { - @include placeholder(); - - background-color: lighten( $alert-green, 40 ); - margin-left: auto; - margin-right: auto; - width: 35%; - } -} - -.plan-thank-you-card__plan-price { - font-size: 15px; - font-weight: 500; - color: lighten( $alert-green, 40 ); - - &.is-placeholder { - @include placeholder(); - - background-color: lighten( $alert-green, 40 ); - margin-left: auto; - margin-right: auto; - width: 10%; - } -} - @keyframes floating { 0% { opacity: 0; @@ -146,7 +156,7 @@ } } -.plan-thank-you-card__background-icons { +.thank-you-card__background-icons { position: absolute; top: 0; left: 0; @@ -221,13 +231,3 @@ animation-delay: random(10) + s; } } - -.plan-thank-you-card__main-icon { - width: 72px; - height: 72px; - - @include breakpoint( ">480px" ) { - width: 96px; - height: 96px; - } -} diff --git a/client/my-sites/upgrades/checkout-thank-you/index.jsx b/client/my-sites/upgrades/checkout-thank-you/index.jsx index cc08e83ec73b0..5122eb70108ed 100644 --- a/client/my-sites/upgrades/checkout-thank-you/index.jsx +++ b/client/my-sites/upgrades/checkout-thank-you/index.jsx @@ -4,7 +4,7 @@ import { connect } from 'react-redux'; import { find } from 'lodash'; import page from 'page'; -import React from 'react'; +import React, { PropTypes } from 'react'; import moment from 'moment'; /** @@ -16,6 +16,7 @@ import Card from 'components/card'; import ChargebackDetails from './chargeback-details'; import CheckoutThankYouFeaturesHeader from './features-header'; import CheckoutThankYouHeader from './header'; +import { domainManagementList } from 'my-sites/upgrades/paths'; import DomainMappingDetails from './domain-mapping-details'; import DomainRegistrationDetails from './domain-registration-details'; import { fetchReceipt } from 'state/receipts/actions'; @@ -56,6 +57,7 @@ import PurchaseDetail from 'components/purchase-detail'; import { getFeatureByKey, shouldFetchSitePlans } from 'lib/plans'; import SiteRedirectDetails from './site-redirect-details'; import Notice from 'components/notice'; +import ThankYouCard from 'components/thank-you-card'; import upgradesPaths from 'my-sites/upgrades/paths'; import config from 'config'; @@ -75,13 +77,14 @@ function findPurchaseAndDomain( purchases, predicate ) { const CheckoutThankYou = React.createClass( { propTypes: { - failedPurchases: React.PropTypes.array, - productsList: React.PropTypes.object.isRequired, - receiptId: React.PropTypes.number, - selectedFeature: React.PropTypes.string, - selectedSite: React.PropTypes.oneOfType( [ - React.PropTypes.bool, - React.PropTypes.object + domainOnlySiteFlow: PropTypes.bool.isRequired, + failedPurchases: PropTypes.array, + productsList: PropTypes.object.isRequired, + receiptId: PropTypes.number, + selectedFeature: PropTypes.string, + selectedSite: PropTypes.oneOfType( [ + PropTypes.bool, + PropTypes.object ] ).isRequired }, @@ -196,10 +199,11 @@ const CheckoutThankYou = React.createClass( { }, render() { - let purchases = null, - failedPurchases = null, + let purchases = [], + failedPurchases = [], wasJetpackPlanPurchased = false, wasDotcomPlanPurchased = false; + if ( this.isDataLoaded() && ! this.isGenericReceipt() ) { purchases = getPurchases( this.props ); failedPurchases = getFailedPurchases( this.props ); @@ -207,12 +211,8 @@ const CheckoutThankYou = React.createClass( { wasDotcomPlanPurchased = purchases.some( isDotComPlan ); } - const userCreatedMoment = moment( this.props.userDate ), - isNewUser = userCreatedMoment.isAfter( moment().subtract( 2, 'hours' ) ), - goBackText = this.props.selectedSite ? this.translate( 'Back to my site' ) : this.translate( 'Register Domain' ); - // this placeholder is using just wp logo here because two possible states do not share a common layout - if ( ! purchases && ! failedPurchases && ! this.isGenericReceipt() ) { + if ( ! purchases.length && ! failedPurchases.length && ! this.isGenericReceipt() ) { // disabled because we use global loader icon /* eslint-disable wpcalypso/jsx-classname-namespace */ return ( @@ -221,6 +221,9 @@ const CheckoutThankYou = React.createClass( { /* eslint-enable wpcalypso/jsx-classname-namespace */ } + const userCreatedMoment = moment( this.props.userDate ), + isNewUser = userCreatedMoment.isAfter( moment().subtract( 2, 'hours' ) ); + // streamlined paid NUX thanks page if ( isNewUser && wasDotcomPlanPurchased ) { return ( @@ -238,6 +241,27 @@ const CheckoutThankYou = React.createClass( { ); } + if ( this.props.domainOnlySiteFlow && purchases.length > 0 && ! failedPurchases.length ) { + const domainName = find( purchases, isDomainRegistration ).meta; + + return ( +
+ { this.renderConfirmationNotice() } + + +
+ ); + } + + const goBackText = this.props.selectedSite ? this.translate( 'Back to my site' ) : this.translate( 'Register Domain' ); + // standard thanks page return (
diff --git a/client/my-sites/upgrades/checkout/checkout.jsx b/client/my-sites/upgrades/checkout/checkout.jsx index 486c0cd6049dd..0083407086342 100644 --- a/client/my-sites/upgrades/checkout/checkout.jsx +++ b/client/my-sites/upgrades/checkout/checkout.jsx @@ -43,7 +43,6 @@ import { getSelectedSiteSlug, } from 'state/ui/selectors'; import { getDomainNameFromReceiptOrCart } from 'lib/domains/utils'; -import { domainManagementList } from 'my-sites/upgrades/paths'; import { fetchSitesAndUser } from 'lib/signup/step-actions'; const Checkout = React.createClass( { @@ -206,11 +205,6 @@ const Checkout = React.createClass( { ? `/plans/${ selectedSiteSlug }/thank-you` : '/checkout/thank-you/plans'; } else if ( cart.create_new_blog ) { - const domainName = getDomainNameFromReceiptOrCart( receipt, cart ); - if ( domainName && receipt && isEmpty( receipt.failed_purchases ) ) { - return domainManagementList( domainName ); - } - return `/checkout/thank-you/no-site/${ receiptId }`; } @@ -291,9 +285,9 @@ const Checkout = React.createClass( { const receiptId = receipt.receipt_id; this.props.fetchReceiptCompleted( receiptId, { - receiptId, + ...receipt, purchases: this.flattenPurchases( this.props.transaction.step.data.purchases ), - failedPurchases: this.flattenPurchases( this.props.transaction.step.data.failed_purchases ), + failedPurchases: this.flattenPurchases( this.props.transaction.step.data.failed_purchases ) } ); } diff --git a/client/my-sites/upgrades/controller.jsx b/client/my-sites/upgrades/controller.jsx index 4390521ab0374..024bebe263a59 100644 --- a/client/my-sites/upgrades/controller.jsx +++ b/client/my-sites/upgrades/controller.jsx @@ -6,7 +6,7 @@ import qs from 'qs'; import i18n from 'i18n-calypso'; import ReactDom from 'react-dom'; import React from 'react'; -import { get } from 'lodash'; +import { get, isEmpty } from 'lodash'; /** * Internal Dependencies @@ -264,6 +264,7 @@ module.exports = { ), diff --git a/client/my-sites/upgrades/index.js b/client/my-sites/upgrades/index.js index 460ce064670f6..185b01f4e9b40 100644 --- a/client/my-sites/upgrades/index.js +++ b/client/my-sites/upgrades/index.js @@ -234,7 +234,7 @@ module.exports = function() { if ( config.isEnabled( 'upgrades/checkout' ) ) { page( - '/checkout/thank-you/no-site/:receiptId', + '/checkout/thank-you/no-site/:receiptId?', upgradesController.checkoutThankYou ); diff --git a/client/state/receipts/assembler.js b/client/state/receipts/assembler.js index 4cf9808caa403..410b56f1833bf 100644 --- a/client/state/receipts/assembler.js +++ b/client/state/receipts/assembler.js @@ -1,6 +1,7 @@ export function createReceiptObject( data ) { return { receiptId: data.receipt_id, + displayPrice: data.display_price, purchases: data.purchases.map( purchase => { return { freeTrial: purchase.free_trial,