@movvjs/svelte-schedule-view 0.0.1
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/README.md +26 -0
- package/dist/alert/component.svelte +23 -0
- package/dist/alert/component.svelte.d.ts +14 -0
- package/dist/alert/index.d.ts +7 -0
- package/dist/alert/index.js +20 -0
- package/dist/alert/types.d.ts +9 -0
- package/dist/alert/types.js +1 -0
- package/dist/api/booking/dto.d.ts +60 -0
- package/dist/api/booking/dto.js +1 -0
- package/dist/api/booking/index.d.ts +28 -0
- package/dist/api/booking/index.js +159 -0
- package/dist/api/common/dto.d.ts +11 -0
- package/dist/api/common/dto.js +1 -0
- package/dist/api/common/index.d.ts +18 -0
- package/dist/api/common/index.js +117 -0
- package/dist/assets/icon/dest.png +0 -0
- package/dist/assets/icon/place.png +0 -0
- package/dist/assets/icon/start.png +0 -0
- package/dist/assets/icon/transparent.png +0 -0
- package/dist/assets/scss/indie_booking.scss +4464 -0
- package/dist/axios/index.d.ts +1 -0
- package/dist/axios/index.js +71 -0
- package/dist/components/BaseSearchInput.svelte +115 -0
- package/dist/components/BaseSearchInput.svelte.d.ts +31 -0
- package/dist/components/Layout.svelte +33 -0
- package/dist/components/Layout.svelte.d.ts +17 -0
- package/dist/confirm/component.svelte +35 -0
- package/dist/confirm/component.svelte.d.ts +14 -0
- package/dist/confirm/index.d.ts +8 -0
- package/dist/confirm/index.js +32 -0
- package/dist/confirm/types.d.ts +14 -0
- package/dist/confirm/types.js +1 -0
- package/dist/constant/index.d.ts +58 -0
- package/dist/constant/index.js +58 -0
- package/dist/contents/telCodes.json +235 -0
- package/dist/dayjs/index.d.ts +11 -0
- package/dist/dayjs/index.js +30 -0
- package/dist/i18n/index.js +8 -0
- package/dist/i18n/locales/en.json +116 -0
- package/dist/i18n/locales/ko.json +92 -0
- package/dist/i18n/locales/vi.json +92 -0
- package/dist/i18n/locales/zh-cn.json +92 -0
- package/dist/i18n/locales/zh-tw.json +92 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/init.d.ts +11 -0
- package/dist/init.js +14 -0
- package/dist/loaders/component.svelte +7 -0
- package/dist/loaders/component.svelte.d.ts +16 -0
- package/dist/loaders/index.d.ts +6 -0
- package/dist/loaders/index.js +16 -0
- package/dist/schedule/BookingInfo.svelte +547 -0
- package/dist/schedule/BookingInfo.svelte.d.ts +14 -0
- package/dist/schedule/CarSearch.svelte +22 -0
- package/dist/schedule/CarSearch.svelte.d.ts +23 -0
- package/dist/schedule/FileUploader.svelte +76 -0
- package/dist/schedule/FileUploader.svelte.d.ts +23 -0
- package/dist/schedule/FlightSearch.svelte +261 -0
- package/dist/schedule/FlightSearch.svelte.d.ts +24 -0
- package/dist/schedule/Map.svelte +132 -0
- package/dist/schedule/Map.svelte.d.ts +14 -0
- package/dist/schedule/PhoneNumberInput.svelte +82 -0
- package/dist/schedule/PhoneNumberInput.svelte.d.ts +19 -0
- package/dist/schedule/PickupPointView.svelte +88 -0
- package/dist/schedule/PickupPointView.svelte.d.ts +17 -0
- package/dist/schedule/PlaceSearch.svelte +27 -0
- package/dist/schedule/PlaceSearch.svelte.d.ts +21 -0
- package/dist/schedule/Plan.svelte +175 -0
- package/dist/schedule/Plan.svelte.d.ts +14 -0
- package/dist/schedule/PlanItem.svelte +174 -0
- package/dist/schedule/PlanItem.svelte.d.ts +34 -0
- package/dist/schedule/Schedule.svelte +183 -0
- package/dist/schedule/Schedule.svelte.d.ts +45 -0
- package/dist/schedule/ServiceZone.svelte +76 -0
- package/dist/schedule/ServiceZone.svelte.d.ts +14 -0
- package/dist/schedule/ServiceZoneItem.svelte +73 -0
- package/dist/schedule/ServiceZoneItem.svelte.d.ts +33 -0
- package/dist/schedule/Translation.svelte +136 -0
- package/dist/schedule/Translation.svelte.d.ts +17 -0
- package/dist/schedule/booking.d.ts +114 -0
- package/dist/schedule/booking.js +150 -0
- package/dist/store/env.d.ts +16 -0
- package/dist/store/env.js +33 -0
- package/dist/types/booking.d.ts +88 -0
- package/dist/types/booking.js +40 -0
- package/dist/types/common.d.ts +28 -0
- package/dist/types/common.js +14 -0
- package/dist/types/file.d.ts +13 -0
- package/dist/types/file.js +5 -0
- package/dist/types/flight.d.ts +25 -0
- package/dist/types/flight.js +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +5 -0
- package/dist/types/price.d.ts +18 -0
- package/dist/types/price.js +1 -0
- package/dist/utils/index.d.ts +14 -0
- package/dist/utils/index.js +48 -0
- package/package.json +62 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
<script>import { dayjs } from "../dayjs";
|
|
2
|
+
import { padStart, range } from "lodash-es";
|
|
3
|
+
import { BookingServiceType, ExtraServiceType, FileType } from "../types";
|
|
4
|
+
import { copiedBooking, originalBooking } from "./booking";
|
|
5
|
+
import { isEdit } from "./Schedule.svelte";
|
|
6
|
+
import { axios } from "../axios";
|
|
7
|
+
import { alert } from "../alert";
|
|
8
|
+
import { t } from "../i18n";
|
|
9
|
+
import { getCarName } from "../utils";
|
|
10
|
+
import Translation from "./Translation.svelte";
|
|
11
|
+
import FlightSearch from "./FlightSearch.svelte";
|
|
12
|
+
import PhoneNumberInput from "./PhoneNumberInput.svelte";
|
|
13
|
+
import FileUploader from "./FileUploader.svelte";
|
|
14
|
+
import CarSearch from "./CarSearch.svelte";
|
|
15
|
+
import { env } from "../store/env";
|
|
16
|
+
const { stdt, fullName, pax, extraServices, files, plans } = originalBooking;
|
|
17
|
+
const {
|
|
18
|
+
withPreserveAndPreview,
|
|
19
|
+
hour,
|
|
20
|
+
minute,
|
|
21
|
+
pax: editPax,
|
|
22
|
+
telNumber,
|
|
23
|
+
telCountryCode,
|
|
24
|
+
isPicketServiceAvailable,
|
|
25
|
+
isPicketServiceSelected,
|
|
26
|
+
isBabySeatServiceAvailable,
|
|
27
|
+
defaultFiles,
|
|
28
|
+
picketFiles,
|
|
29
|
+
extraServices: editExtraServices,
|
|
30
|
+
isAutoPicketFile,
|
|
31
|
+
availableExtraServices,
|
|
32
|
+
selectedPrice
|
|
33
|
+
} = copiedBooking;
|
|
34
|
+
let translation$;
|
|
35
|
+
let flightSearch$;
|
|
36
|
+
$:
|
|
37
|
+
mutation = {
|
|
38
|
+
get hour() {
|
|
39
|
+
return $hour;
|
|
40
|
+
},
|
|
41
|
+
set hour(h) {
|
|
42
|
+
withPreserveAndPreview(() => {
|
|
43
|
+
copiedBooking.update(($booking) => {
|
|
44
|
+
$booking.ymd = dayjs($booking.ymd).hour(h).format("YYYY-MM-DD HH:mm:ss");
|
|
45
|
+
return $booking;
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
get minute() {
|
|
50
|
+
return $minute;
|
|
51
|
+
},
|
|
52
|
+
set minute(m) {
|
|
53
|
+
withPreserveAndPreview(() => {
|
|
54
|
+
copiedBooking.update(($booking) => {
|
|
55
|
+
$booking.ymd = dayjs($booking.ymd).minute(m).format("YYYY-MM-DD HH:mm:ss");
|
|
56
|
+
return $booking;
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
get firstName() {
|
|
61
|
+
return $copiedBooking?.firstName ?? "";
|
|
62
|
+
},
|
|
63
|
+
set firstName(value) {
|
|
64
|
+
copiedBooking.update(($booking) => {
|
|
65
|
+
$booking.firstName = value;
|
|
66
|
+
$booking.name = `${value} ${$booking.lastName}`;
|
|
67
|
+
return $booking;
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
get lastName() {
|
|
71
|
+
return $copiedBooking?.lastName ?? "";
|
|
72
|
+
},
|
|
73
|
+
set lastName(value) {
|
|
74
|
+
copiedBooking.update(($booking) => {
|
|
75
|
+
$booking.lastName = value;
|
|
76
|
+
$booking.name = `${$booking.firstName} ${value}`;
|
|
77
|
+
return $booking;
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
get pax() {
|
|
81
|
+
return $editPax;
|
|
82
|
+
},
|
|
83
|
+
set pax(value) {
|
|
84
|
+
withPreserveAndPreview(() => {
|
|
85
|
+
copiedBooking.update(($booking) => {
|
|
86
|
+
$booking.person.adult = value;
|
|
87
|
+
return $booking;
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
get telCountryCode() {
|
|
92
|
+
return $telCountryCode ?? null;
|
|
93
|
+
},
|
|
94
|
+
set telCountryCode(value) {
|
|
95
|
+
copiedBooking.update(($booking) => {
|
|
96
|
+
const tels = [];
|
|
97
|
+
if (value)
|
|
98
|
+
tels.push(value);
|
|
99
|
+
if ($telNumber)
|
|
100
|
+
tels.push($telNumber);
|
|
101
|
+
$booking.tel = tels.join(" ");
|
|
102
|
+
return $booking;
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
get telNumber() {
|
|
106
|
+
return $telNumber ?? null;
|
|
107
|
+
},
|
|
108
|
+
set telNumber(value) {
|
|
109
|
+
copiedBooking.update(($booking) => {
|
|
110
|
+
const tels = [];
|
|
111
|
+
if ($telCountryCode)
|
|
112
|
+
tels.push($telCountryCode);
|
|
113
|
+
if (value)
|
|
114
|
+
tels.push(value);
|
|
115
|
+
$booking.tel = tels.join(" ");
|
|
116
|
+
return $booking;
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
extraServices: {
|
|
120
|
+
get babySeat() {
|
|
121
|
+
const service = $editExtraServices.find((extra) => extra.type === ExtraServiceType.baby) ?? null;
|
|
122
|
+
return !!service;
|
|
123
|
+
},
|
|
124
|
+
set babySeat(checked) {
|
|
125
|
+
withPreserveAndPreview(() => {
|
|
126
|
+
copiedBooking.update(($booking) => {
|
|
127
|
+
let extra = $editExtraServices;
|
|
128
|
+
const addService = $availableExtraServices.find((extra2) => extra2.type === ExtraServiceType.baby);
|
|
129
|
+
if (checked) {
|
|
130
|
+
extra = extra.filter((extra2) => extra2.type !== ExtraServiceType.baby);
|
|
131
|
+
extra = [...extra, addService];
|
|
132
|
+
} else {
|
|
133
|
+
extra = extra.filter((extra2) => extra2.type !== ExtraServiceType.baby);
|
|
134
|
+
}
|
|
135
|
+
$booking.extra = extra;
|
|
136
|
+
return $booking;
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
get picket() {
|
|
141
|
+
const service = $editExtraServices.find((extra) => extra.type === ExtraServiceType.picket) ?? null;
|
|
142
|
+
return !!service;
|
|
143
|
+
},
|
|
144
|
+
set picket(checked) {
|
|
145
|
+
withPreserveAndPreview(() => {
|
|
146
|
+
copiedBooking.update(($booking) => {
|
|
147
|
+
let extra = $editExtraServices;
|
|
148
|
+
const addService = $availableExtraServices.find((extra2) => extra2.type === ExtraServiceType.picket);
|
|
149
|
+
if (checked) {
|
|
150
|
+
extra = extra.filter((extra2) => extra2.type !== ExtraServiceType.picket);
|
|
151
|
+
extra = [...extra, addService];
|
|
152
|
+
} else {
|
|
153
|
+
extra = extra.filter((extra2) => extra2.type !== ExtraServiceType.picket);
|
|
154
|
+
$booking.files = $booking.files.filter((f) => f.type !== FileType.picket);
|
|
155
|
+
}
|
|
156
|
+
$booking.extra = extra;
|
|
157
|
+
return $booking;
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
get addTime() {
|
|
163
|
+
return $copiedBooking?.addTime ?? 0;
|
|
164
|
+
},
|
|
165
|
+
set addTime(hour2) {
|
|
166
|
+
withPreserveAndPreview(() => {
|
|
167
|
+
copiedBooking.update(($booking) => {
|
|
168
|
+
$booking.addTime = hour2;
|
|
169
|
+
return $booking;
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
async function copyContents() {
|
|
175
|
+
const texts = [];
|
|
176
|
+
texts.push(`FMS CODE : ${$originalBooking.code}`);
|
|
177
|
+
texts.push(`Group excode : ${$originalBooking.bookingCode}`);
|
|
178
|
+
texts.push(`${$t("booking.travelDate")} : ${dayjs($stdt).format("ll (dd)")}`);
|
|
179
|
+
texts.push(`${$t("booking.startTime")} : ${dayjs($stdt).format("HH:mm")}`);
|
|
180
|
+
texts.push(`${$t("booking.carInfo")} : ${getCarName($originalBooking.carInfo, { seat: true, seatPostfix: $t("booking.seater") })}`);
|
|
181
|
+
texts.push(`${$t("booking.pax")} : ${$pax}`);
|
|
182
|
+
texts.push(
|
|
183
|
+
`${$t("booking.flight")} : ${$originalBooking.flight?.name || "- -"} ${$originalBooking.flight?.selectType === "AUTO" && $originalBooking.flight?.arrivalTerminal ? `/ ${$t("flight.terminal", { values: { number: $originalBooking.flight.arrivalTerminal } })}` : ""}`
|
|
184
|
+
);
|
|
185
|
+
texts.push(`${$t("booking.guestName")} : ${$fullName}`);
|
|
186
|
+
texts.push(`${$t("booking.telNo")} : ${$originalBooking.tel || "- -"}`);
|
|
187
|
+
const extraServiceText = $originalBooking.extra?.length > 0 ? $originalBooking.extra.map((s) => $t(`extraServiceType.${s.type}`)).join(", ") : "- -";
|
|
188
|
+
texts.push(`${$t("booking.extraService")} : ${extraServiceText}`);
|
|
189
|
+
texts.push(`${$t("booking.reservationStatus")} : ${$originalBooking.status}`);
|
|
190
|
+
if ($originalBooking.serviceType === BookingServiceType.day || $originalBooking.serviceType === BookingServiceType.oneWay) {
|
|
191
|
+
texts.push(`${$t("booking.useTime")} : ${$originalBooking.useTime} hour(s)`);
|
|
192
|
+
}
|
|
193
|
+
const occupantInformationText = $originalBooking.addInfo?.length > 0 ? `
|
|
194
|
+
${$originalBooking.addInfo.map((info, i) => `${i + 1}. ${info.engName || "Empty Name"} (${info.birth || "Empty Birth date"})`).join("\n")}` : "- -";
|
|
195
|
+
texts.push(`${$t("booking.passengerInfo")}: ${occupantInformationText}`);
|
|
196
|
+
texts.push(`${$t("booking.memo")} : ${$originalBooking.memo || "- -"}`);
|
|
197
|
+
const scheduleTexts = [];
|
|
198
|
+
scheduleTexts.push(`
|
|
199
|
+
${$t("booking.schedule")}`);
|
|
200
|
+
scheduleTexts.push(`<${$t("schedule.start")}> ${$plans.origin.title} (${$plans.origin.address})`);
|
|
201
|
+
if ($plans.waypoints.length > 0) {
|
|
202
|
+
scheduleTexts.push(`${$plans.waypoints.map((w, i) => `${i + 1}. ${w.title} (${w.address})`).join("\n")}`);
|
|
203
|
+
}
|
|
204
|
+
scheduleTexts.push(`<${$t("schedule.finish")}> ${$plans.dest.title} (${$plans.dest.address})`);
|
|
205
|
+
texts.push(scheduleTexts.join("\n"));
|
|
206
|
+
const resultTexts = texts.join("\n");
|
|
207
|
+
try {
|
|
208
|
+
await navigator.clipboard.writeText(resultTexts);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
} finally {
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async function toggleAutoPicket(e) {
|
|
214
|
+
e.target.checked = $isAutoPicketFile;
|
|
215
|
+
try {
|
|
216
|
+
const payload = {
|
|
217
|
+
firstName: $copiedBooking.firstName?.trim() ?? "",
|
|
218
|
+
lastName: $copiedBooking.lastName?.trim() ?? "",
|
|
219
|
+
flightName: $copiedBooking.flight?.name || ""
|
|
220
|
+
};
|
|
221
|
+
const { data } = await axios.post(`/partner/booking/auto/picket`, payload);
|
|
222
|
+
const name = [payload.firstName, payload.lastName, payload.flightName].filter(Boolean).join("_");
|
|
223
|
+
$copiedBooking.files = [
|
|
224
|
+
...$copiedBooking.files,
|
|
225
|
+
{
|
|
226
|
+
...data.data,
|
|
227
|
+
name: `(auto)_${name}_picket.${data.data.ext}`,
|
|
228
|
+
auto: true
|
|
229
|
+
}
|
|
230
|
+
];
|
|
231
|
+
} catch (e2) {
|
|
232
|
+
} finally {
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function openFlightSearch() {
|
|
236
|
+
flightSearch$.open({
|
|
237
|
+
dateTime: $copiedBooking.ymd,
|
|
238
|
+
iata: $copiedBooking.origin?.iata
|
|
239
|
+
}).then((flight) => {
|
|
240
|
+
$copiedBooking.flight = flight;
|
|
241
|
+
}).catch((e) => {
|
|
242
|
+
alert.open({ text: e.message });
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
$: {
|
|
246
|
+
console.log($copiedBooking);
|
|
247
|
+
}
|
|
248
|
+
</script>
|
|
249
|
+
|
|
250
|
+
<Translation bind:this={translation$} />
|
|
251
|
+
<FlightSearch bind:this={flightSearch$} />
|
|
252
|
+
|
|
253
|
+
<div class="bookingInfoZone">
|
|
254
|
+
<h3>
|
|
255
|
+
{$t('booking.bookingInfo')}
|
|
256
|
+
{#if !$isEdit}
|
|
257
|
+
<button type="button" class="indie_btn_copy_1" on:click={() => copyContents()}>{$t('booking.contentCopy')}</button>
|
|
258
|
+
{/if}
|
|
259
|
+
</h3>
|
|
260
|
+
|
|
261
|
+
<div class="table_box">
|
|
262
|
+
<table class="tbl_bookingInfo">
|
|
263
|
+
<colgroup>
|
|
264
|
+
<col style="width: 130px;" />
|
|
265
|
+
<col style="width: auto;" />
|
|
266
|
+
</colgroup>
|
|
267
|
+
<tbody>
|
|
268
|
+
<tr>
|
|
269
|
+
<th>{$t('booking.travelDate')}</th>
|
|
270
|
+
<td>
|
|
271
|
+
<p class="value-txt">{dayjs($stdt).format('ll (dd)')}</p>
|
|
272
|
+
<!-- <input type="text" class="indie_text_nor xs3 white w100" value="2023-10-16"> -->
|
|
273
|
+
</td>
|
|
274
|
+
</tr>
|
|
275
|
+
<tr>
|
|
276
|
+
<th>{$t('booking.startTime')}</th>
|
|
277
|
+
<td>
|
|
278
|
+
{#if !$isEdit}
|
|
279
|
+
<p class="value-txt">{dayjs($stdt).format('HH:mm')}</p>
|
|
280
|
+
{:else}
|
|
281
|
+
<div class="indie_time_select_box sm">
|
|
282
|
+
<select bind:value={mutation.hour}>
|
|
283
|
+
{#each range(0, 24, 1) as hour}
|
|
284
|
+
<option value={hour}>{padStart(`${hour}`, 2, '0')}</option>
|
|
285
|
+
{/each}
|
|
286
|
+
</select>
|
|
287
|
+
<span>:</span>
|
|
288
|
+
<select bind:value={mutation.minute}>
|
|
289
|
+
{#each range(0, 60, 1) as minute}
|
|
290
|
+
<option value={minute}>{padStart(`${minute}`, 2, '0')}</option>
|
|
291
|
+
{/each}
|
|
292
|
+
</select>
|
|
293
|
+
</div>
|
|
294
|
+
{/if}
|
|
295
|
+
</td>
|
|
296
|
+
</tr>
|
|
297
|
+
|
|
298
|
+
<tr>
|
|
299
|
+
<th>{$t('booking.reservationStatus')}</th>
|
|
300
|
+
<td>
|
|
301
|
+
<p class="value-txt">{$t(`bookingStatus.${$originalBooking.status}`)}</p>
|
|
302
|
+
</td>
|
|
303
|
+
</tr>
|
|
304
|
+
|
|
305
|
+
{#if $originalBooking.serviceType === BookingServiceType.pickup}
|
|
306
|
+
<tr>
|
|
307
|
+
<th>{$t('booking.flight')}</th>
|
|
308
|
+
<td>
|
|
309
|
+
{#if !$isEdit}
|
|
310
|
+
{#if $originalBooking.flight}
|
|
311
|
+
<p class="indie_value-text flight">
|
|
312
|
+
<b>{$originalBooking.flight.name}</b>
|
|
313
|
+
{#if $originalBooking.flight.selectType === 'AUTO' && $originalBooking.flight.arrivalTerminal}
|
|
314
|
+
/ {$t('flight.terminal', { values: { number: $originalBooking.flight.arrivalTerminal } })}
|
|
315
|
+
{/if}
|
|
316
|
+
</p>
|
|
317
|
+
{#if $originalBooking.flight.selectType === 'MANUAL'}
|
|
318
|
+
<div class="indie_exclamation_mark_box sm black">
|
|
319
|
+
<p class="normal">{$t('filght.delayDescription')}</p>
|
|
320
|
+
</div>
|
|
321
|
+
{/if}
|
|
322
|
+
{:else}
|
|
323
|
+
<p class="indie_value-text flight">- -</p>
|
|
324
|
+
{/if}
|
|
325
|
+
{:else}
|
|
326
|
+
<!-- -->
|
|
327
|
+
{#if $copiedBooking.flight}
|
|
328
|
+
<p class="indie_value-text flight">
|
|
329
|
+
<b>{$copiedBooking.flight.name}</b>
|
|
330
|
+
{#if $copiedBooking.flight.selectType === 'AUTO' && $copiedBooking.flight.arrivalTerminal}
|
|
331
|
+
/ {$t('flight.terminal', { values: { number: $copiedBooking.flight.arrivalTerminal } })}
|
|
332
|
+
{/if}
|
|
333
|
+
</p>
|
|
334
|
+
<button type="button" class="indie_btn_squre only refresh_black mgl10" on:click={() => openFlightSearch()}>다시선택</button>
|
|
335
|
+
{#if $copiedBooking.flight.selectType !== 'AUTO'}
|
|
336
|
+
<div class="indie_exclamation_mark_box sm black">
|
|
337
|
+
<p class="normal">{$t('filght.delayDescription')}</p>
|
|
338
|
+
</div>
|
|
339
|
+
{/if}
|
|
340
|
+
{:else}
|
|
341
|
+
<p class="indie_value-text flight">- -</p>
|
|
342
|
+
<button type="button" class="indie_btn_squre only refresh_black mgl10" on:click={() => openFlightSearch()}>다시선택</button>
|
|
343
|
+
{/if}
|
|
344
|
+
{/if}
|
|
345
|
+
</td>
|
|
346
|
+
</tr>
|
|
347
|
+
{/if}
|
|
348
|
+
|
|
349
|
+
<tr>
|
|
350
|
+
<th>{$t('booking.guestName')}</th>
|
|
351
|
+
<td>
|
|
352
|
+
{#if !$isEdit}
|
|
353
|
+
<p class="value-txt">{$originalBooking.name}</p>
|
|
354
|
+
{:else}
|
|
355
|
+
<div class="f-row gap">
|
|
356
|
+
<input bind:value={mutation.firstName} type="text" class="indie_text_nor flexOne" placeholder={$t('booking.firstName')} />
|
|
357
|
+
<input bind:value={mutation.lastName} type="text" class="indie_text_nor flexOne" placeholder={$t('booking.lastName')} />
|
|
358
|
+
</div>
|
|
359
|
+
{/if}
|
|
360
|
+
</td>
|
|
361
|
+
</tr>
|
|
362
|
+
|
|
363
|
+
<tr>
|
|
364
|
+
<th>E-mail</th>
|
|
365
|
+
<td>
|
|
366
|
+
{#if !$isEdit}
|
|
367
|
+
<p class="value-txt">{$originalBooking.email}</p>
|
|
368
|
+
{:else}
|
|
369
|
+
<input bind:value={$copiedBooking.email} type="email" class="indie_text_nor xs3 white w100" placeholder="E-mail" />
|
|
370
|
+
{/if}
|
|
371
|
+
</td>
|
|
372
|
+
</tr>
|
|
373
|
+
|
|
374
|
+
<tr>
|
|
375
|
+
<th>{$t('booking.telNo')}</th>
|
|
376
|
+
<td>
|
|
377
|
+
{#if !$isEdit}
|
|
378
|
+
<p class="value-txt">{$originalBooking.tel || '- -'}</p>
|
|
379
|
+
{:else}
|
|
380
|
+
<PhoneNumberInput bind:telCountryCode={mutation.telCountryCode} bind:telNumber={mutation.telNumber} />
|
|
381
|
+
{/if}
|
|
382
|
+
</td>
|
|
383
|
+
</tr>
|
|
384
|
+
|
|
385
|
+
<tr>
|
|
386
|
+
<th>{$t('booking.pax')}</th>
|
|
387
|
+
<td>
|
|
388
|
+
{#if !$isEdit}
|
|
389
|
+
<p class="value-txt">{$pax}</p>
|
|
390
|
+
{:else}
|
|
391
|
+
<select bind:value={mutation.pax} class="indie_select_nor xs3">
|
|
392
|
+
{#each range(1, 30, 1) as number}
|
|
393
|
+
<option value={number}>{number}</option>
|
|
394
|
+
{/each}
|
|
395
|
+
</select>
|
|
396
|
+
{/if}
|
|
397
|
+
</td>
|
|
398
|
+
</tr>
|
|
399
|
+
|
|
400
|
+
<tr>
|
|
401
|
+
<th>{$t('booking.extraService')}</th>
|
|
402
|
+
<td>
|
|
403
|
+
{#if !$isEdit}
|
|
404
|
+
{#each $extraServices as service}
|
|
405
|
+
<p class="indie_tag_round gray">{$t(`extraServiceType.${service.type}`)}</p>
|
|
406
|
+
{:else}
|
|
407
|
+
- -
|
|
408
|
+
{/each}
|
|
409
|
+
{:else}
|
|
410
|
+
<div class="indie_f-row mgt5">
|
|
411
|
+
{#if $isBabySeatServiceAvailable}
|
|
412
|
+
<span>
|
|
413
|
+
<input bind:checked={mutation.extraServices.babySeat} type="checkbox" class="indie_check_base fz xs color" id="check_extra_baby" />
|
|
414
|
+
<label for="check_extra_baby">{$t('extraServiceType.BABY')}</label>
|
|
415
|
+
</span>
|
|
416
|
+
{/if}
|
|
417
|
+
|
|
418
|
+
{#if $isPicketServiceAvailable}
|
|
419
|
+
<span>
|
|
420
|
+
<input bind:checked={mutation.extraServices.picket} type="checkbox" class="indie_check_base fz xs color" id="check_extra_picket" />
|
|
421
|
+
<label for="check_extra_picket">{$t('extraServiceType.PICKET')}</label>
|
|
422
|
+
</span>
|
|
423
|
+
{/if}
|
|
424
|
+
|
|
425
|
+
<!-- ! AUTO 기능은 FMS만 가능 (임시) -->
|
|
426
|
+
{#if $isPicketServiceSelected && $env.target === 'FMS'}
|
|
427
|
+
<p class="switchs mg-l-auto">
|
|
428
|
+
<input checked={$isAutoPicketFile} type="checkbox" name="confirm" class="indie_switch_type_5" id="picket_auto" on:input={toggleAutoPicket} />
|
|
429
|
+
<label for="picket_auto">{$t('booking.autoPicket')}</label>
|
|
430
|
+
</p>
|
|
431
|
+
{/if}
|
|
432
|
+
</div>
|
|
433
|
+
|
|
434
|
+
{#if $isPicketServiceSelected}
|
|
435
|
+
<div class="mgt10">
|
|
436
|
+
<FileUploader
|
|
437
|
+
single
|
|
438
|
+
title={$t('booking.uploadPicketFile')}
|
|
439
|
+
fileList={$picketFiles}
|
|
440
|
+
fileType={FileType.picket}
|
|
441
|
+
on:success={({ detail: files }) => {
|
|
442
|
+
$copiedBooking.files = [...$copiedBooking.files, ...files]
|
|
443
|
+
}}
|
|
444
|
+
on:remove={({ detail: file }) => {
|
|
445
|
+
$copiedBooking.files = $copiedBooking.files.filter(f => f !== file)
|
|
446
|
+
}} />
|
|
447
|
+
</div>
|
|
448
|
+
{/if}
|
|
449
|
+
{/if}
|
|
450
|
+
</td>
|
|
451
|
+
</tr>
|
|
452
|
+
|
|
453
|
+
<tr>
|
|
454
|
+
<th>{$t('booking.file')}</th>
|
|
455
|
+
<td>
|
|
456
|
+
{#if !$isEdit}
|
|
457
|
+
{#each $files as file}
|
|
458
|
+
<a href={null} class="indie_file-upload-download-form sm w100" on:click={() => window.open(file.url)} download={file.name}>
|
|
459
|
+
<span class="name">{file.name}</span>
|
|
460
|
+
</a>
|
|
461
|
+
{:else}
|
|
462
|
+
- -
|
|
463
|
+
{/each}
|
|
464
|
+
{:else}
|
|
465
|
+
<FileUploader
|
|
466
|
+
title={$t('booking.fileUpload')}
|
|
467
|
+
fileList={$defaultFiles}
|
|
468
|
+
fileType={FileType.default}
|
|
469
|
+
on:success={({ detail: files }) => {
|
|
470
|
+
$copiedBooking.files = [...$copiedBooking.files, ...files]
|
|
471
|
+
}}
|
|
472
|
+
on:remove={({ detail: file }) => {
|
|
473
|
+
$copiedBooking.files = $copiedBooking.files.filter(f => f !== file)
|
|
474
|
+
}} />
|
|
475
|
+
{/if}
|
|
476
|
+
</td>
|
|
477
|
+
</tr>
|
|
478
|
+
|
|
479
|
+
<tr>
|
|
480
|
+
<th>{$t('booking.memo')}</th>
|
|
481
|
+
<td>
|
|
482
|
+
{#if !$isEdit}
|
|
483
|
+
<p class="value-txt">
|
|
484
|
+
{$originalBooking.memo || '- -'}
|
|
485
|
+
</p>
|
|
486
|
+
<button type="button" class="indie_btn_translation_nor" on:click={() => translation$.open($originalBooking.memo)}>{$t('booking.translate')}</button>
|
|
487
|
+
{:else}
|
|
488
|
+
<textarea bind:value={$copiedBooking.memo} class="modify-textarea" />
|
|
489
|
+
{/if}
|
|
490
|
+
</td>
|
|
491
|
+
</tr>
|
|
492
|
+
|
|
493
|
+
{#if $originalBooking.serviceType === BookingServiceType.day || $originalBooking.serviceType === BookingServiceType.oneWay}
|
|
494
|
+
<tr>
|
|
495
|
+
<th>{$t('booking.useTime')}</th>
|
|
496
|
+
<td>
|
|
497
|
+
{#if !$isEdit}
|
|
498
|
+
<p class="value-txt">{$t('booking.hours', { values: { hour: $originalBooking.useTime } })}</p>
|
|
499
|
+
{:else}
|
|
500
|
+
<div class="indie_f-row gap">
|
|
501
|
+
<select value={$copiedBooking.useTime} class="indie_select_nor xs3 col" disabled>
|
|
502
|
+
{#each range(1, 15, 1) as h}
|
|
503
|
+
<option value={h}>{$t('booking.hours', { values: { hour: h } })}</option>
|
|
504
|
+
{/each}
|
|
505
|
+
</select>
|
|
506
|
+
<select bind:value={mutation.addTime} class="indie_select_nor xs3 col">
|
|
507
|
+
<option value={0}>{$t('booking.extraHours')}</option>
|
|
508
|
+
{#each range(1, 15, 1) as h}
|
|
509
|
+
<option value={h}>{$t('booking.hours', { values: { hour: h } })}</option>
|
|
510
|
+
{/each}
|
|
511
|
+
</select>
|
|
512
|
+
</div>
|
|
513
|
+
{/if}
|
|
514
|
+
</td>
|
|
515
|
+
</tr>
|
|
516
|
+
{/if}
|
|
517
|
+
|
|
518
|
+
<tr>
|
|
519
|
+
<th>
|
|
520
|
+
{@html $t('booking.carInfo')}
|
|
521
|
+
</th>
|
|
522
|
+
<td>
|
|
523
|
+
{#if !$isEdit}
|
|
524
|
+
<p class="value-txt">{getCarName($originalBooking.carInfo, { seat: true, seatPostfix: $t('booking.seater') })}</p>
|
|
525
|
+
{:else}
|
|
526
|
+
<CarSearch
|
|
527
|
+
inputId="reqModel-reqSeat"
|
|
528
|
+
title={$selectedPrice
|
|
529
|
+
? getCarName($selectedPrice.carInfo, { seat: true, seatPostfix: $t('booking.seater') })
|
|
530
|
+
: getCarName($copiedBooking.carInfo, { seat: true, seatPostfix: $t('booking.seater') })}
|
|
531
|
+
placeholder={$t('booking.carInfo')}
|
|
532
|
+
carList={$copiedBooking.carList}
|
|
533
|
+
on:select={({ detail: searchPrice }) =>
|
|
534
|
+
withPreserveAndPreview(() => {
|
|
535
|
+
$selectedPrice = searchPrice
|
|
536
|
+
})}
|
|
537
|
+
on:clear={() =>
|
|
538
|
+
withPreserveAndPreview(() => {
|
|
539
|
+
$selectedPrice = null
|
|
540
|
+
})} />
|
|
541
|
+
{/if}
|
|
542
|
+
</td>
|
|
543
|
+
</tr>
|
|
544
|
+
</tbody>
|
|
545
|
+
</table>
|
|
546
|
+
</div>
|
|
547
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type BookingInfoProps = typeof __propDef.props;
|
|
10
|
+
export type BookingInfoEvents = typeof __propDef.events;
|
|
11
|
+
export type BookingInfoSlots = typeof __propDef.slots;
|
|
12
|
+
export default class BookingInfo extends SvelteComponent<BookingInfoProps, BookingInfoEvents, BookingInfoSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script>import BaseSearchInput, {} from "../components/BaseSearchInput.svelte";
|
|
2
|
+
import { t } from "../i18n";
|
|
3
|
+
import { getCarName } from "../utils";
|
|
4
|
+
export let placeholder = $t("booking.carInfo");
|
|
5
|
+
export let inputId;
|
|
6
|
+
export let title;
|
|
7
|
+
export let carList = [];
|
|
8
|
+
let list = [];
|
|
9
|
+
async function search(keyword) {
|
|
10
|
+
list = carList.filter((item) => {
|
|
11
|
+
const { model, seat, maker } = item.carInfo;
|
|
12
|
+
const escapedString = keyword.trim().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13
|
+
return new RegExp(escapedString, "gi").test(`${model} ${seat} ${maker}`);
|
|
14
|
+
}).map((item) => ({
|
|
15
|
+
title: getCarName(item.carInfo, { seat: true }),
|
|
16
|
+
subTitle: `${item.useTime} Hour`,
|
|
17
|
+
value: item
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<BaseSearchInput bind:list width="w220px" {inputId} {title} {placeholder} on:clear on:select on:search={({ detail: keyword }) => search(keyword)} />
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { SearchPriceV2 } from '../types';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
inputId: string;
|
|
7
|
+
title: string;
|
|
8
|
+
carList?: SearchPriceV2[];
|
|
9
|
+
};
|
|
10
|
+
events: {
|
|
11
|
+
clear: CustomEvent<any>;
|
|
12
|
+
select: CustomEvent<any>;
|
|
13
|
+
} & {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
};
|
|
16
|
+
slots: {};
|
|
17
|
+
};
|
|
18
|
+
export type CarSearchProps = typeof __propDef.props;
|
|
19
|
+
export type CarSearchEvents = typeof __propDef.events;
|
|
20
|
+
export type CarSearchSlots = typeof __propDef.slots;
|
|
21
|
+
export default class CarSearch extends SvelteComponent<CarSearchProps, CarSearchEvents, CarSearchSlots> {
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script>import { alert } from "../alert";
|
|
2
|
+
import { CommonAPI } from "../api/common";
|
|
3
|
+
import { axios } from "../axios";
|
|
4
|
+
import { t } from "../i18n";
|
|
5
|
+
import { loaders } from "../loaders";
|
|
6
|
+
import { map } from "lodash-es";
|
|
7
|
+
import { createEventDispatcher } from "svelte";
|
|
8
|
+
const dispatch = createEventDispatcher();
|
|
9
|
+
export let single = false;
|
|
10
|
+
export let title = $t("booking.fileUpload");
|
|
11
|
+
export let fileList = [];
|
|
12
|
+
export let fileType;
|
|
13
|
+
let files;
|
|
14
|
+
let input$;
|
|
15
|
+
$:
|
|
16
|
+
uploadButtonShow = (() => {
|
|
17
|
+
if (single) {
|
|
18
|
+
return fileList.length === 0;
|
|
19
|
+
} else {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
23
|
+
function browseFiles() {
|
|
24
|
+
input$.click();
|
|
25
|
+
}
|
|
26
|
+
async function uploadFile() {
|
|
27
|
+
const uploadPromises = map(files, async (file) => {
|
|
28
|
+
const data = new FormData();
|
|
29
|
+
data.append("file", file);
|
|
30
|
+
return CommonAPI.upload(data);
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
loaders.show();
|
|
34
|
+
const results = await Promise.all(uploadPromises);
|
|
35
|
+
const files2 = results.map(({ name, url }) => ({ name, url }));
|
|
36
|
+
success(files2);
|
|
37
|
+
} catch (e) {
|
|
38
|
+
alert.open({ text: $t("alert.failedToUploadFile") });
|
|
39
|
+
} finally {
|
|
40
|
+
files = null;
|
|
41
|
+
loaders.hide();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function success(files2) {
|
|
45
|
+
dispatch(
|
|
46
|
+
"success",
|
|
47
|
+
files2.map((file) => ({ ...file, type: fileType }))
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
function remove(file) {
|
|
51
|
+
dispatch("remove", file);
|
|
52
|
+
}
|
|
53
|
+
function download(file) {
|
|
54
|
+
const a$ = document.createElement("a");
|
|
55
|
+
a$.href = file.url;
|
|
56
|
+
a$.setAttribute("download", file.name);
|
|
57
|
+
a$.click();
|
|
58
|
+
}
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
{#if uploadButtonShow}
|
|
62
|
+
<a href={null} class="indie_file-upload-select-form sm w100" on:click={() => browseFiles()}>
|
|
63
|
+
<span class="gray">{title}</span>
|
|
64
|
+
<span class="black">{$t('booking.selectFile')}</span>
|
|
65
|
+
<input bind:this={input$} bind:files type="file" style="display: none;" on:change={() => uploadFile()} accept="image/*,.pdf" multiple={!single} />
|
|
66
|
+
</a>
|
|
67
|
+
{/if}
|
|
68
|
+
|
|
69
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
70
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
71
|
+
{#each fileList as file}
|
|
72
|
+
<span class="indie_file-upload-view-form sm w100" on:click={() => download(file)}>
|
|
73
|
+
<span class="name">{file.name}</span>
|
|
74
|
+
<button type="button" class="indie_btn_close_sm" on:click|stopPropagation={() => remove(file)}>삭제</button>
|
|
75
|
+
</span>
|
|
76
|
+
{/each}
|