|
|
@@ -43,64 +43,54 @@
|
|
|
'solicitation-card--multiple': visibleSolicitations.length > 1,
|
|
|
}"
|
|
|
:flat="false"
|
|
|
- class="bg-surface card-border q-ma-md shadow-card solicitation-card"
|
|
|
+ class="bg-surface q-ma-md shadow-card solicitation-card"
|
|
|
>
|
|
|
<q-card-section class="q-pa-sm solicitation-card-section">
|
|
|
- <div class="items-start no-wrap q-gutter-x-sm row text-text">
|
|
|
- <div class="solicitation-avatar-column">
|
|
|
- <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.client_name)
|
|
|
- ?.slice(0, 2)
|
|
|
- .toUpperCase() ?? "??"
|
|
|
- }}
|
|
|
- </span>
|
|
|
- </q-avatar>
|
|
|
+ <div class="items-center no-wrap q-gutter-x-sm row text-text">
|
|
|
+ <q-avatar size="48px">
|
|
|
+ <img
|
|
|
+ v-if="item.customer_photo"
|
|
|
+ :src="item.customer_photo"
|
|
|
+ style="object-fit: cover"
|
|
|
+ />
|
|
|
|
|
|
- </div>
|
|
|
+ <span
|
|
|
+ v-else
|
|
|
+ class="flex flex-center full-height full-width"
|
|
|
+ style="border-radius: 50%"
|
|
|
+ :style="avatarColors[item.id % avatarColors.length]"
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ getFirstName(item.client_name)
|
|
|
+ ?.slice(0, 2)
|
|
|
+ .toUpperCase() ?? "??"
|
|
|
+ }}
|
|
|
+ </span>
|
|
|
+ </q-avatar>
|
|
|
|
|
|
<div class="column flex-1 solicitation-info">
|
|
|
- <div class="info-line solicitation-top-line no-wrap row">
|
|
|
- <div class="items-center no-wrap row info-line__main">
|
|
|
- <span class="ellipsis font12 fontbold">
|
|
|
- {{ getFirstName(item.client_name) || "—" }}
|
|
|
- </span>
|
|
|
+ <div class="items-center no-wrap q-gutter-x-xs row">
|
|
|
+ <span class="ellipsis font12 fontmedium text-name">
|
|
|
+ {{ getFirstName(item.client_name) || "—" }}
|
|
|
+ </span>
|
|
|
|
|
|
+ <div class="items-center no-wrap row">
|
|
|
<q-icon
|
|
|
- class="q-ml-xs"
|
|
|
color="warning"
|
|
|
name="mdi-star"
|
|
|
- size="12px"
|
|
|
+ size="14px"
|
|
|
/>
|
|
|
|
|
|
- <span class="font9 text-text no-wrap">
|
|
|
+ <span class="font11 no-wrap text-text">
|
|
|
{{ item.average_rating }}
|
|
|
</span>
|
|
|
</div>
|
|
|
-
|
|
|
- <div class="column items-end no-wrap q-ml-xs solicitation-price">
|
|
|
- <span class="font12 fontbold no-wrap">
|
|
|
- {{ formatCurrency(packageTotal(item)) }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="schedule-list font9">
|
|
|
+ <div class="schedule-list">
|
|
|
<div
|
|
|
v-if="item.package_items.length > 1"
|
|
|
- class="package-summary font8"
|
|
|
+ class="font8 package-summary"
|
|
|
>
|
|
|
{{ $t("provider.dashboard.solicitations.package_count", { count: item.package_items.length }) }}
|
|
|
</div>
|
|
|
@@ -110,49 +100,68 @@
|
|
|
:key="scheduleItem.id"
|
|
|
class="solicitation-date-time"
|
|
|
>
|
|
|
- <span class="schedule-weekday">
|
|
|
- {{ formatWeekday(scheduleItem.date) }}
|
|
|
- </span>
|
|
|
+ <div class="items-center no-wrap row">
|
|
|
+ <span class="font9 fontbold text-schedule-date-bold">
|
|
|
+ {{ formatWeekday(scheduleItem.date) }}
|
|
|
+ </span>
|
|
|
|
|
|
- <span class="fontbold schedule-day-month">
|
|
|
- {{ formatDayMonth(scheduleItem.date) }}
|
|
|
- </span>
|
|
|
+ <span class="font9 text-schedule-date-regular">
|
|
|
+ {{ ", " + formatDayMonth(scheduleItem.date) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
|
|
|
- <span class="fontbold schedule-time">
|
|
|
+ <div class="font9 text-schedule-date-regular">
|
|
|
{{ $t("common.from") }}
|
|
|
- {{ scheduleItem.start_time?.slice(0, 5) }}
|
|
|
+
|
|
|
+ <span class="fontbold text-schedule-date-bold">
|
|
|
+ {{ scheduleItem.start_time?.slice(0, 5) }}
|
|
|
+ </span>
|
|
|
+
|
|
|
{{ $t("common.to") }}
|
|
|
- {{ scheduleItem.end_time?.slice(0, 5) }}
|
|
|
- </span>
|
|
|
+
|
|
|
+ <span class="fontbold text-schedule-date-bold">
|
|
|
+ {{ scheduleItem.end_time?.slice(0, 5) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+ <div class="font9 text-time-since">
|
|
|
+ {{ formatTimeSinceRequest(item.time_since_request) }}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <div class="font9 info-line solicitation-address-line row text-text">
|
|
|
- {{ formatTimeSinceRequest(item.time_since_request) }} -
|
|
|
+ <div class="column items-end no-wrap solicitation-meta text-text">
|
|
|
+ <div class="font14 fontbold no-wrap text-price">
|
|
|
+ {{ formatCurrency(packageTotal(item)) }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="font10 fontmedium text-type">
|
|
|
+ {{ periodTypeLabel(item) }}
|
|
|
+ </div>
|
|
|
|
|
|
- <span class="info-line__main solicitation-address">
|
|
|
- {{ item.address?.district || "N/A" }}
|
|
|
+ <div class="ellipsis font10 text-region">
|
|
|
+ {{ item.address?.district || "N/A" }}
|
|
|
+ </div>
|
|
|
|
|
|
- <span class="fontbold no-wrap solicitation-distance">
|
|
|
+ <div class="font10 no-wrap text-distance">
|
|
|
{{ item.distance_km ?? 0 }} {{ $t("common.km") }}
|
|
|
- </span>
|
|
|
- </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
<div class="items-center q-gutter-x-sm q-mt-sm row solicitation-actions">
|
|
|
- <div class="solicitation-details">
|
|
|
- <q-btn
|
|
|
- class="col-auto q-px-none solicitation-details-btn"
|
|
|
- color="primary"
|
|
|
- flat
|
|
|
- no-caps
|
|
|
- size="xs"
|
|
|
- :label="$t('common.details')"
|
|
|
- @click="emit('view-details', item)"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <q-btn
|
|
|
+ class="col-auto solicitation-details-btn"
|
|
|
+ color="primary"
|
|
|
+ flat
|
|
|
+ no-caps
|
|
|
+ padding="4px 8px"
|
|
|
+ size="xs"
|
|
|
+ unelevated
|
|
|
+ :label="$t('common.details')"
|
|
|
+ @click="emit('view-details', item)"
|
|
|
+ />
|
|
|
|
|
|
<q-space />
|
|
|
|
|
|
@@ -186,6 +195,7 @@
|
|
|
<script setup>
|
|
|
import { avatarColors, formatCurrency, getFirstName } from "src/helpers/utils";
|
|
|
import { computed } from "vue";
|
|
|
+import { labelsPeriodTypes } from "src/helpers/labelsPeriodTypes.js";
|
|
|
import { useI18n } from "vue-i18n";
|
|
|
|
|
|
const props = defineProps({
|
|
|
@@ -223,6 +233,14 @@ const visibleSolicitations = computed(() =>
|
|
|
groupedSolicitations.value.slice(0, 3)
|
|
|
);
|
|
|
|
|
|
+const periodTypeLabel = (item) => {
|
|
|
+ const label = labelsPeriodTypes.find(
|
|
|
+ (periodType) => periodType.value == item.period_type,
|
|
|
+ )?.label;
|
|
|
+
|
|
|
+ return label ? t(label) : "";
|
|
|
+};
|
|
|
+
|
|
|
const packageTotal = (item) =>
|
|
|
item.package_items.reduce(
|
|
|
(total, packageItem) => total + (Number(packageItem.total_amount) || 0),
|
|
|
@@ -306,7 +324,7 @@ const formatTimeSinceRequest = (value) => {
|
|
|
}
|
|
|
|
|
|
.solicitation-card {
|
|
|
- box-shadow: -4px 2px 12px rgba(0, 0, 0, 0.08), 0 1px 4px rgba(0, 0, 0, 0.06) !important;
|
|
|
+ border-radius: 12px;
|
|
|
overflow: visible;
|
|
|
}
|
|
|
|
|
|
@@ -338,93 +356,47 @@ const formatTimeSinceRequest = (value) => {
|
|
|
min-width: 0;
|
|
|
}
|
|
|
|
|
|
-.solicitation-avatar-column {
|
|
|
- flex: 0 0 48px;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-
|
|
|
-.solicitation-time {
|
|
|
- margin-bottom: 6px;
|
|
|
- white-space: nowrap;
|
|
|
-}
|
|
|
-
|
|
|
.solicitation-info {
|
|
|
- align-self: stretch;
|
|
|
- justify-content: space-around;
|
|
|
gap: 2px;
|
|
|
-}
|
|
|
-
|
|
|
-.info-line {
|
|
|
- align-items: baseline;
|
|
|
- justify-content: space-between;
|
|
|
- min-width: 0;
|
|
|
-}
|
|
|
-
|
|
|
-.solicitation-top-line {
|
|
|
- align-items: flex-start;
|
|
|
-}
|
|
|
-
|
|
|
-.info-line__main {
|
|
|
min-width: 0;
|
|
|
}
|
|
|
|
|
|
-.solicitation-address {
|
|
|
- max-width: 100%;
|
|
|
- overflow-wrap: anywhere;
|
|
|
- white-space: normal;
|
|
|
-}
|
|
|
-
|
|
|
-.solicitation-distance::before {
|
|
|
- content: " - ";
|
|
|
+.solicitation-meta {
|
|
|
+ gap: 2px;
|
|
|
+ max-width: 42%;
|
|
|
+ text-align: right;
|
|
|
}
|
|
|
|
|
|
.schedule-list {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 2px;
|
|
|
- margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
.solicitation-date-time {
|
|
|
- align-items: center;
|
|
|
- display: grid;
|
|
|
- grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.4fr);
|
|
|
- border-bottom: 1px dotted #d5d5df;
|
|
|
- padding: 1px 0;
|
|
|
- width: 100%;
|
|
|
line-height: 1.35;
|
|
|
+ min-width: 0;
|
|
|
}
|
|
|
|
|
|
-.schedule-weekday {
|
|
|
- text-align: left;
|
|
|
-}
|
|
|
-
|
|
|
-.schedule-day-month {
|
|
|
- text-align: center;
|
|
|
+.font11 {
|
|
|
+ font-size: 11px;
|
|
|
}
|
|
|
|
|
|
-.schedule-time {
|
|
|
- min-width: 0;
|
|
|
- text-align: right;
|
|
|
- white-space: nowrap;
|
|
|
+.text-name,
|
|
|
+.text-price,
|
|
|
+.text-schedule-date-bold {
|
|
|
+ color: #3a3a4a;
|
|
|
}
|
|
|
|
|
|
-.solicitation-address-line {
|
|
|
- display: block;
|
|
|
- margin: 8px -8px 0;
|
|
|
- padding: 8px 8px 6px;
|
|
|
- text-align: center;
|
|
|
-
|
|
|
- &::before {
|
|
|
- color: var(--q-primary);
|
|
|
- content: "●";
|
|
|
- margin-right: 4px;
|
|
|
- }
|
|
|
+.text-distance,
|
|
|
+.text-region,
|
|
|
+.text-schedule-date-regular,
|
|
|
+.text-type {
|
|
|
+ color: #666;
|
|
|
}
|
|
|
|
|
|
-.solicitation-details {
|
|
|
- align-items: center;
|
|
|
- display: flex;
|
|
|
+.text-time-since {
|
|
|
+ color: #9a9aa5;
|
|
|
}
|
|
|
|
|
|
.solicitation-details-btn {
|