|
|
@@ -0,0 +1,302 @@
|
|
|
+<template>
|
|
|
+ <div class="q-mx-md q-mb-md">
|
|
|
+ <div class="font16 fontbold gradient-diarista q-mb-sm section-title">
|
|
|
+ {{ $t("provider.dashboard.pending_confirmation.title") }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="!data.length" class="empty-alert row no-wrap items-start">
|
|
|
+ <q-icon
|
|
|
+ class="empty-alert__icon"
|
|
|
+ name="mdi-alert-outline"
|
|
|
+ size="28px"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div class="empty-alert__text font10">
|
|
|
+ <span class="fontbold">
|
|
|
+ {{ $t("provider.dashboard.pending_confirmation.empty_alert_bold") }}
|
|
|
+ </span>
|
|
|
+
|
|
|
+ {{ $t("provider.dashboard.pending_confirmation.empty_alert_text") }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-else
|
|
|
+ class="scroll-wrapper"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="scroll-track"
|
|
|
+ :class="{ 'scroll-track--single': data.length === 1 }"
|
|
|
+ >
|
|
|
+ <q-card
|
|
|
+ v-for="item in data"
|
|
|
+ :key="item.id"
|
|
|
+ :class="{ 'schedule-card--single': data.length === 1 }"
|
|
|
+ :flat="false"
|
|
|
+ class="schedule-card card-border shadow-card bg-surface"
|
|
|
+ >
|
|
|
+ <q-card-section class="q-pa-sm">
|
|
|
+ <div class="row no-wrap items-center q-gutter-x-sm">
|
|
|
+ <q-avatar size="48px">
|
|
|
+ <img
|
|
|
+ v-if="item.customer_photo"
|
|
|
+ :src="item.customer_photo"
|
|
|
+ style="object-fit: cover"
|
|
|
+ />
|
|
|
+
|
|
|
+ <span
|
|
|
+ v-else
|
|
|
+ class="flex flex-center full-height full-width"
|
|
|
+ style="border-radius: 50%"
|
|
|
+ :style="avatarColors[item.id % avatarColors.length]"
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ getFirstName(item.customer_name ?? item.client_name)
|
|
|
+ ?.slice(0, 2)
|
|
|
+ .toUpperCase() ?? "??"
|
|
|
+ }}
|
|
|
+ </span>
|
|
|
+ </q-avatar>
|
|
|
+
|
|
|
+ <div class="column flex-1">
|
|
|
+ <div class="row items-center q-gutter-x-xs">
|
|
|
+ <span class="ellipsis font12 fontmedium text-name">
|
|
|
+ {{ getFirstName(item.customer_name ?? item.client_name) || "—" }}
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-if="item.customer_rating"
|
|
|
+ class="row items-center"
|
|
|
+ >
|
|
|
+ <q-icon
|
|
|
+ color="warning"
|
|
|
+ name="mdi-star"
|
|
|
+ size="14px"
|
|
|
+ />
|
|
|
+
|
|
|
+ <span class="text-text font11">
|
|
|
+ {{ item.customer_rating }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="row items-center no-wrap">
|
|
|
+ <span class="font9 fontbold text-schedule-date-bold">
|
|
|
+ {{ formatWeekday(item.date) }}
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <span class="font9 text-schedule-date-regular">
|
|
|
+ {{ ", " + formatDayMonth(item.date) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="text-schedule-date-regular font9">
|
|
|
+ {{ $t("common.from") }}
|
|
|
+
|
|
|
+ <span class="text-schedule-date-bold fontbold">
|
|
|
+ {{ item.start_time?.slice(0, 5) }}
|
|
|
+ </span>
|
|
|
+
|
|
|
+ {{ $t("common.to") }}
|
|
|
+
|
|
|
+ <span class="text-schedule-date-bold fontbold">
|
|
|
+ {{ item.end_time?.slice(0, 5) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="column items-end text-text">
|
|
|
+ <div class="font14 fontbold text-price">
|
|
|
+ {{ formatCurrency(item.total_amount) }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="font10 fontmedium text-type">
|
|
|
+ {{ t(labelsPeriodTypes.find((label) => label.value == item.period_type)?.label) }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="font10 text-distance">
|
|
|
+ {{ item.distance_km ?? 0 }}{{ $t("common.km") }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="font9 fontmedium items-center q-mt-md q-px-xs row text-text"
|
|
|
+ >
|
|
|
+ <div class="col ellipsis text-grey-7">
|
|
|
+ {{ formatAddress(item.address) || "N/A" }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <q-icon
|
|
|
+ class="q-ml-xs"
|
|
|
+ color="primary"
|
|
|
+ name="mdi-content-copy"
|
|
|
+ size="12px"
|
|
|
+ @click="copyAddress(item.address)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="row q-mt-sm items-center">
|
|
|
+ <q-btn
|
|
|
+ color="primary"
|
|
|
+ flat
|
|
|
+ no-caps
|
|
|
+ padding="4px 8px"
|
|
|
+ size="xs"
|
|
|
+ unelevated
|
|
|
+ :label="$t('provider.dashboard.pending_confirmation.details')"
|
|
|
+ @click="emit('view-details', item)"
|
|
|
+ />
|
|
|
+
|
|
|
+ <q-space />
|
|
|
+
|
|
|
+ <div class="font9 items-center q-gutter-x-xs row text-grey-7">
|
|
|
+ <q-icon
|
|
|
+ size="14px"
|
|
|
+ :color="item.offers_meal ? 'secondary' : 'grey-5'"
|
|
|
+ :name="item.offers_meal ? 'mdi-silverware' : 'mdi-close-outline'"
|
|
|
+ />
|
|
|
+
|
|
|
+ <span :class="item.offers_meal ? 'fontmedium' : ''">
|
|
|
+ {{
|
|
|
+ item.offers_meal
|
|
|
+ ? $t("provider.dashboard.pending_confirmation.offers_meal")
|
|
|
+ : $t("provider.dashboard.pending_confirmation.no_meal")
|
|
|
+ }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+ </q-card>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { avatarColors, formatAddress, formatCurrency, getFirstName } from "src/helpers/utils";
|
|
|
+import { labelsPeriodTypes } from "src/helpers/labelsPeriodTypes.js";
|
|
|
+import { useI18n } from "vue-i18n";
|
|
|
+import { useQuasar } from "quasar";
|
|
|
+
|
|
|
+defineProps({
|
|
|
+ data: {
|
|
|
+ default: () => [],
|
|
|
+ type: Array,
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+const emit = defineEmits(["view-details"]);
|
|
|
+
|
|
|
+const $q = useQuasar();
|
|
|
+
|
|
|
+const { t } = useI18n();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const copyAddress = (address) => {
|
|
|
+ const formatted = formatAddress(address);
|
|
|
+
|
|
|
+ if (formatted) {
|
|
|
+ navigator.clipboard.writeText(formatted);
|
|
|
+ }
|
|
|
+
|
|
|
+ $q.notify({
|
|
|
+ color: "positive",
|
|
|
+ message: t("provider.dashboard.pending_confirmation.address_copied"),
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const formatDayMonth = (iso) => {
|
|
|
+ if (!iso) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ return new Date(iso).toLocaleDateString("pt-BR", {
|
|
|
+ day: "2-digit",
|
|
|
+ month: "2-digit",
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const formatWeekday = (iso) => {
|
|
|
+ if (!iso) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ const date = new Date(iso);
|
|
|
+
|
|
|
+ const weekday = date.toLocaleDateString("pt-BR", { weekday: "long" });
|
|
|
+
|
|
|
+ return weekday.charAt(0).toUpperCase() + weekday.slice(1);
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.scroll-wrapper {
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+.empty-alert {
|
|
|
+ background: #e3efff;
|
|
|
+ border-radius: 8px;
|
|
|
+ gap: 12px;
|
|
|
+ padding: 13px 14px;
|
|
|
+}
|
|
|
+.empty-alert__icon {
|
|
|
+ color: #6554d9;
|
|
|
+ flex: 0 0 auto;
|
|
|
+}
|
|
|
+.empty-alert__text {
|
|
|
+ color: #6554d9;
|
|
|
+ line-height: 1.2;
|
|
|
+ padding-top: 1px;
|
|
|
+}
|
|
|
+.scroll-track {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ gap: 12px;
|
|
|
+ overscroll-behavior-x: contain;
|
|
|
+ overflow-x: auto;
|
|
|
+ padding-bottom: 8px;
|
|
|
+ scroll-snap-type: x proximity;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ content: "";
|
|
|
+ flex: 0 0 1px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.schedule-card {
|
|
|
+ border-radius: 12px;
|
|
|
+ min-width: 82vw;
|
|
|
+}
|
|
|
+.schedule-card--single {
|
|
|
+ min-width: 100%;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+.text-name {
|
|
|
+ color: #3a3a4a;
|
|
|
+}
|
|
|
+.text-schedule-date-bold {
|
|
|
+ color: #3a3a4a;
|
|
|
+}
|
|
|
+.text-schedule-date-regular {
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+.text-date,
|
|
|
+.text-time,
|
|
|
+.text-type,
|
|
|
+.text-region,
|
|
|
+.text-distance {
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+.text-price {
|
|
|
+ color: #3a3a4a;
|
|
|
+}
|
|
|
+.flex-1 {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+</style>
|