Skip to content

Commit

Permalink
Merge pull request #95 from Videodock/feat/payments-page
Browse files Browse the repository at this point in the history
Feat / payments page
  • Loading branch information
ChristiaanScheermeijer authored Jul 27, 2021
2 parents b28b661 + 83de9aa commit 91b32aa
Show file tree
Hide file tree
Showing 25 changed files with 640 additions and 210 deletions.
12 changes: 3 additions & 9 deletions src/components/Account/Account.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,15 @@ import React from 'react';
import { render } from '@testing-library/react';
import type { Customer } from 'types/account';

import customer from '../../fixtures/customer.json';

import Account from './Account';

describe('<Account>', () => {
test('renders and matches snapshot', () => {
const customer: Customer = {
id: '1',
email: '[email protected]',
locale: 'en_en',
country: 'England',
currency: 'Euro',
lastUserIp: 'temp',
};
const { container } = render(
<Account
customer={customer}
customer={customer as Customer}
isLoading={false}
consentsLoading={false}
onUpdateEmailSubmit={() => null}
Expand Down
23 changes: 10 additions & 13 deletions src/components/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,16 @@ const Account = ({
<h3>{t('account.email')}</h3>
</div>
<div className={styles.flexBox}>
{editing === 'account' ? (
<TextField
name="email"
label={t('account.email')}
value={values.email as string}
onChange={handleChange}
error={!!errors?.email}
helperText={errors?.email}
disabled={isLoading}
/>
) : (
<p>{customer?.email}</p>
)}
<TextField
name="email"
label={t('account.email')}
value={values.email as string}
onChange={handleChange}
error={!!errors?.email}
helperText={errors?.email}
disabled={isLoading}
editing={editing === 'account'}
/>
{editing === 'account' && (
<TextField
name="confirmationPassword"
Expand Down
24 changes: 19 additions & 5 deletions src/components/Account/__snapshots__/Account.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@ exports[`<Account> renders and matches snapshot 1`] = `
<div
class="flexBox"
>
<p>
[email protected]
</p>
<div
class="textField"
>
<label
class="label"
for="text-field_1235_email"
>
account.email
</label>
<p>
[email protected]
</p>
</div>
<div
class="controls"
>
Expand Down Expand Up @@ -73,7 +83,9 @@ exports[`<Account> renders and matches snapshot 1`] = `
>
account.firstname
</label>
<p />
<p>
John
</p>
</div>
<div
class="textField"
Expand All @@ -84,7 +96,9 @@ exports[`<Account> renders and matches snapshot 1`] = `
>
account.lastname
</label>
<p />
<p>
Doe
</p>
</div>
<div
class="controls"
Expand Down
8 changes: 3 additions & 5 deletions src/components/Payment/Payment.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
font-size: 14px;
line-height: 18px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.14), 0 3px 4px rgba(0, 0, 0, 0.12), 0 1px 5px rgba(0, 0, 0, 0.2);
background: rgba(61, 59, 59, 0.08);
background: theme.$panel-bg;
border-radius: 4px;

> strong {
line-height: 16px;
letter-spacing: 0.25px;
Expand All @@ -31,8 +32,5 @@

.cardDetails {
display: flex;
}

.expiryDate {
width: 250px;
margin-top: variables.$base-spacing * 2;
}
21 changes: 16 additions & 5 deletions src/components/Payment/Payment.test.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import React from 'react';
import { render } from '@testing-library/react';
import type { Subscription } from 'types/subscription';

import customer from '../../fixtures/customer.json';
import transactions from '../../fixtures/transactions.json';
import paymentDetail from '../../fixtures/paymentDetail.json';
import subscription from '../../fixtures/subscription.json';
import type { Customer } from '../../../types/account';
import type { PaymentDetail, Subscription, Transaction } from '../../../types/subscription';

import Payment from './Payment';

describe('<Payment>', () => {
test('renders and matches snapshot', () => {
const subscription = {} as Subscription;

const { container } = render(<Payment subscription={subscription} onEditSubscriptionClick={(subscription) => console.info(subscription)} />);
const { container } = render(
<Payment
customer={customer as Customer}
transactions={transactions as Transaction[]}
activeSubscription={subscription as Subscription}
activePaymentDetail={paymentDetail as PaymentDetail}
isLoading={false}
/>,
);

// todo
expect(container).toMatchSnapshot();
});
});
122 changes: 73 additions & 49 deletions src/components/Payment/Payment.tsx
Original file line number Diff line number Diff line change
@@ -1,81 +1,105 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import type { Subscription } from 'types/subscription';
import type { PaymentDetail, Subscription, Transaction } from 'types/subscription';

import Button from '../Button/Button';
import { formatDate, formatPrice } from '../../utils/formatting';
import TextField from '../TextField/TextField';
import type { Customer } from '../../../types/account';
import LoadingOverlay from '../LoadingOverlay/LoadingOverlay';

import styles from './Payment.module.scss';
import Button from '../Button/Button';

type Props = {
subscription: Subscription;
onEditSubscriptionClick: (subscription: Subscription) => void;
activeSubscription?: Subscription;
activePaymentDetail?: PaymentDetail;
transactions: Transaction[];
customer: Customer;
isLoading: boolean;
panelClassName?: string;
panelHeaderClassName?: string;
};

const Payment = ({ subscription, onEditSubscriptionClick, panelClassName, panelHeaderClassName }: Props): JSX.Element => {
const { t } = useTranslation('user');
const showAllTransactions = () => console.info('show all');
const Payment = ({
activePaymentDetail,
activeSubscription,
transactions,
customer,
isLoading,
panelClassName,
panelHeaderClassName,
}: Props): JSX.Element => {
const { t } = useTranslation(['user', 'account']);

return (
<>
<div className={panelClassName}>
<div className={panelHeaderClassName}>
<h3>{t('payment.subscription_details')}</h3>
</div>
<div className={styles.infoBox}>
<p>
<strong>{t('payment.monthly_subscription')}</strong> <br />
{t('payment.next_billing_date_on')}
{'<date>'}
</p>
<p className={styles.price}>
<strong>{'€ 14.76'}</strong>
{'/'}
{t('payment.month')}
</p>
<h3>{t('user:payment.subscription_details')}</h3>
</div>
<Button label={t('payment.edit_subscription')} onClick={() => onEditSubscriptionClick} />
{activeSubscription ? (
<div className={styles.infoBox} key={activeSubscription.subscriptionId}>
<p>
<strong>{t('user:payment.monthly_subscription')}</strong> <br />
{t('user:payment.next_billing_date_on')} {formatDate(activeSubscription.expiresAt)}
</p>
<p className={styles.price}>
<strong>{formatPrice(activeSubscription.totalPrice, activeSubscription.nextPaymentCurrency, customer.country)}</strong>
<small>/{t(`account:periods.${activeSubscription.period}`)}</small>
</p>
</div>
) : (
<React.Fragment>
<p>{t('user:payment.no_subscription')}</p>
<Button variant="contained" color="primary" label={t('user:payment.complete_subscription')} />
</React.Fragment>
)}
</div>
<div className={panelClassName}>
<div className={panelHeaderClassName}>
<h3>{t('payment.payment_method')}</h3>
<h3>{t('user:payment.payment_method')}</h3>
</div>
<div>
<strong>{t('payment.card_number')}</strong>
<p>xxxx xxxx xxxx 3456</p>
<div className={styles.cardDetails}>
<div className={styles.expiryDate}>
<strong>{t('payment.expiry_date')}</strong>
<p>{subscription.expiresAt}</p>
</div>
<div>
<strong>{t('payment.cvc_cvv')}</strong>
<p>******</p>
{activePaymentDetail ? (
<div key={activePaymentDetail.id}>
<TextField
label={t('user:payment.card_number')}
value={`•••• •••• •••• ${activePaymentDetail.paymentMethodSpecificParams.lastCardFourDigits || ''}`}
editing={false}
/>
<div className={styles.cardDetails}>
<TextField
label={t('user:payment.expiry_date')}
value={activePaymentDetail.paymentMethodSpecificParams.cardExpirationDate}
editing={false}
/>
<TextField label={t('user:payment.cvc_cvv')} value={'******'} editing={false} />
</div>
</div>
</div>
) : null}
</div>
<div className={panelClassName}>
<div className={panelHeaderClassName}>
<h3>{t('payment.transactions')}</h3>
</div>
<div className={styles.infoBox}>
<p>
<strong>{t('payment.monthly_subscription')}</strong> <br />
{t('payment.price_payed_with_card')}
</p>
<p>
{'<Invoice code>'}
<br />
{'<Date>'}
</p>
<h3>{t('user:payment.transactions')}</h3>
</div>
<p>{t('payment.more_transactions', { amount: 4 })}</p>
<Button label="Show all" onClick={() => showAllTransactions()} />
{transactions?.map((transaction) => (
<div className={styles.infoBox} key={transaction.transactionId}>
<p>
<strong>{transaction.offerTitle}</strong> <br />
{t('user:payment.price_payed_with', {
price: formatPrice(parseInt(transaction.transactionPriceInclTax), transaction.transactionCurrency, transaction.customerCountry),
method: transaction.paymentMethod,
})}
</p>
<p>
{transaction.transactionId}
<br />
{formatDate(transaction.transactionDate)}
</p>
</div>
))}
</div>
{isLoading && <LoadingOverlay inline />}
</>
);
};

export default Payment;
Loading

0 comments on commit 91b32aa

Please sign in to comment.