esoftplay-event 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/event/additional.tsx +1 -1
  2. package/event/additional_input.tsx +15 -0
  3. package/event/additional_new.tsx +565 -0
  4. package/event/artist.tsx +14 -34
  5. package/event/artist_detail.tsx +336 -239
  6. package/event/artist_detail_multi.tsx +266 -157
  7. package/event/artist_detailv2.tsx +129 -69
  8. package/event/artistv2.tsx +5 -13
  9. package/event/button.tsx +2 -2
  10. package/event/button_order_detail.tsx +20 -8
  11. package/event/capture.tsx +2 -0
  12. package/event/checkout.ts +135 -0
  13. package/event/countdown.tsx +13 -9
  14. package/event/countdown_base.tsx +88 -48
  15. package/event/countdown_event.tsx +3 -0
  16. package/event/countdown_timestamp.tsx +106 -0
  17. package/event/coupon.tsx +1 -1
  18. package/event/coupon_generate.tsx +35 -22
  19. package/event/detail.tsx +9 -15
  20. package/event/detail2.tsx +63 -61
  21. package/event/dialog_custom.tsx +67 -0
  22. package/event/exchange_ticket_list.tsx +23 -14
  23. package/event/exchange_ticket_result.tsx +1 -1
  24. package/event/firebase_socket.ts +14 -12
  25. package/event/htmltext.tsx +40 -28
  26. package/event/index.tsx +8 -2
  27. package/event/label_input.tsx +2 -2
  28. package/event/layout.tsx +312 -0
  29. package/event/loading_page.tsx +62 -82
  30. package/event/message.tsx +2 -2
  31. package/event/order_detail.tsx +408 -477
  32. package/event/order_detail_addons.tsx +60 -0
  33. package/event/order_detail_addons_booked.tsx +61 -0
  34. package/event/order_detail_coupon.tsx +66 -0
  35. package/event/order_detail_instruction.tsx +96 -0
  36. package/event/order_detail_payment.tsx +1 -1
  37. package/event/order_detail_reschedule.tsx +109 -0
  38. package/event/order_detail_return.tsx +231 -0
  39. package/event/order_detail_review.tsx +174 -0
  40. package/event/order_detail_share.tsx +304 -0
  41. package/event/order_detail_tnc.tsx +76 -0
  42. package/event/order_detail_upgrade.tsx +140 -90
  43. package/event/order_detail_upgrade_payment.tsx +120 -38
  44. package/event/order_detail_visitor.tsx +21 -10
  45. package/event/order_detail_waiting.tsx +3 -3
  46. package/event/order_history.tsx +1 -1
  47. package/event/order_item.tsx +1 -1
  48. package/event/order_lottery.tsx +1 -1
  49. package/event/order_reschedule.tsx +29 -16
  50. package/event/order_share_to.tsx +14 -0
  51. package/event/order_waiting.tsx +1 -1
  52. package/event/payment_subscribe.tsx +18 -0
  53. package/event/point_events.tsx +35 -0
  54. package/event/point_redemption.tsx +101 -0
  55. package/event/point_redemption_exchange.tsx +60 -0
  56. package/event/point_redemption_input.tsx +56 -0
  57. package/event/point_redemption_success.tsx +50 -0
  58. package/event/point_summary.tsx +48 -0
  59. package/event/popup.tsx +4 -4
  60. package/event/queue.tsx +111 -0
  61. package/event/queue_pricing.tsx +17 -6
  62. package/event/review_add.tsx +2 -2
  63. package/event/scan_item.tsx +1 -1
  64. package/event/schedule.tsx +33 -30
  65. package/event/schedule2.tsx +86 -0
  66. package/event/seat.tsx +135 -374
  67. package/event/seat_map.tsx +8 -8
  68. package/event/seat_map_new.tsx +211 -38
  69. package/event/step.tsx +1 -1
  70. package/event/test.tsx +8 -8
  71. package/event/ticket.tsx +326 -0
  72. package/event/ticket_list.tsx +316 -258
  73. package/event/ticket_list2.tsx +349 -224
  74. package/event/ticket_list_item.tsx +61 -0
  75. package/event/ticket_list_new.tsx +710 -0
  76. package/event/tms_add_result.tsx +10 -5
  77. package/event/tms_check_ticket_result.tsx +16 -7
  78. package/event/tms_dashboard.tsx +87 -12
  79. package/event/tms_gate.tsx +32 -15
  80. package/event/tms_home.tsx +178 -92
  81. package/event/tms_idcard.tsx +43 -26
  82. package/event/tms_in.tsx +2 -3
  83. package/event/tms_in_failed.tsx +1 -1
  84. package/event/tms_in_hall.tsx +4 -1
  85. package/event/tms_in_hall_failed.tsx +36 -16
  86. package/event/tms_in_log.tsx +9 -11
  87. package/event/tms_in_success.tsx +13 -8
  88. package/event/tms_log.tsx +16 -17
  89. package/event/tms_out_hall_failed.tsx +1 -1
  90. package/event/tms_out_temporary.tsx +3 -4
  91. package/event/token_order.tsx +103 -0
  92. package/event/token_payment.tsx +79 -0
  93. package/event/visitor_index.tsx +60 -49
  94. package/event/visitor_input.tsx +336 -54
  95. package/event/visitor_inputv2.tsx +173 -88
  96. package/event/voucher.tsx +1 -1
  97. package/id.json +76 -4
  98. package/package.json +1 -1
  99. package/event/secure_page.debug.tsx +0 -34
  100. package/event/secure_page.live.tsx +0 -35
