Skip to content

Commit 66ec3ce

Browse files
authored
Merge pull request #204 from topcoder-platform/PROD-2450_pay-and-complete
PROD 2450 pay and redirect to thank you page -> Intake form
2 parents bf59292 + 96a2627 commit 66ec3ce

File tree

15 files changed

+273
-26
lines changed

15 files changed

+273
-26
lines changed

src-ts/lib/button/Button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import '../styles/index.scss'
66
import { IconOutline } from '../svgs'
77

88
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
9-
export type ButtonStyle = 'icon' | 'link' | 'primary' | 'secondary' | 'tertiary' | 'text'
9+
export type ButtonStyle = 'icon' | 'icon-bordered' | 'link' | 'primary' | 'secondary' | 'tertiary' | 'text'
1010
export type ButtonType = 'button' | 'submit'
1111

1212
export interface ButtonProps {

src-ts/lib/payment-form/PaymentForm.module.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,10 @@
6060
.pay-button {
6161
width: 100%;
6262
}
63+
64+
.error {
65+
@extend .body-small;
66+
color: $red-120;
67+
margin-bottom: $pad-lg;
68+
}
6369
}

src-ts/lib/payment-form/PaymentForm.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ interface FieldDirtyState {
3131
}
3232

3333
interface PaymentFormProps {
34+
error: boolean
3435
formData: PaymentFormData
3536
isFormValid: boolean
37+
onPay: () => void
3638
onUpdateField: (fieldName: string, value: string | boolean) => void
3739
}
3840

@@ -175,7 +177,7 @@ const PaymentForm: React.FC<PaymentFormProps> = (props: PaymentFormProps) => {
175177
value={props.formData.name}
176178
/>
177179

178-
<InputWrapper className={styles['input-wrapper']} label='Date' tabIndex={3} type='text' disabled={false}>
180+
<InputWrapper className={styles['input-wrapper']} label='Country' tabIndex={3} type='text' disabled={false}>
179181
<ReactSelect
180182
value={props.formData.country}
181183
onChange={(option) => props.onUpdateField('country', option)}
@@ -206,6 +208,14 @@ const PaymentForm: React.FC<PaymentFormProps> = (props: PaymentFormProps) => {
206208
A hold will be placed on your card for the full amount of the project. Once your work is live on the Topcoder platform, you will be charged.
207209
</div>
208210

211+
{
212+
props.error && (
213+
<div className={styles['error']}>
214+
Your card was declined. Please try a different card.
215+
</div>
216+
)
217+
}
218+
209219
<Button
210220
className={styles['pay-button']}
211221
size='lg'
@@ -214,6 +224,7 @@ const PaymentForm: React.FC<PaymentFormProps> = (props: PaymentFormProps) => {
214224
name='pay-button'
215225
label={`Pay ${props.formData.price}`}
216226
disable={!props.isFormValid}
227+
onClick={props.onPay}
217228
/>
218229
</div>
219230
)

src-ts/lib/styles/_buttons.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
font-size: 12px;
176176
}
177177

178+
&.icon-bordered,
178179
&.icon {
179180
margin: 0;
180181
padding: $pad-sm calc($pad-sm - $border-xs) $pad-xs $pad-sm;
@@ -195,4 +196,18 @@
195196
outline: none;
196197
}
197198
}
199+
200+
&.icon-bordered {
201+
width: 60px;
202+
align-items: center;
203+
justify-content: center;
204+
padding: 0;
205+
display: flex;
206+
height: 40px;
207+
& {
208+
border: 1px solid $turq-160;
209+
padding: $pad-lg;
210+
border-radius: 50px;
211+
}
212+
}
198213
}

