|
@@ -8,15 +8,20 @@
|
|
|
<q-card
|
|
<q-card
|
|
|
v-for="item in props.data"
|
|
v-for="item in props.data"
|
|
|
:key="item.id"
|
|
:key="item.id"
|
|
|
- class="today-card card-border shadow-card bg-surface"
|
|
|
|
|
:class="{ 'today-card--single': props.data.length === 1 }"
|
|
:class="{ 'today-card--single': props.data.length === 1 }"
|
|
|
:flat="false"
|
|
:flat="false"
|
|
|
|
|
+ class="today-card card-border shadow-card bg-surface"
|
|
|
>
|
|
>
|
|
|
- <q-card-section class="q-pa-md">
|
|
|
|
|
|
|
+ <q-card-section class="column justify-between q-pa-md full-height">
|
|
|
<div class="row no-wrap items-center q-mb-xs">
|
|
<div class="row no-wrap items-center q-mb-xs">
|
|
|
<div class="col-8 row">
|
|
<div class="col-8 row">
|
|
|
<q-avatar size="40px" class="flex-shrink-0 q-mr-sm">
|
|
<q-avatar size="40px" class="flex-shrink-0 q-mr-sm">
|
|
|
- <img v-if="item.customer_photo" :src="item.customer_photo" style="object-fit:cover" />
|
|
|
|
|
|
|
+ <img
|
|
|
|
|
+ v-if="item.customer_photo"
|
|
|
|
|
+ :src="item.customer_photo"
|
|
|
|
|
+ style="object-fit:cover"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
<span
|
|
<span
|
|
|
v-else
|
|
v-else
|
|
|
:style="avatarColors[item.id % avatarColors.length]"
|
|
:style="avatarColors[item.id % avatarColors.length]"
|
|
@@ -31,16 +36,30 @@
|
|
|
<span class="text-text font12">
|
|
<span class="text-text font12">
|
|
|
<template v-if="cardState(item) === 'finished'">
|
|
<template v-if="cardState(item) === 'finished'">
|
|
|
{{ $t('provider.dashboard.today_services.finished_label') }}
|
|
{{ $t('provider.dashboard.today_services.finished_label') }}
|
|
|
- <span class="fontbold"> {{ ' ' + (getFirstName(item.client_name) || '—') }}</span>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <span class="fontbold">
|
|
|
|
|
+ {{ ' ' + (getFirstName(item.client_name) || '—') }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+
|
|
|
{{ ' ' + $t('provider.dashboard.today_services.finished_suffix') }}
|
|
{{ ' ' + $t('provider.dashboard.today_services.finished_suffix') }}
|
|
|
</template>
|
|
</template>
|
|
|
|
|
+
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
{{ $t('provider.dashboard.today_services.start_label') }}
|
|
{{ $t('provider.dashboard.today_services.start_label') }}
|
|
|
- <span class="fontbold"> {{ ' ' + (getFirstName(item.client_name) || '—') }}</span>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <span class="fontbold">
|
|
|
|
|
+ {{ ' ' + (getFirstName(item.client_name) || '—') }}
|
|
|
|
|
+ </span>
|
|
|
</template>
|
|
</template>
|
|
|
</span>
|
|
</span>
|
|
|
|
|
+
|
|
|
<div class="row items-center q-mt-xs no-wrap">
|
|
<div class="row items-center q-mt-xs no-wrap">
|
|
|
- <q-icon name="mdi-clock-outline" size="12px" class="q-mr-xs gradient-diarista" />
|
|
|
|
|
|
|
+ <q-icon
|
|
|
|
|
+ class="q-mr-xs gradient-diarista"
|
|
|
|
|
+ name="mdi-clock-outline"
|
|
|
|
|
+ size="12px"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
<span class="text-grey-5 font9 fontregular">
|
|
<span class="text-grey-5 font9 fontregular">
|
|
|
{{ $t('common.from') }} {{ item.start_time?.slice(0, 5) }} {{ $t('common.to') }} {{ item.end_time?.slice(0, 5) }}
|
|
{{ $t('common.from') }} {{ item.start_time?.slice(0, 5) }} {{ $t('common.to') }} {{ item.end_time?.slice(0, 5) }}
|
|
|
</span>
|
|
</span>
|
|
@@ -48,99 +67,147 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div class="flex-shrink-0 row items-right justify-end col-4">
|
|
|
|
|
- <div v-if="cardState(item) === 'awaiting_code'" class="col-12 row items-center justify-end q-pb-sm">
|
|
|
|
|
- <div class="hint-text text-text text-center font9 q-mb-xs col-12">
|
|
|
|
|
- {{ $t('provider.dashboard.today_services.code_hint') }}
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="code-input-row col-12">
|
|
|
|
|
- <input
|
|
|
|
|
- v-for="(_, idx) in 4"
|
|
|
|
|
- :key="idx"
|
|
|
|
|
- :ref="el => setCodeRef(item.id, idx, el)"
|
|
|
|
|
- v-model="codeInputs[item.id][idx]"
|
|
|
|
|
- class="code-input-box font9 fontbold"
|
|
|
|
|
- type="tel"
|
|
|
|
|
- maxlength="1"
|
|
|
|
|
- inputmode="numeric"
|
|
|
|
|
- @input="onCodeInput(item, idx)"
|
|
|
|
|
- @keydown.delete="onCodeDelete(item.id, idx)"
|
|
|
|
|
- @paste.prevent="onCodePaste(item, $event)"
|
|
|
|
|
|
|
+ <div class="flex-shrink-0 row items-right justify-end col-4">
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="cardState(item) === 'awaiting_code'"
|
|
|
|
|
+ class="col-12 row items-center justify-end q-pb-sm"
|
|
|
|
|
+ >
|
|
|
|
|
+
|
|
|
|
|
+ <div class="hint-text text-text text-center font9 q-mb-xs col-12">
|
|
|
|
|
+ {{ $t('provider.dashboard.today_services.code_hint') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="code-input-row col-12">
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-for="(_, idx) in 4"
|
|
|
|
|
+ :key="idx"
|
|
|
|
|
+ :ref="el => setCodeRef(item.id, idx, el)"
|
|
|
|
|
+ v-model="codeInputs[item.id][idx]"
|
|
|
|
|
+ class="code-input-box font9 fontbold"
|
|
|
|
|
+ inputmode="numeric"
|
|
|
|
|
+ maxlength="1"
|
|
|
|
|
+ type="tel"
|
|
|
|
|
+ @input="onCodeInput(item, idx)"
|
|
|
|
|
+ @keydown.delete="onCodeDelete(item.id, idx)"
|
|
|
|
|
+ @paste.prevent="onCodePaste(item, $event)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div v-if="codeError[item.id]" class="text-negative code-error-text font9 q-mt-xs text-center">
|
|
|
|
|
+ {{ codeError[item.id] }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-else-if="cardState(item) === 'in_progress'"
|
|
|
|
|
+ class="col-12 text-center q-mb-xs"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="column items-center">
|
|
|
|
|
+ <span class="text-text font9 fontmedium q-my-xs">
|
|
|
|
|
+ {{ $t('provider.dashboard.today_services.in_progress') }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="code-pill font12 fontbold bg-positive row">
|
|
|
|
|
+ <q-icon
|
|
|
|
|
+ class="q-mr-xs q-my-auto"
|
|
|
|
|
+ name="mdi-check"
|
|
|
|
|
+ size="12px"
|
|
|
/>
|
|
/>
|
|
|
- </div>
|
|
|
|
|
- <div v-if="codeError[item.id]" class="text-negative code-error-text font9 q-mt-xs text-center">
|
|
|
|
|
- {{ codeError[item.id] }}
|
|
|
|
|
|
|
+
|
|
|
|
|
+ {{ item.code || localVerified[item.id] }}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- <div v-else-if="cardState(item) === 'in_progress'" class="col-12 text-center q-mb-xs">
|
|
|
|
|
- <div class="column items-center">
|
|
|
|
|
- <span class="text-text font9 fontmedium q-my-xs">
|
|
|
|
|
- {{ $t('provider.dashboard.today_services.in_progress') }}
|
|
|
|
|
- </span>
|
|
|
|
|
- <div class="code-pill font12 fontbold bg-positive row">
|
|
|
|
|
- <q-icon
|
|
|
|
|
- name="mdi-check" size="12px" class="q-mr-xs q-my-auto"
|
|
|
|
|
- />
|
|
|
|
|
- {{ item.code || localVerified[item.id] }}
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div v-else class="">
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="item.provider_reviewed"
|
|
|
|
|
+ class="rate-btn reviewed-badge column fontsemibold"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="text-center">
|
|
|
|
|
+ <q-icon
|
|
|
|
|
+ class="q-mr-xs"
|
|
|
|
|
+ name="mdi-star"
|
|
|
|
|
+ size="14px"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ {{ $t('provider.dashboard.today_services.reviewed_badge') }}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else class="">
|
|
<div v-else class="">
|
|
|
- <div v-if="item.provider_reviewed" class="rate-btn reviewed-badge column fontsemibold">
|
|
|
|
|
- <div class="text-center">
|
|
|
|
|
- <q-icon name="mdi-star" size="14px" class="q-mr-xs " />
|
|
|
|
|
|
|
+ <q-btn
|
|
|
|
|
+ class="rate-btn font10 fontmedium"
|
|
|
|
|
+ no-caps
|
|
|
|
|
+ unelevated
|
|
|
|
|
+ @click.stop="emit('rate', item)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="column items-center">
|
|
|
|
|
+ <q-icon name="mdi-star-outline" size="14px" class="q-mr-xs" />
|
|
|
|
|
+
|
|
|
|
|
+ {{ $t('provider.dashboard.today_services.rate_btn') }}
|
|
|
</div>
|
|
</div>
|
|
|
- {{ $t('provider.dashboard.today_services.reviewed_badge') }}
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-else class="">
|
|
|
|
|
- <q-btn
|
|
|
|
|
- unelevated no-caps
|
|
|
|
|
- class="rate-btn font10 fontmedium"
|
|
|
|
|
- @click.stop="emit('rate', item)"
|
|
|
|
|
- >
|
|
|
|
|
- <div class="column items-center">
|
|
|
|
|
- <q-icon name="mdi-star-outline" size="14px" class="q-mr-xs" />
|
|
|
|
|
- {{ $t('provider.dashboard.today_services.rate_btn') }}
|
|
|
|
|
- </div>
|
|
|
|
|
- </q-btn>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ </q-btn>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
- <div class="progress-track q-mb-sm">
|
|
|
|
|
- <div
|
|
|
|
|
- class="progress-fill"
|
|
|
|
|
- :class="cardState(item) === 'finished' ? 'progress-fill--finished' : ''"
|
|
|
|
|
- :style="{ width: progressByState(item) + '%' }"
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="progress-track q-mb-sm">
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="progress-fill"
|
|
|
|
|
+ :class="cardState(item) === 'finished' ? 'progress-fill--finished' : ''"
|
|
|
|
|
+ :style="{ width: progressByState(item) + '%' }"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="row items-center no-wrap">
|
|
|
|
|
+ <q-btn
|
|
|
|
|
+ class="flex-shrink-0"
|
|
|
|
|
+ color="primary"
|
|
|
|
|
+ flat no-caps dense
|
|
|
|
|
+ size="sm"
|
|
|
|
|
+ :label="$t('provider.dashboard.today_services.help')"
|
|
|
|
|
+ @click.stop="openHelp"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <q-space />
|
|
|
|
|
+
|
|
|
|
|
+ <template v-if="cardState(item) === 'in_progress'">
|
|
|
|
|
+ <q-icon
|
|
|
|
|
+ class="q-mr-xs flex-shrink-0 gradient-diarista"
|
|
|
|
|
+ name="mdi-clock-outline"
|
|
|
|
|
+ size="13px"
|
|
|
/>
|
|
/>
|
|
|
- </div>
|
|
|
|
|
|
|
|
|
|
- <div class="row items-center no-wrap">
|
|
|
|
|
- <q-btn
|
|
|
|
|
- flat no-caps dense
|
|
|
|
|
- :label="$t('provider.dashboard.today_services.help')"
|
|
|
|
|
- color="primary"
|
|
|
|
|
- size="sm"
|
|
|
|
|
- class="flex-shrink-0"
|
|
|
|
|
- @click.stop="openHelp"
|
|
|
|
|
- />
|
|
|
|
|
- <q-space />
|
|
|
|
|
- <template v-if="cardState(item) === 'in_progress'">
|
|
|
|
|
- <q-icon name="mdi-clock-outline" size="13px" class="q-mr-xs flex-shrink-0 gradient-diarista" />
|
|
|
|
|
- <span class="text-grey-6 text-right text-no-wrap font11">
|
|
|
|
|
- {{ $t('provider.dashboard.today_services.end_time_label') }}
|
|
|
|
|
- <span class="gradient-diarista">{{ calculateTimeUntilEnd(item.end_time) }}</span>
|
|
|
|
|
|
|
+ <span class="text-grey-6 text-right text-no-wrap font11">
|
|
|
|
|
+ {{ $t('provider.dashboard.today_services.end_time_label') }}
|
|
|
|
|
+
|
|
|
|
|
+ <span class="gradient-diarista">
|
|
|
|
|
+ {{ calculateTimeUntilEnd(item.end_time) }}
|
|
|
</span>
|
|
</span>
|
|
|
- </template>
|
|
|
|
|
|
|
+ </span>
|
|
|
|
|
+
|
|
|
|
|
+ </template>
|
|
|
<template v-else-if="cardState(item) === 'awaiting_code'">
|
|
<template v-else-if="cardState(item) === 'awaiting_code'">
|
|
|
- <q-icon name="mdi-map-marker-outline" size="13px" color="grey-6" class="q-mr-xs flex-shrink-0" />
|
|
|
|
|
- <span class="text-grey-6 col ellipsis text-right font9 fontmedium">
|
|
|
|
|
|
|
+ <q-icon
|
|
|
|
|
+ class="q-mr-xs flex-shrink-0"
|
|
|
|
|
+ color="grey-6"
|
|
|
|
|
+ name="mdi-map-marker-outline"
|
|
|
|
|
+ size="13px"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <span class="text-grey-6 address-text ellipsis text-right font9 fontmedium">
|
|
|
{{ [item.address?.address, item.address?.number, item.address?.district].filter(Boolean).join(', ') || '—' }}
|
|
{{ [item.address?.address, item.address?.number, item.address?.district].filter(Boolean).join(', ') || '—' }}
|
|
|
</span>
|
|
</span>
|
|
|
- <q-icon name="mdi-content-copy" color="primary" size="16px" class="q-ml-xs" @click="copyAddress(item.address)"/>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <q-icon
|
|
|
|
|
+ class="q-ml-xs"
|
|
|
|
|
+ color="primary"
|
|
|
|
|
+ name="mdi-content-copy"
|
|
|
|
|
+ size="16px"
|
|
|
|
|
+ @click="copyAddress(item.address)"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
</div>
|
|
</div>
|
|
|
</q-card-section>
|
|
</q-card-section>
|
|
@@ -151,18 +218,19 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
|
|
+import { avatarColors, formatAddress, getFirstName } from 'src/helpers/utils';
|
|
|
import { reactive } from 'vue'
|
|
import { reactive } from 'vue'
|
|
|
-import { useQuasar } from 'quasar'
|
|
|
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
|
+import { useQuasar } from 'quasar'
|
|
|
|
|
+import { verifyScheduleCode } from 'src/api/schedule'
|
|
|
|
|
+
|
|
|
import ProfileHelpDialog from 'src/components/profile/ProfileHelpDialog.vue'
|
|
import ProfileHelpDialog from 'src/components/profile/ProfileHelpDialog.vue'
|
|
|
-import { payServicePackage, verifyScheduleCode } from 'src/api/schedule'
|
|
|
|
|
-import { formatAddress, getFirstName } from 'src/helpers/utils';
|
|
|
|
|
|
|
|
|
|
const props = defineProps({ data: { type: Array, default: () => [] } })
|
|
const props = defineProps({ data: { type: Array, default: () => [] } })
|
|
|
-const emit = defineEmits(['rate', 'refresh'])
|
|
|
|
|
|
|
+const emit = defineEmits(['rate', 'refresh'])
|
|
|
|
|
|
|
|
-const $q = useQuasar()
|
|
|
|
|
const { t } = useI18n()
|
|
const { t } = useI18n()
|
|
|
|
|
+const $q = useQuasar()
|
|
|
|
|
|
|
|
const codeInputs = reactive({})
|
|
const codeInputs = reactive({})
|
|
|
const codeRefs = reactive({})
|
|
const codeRefs = reactive({})
|
|
@@ -178,14 +246,21 @@ props.data.forEach(item => ensureCode(item.id))
|
|
|
|
|
|
|
|
const setCodeRef = (id, idx, el) => {
|
|
const setCodeRef = (id, idx, el) => {
|
|
|
ensureCode(id)
|
|
ensureCode(id)
|
|
|
|
|
+
|
|
|
codeRefs[id][idx] = el
|
|
codeRefs[id][idx] = el
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
const onCodeInput = async (item, idx) => {
|
|
const onCodeInput = async (item, idx) => {
|
|
|
const id = item.id
|
|
const id = item.id
|
|
|
|
|
+
|
|
|
const val = codeInputs[id][idx]
|
|
const val = codeInputs[id][idx]
|
|
|
|
|
+
|
|
|
if (!/^\d$/.test(val)) { codeInputs[id][idx] = ''; return }
|
|
if (!/^\d$/.test(val)) { codeInputs[id][idx] = ''; return }
|
|
|
|
|
+
|
|
|
codeError[id] = null
|
|
codeError[id] = null
|
|
|
|
|
+
|
|
|
if (idx < 3) {
|
|
if (idx < 3) {
|
|
|
codeRefs[id][idx + 1]?.focus()
|
|
codeRefs[id][idx + 1]?.focus()
|
|
|
} else {
|
|
} else {
|
|
@@ -196,92 +271,116 @@ const onCodeInput = async (item, idx) => {
|
|
|
const onCodeDelete = (id, idx) => {
|
|
const onCodeDelete = (id, idx) => {
|
|
|
if (codeInputs[id][idx] === '' && idx > 0) {
|
|
if (codeInputs[id][idx] === '' && idx > 0) {
|
|
|
codeInputs[id][idx - 1] = ''
|
|
codeInputs[id][idx - 1] = ''
|
|
|
|
|
+
|
|
|
codeRefs[id][idx - 1]?.focus()
|
|
codeRefs[id][idx - 1]?.focus()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const onCodePaste = async (item, e) => {
|
|
const onCodePaste = async (item, e) => {
|
|
|
const text = e.clipboardData.getData('text').replace(/\D/g, '').slice(0, 4)
|
|
const text = e.clipboardData.getData('text').replace(/\D/g, '').slice(0, 4)
|
|
|
|
|
+
|
|
|
if (text.length !== 4) return
|
|
if (text.length !== 4) return
|
|
|
|
|
+
|
|
|
const id = item.id
|
|
const id = item.id
|
|
|
|
|
+
|
|
|
text.split('').forEach((ch, i) => { codeInputs[id][i] = ch })
|
|
text.split('').forEach((ch, i) => { codeInputs[id][i] = ch })
|
|
|
|
|
+
|
|
|
await submitCode(item)
|
|
await submitCode(item)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const submitCode = async (item) => {
|
|
const submitCode = async (item) => {
|
|
|
const id = item.id
|
|
const id = item.id
|
|
|
|
|
+
|
|
|
const code = codeInputs[id].join('')
|
|
const code = codeInputs[id].join('')
|
|
|
|
|
+
|
|
|
if (code.length < 4) return
|
|
if (code.length < 4) return
|
|
|
- try {
|
|
|
|
|
- if (item.service_package_id) {
|
|
|
|
|
- await payServicePackage(item.service_package_id)
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
|
|
+ try {
|
|
|
const response = await verifyScheduleCode(id, code)
|
|
const response = await verifyScheduleCode(id, code)
|
|
|
- console.log(response)
|
|
|
|
|
|
|
+
|
|
|
if (response?.payload) {
|
|
if (response?.payload) {
|
|
|
localVerified[id] = code
|
|
localVerified[id] = code
|
|
|
emit('refresh')
|
|
emit('refresh')
|
|
|
} else {
|
|
} else {
|
|
|
const msg = response?.data?.message || response?.message || t('provider.dashboard.today_services.code_error')
|
|
const msg = response?.data?.message || response?.message || t('provider.dashboard.today_services.code_error')
|
|
|
|
|
+
|
|
|
codeError[id] = msg
|
|
codeError[id] = msg
|
|
|
codeInputs[id] = ['', '', '', '']
|
|
codeInputs[id] = ['', '', '', '']
|
|
|
|
|
+
|
|
|
codeRefs[id][0]?.focus()
|
|
codeRefs[id][0]?.focus()
|
|
|
}
|
|
}
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
const msg = err?.response?.data?.message || t('provider.dashboard.today_services.code_error')
|
|
const msg = err?.response?.data?.message || t('provider.dashboard.today_services.code_error')
|
|
|
|
|
+
|
|
|
codeError[id] = msg
|
|
codeError[id] = msg
|
|
|
codeInputs[id] = ['', '', '', '']
|
|
codeInputs[id] = ['', '', '', '']
|
|
|
|
|
+
|
|
|
codeRefs[id][0]?.focus()
|
|
codeRefs[id][0]?.focus()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const avatarColors = [
|
|
|
|
|
- { background: '#ffd5df', color: '#932e57' },
|
|
|
|
|
- { background: '#d7e8ff', color: '#2158a8' },
|
|
|
|
|
- { background: '#dfd', color: '#2a7a3b' },
|
|
|
|
|
- { background: '#ffe5cc', color: '#8a4500' },
|
|
|
|
|
-]
|
|
|
|
|
-
|
|
|
|
|
-const cardState = (item) => {
|
|
|
|
|
- const verified = item.code_verified || !!localVerified[item.id]
|
|
|
|
|
- if (!verified) return 'awaiting_code'
|
|
|
|
|
- const [h, m] = (item.end_time || '23:59').slice(0, 5).split(':').map(Number)
|
|
|
|
|
- const endTime = new Date()
|
|
|
|
|
- endTime.setHours(h, m, 0, 0)
|
|
|
|
|
- return new Date() >= endTime ? 'finished' : 'in_progress'
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const progressByState = (item) => {
|
|
|
|
|
- const state = cardState(item)
|
|
|
|
|
- if (state === 'awaiting_code') return 60
|
|
|
|
|
- if (state === 'in_progress') return 80
|
|
|
|
|
- return 100
|
|
|
|
|
-}
|
|
|
|
|
|
|
+//
|
|
|
|
|
|
|
|
const calculateTimeUntilEnd = (endTimeStr) => {
|
|
const calculateTimeUntilEnd = (endTimeStr) => {
|
|
|
const [h, m] = (endTimeStr || '23:59').slice(0, 5).split(':').map(Number)
|
|
const [h, m] = (endTimeStr || '23:59').slice(0, 5).split(':').map(Number)
|
|
|
|
|
+
|
|
|
const now = new Date()
|
|
const now = new Date()
|
|
|
|
|
+
|
|
|
const endTime = new Date()
|
|
const endTime = new Date()
|
|
|
|
|
+
|
|
|
endTime.setHours(h, m, 0, 0)
|
|
endTime.setHours(h, m, 0, 0)
|
|
|
|
|
+
|
|
|
const diffMs = endTime - now
|
|
const diffMs = endTime - now
|
|
|
|
|
+
|
|
|
if (diffMs <= 0) return '00:00'
|
|
if (diffMs <= 0) return '00:00'
|
|
|
|
|
+
|
|
|
const diffH = Math.floor(diffMs / (1000 * 60 * 60))
|
|
const diffH = Math.floor(diffMs / (1000 * 60 * 60))
|
|
|
|
|
+
|
|
|
const diffM = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60))
|
|
const diffM = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60))
|
|
|
|
|
+
|
|
|
return `${String(diffH).padStart(2, '0')}h:${String(diffM).padStart(2, '0')}`
|
|
return `${String(diffH).padStart(2, '0')}h:${String(diffM).padStart(2, '0')}`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const openHelp = () => {
|
|
|
|
|
- $q.dialog({ component: ProfileHelpDialog })
|
|
|
|
|
|
|
+const cardState = (item) => {
|
|
|
|
|
+ const verified = item.code_verified || !!localVerified[item.id]
|
|
|
|
|
+
|
|
|
|
|
+ if (!verified) return 'awaiting_code'
|
|
|
|
|
+
|
|
|
|
|
+ const [h, m] = (item.end_time || '23:59').slice(0, 5).split(':').map(Number)
|
|
|
|
|
+
|
|
|
|
|
+ const endTime = new Date()
|
|
|
|
|
+
|
|
|
|
|
+ endTime.setHours(h, m, 0, 0)
|
|
|
|
|
+
|
|
|
|
|
+ return new Date() >= endTime ? 'finished' : 'in_progress'
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const copyAddress = (address) => {
|
|
const copyAddress = (address) => {
|
|
|
const formatted = formatAddress(address);
|
|
const formatted = formatAddress(address);
|
|
|
|
|
+
|
|
|
if (formatted) {
|
|
if (formatted) {
|
|
|
navigator.clipboard.writeText(formatted);
|
|
navigator.clipboard.writeText(formatted);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
$q.notify({ message: t('provider.dashboard.next_schedules.address_copied'), color: 'positive' });
|
|
$q.notify({ message: t('provider.dashboard.next_schedules.address_copied'), color: 'positive' });
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
|
|
+const progressByState = (item) => {
|
|
|
|
|
+ const state = cardState(item)
|
|
|
|
|
+
|
|
|
|
|
+ if (state === 'awaiting_code') return 60
|
|
|
|
|
+ if (state === 'in_progress') return 80
|
|
|
|
|
+
|
|
|
|
|
+ return 100
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
|
|
+const openHelp = () => {
|
|
|
|
|
+ $q.dialog({ component: ProfileHelpDialog })
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
@@ -299,10 +398,11 @@ const copyAddress = (address) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.today-card {
|
|
.today-card {
|
|
|
- min-width: 80%;
|
|
|
|
|
|
|
+ min-width: 82vw;
|
|
|
scroll-snap-align: start;
|
|
scroll-snap-align: start;
|
|
|
border-radius: 12px;
|
|
border-radius: 12px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.today-card--single {
|
|
.today-card--single {
|
|
|
min-width: 100%;
|
|
min-width: 100%;
|
|
|
width: 100%;
|
|
width: 100%;
|
|
@@ -323,7 +423,7 @@ const copyAddress = (address) => {
|
|
|
padding: 4px 8px;
|
|
padding: 4px 8px;
|
|
|
width: 110px;
|
|
width: 110px;
|
|
|
height: 28px;
|
|
height: 28px;
|
|
|
- margin: 0 0 0 auto;
|
|
|
|
|
|
|
+ margin: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.code-input-box {
|
|
.code-input-box {
|
|
@@ -348,6 +448,11 @@ const copyAddress = (address) => {
|
|
|
line-height: 1.2;
|
|
line-height: 1.2;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.address-text {
|
|
|
|
|
+ max-width: 110px;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.code-pill {
|
|
.code-pill {
|
|
|
color: white;
|
|
color: white;
|
|
|
letter-spacing: 2px;
|
|
letter-spacing: 2px;
|