@@ -97,7 +97,7 @@ export default function m(props: EventAdditionalProps): any {
97
97
  {
98
98
  it.display_value?.map((x: any, z: number) => {
99
99
  return (
100
- <Text allowFontScaling={false} style={{ fontSize: 12, color: '#000', marginRight: 6 }}>{x}</Text>
100
+ <Text key={z} allowFontScaling={false} style={{ fontSize: 12, color: '#000', marginRight: 6 }}>{x}</Text>
101
101
  )
102
102
  })
103
103
  }
@@ -64,6 +64,8 @@ export default function m(props: EventAdditional_inputProps): any {
64
64
 
65
65
  const [newData, setNewData] = useSafeState()
66
66
  const [, setIdx, getIdx] = useLazyState<number>()
67
+ const inputRefs = useRef<React.RefObject<EventInput_rectangle>[]>([]);
68
+
67
69
 
68
70
  useEffect(() => {
69
71
  if (Object.keys(itemAddition).length > 0) {
@@ -75,6 +77,12 @@ export default function m(props: EventAdditional_inputProps): any {
75
77
  return () => LibNavigation.cancelBackResult(LibNavigation.getResultKey(props))
76
78
  }, [])
77
79
 
80
+ useEffect(() => {
81
+ if (data?.additions?.length) {
82
+ inputRefs.current = data.additions.map((_, i: number) => inputRefs.current[i] || React.createRef<EventInput_rectangle>());
83
+ }
84
+ }, [data?.additions]);
85
+
78
86
  function save() {
79
87
  let stillEmpty1 = newData?.additions?.filter((item: any) => item.is_required == 1).filter((it: any) => (it.value?.length == 0 && !it.subvalue)).length > 0
80
88
  if (stillEmpty1) {
@@ -85,6 +93,7 @@ export default function m(props: EventAdditional_inputProps): any {
85
93
  }
86
94
  }
87
95
 
96
+
88
97
  function renderCatNew(item: any, i: number) {
89
98
  let values = newData?.additions?.[i]?.value
90
99
  let display_values = newData?.additions?.[i]?.display_value
@@ -109,11 +118,17 @@ export default function m(props: EventAdditional_inputProps): any {
109
118
  {
110
119
  item.type == 1 && // text field
111
120
  <EventInput_rectangle
121
+ ref={inputRefs.current[i]}
112
122
  placeholder={item.question}
123
+ returnKeyType='next'
113
124
  placeholderTextColor='#c9c9c9'
114
125
  style={{ borderRadius: 5, borderColor: '#c9c9c9' }}
115
126
  defaultValue={newData?.additions?.[i]?.value?.[0]}
116
127
  inputStyle={{ marginLeft: 0 }}
128
+ onSubmitEditing={() => {
129
+ const nextInput = inputRefs.current[i + 1];
130
+ nextInput?.current?.focus();
131
+ }}
117
132
  onChangeText={(text) => {
118
133
  let t = text?.length == 0 ? [] : [text]
119
134
  let updateValue = LibObject.set(newData, t)('additions', i, 'value')
@@ -0,0 +1,565 @@
1
+ // withHooks
2
+ import { EventButton } from 'esoftplay/cache/event/button/import';
3
+ import { EventHeader } from 'esoftplay/cache/event/header/import';
4
+ import { EventInput_rectangle } from 'esoftplay/cache/event/input_rectangle/import';
5
+ import { EventMessage } from 'esoftplay/cache/event/message/import';
6
+ import { LibCollaps } from 'esoftplay/cache/lib/collaps/import';
7
+ import { LibCurl } from 'esoftplay/cache/lib/curl/import';
8
+ import { LibDatepicker } from 'esoftplay/cache/lib/datepicker/import';
9
+ import { LibDialog } from 'esoftplay/cache/lib/dialog/import';
10
+ import { LibIcon } from 'esoftplay/cache/lib/icon/import';
11
+ import { LibKeyboard_avoid } from 'esoftplay/cache/lib/keyboard_avoid/import';
12
+ import { LibLoading } from 'esoftplay/cache/lib/loading/import';
13
+ import { LibNavigation } from 'esoftplay/cache/lib/navigation/import';
14
+ import { LibProgress } from 'esoftplay/cache/lib/progress/import';
15
+ import { LibSlidingup } from 'esoftplay/cache/lib/slidingup/import';
16
+ import { LibStyle } from 'esoftplay/cache/lib/style/import';
17
+ import { LibToastProperty } from 'esoftplay/cache/lib/toast/import';
18
+ import { LibUtils } from 'esoftplay/cache/lib/utils/import';
19
+ import { UseCondition } from 'esoftplay/cache/use/condition/import';
20
+ import esp from 'esoftplay/esp';
21
+ import useLazyState from 'esoftplay/lazy';
22
+ import useSafeState from 'esoftplay/state';
23
+ import { useEffect, useRef } from 'react';
24
+
25
+ import React from 'react';
26
+ import { Pressable, ScrollView, Text, TouchableOpacity, View } from 'react-native';
27
+
28
+
29
+ export interface EventAdditional_newArgs {
30
+
31
+ }
32
+ export interface EventAdditional_newProps {
33
+
34
+ }
35
+ export default function m(props: EventAdditional_newProps): any {
36
+ const { dataTicket, additionalGlobal } = LibNavigation.getArgsAll(props)
37
+ const dialogDatePicker = useRef<LibSlidingup>(null)
38
+ const dialogDropdown = useRef<LibSlidingup>(null)
39
+ const [dropdownData, setDropdownData] = useSafeState()
40
+
41
+ const sampleForms = {
42
+ "2671": {
43
+ "loading": false,
44
+ "loaded": true,
45
+ "questions": [],
46
+ "responses": [
47
+ {
48
+ "ticket_no": 1,
49
+ "answers": {}
50
+ }
51
+ ]
52
+ }
53
+ }
54
+
55
+ const [forms, setForms] = useSafeState<any>({})
56
+ const [params, setParams] = useSafeState<any>()
57
+ const [loading, setLoading] = useSafeState<any>(true)
58
+ const [reload, setReload] = useLazyState<any>(1)
59
+ const additionTickets = dataTicket?.filter((item: any) => Number(item?.has_addition) == 1)
60
+
61
+ useEffect(() => {
62
+ if (additionalGlobal) {
63
+ loadForm(dataTicket?.[0])
64
+ } else {
65
+ dataTicket?.forEach((item: any) => {
66
+ loadForm(item)
67
+ })
68
+ }
69
+ return () => LibNavigation.cancelBackResult(LibNavigation.getResultKey(props))
70
+ }, [])
71
+
72
+ useEffect(() => {
73
+ dataTicket?.forEach((item: any, i: number) => {
74
+ loadForm(item)
75
+ })
76
+ }, [reload])
77
+
78
+ function loadForm(item: any) {
79
+ const formKey = additionalGlobal ? "GLOBAL_ADDITION" : item.list_id
80
+
81
+ setForms((prev: any) => ({
82
+ ...prev,
83
+ [formKey]: {
84
+ }
85
+ }))
86
+
87
+ let url = additionalGlobal
88
+ ? 'event_booking_addition_form?event_id=' + item?.event_id
89
+ : 'event_booking_addition_form?event_id=' + item?.event_id + "&price_id=" + item?.price_id
90
+
91
+ LibProgress.show("Mohon tunggu data sedang dimuat")
92
+ new LibCurl(url, null, (res, msg) => {
93
+ setLoading(false)
94
+ const questions = res?.additions || []
95
+ const responses = Array.from({ length: additionalGlobal ? 1 : item.qty }).map((_, idx) => ({
96
+ ticket_no: idx + 1,
97
+ answers: questions.reduce((obj: any, q: any) => {
98
+ obj[q.id] = q?.type == 5 ? [] : ""
99
+
100
+ return obj
101
+ }, {})
102
+ }))
103
+
104
+ setForms((prev: any) => ({
105
+ ...prev,
106
+ [formKey]: {
107
+ error: false,
108
+ ondate: item?.ondate,
109
+ questions,
110
+ responses
111
+ }
112
+ }))
113
+
114
+ LibProgress.hide()
115
+ }, (err) => {
116
+ setLoading(false)
117
+ LibProgress.hide()
118
+ setForms((prev: any) => ({
119
+ ...prev,
120
+ [formKey]: {
121
+ ondate: item?.ondate,
122
+ error: true,
123
+ message: err?.message
124
+ }
125
+ }))
126
+ }
127
+ )
128
+ }
129
+
130
+ function updateAnswer(listId: string, ticketIndex: number, questionId: string, value: string) {
131
+ setForms((prev: any) => {
132
+ const temp = { ...prev }
133
+ temp[listId]
134
+ .responses[ticketIndex]
135
+ .answers[questionId] = value
136
+
137
+ return {
138
+ ...temp
139
+ }
140
+
141
+ })
142
+ }
143
+
144
+ function validateAdditionalForm() {
145
+ let errorMessage = ""
146
+ const hasError = Object.values(forms).some((form: any) => {
147
+ return form?.questions?.some((question: any) => {
148
+ const isRequired = Number(question?.is_required) === 1
149
+
150
+ if (!isRequired) {
151
+ return false
152
+ }
153
+
154
+ return form?.responses?.some((response: any) => {
155
+ const value = response?.answers?.[question.id]
156
+ const isEmpty = value == null || String(value).trim() == ""
157
+
158
+ if (isEmpty) {
159
+ errorMessage = "Info tambahan #" + response?.ticket_no + " : " + question?.question + " wajib diisi"
160
+ return true
161
+ }
162
+ return false
163
+ })
164
+ })
165
+ })
166
+
167
+ if (hasError) {
168
+ LibToastProperty.show(errorMessage, 3000)
169
+ return false
170
+ }
171
+
172
+ return true
173
+ }
174
+
175
+ function copyFirstTicket(listId: string) {
176
+ const key = String(listId)
177
+ setForms((prev: any) => {
178
+ const temp = { ...prev }
179
+ const form = temp[key]
180
+
181
+ if (!form || !form.responses || form.responses.length <= 1) {
182
+ return prev
183
+ }
184
+
185
+ const firstAnswers = form.responses[0].answers
186
+
187
+ form.responses = form.responses.map((response: any, index: number) => {
188
+ // ticket pertama jangan diubah
189
+ if (index == 0) {
190
+ return response
191
+ }
192
+ return {
193
+ ...response,
194
+ answers: JSON.parse(JSON.stringify(firstAnswers))
195
+ }
196
+ })
197
+
198
+ return {
199
+ ...temp
200
+ }
201
+ })
202
+ }
203
+
204
+ function transformAdditionPayload() {
205
+ const addition: any[] = []
206
+ Object.values(forms).forEach((form: any) => {
207
+ form.responses.forEach((response: any) => {
208
+ const attendee = Object.entries(response.answers).map(([questionId, value]: any) => {
209
+ const question = form.questions.find((q: any) => q.id == questionId)
210
+ const type = String(question?.type)
211
+
212
+ // INPUT / TEXTAREA / DATE
213
+ if (type == "1" || type == "2" || type == "3") {
214
+ return [
215
+ questionId,
216
+ [],
217
+ value || ""
218
+ ]
219
+ }
220
+
221
+ // RADIO
222
+ if (type == "4") {
223
+ return [
224
+ questionId,
225
+ value ? [value] : [],
226
+ ""
227
+ ]
228
+ }
229
+
230
+ // CHECKBOX
231
+ if (type == "5") {
232
+ return [
233
+ questionId,
234
+ value || [],
235
+ ""
236
+ ]
237
+ }
238
+
239
+ // DROPDOWN
240
+ if (type == "6") {
241
+ return [
242
+ questionId,
243
+ value?.id ? [value.id] : [],
244
+ ""
245
+ ]
246
+ }
247
+ return [
248
+ questionId,
249
+ [],
250
+ ""
251
+ ]
252
+ })
253
+
254
+ addition.push(attendee)
255
+ })
256
+ })
257
+
258
+ return addition
259
+ }
260
+
261
+ function renderForm(form: any, item: any) {
262
+ // item itu adalah ticket item ya geyz
263
+ esp.log({ form, item });
264
+ return (
265
+ <View>
266
+ {
267
+ form?.responses?.map((ticket: any, ticketIndex: number) => (
268
+ <View key={ticketIndex} style={{ padding: 10, marginBottom: 10, borderRadius: 5, backgroundColor: LibStyle.colorBgGrey }}>
269
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignContent: 'center', alignItems: 'center' }}>
270
+ <Text allowFontScaling={false} style={{ flex: 1, fontWeight: 'bold', fontSize: 14, }} >Addition #{ticket.ticket_no}</Text>
271
+ {
272
+ ticket?.ticket_no == 2 &&
273
+ <TouchableOpacity
274
+ onPress={() => {
275
+ LibDialog.confirm("Informasi", "Apakah anda ingin menggunakan data Addition #1 untuk semua addition ?", "Ya", () => {
276
+ copyFirstTicket(item.list_id)
277
+
278
+ }, "Tidak", () => { })
279
+ }}
280
+ style={{ flexDirection: 'row', alignContent: 'center', alignItems: 'center' }} >
281
+ <Text style={{ color: "#0d6efd", fontWeight: 'bold' }} >Apply to all</Text>
282
+ </TouchableOpacity>
283
+ }
284
+ </View>
285
+ {
286
+ form?.questions?.map((question: any, ii: number) => {
287
+ let value = ticket.answers[question.id]
288
+ const formKey = additionalGlobal ? "GLOBAL_ADDITION" : item.list_id
289
+
290
+ return (
291
+ <View key={question.id + ii} style={{ marginBottom: 10 }} >
292
+ <Text allowFontScaling={false} style={{ marginVertical: 8, color: '#495057' }} >{question.question}
293
+ {question?.is_required == 1 && <Text style={{ color: LibStyle.colorRed }}> *</Text>}
294
+ </Text>
295
+
296
+ {
297
+ question?.type == 1 && // text field
298
+ <EventInput_rectangle
299
+ key={question?.id}
300
+ placeholder={"Isi jawaban"}
301
+ placeholderTextColor='#c9c9c9'
302
+ style={{ marginTop: 0, borderRadius: 5, borderColor: '#c9c9c9' }}
303
+ value={value}
304
+ inputStyle={{ marginLeft: 0 }}
305
+ onChangeText={(text) => {
306
+ updateAnswer(formKey, ticketIndex, question.id, text)
307
+ }} />
308
+ }
309
+
310
+ {
311
+ question?.type == 2 && // text area
312
+ <EventInput_rectangle
313
+ key={question?.id}
314
+ multiline={true}
315
+ placeholder={"Isi jawaban"}
316
+ placeholderTextColor='#c9c9c9'
317
+ style={{ marginTop: 0, borderRadius: 5, borderColor: '#c9c9c9', height: 100, justifyContent: 'flex-start' }}
318
+ defaultValue={value}
319
+ inputStyle={{ textAlignVertical: 'top', marginLeft: 0, height: 100 }}
320
+ onChangeText={(text) => {
321
+ updateAnswer(formKey, ticketIndex, question.id, text)
322
+ }} />
323
+ }
324
+
325
+ {
326
+ question?.type == 3 && // datepicker
327
+ <TouchableOpacity onPress={() => {
328
+ setParams({
329
+ listId: formKey,
330
+ ticketIndex,
331
+ questionId: String(question.id)
332
+ })
333
+ dialogDatePicker.current?.show()
334
+ }} style={{ height: 40, borderRadius: 5, backgroundColor: "#ffffff", borderWidth: 1, borderColor: "#c5c5c5", flexDirection: 'row', alignContent: 'center', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 9 }}>
335
+ <Text allowFontScaling={false} style={{ fontSize: 12, color: value != "" ? "#000" : "#e5e5e5", marginRight: 15, }}>{value != "" ? LibUtils.moment(value).format("DD MMM YYYY") : question?.question}</Text>
336
+ <LibIcon name='chevron-down' />
337
+ </TouchableOpacity>
338
+ }
339
+
340
+ {
341
+ question?.type == 4 && // choice
342
+ <View style={{}}>
343
+ {
344
+ question?.options?.length > 0 && question?.options?.map((it: any, z: number) => {
345
+ let _value = value == it?.id
346
+ return (
347
+ <Pressable
348
+ key={z}
349
+ hitSlop={{ top: 10, right: 10 }}
350
+ onPress={() => {
351
+ updateAnswer(formKey, ticketIndex, question.id, it?.id)
352
+ }}
353
+ style={{ flexDirection: 'row', marginBottom: 5, alignContent: 'center', alignItems: 'center' }}>
354
+ <LibIcon name={_value ? 'circle' : 'circle-outline'} size={20} color={_value ? LibStyle.colorPrimary : '#9b9b9b'} />
355
+ <Text allowFontScaling={false} style={{ marginLeft: 7, marginRight: 15, color: _value ? "#000" : "#9b9b9b" }}>{it.content}</Text>
356
+ </Pressable>
357
+ )
358
+ })
359
+ }
360
+ </View>
361
+ }
362
+
363
+ {
364
+ question?.type == 5 && // multichoice
365
+ <View style={{}}>
366
+ {
367
+ question?.options?.length > 0 && question?.options?.map((it: any, ii: number) => {
368
+ const checked = value.includes(it.id)
369
+ return (
370
+ <Pressable
371
+ key={ii}
372
+ hitSlop={{ top: 10, right: 10 }}
373
+ onPress={() => {
374
+ let newValue = checked ? value.filter((x: any) => x != it.id) : [...value, it.id]
375
+ updateAnswer(
376
+ formKey,
377
+ ticketIndex,
378
+ question.id,
379
+ newValue
380
+ )
381
+ }}
382
+ style={{ flexDirection: 'row', marginBottom: 5, alignContent: 'center', alignItems: 'center' }}>
383
+ <LibIcon name={checked ? 'checkbox-marked' : 'square-outline'} size={20} color={checked ? LibStyle.colorPrimary : '#9b9b9b'} />
384
+ <Text allowFontScaling={false} style={{ marginLeft: 7, marginRight: 15, color: checked ? "#000" : "#9b9b9b" }}>{it.content}</Text>
385
+ </Pressable>
386
+ )
387
+ })
388
+ }
389
+ </View>
390
+ }
391
+
392
+ {
393
+ question.type == 6 && // dropdown
394
+ <TouchableOpacity onPress={() => {
395
+ dialogDropdown.current?.show()
396
+ setDropdownData(question)
397
+ setParams({
398
+ listId: formKey,
399
+ ticketIndex,
400
+ questionId: String(question.id)
401
+ })
402
+ }} style={{ height: 40, borderRadius: 5, backgroundColor: "#ffffff", borderWidth: 1, borderColor: "#c5c5c5", flexDirection: 'row', alignContent: 'center', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 9 }}>
403
+ <Text allowFontScaling={false} style={{ fontSize: 12, color: value != "" ? "#000" : "#e5e5e5", marginRight: 15, }}>{value != "" ? value?.content : question.question}</Text>
404
+ <LibIcon name='chevron-down' />
405
+ </TouchableOpacity>
406
+ }
407
+
408
+ </View>
409
+ )
410
+ }
411
+ )}
412
+ </View>
413
+ )
414
+ )}
415
+ </View>
416
+ )
417
+ }
418
+
419
+ if (loading) {
420
+ return <LibLoading />
421
+ }
422
+
423
+ // esp.log(forms);
424
+
425
+ return (
426
+ <LibKeyboard_avoid style={{ flex: 1, backgroundColor: LibStyle.colorBgGrey }}>
427
+ <EventHeader title='Info Tambahan' />
428
+ <ScrollView>
429
+ <UseCondition if={additionalGlobal} fallback={
430
+ <>
431
+ {
432
+ additionTickets.map((item: any, i: number) => {
433
+ const form = forms[item.list_id]
434
+ return (
435
+ <LibCollaps
436
+ key={i}
437
+ header={(show) => (
438
+ <View style={{ margin: 15, marginBottom: 0, paddingHorizontal: 15, paddingVertical: 12, borderRadius: 7, backgroundColor: '#fff', flexDirection: 'row', alignItems: 'center' }} >
439
+ <View style={{ flex: 1 }}>
440
+ <Text style={{ fontWeight: 'bold', fontSize: 14, color: "#495057" }} >{"Info tambahan untuk " + item?.type} </Text>
441
+ <View style={{ flexDirection: 'row', alignContent: 'center', alignItems: 'center', marginTop: 3, }}>
442
+ <Text style={{ fontSize: 12, marginRight: 10, color: '#6c757d' }} >({item.qty + " Tiket"})</Text>
443
+ {form?.ondate != "0000-00-00" && <Text style={{ color: LibStyle.colorPrimary }}>{LibUtils.moment(form?.ondate).format("DD MMM YYYY")}</Text>}
444
+ </View>
445
+ </View>
446
+ <LibIcon name={!show ? "chevron-down" : "chevron-up"} />
447
+ </View>
448
+ )} >
449
+
450
+ <View style={{ padding: 15, backgroundColor: '#fff', marginHorizontal: 15, borderRadius: 7, marginTop: 1, marginBottom: 0 }} >
451
+
452
+ {/* ERROR */}
453
+ {
454
+ form?.error &&
455
+ <>
456
+ <EventMessage message={form?.message || "Gagal memuat data"}
457
+ children={
458
+ <EventButton label='Coba lagi' onPress={() => {
459
+ setReload(reload + 1)()
460
+ }} />
461
+ }
462
+ />
463
+ </>
464
+ }
465
+
466
+ {/* FORM */}
467
+ {
468
+ renderForm(form, item)
469
+ }
470
+ </View>
471
+ </LibCollaps>
472
+ )
473
+ })
474
+ }
475
+ </>
476
+ } >
477
+ <View>
478
+ <View style={{ margin: 15, marginBottom: 0, paddingHorizontal: 15, paddingVertical: 12, borderRadius: 7, backgroundColor: '#fff', flexDirection: 'row', alignItems: 'center' }} >
479
+ <Text style={{ fontWeight: 'bold', fontSize: 14, color: "#495057" }} >{"Info tambahan"} </Text>
480
+ </View>
481
+
482
+ <View style={{ padding: 15, backgroundColor: '#fff', marginHorizontal: 15, borderRadius: 7, marginTop: 1, marginBottom: 0 }} >
483
+ {
484
+ renderForm(forms?.GLOBAL_ADDITION, additionTickets[0])
485
+ }
486
+ </View>
487
+
488
+ </View>
489
+ </UseCondition>
490
+
491
+ </ScrollView>
492
+
493
+ <EventButton
494
+ label='Selanjutnya'
495
+ style={{ margin: 10 }}
496
+ backgroundColor={LibStyle.colorGreen}
497
+ onPress={() => {
498
+ const valid = validateAdditionalForm()
499
+
500
+ if (!valid) {
501
+ return
502
+ }
503
+
504
+ const payload = {
505
+ addition: transformAdditionPayload()
506
+ }
507
+ LibNavigation.sendBackResult(payload, LibNavigation.getResultKey(props))
508
+ }}
509
+ />
510
+
511
+ <LibSlidingup ref={dialogDatePicker}>
512
+ <View style={{ backgroundColor: 'white', paddingBottom: 25, height: 230 }}>
513
+ <LibDatepicker
514
+ minDate={LibUtils.moment().add(-90, 'years').localeFormat('YYYY-MM-DD')}
515
+ maxDate={LibUtils.moment().localeFormat('YYYY-MM-DD')}
516
+ onDateChange={(dt) => {
517
+ updateAnswer(
518
+ params?.listId,
519
+ params?.ticketIndex,
520
+ params?.questionId,
521
+ LibUtils.moment(dt).localeFormat('YYYY-MM-DD'))
522
+ dialogDatePicker.current?.hide()
523
+ }}
524
+ selectedDate={LibUtils.moment().localeFormat('YYYY-MM-DD')}
525
+ />
526
+ </View>
527
+ </LibSlidingup>
528
+
529
+ <LibSlidingup ref={dialogDropdown} >
530
+ <View style={{ paddingVertical: 20, maxHeight: LibStyle.height - (LibStyle.height / 5), backgroundColor: 'white', borderTopLeftRadius: 15, paddingHorizontal: 25, borderTopRightRadius: 15, padding: 10 }} >
531
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignContent: 'center', alignItems: 'center' }}>
532
+ <Text allowFontScaling={false} style={{ fontWeight: 'bold', flex: 3 }}>{dropdownData?.question}</Text>
533
+ <Pressable style={{ flex: 1, justifyContent: 'flex-end', alignContent: 'flex-end', alignItems: 'flex-end', alignSelf: 'flex-end' }} onPress={() => dialogDropdown.current?.hide()}>
534
+ <LibIcon name='close' color={"#c9c9c9"} />
535
+ </Pressable>
536
+ </View>
537
+
538
+ <ScrollView>
539
+ {
540
+ dropdownData?.options?.map((item: any, i: number) => {
541
+ return (
542
+ <Pressable onPress={() => {
543
+ updateAnswer(
544
+ params?.listId,
545
+ params?.ticketIndex,
546
+ params?.questionId,
547
+ item
548
+ )
549
+
550
+ dialogDropdown.current?.hide()
551
+ }} key={i} style={{ marginVertical: 10, marginBottom: 0, backgroundColor: '#fff', borderRadius: 10, borderWidth: 1, borderColor: '#c5c5c5', padding: 10, flexDirection: 'row', alignItems: "center" }}>
552
+ <Text allowFontScaling={false} style={{ color: '#2C2B2D' }}>{item?.content}</Text>
553
+ </Pressable>
554
+ )
555
+ })
556
+ }
557
+
558
+ </ScrollView>
559
+
560
+ </View>
561
+ </LibSlidingup>
562
+
563
+ </LibKeyboard_avoid>
564
+ )
565
+ }