src-ts/tools/work/work-lib/work-provider/work-functions/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export {
2323
export * from './work-by-status.model'
2424
export {
2525
createAsync as workCreateAsync,
26+
createCustomerPayment as workCreateCustomerPayment,
27+
confirmCustomerPayment as workConfirmCustomerPayment,
2628
createFromChallenge as workCreateFromChallenge,
2729
deleteAsync as workDeleteAsync,
2830
getAllAsync as workGetAllAsync,

src-ts/tools/work/work-lib/work-provider/work-functions/work-factory/work.factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525

2626
import { ChallengeStatus } from './challenge-status.enum'
2727

28-
interface FormDetail {
28+
export interface FormDetail {
2929
key: string,
3030
title: string,
3131
value: any

src-ts/tools/work/work-lib/work-provider/work-functions/work-store/challenge.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface Challenge {
1616
numOfSubmissions?: number
1717
phases: Array<ChallengePhase>
1818
prizeSets?: Array<WorkPrize>
19+
projectId?: number
1920
status: string
2021
tags: Array<ChallengeTag>
2122
timelineTemplateId?: string

src-ts/tools/work/work-lib/work-provider/work-functions/work-store/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ export * from './work-type.enum'
2828
export * from './work-type.model'
2929
export * from './work-type-category.enum'
3030
export * from './work.model'
31+
export * from './work-customer-payment.model'
3132
export {
33+
createCustomerPayment as workStoreCreateCustomerPaymentAsync,
3234
createAsync as workStoreCreateAsync,
35+
confirmCustomerPayment as workStoreConfirmCustomerPaymentAsync,
3336
deleteAsync as workStoreDeleteAsync,
3437
getAsync as workStoreGetAsync,
3538
getChallengeByWorkId as workStoreGetChallengeByWorkId,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface CustomerPayment {
2+
clientSecret: string
3+
id: string
4+
status: string
5+
}

src-ts/tools/work/work-lib/work-provider/work-functions/work-store/work-url.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,13 @@ export function updateUrl(workId: string): string {
1717
return `${challengesPath}/${workId}`
1818
}
1919

20+
export function updatePaymentUrl(id: string): string {
21+
return `${customerPaymentPath}/${id}/confirm`
22+
}
23+
24+
export function createPaymentUrl(): string {
25+
return customerPaymentPath
26+
}
27+
2028
const challengesPath: string = `${EnvironmentConfig.API.V5}/challenges`
29+
const customerPaymentPath: string = `${EnvironmentConfig.API.V5}/customer-payments`

src-ts/tools/work/work-lib/work-provider/work-functions/work-store/work.store.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Page, xhrDeleteAsync, xhrGetAsync, xhrPatchAsync, xhrPostAsync } from '../../../../../../lib'
22

33
import { Challenge, ChallengeCreateBody, ChallengeUpdateBody } from './challenge.model'
4+
import { CustomerPayment } from './work-customer-payment.model'
45
import { WorkStatusFilter } from './work-status-filter.enum'
56
import { WorkStatus } from './work-status.enum'
6-
import { createUrl, deleteUrl, getUrl, updateUrl } from './work-url.config'
7+
import { createPaymentUrl, createUrl, deleteUrl, getUrl, updatePaymentUrl, updateUrl } from './work-url.config'
78
import { Work } from './work.model'
89

910
export async function createAsync(body: ChallengeCreateBody): Promise<void> {
@@ -22,6 +23,14 @@ export async function getChallengeByWorkId(workId: string): Promise<Challenge> {
2223
return xhrGetAsync<Challenge>(updateUrl(workId))
2324
}
2425

26+
export async function createCustomerPayment(payment: string): Promise<CustomerPayment> {
27+
return xhrPostAsync(createPaymentUrl(), payment)
28+
}
29+
30+
export async function confirmCustomerPayment(id: string): Promise<CustomerPayment> {
31+
return xhrPatchAsync(updatePaymentUrl(id), JSON.stringify({}))
32+
}
33+
2534
export function getFilteredByStatus(work: ReadonlyArray<Work>, workStatusFilter?: WorkStatusFilter): Array<Work> {
2635
// this is implemented in the work store
2736
// bc in the future we might actually want

src-ts/tools/work/work-lib/work-provider/work-functions/work.functions.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ import {
77
Challenge,
88
ChallengeCreateBody,
99
ChallengeUpdateBody,
10+
CustomerPayment,
1011
Work,
1112
workGetPricesConfig,
1213
WorkPricesType,
1314
WorkStatus,
1415
WorkStatusFilter,
16+
workStoreConfirmCustomerPaymentAsync,
1517
workStoreCreateAsync,
18+
workStoreCreateCustomerPaymentAsync,
1619
workStoreDeleteAsync,
1720
workStoreGetAsync,
1821
workStoreGetFilteredByStatus,
@@ -36,6 +39,14 @@ export async function deleteAsync(workId: string): Promise<void> {
3639
return workStoreDeleteAsync(workId)
3740
}
3841

42+
export async function createCustomerPayment(body: string): Promise<CustomerPayment> {
43+
return workStoreCreateCustomerPaymentAsync(body)
44+
}
45+
46+
export async function confirmCustomerPayment(id: string): Promise<CustomerPayment> {
47+
return workStoreCreateCustomerPaymentAsync(id)
48+
}
49+
3950
export async function getAllAsync(profile: UserProfile): Promise<Array<Work>> {
4051

4152
// TODO: actual pagination and sorting

src-ts/tools/work/work-self-service/intake-forms/bug-hunt/bug-hunt.form.config.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const BugHuntFormConfig: FormDefinition = {
2323
],
2424
secondaryGroup: [
2525
{
26-
buttonStyle: 'icon',
26+
buttonStyle: 'icon-bordered',
2727
icon: BackIcon,
2828
onClick: () => { },
2929
type: 'button',

src-ts/tools/work/work-self-service/intake-forms/review/Review.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,8 @@
4545
}
4646
}
4747
}
48+
49+
.button-wrapper {
50+
margin: 0 $pad-xxxxl $pad-xxxxl $pad-xxxxl;
51+
}
4852
}

0 commit comments

Comments
 (0)