|
|
@@ -1269,13 +1269,50 @@
|
|
|
<span class="panel-label">Service</span>
|
|
|
<span class="panel-value panel-id">{{ serviceName(selection.service) }}{{ selection.reservation_id ? ': ' + selection.reservation_id : '' }}</span>
|
|
|
</div>
|
|
|
- <div v-if="selection.door_code" class="panel-row">
|
|
|
+ <div class="panel-row" :class="{ 'is-saving': resDoorState==='saving', 'is-error': resDoorState==='error' }">
|
|
|
<span class="panel-label">Door</span>
|
|
|
- <span class="panel-value">{{ selection.door_code }}</span>
|
|
|
+ <span class="panel-value">
|
|
|
+ <input class="panel-input" type="text"
|
|
|
+ :value="editingDoorCode ?? (selection.door_code || '')"
|
|
|
+ @focus="editingDoorCode = selection.door_code || ''"
|
|
|
+ @input="editingDoorCode = $event.target.value"
|
|
|
+ @blur="commitResField('door_code')"
|
|
|
+ @keydown.enter="$event.target.blur()"
|
|
|
+ @keydown.escape="editingDoorCode = null; $event.target.blur()"
|
|
|
+ />
|
|
|
+ <span v-if="resDoorState==='saving'" class="row-spinner"></span>
|
|
|
+ <span v-else-if="resDoorState==='error'" class="row-err">Failed</span>
|
|
|
+ </span>
|
|
|
</div>
|
|
|
- <div v-if="selection.wifi_key" class="panel-row">
|
|
|
- <span class="panel-label">WiFi</span>
|
|
|
- <span class="panel-value">{{ selection.wifi_key }}</span>
|
|
|
+ <div class="panel-row" :class="{ 'is-saving': resKeyState==='saving', 'is-error': resKeyState==='error' }">
|
|
|
+ <span class="panel-label">WiFi key</span>
|
|
|
+ <span class="panel-value">
|
|
|
+ <input class="panel-input" type="text"
|
|
|
+ :value="editingWifiKey ?? (selection.wifi_key || '')"
|
|
|
+ @focus="editingWifiKey = selection.wifi_key || ''"
|
|
|
+ @input="editingWifiKey = $event.target.value"
|
|
|
+ @blur="commitResField('wifi_key')"
|
|
|
+ @keydown.enter="$event.target.blur()"
|
|
|
+ @keydown.escape="editingWifiKey = null; $event.target.blur()"
|
|
|
+ />
|
|
|
+ <span v-if="resKeyState==='saving'" class="row-spinner"></span>
|
|
|
+ <span v-else-if="resKeyState==='error'" class="row-err">Failed</span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="panel-row" :class="{ 'is-saving': resSsidState==='saving', 'is-error': resSsidState==='error' }">
|
|
|
+ <span class="panel-label">WiFi SSID</span>
|
|
|
+ <span class="panel-value">
|
|
|
+ <input class="panel-input" type="text"
|
|
|
+ :value="editingWifiSsid ?? (selection.wifi_ssid || '')"
|
|
|
+ @focus="editingWifiSsid = selection.wifi_ssid || ''"
|
|
|
+ @input="editingWifiSsid = $event.target.value"
|
|
|
+ @blur="commitResField('wifi_ssid')"
|
|
|
+ @keydown.enter="$event.target.blur()"
|
|
|
+ @keydown.escape="editingWifiSsid = null; $event.target.blur()"
|
|
|
+ />
|
|
|
+ <span v-if="resSsidState==='saving'" class="row-spinner"></span>
|
|
|
+ <span v-else-if="resSsidState==='error'" class="row-err">Failed</span>
|
|
|
+ </span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -1416,6 +1453,12 @@ createApp({
|
|
|
const selection = ref(null);
|
|
|
const editingBase = ref(null);
|
|
|
const editingDiscount = ref(null);
|
|
|
+ const editingWifiSsid = ref(null);
|
|
|
+ const editingWifiKey = ref(null);
|
|
|
+ const editingDoorCode = ref(null);
|
|
|
+ const resSsidState = ref(null);
|
|
|
+ const resKeyState = ref(null);
|
|
|
+ const resDoorState = ref(null);
|
|
|
const pendingDiscountType = ref(null);
|
|
|
const pendingClosed = ref(null);
|
|
|
const discountInputRef = ref(null);
|
|
|
@@ -1748,6 +1791,39 @@ createApp({
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ async function commitResField(field) {
|
|
|
+ const editingMap = { wifi_ssid: editingWifiSsid, wifi_key: editingWifiKey, door_code: editingDoorCode };
|
|
|
+ const stateMap = { wifi_ssid: resSsidState, wifi_key: resKeyState, door_code: resDoorState };
|
|
|
+ const editRef = editingMap[field];
|
|
|
+ const stateRef = stateMap[field];
|
|
|
+ const newVal = editRef.value;
|
|
|
+ editRef.value = null;
|
|
|
+ const original = selection.value?.[field] ?? '';
|
|
|
+ if (newVal === null || newVal === original) return;
|
|
|
+ stateRef.value = 'saving';
|
|
|
+ try {
|
|
|
+ const res = await fetch(`/reservation/${selection.value.uid}`, {
|
|
|
+ method: 'PATCH',
|
|
|
+ headers: { 'Content-Type': 'application/json' },
|
|
|
+ body: JSON.stringify({ checkin_date: selection.value.checkin_date, [field]: newVal }),
|
|
|
+ });
|
|
|
+ if (!res.ok) throw new Error(await res.text());
|
|
|
+ const updated = await res.json();
|
|
|
+ selection.value.wifi_key = updated.wifi_key ?? selection.value.wifi_key;
|
|
|
+ selection.value.wifi_ssid = updated.wifi_ssid ?? selection.value.wifi_ssid;
|
|
|
+ selection.value.door_code = updated.door_code ?? selection.value.door_code;
|
|
|
+ const cd = selection.value.checkin_date;
|
|
|
+ if (reservations.value[cd]) {
|
|
|
+ Object.assign(reservations.value[cd], {
|
|
|
+ wifi_key: updated.wifi_key, wifi_ssid: updated.wifi_ssid, door_code: updated.door_code,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ stateRef.value = null;
|
|
|
+ } catch {
|
|
|
+ setError(stateRef);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// ── Helpers ────────────────────────────────────────────
|
|
|
function pad(n) { return String(n).padStart(2, '0'); }
|
|
|
|
|
|
@@ -1994,6 +2070,7 @@ createApp({
|
|
|
selection.value = {
|
|
|
type: 'res',
|
|
|
key: span.resKey,
|
|
|
+ uid: span.uid,
|
|
|
guest_name: span.guest_name,
|
|
|
service: span.service,
|
|
|
reservation_id: span.reservation_id,
|
|
|
@@ -2025,6 +2102,7 @@ createApp({
|
|
|
label: (res.guest_name || 'Guest').split(' ')[0],
|
|
|
cls: 'res',
|
|
|
resKey: key,
|
|
|
+ uid: res.uid ?? null,
|
|
|
guest_name: res.guest_name,
|
|
|
service: res.service,
|
|
|
reservation_id: res.reservation_id,
|