1
+ import { useParams } from "react-router-dom" ;
2
+ import { useForm , useField } from "@shopify/react-form" ;
3
+ import { CurrencyCode } from "@shopify/react-i18n" ;
4
+ import { Redirect } from "@shopify/app-bridge/actions" ;
5
+ import { useAppBridge } from "@shopify/app-bridge-react" ;
6
+
7
+ import {
8
+ ActiveDatesCard ,
9
+ CombinationCard ,
10
+ DiscountClass ,
11
+ DiscountMethod ,
12
+ MethodCard ,
13
+ DiscountStatus ,
14
+ RequirementType ,
15
+ SummaryCard ,
16
+ UsageLimitsCard ,
17
+ onBreadcrumbAction ,
18
+ } from "@shopify/discount-app-components" ;
19
+ import {
20
+ Banner ,
21
+ Card ,
22
+ Layout ,
23
+ Page ,
24
+ TextField ,
25
+ Stack ,
26
+ PageActions ,
27
+ } from "@shopify/polaris" ;
28
+ import { data } from "@shopify/app-bridge/actions/Modal" ;
29
+ import { useAuthenticatedFetch } from "../../../hooks" ;
30
+
31
+ const todaysDate = new Date ( ) ;
32
+ const METAFIELD_NAMESPACE = "discounts-tutorial" ;
33
+ const METAFIELD_CONFIGURATION_KEY = "volume-config" ;
34
+
35
+ export default function VolumeNew ( ) {
36
+ // Read the function ID from the URL
37
+ const { functionId } = useParams ( ) ;
38
+
39
+ const app = useAppBridge ( ) ;
40
+ const redirect = Redirect . create ( app ) ;
41
+ const currencyCode = CurrencyCode . Cad ;
42
+ const authenticatedFetch = useAuthenticatedFetch ( ) ;
43
+
44
+ const {
45
+ fields : {
46
+ discountTitle,
47
+ discountCode,
48
+ discountMethod,
49
+ combinesWith,
50
+ requirementType,
51
+ requirementSubtotal,
52
+ requirementQuantity,
53
+ usageTotalLimit,
54
+ usageOncePerCustomer,
55
+ startDate,
56
+ endDate,
57
+ configuration,
58
+ } ,
59
+ submit,
60
+ submitting,
61
+ dirty,
62
+ reset,
63
+ submitErrors,
64
+ makeClean,
65
+ } = useForm ( {
66
+ fields : {
67
+ discountTitle : useField ( "" ) ,
68
+ discountMethod : useField ( DiscountMethod . Code ) ,
69
+ discountCode : useField ( "" ) ,
70
+ combinesWith : useField ( {
71
+ orderDiscounts : false ,
72
+ productDiscounts : false ,
73
+ shippingDiscounts : false ,
74
+ } ) ,
75
+ requirementType : useField ( RequirementType . None ) ,
76
+ requirementSubtotal : useField ( "0" ) ,
77
+ requirementQuantity : useField ( "0" ) ,
78
+ usageTotalLimit : useField ( null ) ,
79
+ usageOncePerCustomer : useField ( false ) ,
80
+ startDate : useField ( todaysDate ) ,
81
+ endDate : useField ( null ) ,
82
+ configuration : { } ,
83
+ } ,
84
+ onSubmit : async ( form ) => {
85
+ const discount = {
86
+ functionId,
87
+ combinesWith : form . combinesWith ,
88
+ startsAt : form . startDate ,
89
+ endsAt : form . endDate ,
90
+ metafields : [
91
+ {
92
+ namespace : METAFIELD_NAMESPACE ,
93
+ key : METAFIELD_CONFIGURATION_KEY ,
94
+ type : "json" ,
95
+ value : JSON . stringify ( { } ) ,
96
+ } ,
97
+ ] ,
98
+ } ;
99
+
100
+ let response ;
101
+ if ( form . discountMethod === DiscountMethod . Automatic ) {
102
+ response = await authenticatedFetch ( "/api/discounts/automatic" , {
103
+ method : "POST" ,
104
+ headers : { "Content-Type" : "application/json" } ,
105
+ body : JSON . stringify ( { ...discount , title : form . discountTitle } ) ,
106
+ } ) ;
107
+ } else {
108
+ response = await authenticatedFetch ( "/api/discounts/code" , {
109
+ method : "POST" ,
110
+ headers : { "Content-Type" : "application/json" } ,
111
+ body : JSON . stringify ( {
112
+ ...discount ,
113
+ title : form . discountCode ,
114
+ code : form . discountCode ,
115
+ } ) ,
116
+ } ) ;
117
+ }
118
+
119
+ const data = ( await response . json ( ) ) . data ;
120
+ const remoteErrors = data . discountCreate . userErrors ;
121
+ if ( remoteErrors . length > 0 ) {
122
+ return { status : "fail" , errors : remoteErrors } ;
123
+ }
124
+
125
+ redirect . dispatch ( Redirect . Action . ADMIN_SECTION , {
126
+ name : Redirect . ResourceType . Discount ,
127
+ } ) ;
128
+ return { status : "success" } ;
129
+ } ,
130
+ } ) ;
131
+
132
+ const errorBanner =
133
+ submitErrors . length > 0 ? (
134
+ < Layout . Section >
135
+ < Banner status = "critical" >
136
+ < p > There were some issues with your form submission:</ p >
137
+ < ul >
138
+ { submitErrors . map ( ( { message, field } , index ) => {
139
+ return (
140
+ < li key = { `${ message } ${ index } ` } >
141
+ { field . join ( "." ) } { message }
142
+ </ li >
143
+ ) ;
144
+ } ) }
145
+ </ ul >
146
+ </ Banner >
147
+ </ Layout . Section >
148
+ ) : null ;
149
+
150
+ return (
151
+ < Page
152
+ title = "Create volume discount"
153
+ breadcrumbs = { [
154
+ {
155
+ content : "Discounts" ,
156
+ onAction : ( ) => onBreadcrumbAction ( redirect , true ) ,
157
+ } ,
158
+ ] }
159
+ primaryAction = { {
160
+ content : "Save" ,
161
+ onAction : submit ,
162
+ disabled : ! dirty ,
163
+ loading : submitting ,
164
+ } }
165
+ >
166
+ < Layout >
167
+ { errorBanner }
168
+ < Layout . Section >
169
+ < form onSubmit = { submit } >
170
+ < MethodCard
171
+ title = "Volume"
172
+ discountTitle = { discountTitle }
173
+ discountClass = { DiscountClass . Product }
174
+ discountCode = { discountCode }
175
+ discountMethod = { discountMethod }
176
+ />
177
+ { discountMethod . value === DiscountMethod . Code && (
178
+ < UsageLimitsCard
179
+ totalUsageLimit = { usageTotalLimit }
180
+ oncePerCustomer = { usageOncePerCustomer }
181
+ />
182
+ ) }
183
+ < CombinationCard
184
+ combinableDiscountTypes = { combinesWith }
185
+ discountClass = { DiscountClass . Product }
186
+ discountDescriptor = {
187
+ discountMethod . value === DiscountMethod . Automatic
188
+ ? discountTitle . value
189
+ : discountCode . value
190
+ }
191
+ />
192
+ < ActiveDatesCard
193
+ startDate = { startDate }
194
+ endDate = { endDate }
195
+ timezoneAbbreviation = "EST"
196
+ />
197
+ </ form >
198
+ </ Layout . Section >
199
+ < Layout . Section secondary >
200
+ < SummaryCard
201
+ header = { {
202
+ discountMethod : discountMethod . value ,
203
+ discountDescriptor :
204
+ discountMethod . value === DiscountMethod . Automatic
205
+ ? discountTitle . value
206
+ : discountCode . value ,
207
+ appDiscountType : "Volume" ,
208
+ isEditing : false ,
209
+ } }
210
+ performance = { {
211
+ status : DiscountStatus . Scheduled ,
212
+ usageCount : 0 ,
213
+ } }
214
+ minimumRequirements = { {
215
+ requirementType : requirementType . value ,
216
+ subtotal : requirementSubtotal . value ,
217
+ quantity : requirementQuantity . value ,
218
+ currencyCode : currencyCode ,
219
+ } }
220
+ usageLimits = { {
221
+ oncePerCustomer : usageOncePerCustomer . value ,
222
+ totalUsageLimit : usageTotalLimit . value ,
223
+ } }
224
+ activeDates = { {
225
+ startDate : startDate . value ,
226
+ endDate : endDate . value ,
227
+ } }
228
+ />
229
+ </ Layout . Section >
230
+ < Layout . Section >
231
+ < PageActions
232
+ primaryAction = { {
233
+ content : "Save discount" ,
234
+ onAction : submit ,
235
+ disabled : ! dirty ,
236
+ loading : submitting ,
237
+ } }
238
+ secondaryActions = { [
239
+ {
240
+ content : "Discard" ,
241
+ onAction : ( ) => onBreadcrumbAction ( redirect , true ) ,
242
+ } ,
243
+ ] }
244
+ />
245
+ </ Layout . Section >
246
+ </ Layout >
247
+ </ Page >
248
+ ) ;
249
+ }
0 commit comments