|
|
@@ -7,16 +7,17 @@
|
|
|
<q-card
|
|
|
v-for="item in data"
|
|
|
:key="item.id"
|
|
|
- class="schedule-card card-border shadow-card bg-surface"
|
|
|
:flat="false"
|
|
|
- >
|
|
|
- <q-card-section class="q-pa-md row col-12 no-wrap">
|
|
|
- <div class="col-3 column text-center">
|
|
|
+ class="schedule-card card-border shadow-card bg-surface"
|
|
|
+ >
|
|
|
+ <q-card-section class="q-pa-md row col-12 no-wrap schedule-card-section">
|
|
|
+ <div class="column text-center schedule-avatar">
|
|
|
<div class="col-7">
|
|
|
<q-avatar :style="avatarColors[item.id % avatarColors.length]" class="text-weight-bold q-mx-auto">
|
|
|
{{ item.provider_name?.slice(0,1) ?? '—' }}
|
|
|
</q-avatar>
|
|
|
</div>
|
|
|
+
|
|
|
<div class="col-5 column justify-end">
|
|
|
<span class="text-pill text-primary customColor">
|
|
|
{{ item.schedule_type === 'custom' ? $t('dashboard_client.next_schedules.tag_custom') : $t('dashboard_client.next_schedules.tag_default') }}
|
|
|
@@ -24,47 +25,72 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="col-5 column text-text q-px-sm">
|
|
|
- <div class="col-7 column">
|
|
|
- <div class="col-4">
|
|
|
- <span class="text-provider-name">{{ item.provider_name ?? $t('dashboard_client.next_schedules.no_provider') }}</span>
|
|
|
+ <div class="column text-text q-px-sm schedule-main">
|
|
|
+ <div class="column schedule-info">
|
|
|
+ <div>
|
|
|
+ <span class="text-provider-name provider-name-ellipsis">
|
|
|
+ {{ item.provider_name ?? $t('dashboard_client.next_schedules.no_provider') }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
- <div class="col-4 column">
|
|
|
- <div class="col-6">
|
|
|
- <span class="text-schedule-date-bold">{{ formatWeekday(item.date) }}</span><span class="text-schedule-date-regular">{{ ', ' + formatDayMonth(item.date) }}</span>
|
|
|
+
|
|
|
+ <div class="column schedule-date-time">
|
|
|
+ <div class="schedule-line">
|
|
|
+ <span class="text-schedule-date-bold">
|
|
|
+ {{ formatWeekday(item.date) }}
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <span class="text-schedule-date-regular">
|
|
|
+ {{ ', ' + formatDayMonth(item.date) }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
- <div class="col-6 q-pt-sm">
|
|
|
- <span class="text-schedule-date-regular">{{ $t('dashboard_client.next_schedules.from') }} </span>
|
|
|
- <span class="text-schedule-date-bold">{{ item.start_time?.slice(0,5) }} {{ $t('dashboard_client.next_schedules.to') }} {{ item.end_time?.slice(0,5) }}</span>
|
|
|
+
|
|
|
+ <div class="schedule-line q-pt-xs">
|
|
|
+ <span class="text-schedule-date-regular">
|
|
|
+ {{ $t('dashboard_client.next_schedules.from') }}
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <span class="text-schedule-date-bold">
|
|
|
+ {{ item.start_time?.slice(0,5) }} {{ $t('dashboard_client.next_schedules.to') }} {{ item.end_time?.slice(0,5) }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="col-5">
|
|
|
- <div class="full-height column justify-end">
|
|
|
- <div class="row text-pill-place">
|
|
|
- <q-icon :name="addressIcon(item.address?.address_type ?? item.custom_address_type)" size="15px" color="primary" />
|
|
|
- <span class="row items-end">{{ addressLabel(item.address?.address_type ?? item.custom_address_type) }}</span>
|
|
|
+
|
|
|
+ <div class="schedule-place">
|
|
|
+ <div class="column justify-end">
|
|
|
+ <div class="row items-center no-wrap text-pill-place schedule-place-content">
|
|
|
+ <q-icon
|
|
|
+ :name="addressIcon(item.address?.address_type ?? item.custom_address_type)"
|
|
|
+ color="primary"
|
|
|
+ size="15px"
|
|
|
+ />
|
|
|
+
|
|
|
+ <span>
|
|
|
+ {{ addressLabel(item.address?.address_type ?? item.custom_address_type) }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="col-4 column text-text">
|
|
|
- <div class="column col-5">
|
|
|
- <span class="text-price-main col-6">
|
|
|
+ <div class="column text-text schedule-price">
|
|
|
+ <div class="column schedule-price-info">
|
|
|
+ <span class="text-price-main">
|
|
|
{{ item.total_amount && item.total_amount !== '0.00' ? formatCurrency(item.total_amount) : $t('dashboard_client.next_schedules.to_combine') }}
|
|
|
</span>
|
|
|
- <span class="text-price-label col-6">
|
|
|
+
|
|
|
+ <span class="text-price-label schedule-price-label">
|
|
|
{{ formatLabelByPeriodType(item.period_type) }}
|
|
|
</span>
|
|
|
</div>
|
|
|
- <div class="col-7 column justify-end items-end">
|
|
|
+
|
|
|
+ <div class="column justify-end items-end">
|
|
|
<q-btn
|
|
|
- unelevated rounded no-caps
|
|
|
+ class="full-width"
|
|
|
color="primary"
|
|
|
padding="1px 5px"
|
|
|
size="sm"
|
|
|
- class="full-width"
|
|
|
+ unelevated rounded no-caps
|
|
|
:label="$t('dashboard_client.next_schedules.details')"
|
|
|
@click="emit('view-details', item)"
|
|
|
/>
|
|
|
@@ -78,11 +104,12 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { useI18n } from 'vue-i18n';
|
|
|
import { formatCurrency } from 'src/helpers/utils';
|
|
|
import { formatLabelByPeriodType } from 'src/helpers/utils';
|
|
|
+import { useI18n } from 'vue-i18n';
|
|
|
|
|
|
defineProps({ data: { type: Array, default: () => [] } });
|
|
|
+
|
|
|
const emit = defineEmits(['view-details']);
|
|
|
|
|
|
const { t } = useI18n();
|
|
|
@@ -94,33 +121,36 @@ const avatarColors = [
|
|
|
{ background: '#ffe5cc', color: '#8a4500' },
|
|
|
];
|
|
|
|
|
|
-const formatWeekday = (iso) => {
|
|
|
- if (!iso) return '';
|
|
|
- const d = new Date(iso);
|
|
|
- const w = d.toLocaleDateString('pt-BR', { weekday: 'long' });
|
|
|
- return w.charAt(0).toUpperCase() + w.slice(1);
|
|
|
+const addressIcon = (type) => type === 'home' ? 'mdi-home-outline' : 'mdi-office-building-outline';
|
|
|
+
|
|
|
+const addressLabel = (type) => {
|
|
|
+ if (type === 'home') return t('address.types.commercial.home');
|
|
|
+ if (type === 'apartment') return t('dashboard_client.next_schedules.place_apartment');
|
|
|
+ if (type === 'commercial') return t('address.types.commercial.commercial');
|
|
|
+
|
|
|
+ return t('dashboard_client.next_schedules.place_unknown');
|
|
|
};
|
|
|
|
|
|
const formatDayMonth = (iso) => {
|
|
|
if (!iso) return '';
|
|
|
+
|
|
|
return new Date(iso).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' });
|
|
|
};
|
|
|
|
|
|
-const addressIcon = (type) => type === 'home' ? 'mdi-home-outline' : 'mdi-office-building-outline';
|
|
|
-
|
|
|
-const addressLabel = (type) => {
|
|
|
- if (type === 'home') return t('address.types.commercial.home');
|
|
|
- if (type === 'apartment') return t('dashboard_client.next_schedules.place_apartment');
|
|
|
- if (type === 'commercial') return t('address.types.commercial.commercial');
|
|
|
- return t('dashboard_client.next_schedules.place_unknown');
|
|
|
-};
|
|
|
+const formatWeekday = (iso) => {
|
|
|
+ if (!iso) return '';
|
|
|
|
|
|
+ const d = new Date(iso);
|
|
|
|
|
|
+ const w = d.toLocaleDateString('pt-BR', { weekday: 'long' });
|
|
|
|
|
|
+ return w.charAt(0).toUpperCase() + w.slice(1);
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.scroll-wrapper { overflow: hidden; }
|
|
|
+
|
|
|
.scroll-track {
|
|
|
display: flex;
|
|
|
flex-direction: row;
|
|
|
@@ -132,9 +162,95 @@ const addressLabel = (type) => {
|
|
|
&::-webkit-scrollbar { display: none; }
|
|
|
&::after { content: ''; flex: 0 0 1px; }
|
|
|
}
|
|
|
+
|
|
|
.schedule-card {
|
|
|
- min-width: 80%;
|
|
|
- min-height: 90px;
|
|
|
+ min-width: 90%;
|
|
|
+ min-height: 112px;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-card-section {
|
|
|
+ align-items: stretch;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-avatar {
|
|
|
+ flex: 0 0 52px;
|
|
|
+ max-width: 52px;
|
|
|
+ min-width: 52px;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-main {
|
|
|
+ flex: 1 1 auto;
|
|
|
+ min-width: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-info {
|
|
|
+ flex: 0 1 auto;
|
|
|
+ gap: 6px;
|
|
|
+ min-height: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-date-time {
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-line {
|
|
|
+ display: block;
|
|
|
+ max-width: 100%;
|
|
|
+ line-height: 1.15;
|
|
|
+ overflow: visible;
|
|
|
+ white-space: normal;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-price {
|
|
|
+ flex: 0 0 92px;
|
|
|
+ max-width: 92px;
|
|
|
+ min-width: 92px;
|
|
|
+ gap: 8px;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-price-info {
|
|
|
+ gap: 2px;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-price-label {
|
|
|
+ align-self: stretch;
|
|
|
+ line-height: 1.15;
|
|
|
+ white-space: normal;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-place {
|
|
|
+ margin-top: auto;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.schedule-place-content {
|
|
|
+ max-width: 100%;
|
|
|
+ min-width: 0;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .q-icon {
|
|
|
+ flex: 0 0 auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ flex: 1 1 auto;
|
|
|
+ min-width: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.provider-name-ellipsis {
|
|
|
+ display: block;
|
|
|
+ max-width: 100%;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
.customColor {
|