esoftplay-event 0.0.2-s → 0.0.2-u
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.
- package/event/htmltext.tsx +40 -28
- package/event/message.tsx +2 -2
- package/event/order_detail.tsx +45 -555
- package/event/order_detail_addons.tsx +60 -0
- package/event/order_detail_addons_booked.tsx +61 -0
- package/event/order_detail_coupon.tsx +66 -0
- package/event/order_detail_instruction.tsx +96 -0
- package/event/order_detail_payment.tsx +1 -1
- package/event/order_detail_reschedule.tsx +109 -0
- package/event/order_detail_return.tsx +1 -1
- package/event/order_detail_review.tsx +174 -0
- package/event/order_detail_share.tsx +9 -6
- package/event/order_detail_tnc.tsx +76 -0
- package/event/review_add.tsx +2 -2
- package/event/seat.tsx +130 -378
- package/event/seat_map.tsx +8 -8
- package/event/seat_map_new.tsx +191 -24
- package/event/test.tsx +8 -8
- package/id.json +9 -0
- package/package.json +1 -1
package/event/seat_map_new.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// withHooks
|
|
2
|
+
import { doc, getFirestore, runTransaction } from '@react-native-firebase/firestore';
|
|
2
3
|
import { Canvas, Group, RoundedRect, Text, useFont } from '@shopify/react-native-skia';
|
|
3
4
|
import { EventButton } from 'esoftplay/cache/event/button/import';
|
|
4
5
|
import { EventHeader } from 'esoftplay/cache/event/header/import';
|
|
5
6
|
import { EventMessage } from 'esoftplay/cache/event/message/import';
|
|
7
|
+
import { LibBackground_task } from 'esoftplay/cache/lib/background_task/import';
|
|
6
8
|
import { LibCurl } from 'esoftplay/cache/lib/curl/import';
|
|
7
9
|
import { LibIcon } from 'esoftplay/cache/lib/icon/import';
|
|
8
10
|
import { LibNavigation } from 'esoftplay/cache/lib/navigation/import';
|
|
@@ -11,8 +13,9 @@ import { LibTextstyle } from 'esoftplay/cache/lib/textstyle/import';
|
|
|
11
13
|
import { LibToastProperty } from 'esoftplay/cache/lib/toast/import';
|
|
12
14
|
import { UseMap } from 'esoftplay/cache/use/map/import';
|
|
13
15
|
import esp from 'esoftplay/esp';
|
|
16
|
+
import useLazyState from 'esoftplay/lazy';
|
|
14
17
|
import useSafeState from 'esoftplay/state';
|
|
15
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
|
18
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
16
19
|
import { Dimensions, Pressable, ScrollView, View } from 'react-native';
|
|
17
20
|
import { TapGestureHandler, TapGestureHandlerStateChangeEvent } from 'react-native-gesture-handler';
|
|
18
21
|
|
|
@@ -23,10 +26,38 @@ export interface EventSeat_map_newArgs {
|
|
|
23
26
|
export interface EventSeat_map_newProps {
|
|
24
27
|
|
|
25
28
|
}
|
|
29
|
+
|
|
30
|
+
function getEventPath() {
|
|
31
|
+
return "event" + (esp.isDebug("") ? "BBT" : "BBO")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const mainPath = [getEventPath(), "event_seat", "seat_index"]
|
|
35
|
+
export function clearHoldedSeats() {
|
|
36
|
+
const app: any = esp.mod("firestore/index")().instance()
|
|
37
|
+
const firestoreUser = esp.mod("firestore/index")().getUserData(app.name)
|
|
38
|
+
esp.mod("firestore/index")().getCollectionIds(app, mainPath, [["uid", "==", firestoreUser?.uid], ["status", "==", "holding"]], [], (ids) => {
|
|
39
|
+
if (ids?.length > 0)
|
|
40
|
+
esp.mod("firestore/index")().deleteBatchDocument(app, mainPath, ids, () => {
|
|
41
|
+
}, console.log)
|
|
42
|
+
}, console.log)
|
|
43
|
+
}
|
|
44
|
+
|
|
26
45
|
export default function m(props: any): any {
|
|
27
46
|
const { dataTicket, url } = LibNavigation.getArgsAll<any>(props)
|
|
28
47
|
const qty = dataTicket?.qty
|
|
29
48
|
|
|
49
|
+
const eventData = {
|
|
50
|
+
event_id: dataTicket?.event_id,
|
|
51
|
+
price_id: dataTicket?.selected_ticket?.price_id,
|
|
52
|
+
ondate: dataTicket?.ondate || dataTicket?.selected_ticket?.list?.ondate
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const app: any = esp.mod("firestore/index")().instance()
|
|
56
|
+
const firestoreUser = esp.mod("firestore/index")().getUserData(app.name)
|
|
57
|
+
|
|
58
|
+
const [, setHoldedSeats, getHoldedSeats] = useLazyState<string[]>([])
|
|
59
|
+
const [, setLoadingSeats, getLoadingSeats] = useSafeState<string[]>([])
|
|
60
|
+
|
|
30
61
|
const deviceWidth = Dimensions.get('window').width;
|
|
31
62
|
const [scale, setScale] = useState(1);
|
|
32
63
|
const [boundingBox, setBoundingBox] = useSafeState({ "x1": 1, "x2": 2, "y1": 1, "y2": 2 })
|
|
@@ -80,38 +111,161 @@ export default function m(props: any): any {
|
|
|
80
111
|
|
|
81
112
|
const handleTap = useCallback((event: TapGestureHandlerStateChangeEvent) => {
|
|
82
113
|
if (event.nativeEvent.state !== 5) return;
|
|
83
|
-
|
|
114
|
+
|
|
84
115
|
const x = event.nativeEvent.x / scale;
|
|
85
116
|
const y = event.nativeEvent.y / scale;
|
|
117
|
+
|
|
86
118
|
for (let i = 0; i < getData()?.length; i++) {
|
|
87
119
|
const [sx, sy, seatName, status] = getData()?.[i];
|
|
120
|
+
|
|
88
121
|
const xSize = (boxSize / 2) + (sx * boxSize);
|
|
89
122
|
const ySize = (boxSize / 2) + (sy * boxSize);
|
|
90
123
|
|
|
91
124
|
if (x >= xSize && x <= xSize + boxSize && y >= ySize && y <= ySize + boxSize) {
|
|
92
|
-
if (status
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
125
|
+
if (status != 0) return;
|
|
126
|
+
if (getLoadingSeats().includes(seatName)) return;
|
|
127
|
+
|
|
128
|
+
const isSelected = getSelectedSeat().includes(seatName);
|
|
129
|
+
|
|
130
|
+
const seat: any = getHoldedSeats().find((x: any) => x.id === seatName);
|
|
131
|
+
const isHolded = !!seat;
|
|
132
|
+
const isMine = seat?.uid === firestoreUser?.uid;
|
|
133
|
+
|
|
134
|
+
if (isHolded && !isMine) {
|
|
135
|
+
LibToastProperty.show(esp.lang("event/seat_map_new", "other_user"));
|
|
136
|
+
return;
|
|
103
137
|
}
|
|
138
|
+
|
|
139
|
+
if (!isSelected && getSelectedSeat().length >= qty) {
|
|
140
|
+
LibToastProperty.show(esp.lang("event/seat_map", "max_seat", qty));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const action = isSelected ? "release" : "hold";
|
|
145
|
+
setSelectedSeat((prev: any) => {
|
|
146
|
+
if (isSelected) {
|
|
147
|
+
return prev.filter((s: string) => s !== seatName);
|
|
148
|
+
} else {
|
|
149
|
+
return [...prev, seatName];
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
setLoadingSeats(prev => [...prev, seatName]);
|
|
154
|
+
handleSelectedSeat(seatName, action)
|
|
155
|
+
.then(() => { })
|
|
156
|
+
.catch((err: any) => {
|
|
157
|
+
// setSelectedSeat((prev: any) => {
|
|
158
|
+
// if (action === "hold") {
|
|
159
|
+
// return prev.filter((s: string) => s !== seatName);
|
|
160
|
+
// } else {
|
|
161
|
+
// return [...prev, seatName];
|
|
162
|
+
// }
|
|
163
|
+
// });
|
|
164
|
+
// LibToastProperty.show(err?.message || esp.lang("event/seat_map_new", "failed_sync"));
|
|
165
|
+
})
|
|
166
|
+
.finally(() => {
|
|
167
|
+
setLoadingSeats(prev => prev.filter(s => s !== seatName));
|
|
168
|
+
});
|
|
169
|
+
|
|
104
170
|
return;
|
|
105
171
|
}
|
|
172
|
+
}
|
|
173
|
+
}, [data, boxSize, scale, firestoreUser]);
|
|
106
174
|
|
|
175
|
+
async function handleSelectedSeat(seatName: string, action?: "hold" | "release") {
|
|
176
|
+
const pathKey = `${eventData?.event_id}_${eventData?.price_id}_${eventData?.ondate}_${seatName}`
|
|
177
|
+
const path = [...mainPath, pathKey]
|
|
178
|
+
const fixedPath = esp.mod("firestore/index")().castPathToString(path)
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
await holdSeat(fixedPath, pathKey, action)
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.warn("Failed to hold seat:", error, firestoreUser.uid);
|
|
184
|
+
throw error
|
|
107
185
|
}
|
|
108
|
-
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const cat_id = `${eventData?.price_id}_${eventData?.ondate}`
|
|
189
|
+
async function holdSeat(path: string, pathKey: string, action?: "hold" | "release") {
|
|
190
|
+
const uid = firestoreUser?.uid
|
|
191
|
+
|
|
192
|
+
const db = getFirestore(app)
|
|
193
|
+
const seatRef = doc(db, path);
|
|
194
|
+
|
|
195
|
+
await runTransaction(db, async (tx) => {
|
|
196
|
+
const snap = await tx.get(seatRef);
|
|
197
|
+
const value = {
|
|
198
|
+
status: "holding",
|
|
199
|
+
id: pathKey,
|
|
200
|
+
cat_id,
|
|
201
|
+
uid,
|
|
202
|
+
updated: Date.now(),
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (!snap.exists()) {
|
|
206
|
+
tx.set(seatRef, value);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const data: any = snap.data();
|
|
211
|
+
if (data.status === "holding" && data.uid === uid) {
|
|
212
|
+
if (action === "release") {
|
|
213
|
+
tx.update(seatRef, {
|
|
214
|
+
status: "available"
|
|
215
|
+
});
|
|
216
|
+
return;
|
|
217
|
+
} else {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (data.status === "available") {
|
|
222
|
+
tx.update(seatRef, value);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
throw new Error(esp.lang("event/seat_map_new", "seat_not_avail"));
|
|
226
|
+
});
|
|
227
|
+
}
|
|
109
228
|
|
|
110
229
|
useEffect(() => {
|
|
111
230
|
loadDataSeatmapBooked()
|
|
112
231
|
return () => LibNavigation.cancelBackResult(LibNavigation.getResultKey(props))
|
|
113
232
|
}, [])
|
|
114
233
|
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
getAllHeldSeats()
|
|
236
|
+
updateTimestamp()
|
|
237
|
+
LibBackground_task.set("1", getAllHeldSeats, 2000)
|
|
238
|
+
LibBackground_task.set("2", updateTimestamp, 3000)
|
|
239
|
+
return () => {
|
|
240
|
+
LibBackground_task.clear("1")
|
|
241
|
+
LibBackground_task.clear("2")
|
|
242
|
+
}
|
|
243
|
+
}, [])
|
|
244
|
+
|
|
245
|
+
function getAllHeldSeats() {
|
|
246
|
+
esp.mod("firestore/index")().getCollectionWhere(app, mainPath, [
|
|
247
|
+
["cat_id", "==", cat_id],
|
|
248
|
+
["uid", "!=", firestoreUser?.uid],
|
|
249
|
+
["status", "==", "holding"],
|
|
250
|
+
], (docs) => {
|
|
251
|
+
const seats = docs.map((d: any) => ({ ...d.data, id: d.id.split("_").pop() }));
|
|
252
|
+
setHoldedSeats(seats)()
|
|
253
|
+
}, console.warn)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function updateTimestamp() {
|
|
257
|
+
esp.mod("firestore/index")().getCollectionIds(app, mainPath, [
|
|
258
|
+
["cat_id", "==", cat_id],
|
|
259
|
+
["uid", "==", firestoreUser?.uid],
|
|
260
|
+
["status", "==", "holding"],
|
|
261
|
+
], [], (ids) => {
|
|
262
|
+
esp.mod("firestore/index")().updateBatchDocument(app, mainPath, ids,
|
|
263
|
+
[{ key: "updated", value: Date.now() }],
|
|
264
|
+
() => { },
|
|
265
|
+
console.warn)
|
|
266
|
+
}, console.warn)
|
|
267
|
+
}
|
|
268
|
+
|
|
115
269
|
function updateIndexByRes(data: any, res: any) {
|
|
116
270
|
const resArr = res.split(",").map((item: any) => item.trim()); // biar aman dari spasi
|
|
117
271
|
return data.map((row: any) => {
|
|
@@ -136,6 +290,14 @@ export default function m(props: any): any {
|
|
|
136
290
|
})
|
|
137
291
|
}
|
|
138
292
|
|
|
293
|
+
const holdedSeatsMap = useMemo(() => {
|
|
294
|
+
const map: any = {};
|
|
295
|
+
getHoldedSeats().forEach((x: any) => {
|
|
296
|
+
map[x.id] = x.uid;
|
|
297
|
+
});
|
|
298
|
+
return map;
|
|
299
|
+
}, [getHoldedSeats()]);
|
|
300
|
+
|
|
139
301
|
function loadDataSeatmapBooked() {
|
|
140
302
|
new LibCurl("v3/event_seat_booked", {
|
|
141
303
|
event_id: dataTicket?.event_id,
|
|
@@ -204,7 +366,10 @@ export default function m(props: any): any {
|
|
|
204
366
|
getData()?.map(([x, y, name, status], i) => {
|
|
205
367
|
let newName = name?.replace(/^.*#/, "")
|
|
206
368
|
const isSelected = getSelectedSeat()?.includes(name)
|
|
207
|
-
const
|
|
369
|
+
const uid = holdedSeatsMap[name];
|
|
370
|
+
const isHolded = !!uid;
|
|
371
|
+
const isMine = uid === firestoreUser?.uid;
|
|
372
|
+
const color = isSelected ? "#8EF67B" : (isHolded && !isMine) ? getColorByStatus(9) : getColorByStatus(status)
|
|
208
373
|
const xSize = (boxSize / 2) + (x * boxSize)
|
|
209
374
|
const ySize = (boxSize / 2) + (y * boxSize)
|
|
210
375
|
|
|
@@ -290,22 +455,22 @@ export default function m(props: any): any {
|
|
|
290
455
|
function getLegends() {
|
|
291
456
|
const colors: any = [
|
|
292
457
|
["#fff", esp.lang("event/seat_map", "available"), 0],
|
|
293
|
-
["#8EF67B", esp.lang("event/seat_map", "chosen"), "-1"],
|
|
458
|
+
// ["#8EF67B", esp.lang("event/seat_map", "chosen"), "-1"],
|
|
294
459
|
["#2EBBE8", esp.lang("event/seat_map", "reserved"), 3],
|
|
295
|
-
["#6C432C", esp.lang("event/seat_map", "chosen_by"), 7],
|
|
296
|
-
["#f1f2f3", esp.lang("event/seat_map", "way"), 5],
|
|
297
|
-
["#9FA1A4", esp.lang("event/seat_map", "not_sold"), 1],
|
|
460
|
+
// ["#6C432C", esp.lang("event/seat_map", "chosen_by"), 7],
|
|
461
|
+
// ["#f1f2f3", esp.lang("event/seat_map", "way"), 5],
|
|
462
|
+
// ["#9FA1A4", esp.lang("event/seat_map", "not_sold"), 1],
|
|
298
463
|
["#6B71E6", esp.lang("event/seat_map", "seat_hold"), 2],
|
|
299
|
-
["#FF4866", esp.lang("event/seat_map", "wall"), 6],
|
|
300
|
-
["#FFA601", esp.lang("event/seat_map", "other_type"), 4],
|
|
301
|
-
["purple", esp.lang("event/seat_map", "stage"), 8]
|
|
464
|
+
// ["#FF4866", esp.lang("event/seat_map", "wall"), 6],
|
|
465
|
+
// ["#FFA601", esp.lang("event/seat_map", "other_type"), 4],
|
|
466
|
+
// ["purple", esp.lang("event/seat_map", "stage"), 8]
|
|
467
|
+
["#7e2a0c", esp.lang("event/seat_map_new", "picked_byother"), 9]
|
|
302
468
|
]
|
|
303
469
|
return colors
|
|
304
470
|
}
|
|
305
471
|
|
|
306
472
|
function getColorByStatus(statuses: number) {
|
|
307
473
|
const colors: any = {
|
|
308
|
-
8: 'purple',
|
|
309
474
|
0: '#fff',
|
|
310
475
|
1: "#9FA1A4",
|
|
311
476
|
2: "#6B71E6",
|
|
@@ -313,7 +478,9 @@ function getColorByStatus(statuses: number) {
|
|
|
313
478
|
4: "#FFA601",
|
|
314
479
|
5: "#fff",
|
|
315
480
|
6: "#FF4866",
|
|
316
|
-
7: "#6C432C"
|
|
481
|
+
7: "#6C432C",
|
|
482
|
+
8: 'purple',
|
|
483
|
+
9: "#7e2a0c"
|
|
317
484
|
}
|
|
318
485
|
return colors[statuses]
|
|
319
486
|
}
|
package/event/test.tsx
CHANGED
|
@@ -142,7 +142,7 @@ export default function m(props: any): any {
|
|
|
142
142
|
height: height * scale,
|
|
143
143
|
padding: 10,
|
|
144
144
|
backgroundColor: LibStyle.colorBgGrey,
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
}}>
|
|
147
147
|
{
|
|
148
148
|
data.map(([x, y, name, status], i) => {
|
|
@@ -211,15 +211,15 @@ export default function m(props: any): any {
|
|
|
211
211
|
function getLegends() {
|
|
212
212
|
const colors: any = [
|
|
213
213
|
["#fff", esp.lang("event/seat_map", "available"), 0],
|
|
214
|
-
["#8EF67B", esp.lang("event/seat_map", "chosen"), "-1"],
|
|
214
|
+
// ["#8EF67B", esp.lang("event/seat_map", "chosen"), "-1"],
|
|
215
215
|
["#2EBBE8", esp.lang("event/seat_map", "reserved"), 3],
|
|
216
|
-
["#6C432C", esp.lang("event/seat_map", "chosen_by"), 7],
|
|
217
|
-
["#f1f2f3", esp.lang("event/seat_map", "way"), 5],
|
|
218
|
-
["#9FA1A4", esp.lang("event/seat_map", "not_sold"), 1],
|
|
216
|
+
// ["#6C432C", esp.lang("event/seat_map", "chosen_by"), 7],
|
|
217
|
+
// ["#f1f2f3", esp.lang("event/seat_map", "way"), 5],
|
|
218
|
+
// ["#9FA1A4", esp.lang("event/seat_map", "not_sold"), 1],
|
|
219
219
|
["#6B71E6", esp.lang("event/seat_map", "seat_hold"), 2],
|
|
220
|
-
["#FF4866", esp.lang("event/seat_map", "wall"), 6],
|
|
221
|
-
["#FFA601", esp.lang("event/seat_map", "other_type"), 4],
|
|
222
|
-
["purple", esp.lang("event/seat_map", "stage"), 8]
|
|
220
|
+
// ["#FF4866", esp.lang("event/seat_map", "wall"), 6],
|
|
221
|
+
// ["#FFA601", esp.lang("event/seat_map", "other_type"), 4],
|
|
222
|
+
// ["purple", esp.lang("event/seat_map", "stage"), 8]
|
|
223
223
|
]
|
|
224
224
|
return colors
|
|
225
225
|
}
|
package/id.json
CHANGED
|
@@ -1020,6 +1020,9 @@
|
|
|
1020
1020
|
"transfer_mbanking_instruction": "Petunjuk Transfer mBanking",
|
|
1021
1021
|
"virtual_number_account": "No Virtual Account :"
|
|
1022
1022
|
},
|
|
1023
|
+
"event/order_detail_return": {
|
|
1024
|
+
"send_back_ticket": "Kembalikan Tiket"
|
|
1025
|
+
},
|
|
1023
1026
|
"event/order_detail_share": {
|
|
1024
1027
|
"cancel": "Batal",
|
|
1025
1028
|
"chose_ticket": "PILIH TIKET",
|
|
@@ -1369,6 +1372,12 @@
|
|
|
1369
1372
|
"zoom_out": "Memperkecil denah..",
|
|
1370
1373
|
"zoom_out_max": "Tidak dapat memperkecil lagi"
|
|
1371
1374
|
},
|
|
1375
|
+
"event/seat_map_new": {
|
|
1376
|
+
"failed_sync": "Gagal sinkronisasi kursi",
|
|
1377
|
+
"other_user": "Seat sedang dipilih user lain",
|
|
1378
|
+
"picked_byother": "Dipilih orang lain",
|
|
1379
|
+
"seat_not_avail": "Seat tidak tersedia"
|
|
1380
|
+
},
|
|
1372
1381
|
"event/seat_map_test": {
|
|
1373
1382
|
"front": "DEPAN",
|
|
1374
1383
|
"header_title": "Pilih Kursi"
|