| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- <template>
- <q-dialog
- ref="dialogRef"
- @hide="onDialogHide"
- >
- <q-card
- class="accepted-dialog-card bg-surface"
- :flat="false"
- >
- <q-card-section class="column items-center q-pt-lg q-pb-sm">
- <q-avatar
- class="text-h5 q-mb-sm"
- size="80px"
- :style="avatarStyle"
- >
- <img
- v-if="getProfileMediaUrl(item)"
- :src="getProfileMediaUrl(item)"
- style="object-fit: cover"
- />
- <span v-else>
- {{ displayProviderName.slice(0, 2).toUpperCase() || "??" }}
- </span>
- </q-avatar>
- <div class="font16 fontbold provider-name">
- {{ getFirstName(displayProviderName) || "—" }}
- </div>
- <div class="font14 fontmedium text-text">
- {{ displayDistrict }}
- </div>
- </q-card-section>
- <q-card-section class="text-center q-pt-xs q-pb-md">
- <div class="accepted-title font16 fontbold">
- {{ $t("dashboard_client.pending_schedules.accepted_title") }}
- </div>
- </q-card-section>
- <q-separator />
- <q-card-section class="q-py-md q-px-lg">
- <div
- v-if="activeSchedules.length > 1"
- class="font13 fontbold text-primary q-mb-xs"
- >
- {{ $t("dashboard_client.pending_schedules.detail_schedules_title") }}
- </div>
- <div
- v-for="schedule in activeSchedules"
- :key="schedule.id"
- class="detail-row schedule-row"
- >
- <span class="detail-value font13">
- {{ formatScheduleDate(schedule) }}
- </span>
- <span class="detail-valued text-text font13">
- {{ schedule.start_time?.slice(0, 5) }}
- {{ $t("dashboard_client.next_schedules.to") }}
- {{ schedule.end_time?.slice(0, 5) }}
- </span>
- </div>
- <q-separator class="q-my-sm" />
- <div class="detail-row">
- <span class="text-primary font14 fontmedium">
- {{ $t("dashboard_client.pending_schedules.detail_value") }}
- </span>
- <span class="detail-value font14">
- {{ formatCurrency(baseAmount) }}
- </span>
- </div>
- <div class="detail-row">
- <span class="text-primary font13 fontmedium">
- {{ $t("dashboard_client.pending_schedules.detail_service_fee_pix") }}
- </span>
- <span class="detail-value font13">
- {{ formatCurrency(platformFee("pix")) }}
- </span>
- </div>
- <div class="detail-row">
- <span class="text-primary font14 fontmedium">
- {{ hasServicePackageDiscount
- ? $t("dashboard_client.pending_schedules.detail_package_total")
- : $t("dashboard_client.pending_schedules.detail_pix_total") }}
- </span>
- <span class="total-value font14 fontbold">
- {{ formatCurrency(pixTotal) }}
- </span>
- </div>
- <div
- v-if="pixDiscount > 0"
- class="detail-row discount-row"
- >
- <span class="font13 fontmedium">
- {{ $t("dashboard_client.pending_schedules.detail_pix_discount") }}
- </span>
- <span class="font13 fontbold">
- {{ formatCurrency(pixDiscount) }}
- </span>
- </div>
- <div class="detail-row">
- <span class="text-primary font13 fontmedium">
- {{
- $t(
- "dashboard_client.pending_schedules.detail_service_fee_credit_card",
- )
- }}
- </span>
- <span class="detail-value font13">
- {{ formatCurrency(platformFee("credit_card")) }}
- </span>
- </div>
- <div class="detail-row">
- <span class="text-primary font14 fontmedium">
- {{
- $t("dashboard_client.pending_schedules.detail_credit_card_total")
- }}
- </span>
- <span class="total-value font14 fontbold">
- {{ formatCurrency(creditCardTotal) }}
- </span>
- </div>
- </q-card-section>
- <q-card-section class="q-pt-none q-pb-lg q-px-lg column q-gutter-y-sm">
- <q-btn
- class="payment-btn full-width"
- color="primary"
- padding="4px 12px"
- rounded
- :label="$t('dashboard_client.pending_schedules.btn_payment')"
- @click="onGoToPayment"
- />
- <q-btn
- class="full-width"
- color="grey-6"
- flat
- no-caps
- padding="4px 12px"
- :label="$t('dashboard_client.pending_schedules.btn_cancel')"
- @click="onDialogHide"
- />
- </q-card-section>
- </q-card>
- </q-dialog>
- </template>
- <script setup>
- import { avatarColors } from "src/helpers/avatarColors";
- import { computed, onMounted } from "vue";
- import { formatCurrency, getFirstName } from "src/helpers/utils";
- import { getProfileMediaUrl } from "src/helpers/profileMedia";
- import {
- getSchedulePlatformFeeRate,
- scheduleUsesServicePackageDiscount,
- } from "src/helpers/paymentPlatformFees";
- import { useDialogPluginComponent, useQuasar } from "quasar";
- import { usePaymentPlatformFees } from "src/composables/usePaymentPlatformFees";
- import { usePaymentStore } from "src/stores/payment";
- import SchedulePaymentDialog from "./SchedulePaymentDialog.vue";
- import SchedulePaymentPixDialog from "./SchedulePaymentPixDialog.vue";
- const props = defineProps({
- servicePackage: { type: Object, required: true },
- });
- defineEmits([...useDialogPluginComponent.emits]);
- const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
- const $q = useQuasar();
- const paymentStore = usePaymentStore();
- const { platformFees, loadPlatformFees } = usePaymentPlatformFees();
- const item = computed(() => props.servicePackage);
- const displayProviderName = computed(() => {
- return item.value.provider?.user?.name ?? item.value.provider_name ?? '';
- });
- const activeSchedules = computed(() =>
- (item.value.schedules ?? []).filter(
- (schedule) => !['cancelled', 'rejected'].includes(schedule.status),
- ),
- );
- const displayDistrict = computed(() => {
- return activeSchedules.value[0]?.address?.district ?? item.value.address?.district ?? '';
- });
- const formatScheduleDate = (schedule) => {
- if (!schedule) return '';
- if (schedule.formatted_date) return schedule.formatted_date;
- const raw = String(schedule.date || '');
- const m = raw.match(/^(\d{4})-(\d{2})-(\d{2})/);
- if (!m) return raw;
- const d = new Date(+m[1], +m[2] - 1, +m[3]);
- return d.toLocaleDateString('pt-BR', {
- day: '2-digit',
- month: 'long',
- year: 'numeric',
- });
- };
- const avatarStyle = computed(
- () => avatarColors[item.value.id % avatarColors.length],
- );
- const baseAmount = computed(() => {
- const total = Number(item.value.total_amount);
- if (Number.isFinite(total) && total > 0) return total;
- return activeSchedules.value.reduce(
- (sum, schedule) => sum + (Number(schedule.total_amount) || 0),
- 0,
- );
- });
- const creditCardTotal = computed(() =>
- parseFloat((baseAmount.value + platformFee("credit_card")).toFixed(2)),
- );
- const hasServicePackageDiscount = computed(() =>
- scheduleUsesServicePackageDiscount(item.value),
- );
- const pixDiscount = computed(() =>
- Math.max(0, parseFloat((creditCardTotal.value - pixTotal.value).toFixed(2))),
- );
- const pixTotal = computed(() =>
- parseFloat((baseAmount.value + platformFee("pix")).toFixed(2)),
- );
- const platformFee = (paymentType) => {
- const feeRate = getSchedulePlatformFeeRate(
- item.value,
- paymentType,
- platformFees.value,
- );
- return parseFloat((baseAmount.value * (feeRate ?? 0)).toFixed(2));
- };
- const onGoToPayment = () => {
- const validPixPayment = paymentStore.getValidPixPaymentForServicePackage(item.value.id);
- const hasValidPixPayment = !!validPixPayment;
- $q.dialog({
- component: hasValidPixPayment
- ? SchedulePaymentPixDialog
- : SchedulePaymentDialog,
- componentProps: {
- servicePackage: item.value,
- ...(hasValidPixPayment ? { total: pixTotal.value } : {}),
- },
- }).onOk(() => {
- onDialogOK();
- });
- };
- onMounted(() => {
- loadPlatformFees().catch(() => {});
- });
- </script>
- <style scoped lang="scss">
- .accepted-dialog-card {
- width: 320px;
- max-width: 92vw;
- border-radius: 20px !important;
- overflow: hidden;
- }
- .accepted-title {
- line-height: 1.3;
- color: #8b5cf6;
- }
- .provider-name {
- color: #8b5cf6;
- }
- .detail-row {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 4px 0;
- }
- .detail-label {
- color: #8a8a9a;
- }
- .detail-value {
- color: #3a3a4a;
- }
- .total-value {
- color: #3a3a4a;
- }
- .discount-row {
- color: #16845d;
- background: rgba(22, 132, 93, 0.08);
- border-radius: 8px;
- margin: 2px 0;
- padding: 5px 8px;
- }
- .payment-btn {
- height: 48px;
- }
- </style>
|