164 lines
4.7 KiB
Vue
164 lines
4.7 KiB
Vue
<script setup>
|
|
import { computed, ref, watch } from 'vue';
|
|
import { useStore } from 'dashboard/composables/store';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useAlert } from 'dashboard/composables';
|
|
import Button from 'dashboard/components-next/button/Button.vue';
|
|
import { copyTextToClipboard } from 'shared/helpers/clipboard';
|
|
|
|
const props = defineProps({
|
|
marker: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
});
|
|
|
|
const store = useStore();
|
|
const { t } = useI18n();
|
|
|
|
const reservation = ref(null);
|
|
const isLoading = ref(false);
|
|
|
|
const reservationId = computed(() => props.marker?.reservation_id);
|
|
const hasMarker = computed(() => !!props.marker?.visible);
|
|
const pixValue = computed(
|
|
() => reservation.value?.pix_copy_paste || props.marker?.pix_copy_paste
|
|
);
|
|
|
|
const fetchReservation = async () => {
|
|
if (!reservationId.value) {
|
|
reservation.value = null;
|
|
return;
|
|
}
|
|
|
|
isLoading.value = true;
|
|
try {
|
|
const response = await store.dispatch(
|
|
'captainReservations/show',
|
|
reservationId.value
|
|
);
|
|
reservation.value = response?.id ? response : null;
|
|
} finally {
|
|
isLoading.value = false;
|
|
}
|
|
};
|
|
|
|
watch(reservationId, fetchReservation, { immediate: true });
|
|
|
|
const formatMoney = value =>
|
|
new Intl.NumberFormat('pt-BR', {
|
|
style: 'currency',
|
|
currency: 'BRL',
|
|
}).format(Number(value || 0));
|
|
|
|
const formatDateTime = value => {
|
|
if (!value) return '-';
|
|
return new Intl.DateTimeFormat('pt-BR', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
}).format(new Date(value));
|
|
};
|
|
|
|
const statusLabel = computed(() => {
|
|
const status = reservation.value?.ui_status || props.marker?.status;
|
|
if (!status) return '-';
|
|
|
|
const key = `CAPTAIN_RESERVATIONS.STATUS.${status.toUpperCase()}`;
|
|
const translated = t(key);
|
|
return translated === key
|
|
? reservation.value?.status_label || props.marker?.status_label || status
|
|
: translated;
|
|
});
|
|
|
|
const onCopyPix = async () => {
|
|
if (!pixValue.value) {
|
|
useAlert(
|
|
props.marker?.pix_reason === 'expired'
|
|
? t('CAPTAIN_RESERVATIONS.API.PIX_EXPIRED')
|
|
: t('CAPTAIN_RESERVATIONS.API.PIX_NOT_GENERATED')
|
|
);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await copyTextToClipboard(pixValue.value);
|
|
useAlert(t('CAPTAIN_RESERVATIONS.API.PIX_COPIED'));
|
|
} catch (error) {
|
|
useAlert(t('CAPTAIN_RESERVATIONS.API.PIX_COPY_FAILED'));
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-col gap-2 text-sm">
|
|
<p v-if="!hasMarker" class="text-n-slate-11">
|
|
{{ $t('CAPTAIN_RESERVATIONS.SIDEBAR.NO_RESERVATION') }}
|
|
</p>
|
|
|
|
<div v-else-if="isLoading" class="text-n-slate-11">
|
|
{{ $t('CAPTAIN_RESERVATIONS.SIDEBAR.LOADING') }}
|
|
</div>
|
|
|
|
<template v-else>
|
|
<div class="flex items-start justify-between gap-2">
|
|
<span class="text-n-slate-11">{{
|
|
$t('CAPTAIN_RESERVATIONS.SIDEBAR.STATUS')
|
|
}}</span>
|
|
<span class="font-medium text-n-slate-12">{{ statusLabel }}</span>
|
|
</div>
|
|
<div class="flex items-start justify-between gap-2">
|
|
<span class="text-n-slate-11">{{
|
|
$t('CAPTAIN_RESERVATIONS.SIDEBAR.SUITE')
|
|
}}</span>
|
|
<span class="font-medium text-n-slate-12">{{
|
|
reservation?.suite_identifier || marker?.suite || '-'
|
|
}}</span>
|
|
</div>
|
|
<div class="flex items-start justify-between gap-2">
|
|
<span class="text-n-slate-11">{{
|
|
$t('CAPTAIN_RESERVATIONS.SIDEBAR.CHECK_IN')
|
|
}}</span>
|
|
<span class="font-medium text-n-slate-12">{{
|
|
formatDateTime(reservation?.check_in_at || marker?.check_in_at)
|
|
}}</span>
|
|
</div>
|
|
<div class="flex items-start justify-between gap-2">
|
|
<span class="text-n-slate-11">{{
|
|
$t('CAPTAIN_RESERVATIONS.SIDEBAR.CHECK_OUT')
|
|
}}</span>
|
|
<span class="font-medium text-n-slate-12">{{
|
|
formatDateTime(reservation?.check_out_at || marker?.check_out_at)
|
|
}}</span>
|
|
</div>
|
|
<div class="flex items-start justify-between gap-2">
|
|
<span class="text-n-slate-11">{{
|
|
$t('CAPTAIN_RESERVATIONS.SIDEBAR.AMOUNT')
|
|
}}</span>
|
|
<span class="font-medium text-n-slate-12">{{
|
|
formatMoney(reservation?.amount || marker?.amount)
|
|
}}</span>
|
|
</div>
|
|
<div class="flex items-start justify-between gap-2">
|
|
<span class="text-n-slate-11">{{
|
|
$t('CAPTAIN_RESERVATIONS.SIDEBAR.UPDATED_AT')
|
|
}}</span>
|
|
<span class="font-medium text-n-slate-12">{{
|
|
formatDateTime(reservation?.updated_at || marker?.updated_at)
|
|
}}</span>
|
|
</div>
|
|
|
|
<div class="pt-1">
|
|
<Button
|
|
size="xs"
|
|
variant="outline"
|
|
:label="$t('CAPTAIN_RESERVATIONS.ACTIONS.COPY_PIX')"
|
|
@click="onCopyPix"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|