Untitled
unknown
plain_text
a year ago
37 kB
2
Indexable
Never
<template> <zendo-form v-if="orderForm && formData" v-slot="{ invalid, submit, loading }" class="d-flex" :class="$vuetify.breakpoint.smAndDown && 'secondary lighten-5'" :style="!isInApp ? 'height: calc(100% - 84px)' : 'height: 100%'" > <v-container v-if="orderForm" fluid class="order-page__body pt-2 pb-0 px-3" > <v-row :class="$vuetify.breakpoint.mdAndUp && 'h-100'"> <v-col class="d-flex justify-end secondary lighten-5 pt-5 pt-md-10 px-8 px-md-8 px-lg-15 pb-5 pb-md-10 h-100" cols="12" md="7" > <div :style="$vuetify.breakpoint.width >= $constants.orderPage.maxContainerWidth ? 'width: 700px' : 'max-width: 100%'"> <div class="d-flex justify-space-between align-center mb-5" > <div class="d-flex align-center"> <zendo-back-btn class="mr-6" @click="onClickBackBtn" /> <h3 class="text-h5 pr-2" v-text="orderForm.offer.type === Types.Free ? $t('pages.order.index.slug.index.summary.label') : $t('pages.order.index.slug.index.checkout.label')" /> </div> </div> <div class="d-flex flex-wrap mb-3"> <v-img v-if="orderForm.image_url" :lazy-src="orderForm.image_url" :src="orderForm.image_url" :alt="orderForm.image_url" max-width="200px" max-height="11rem" class="rounded-lg mb-5 mr-8" /> <div class="partial-description" :class="{ 'partial-description-fade': orderForm.description && orderForm.description.length > 200 }" > <h3 v-if="orderForm.title" class="text-h6 mb-2" v-text="orderForm.title" /> <markdown-it-vue v-if="orderForm.description" class="pb-5 message-content text-body-2" :content="orderForm.description" /> </div> </div> <div v-if="formData.selectedPackage.package"> <zendo-orderpage-packages-item-preview summary :currency="orderForm.offer.settings.currency" :cycle="formData.selectedPackage.billing_cycle" :value="formData.selectedPackage.package" /> </div> <div v-if="!orderForm.form_enabled && !isSubscriptionType && orderForm.offer.services.length && quantityArr.length" class="services-select rounded-lg white pa-6 mt-3 pb-8"> <div class="text-h6 pb-4" v-text="$t('pages.order.slug.form.input.services.label')" /> <div v-for="service in orderForm.offer.services" :key="service.id" class="d-flex flex-column justify-center align-center" > <div class="d-flex flex-column flex-md-row justify-space-between w-100 text-body-2 align-center item"> <div class="d-flex flex-column w-100 pr-8 pb-2 pb-md-0"> <v-checkbox v-if="service.is_addon" v-model="formData.services" class="align-center text-body-2 font-weight-bold" color="accent" :value="service" :name="service.name" :label="`${service.name}`" /> <span v-else class="font-weight-bold" v-text="service.name" /> <span v-if="service.is_quantifiable" class="font-italic secondary--text text--lighten"> <span v-if="service.max_quantity && service.min_quantity" v-text="$t('pages.order.index.slug.index.validation_between', {min: service.min_quantity, max: service.max_quantity})" /> <span v-else-if="service.max_quantity && !service.min_quantity" v-text="`${$t('pages.order.index.slug.index.validation_min')} ${service.max_quantity}`" /> <span v-else-if="service.min_quantity && !service.max_quantity" v-text="`${$t('pages.order.index.slug.index.validation_max')} ${service.min_quantity}`" /> </span> </div> <div class="d-flex align-center justify-space-between w-100" :style="$vuetify.breakpoint.mdAndUp && 'max-width: 220px'"> <div class="d-flex align-center mr-2"> <zendo-forms-quantity v-if="service.is_quantifiable" :disabled="service.is_addon && !formData.services.includes(service)" :value="quantityArr.find(item => item.id === service.id).qty" :name="`services.${service.id}.quantity`" :class="`services.${service.id}.quantity`" style="max-width: 110px" small inline :min="service.min_quantity ? service.min_quantity : 1" :max="service.max_quantity ? service.max_quantity : 9999" center controls @change="updateLocalQuantityValues($event, service)" /> <div v-else-if="quantityArr.find(item => item.id === service.id).qty > 1" style="width: 110px; height: 45px" class="d-flex align-center justify-center text-center secondary lighten-5 rounded-sm" v-text="`${quantityArr.find(item => item.id === service.id).qty} x`" /> </div> <div class="d-flex text-right font-weight-bold"> <div style="width: 90px"> <span v-if="service.price === null" v-text="$t('pages.order.slug.form.text.custom_price')" /> <span v-else v-text="service.price ? displayPrice(service.price) : $t('pages.order.slug.form.text.free')" /> </div> </div> </div> </div> <zendo-divider class="w-100 my-4" /> </div> <p v-if="totalPrice" class="text-h5 mb-0 text-right mt-4" v-text="displayPrice(totalPrice)" /> </div> <div v-else-if="formData.services.length" class="white pa-6 rounded-lg"> <zendo-items-list :headers-prop="headersConfig" :type="offer.type" :value="formData.services" :is-tax-enabled="offer.settings.enabled_tax_support" :currency="offer.settings.currency" /> </div> </div> </v-col> <v-col cols="12" md="5" class="d-flex justify-start pt-5 pt-md-10 px-8 px-md-8 px-lg-15" > <div :style="$vuetify.breakpoint.mdAndUp && 'max-width: 462px;'" class="h-100"> <div class="d-flex flex-column h-100"> <v-row class="align-content-start"> <template v-if="showInvoiceDetails"> <v-col cols="12"> <h3 class="text-h5" v-text="$t('pages.order.index.slug.index.checkout.invoice_details_title')" /> <p class="mb-0" v-text="$t('pages.order.index.slug.index.checkout.invoice_details_subtitle')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.firstname" name="firstname" color="accent" rules="required" :label="$t('modules.settings.finances.details.first_name')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.lastname" name="lastname" color="accent" rules="required" :label="$t('modules.settings.finances.details.last_name')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.company_name" name="invoice.company_name" color="accent" :label="$t('modules.settings.finances.details.company_name')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-select v-model="formData.invoiceDetails.country" color="accent" name="invoice.country" :label="$t('modules.settings.finances.details.country')" :rules="$constants.validation.invoice.country" :items="countryItems" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.st_address_1" name="invoice.st_address_1" :rules="$constants.validation.invoice.st_address_1" color="accent" :label="$t('modules.settings.finances.details.address_1')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.st_address_2" name="invoice.st_address_2" :rules="$constants.validation.invoice.st_address_2" color="accent" :label="$t('modules.settings.finances.details.address_2')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.city" name="invoice.city" :rules="$constants.validation.invoice.city" color="accent" :label="$t('modules.settings.finances.details.city')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.state" name="invoice.state" :rules="$constants.validation.invoice.state" color="accent" :label="$t('modules.settings.finances.details.state')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.zip" name="invoice.zip" :rules="$constants.validation.invoice.zip" color="accent" :label="$t('modules.settings.finances.details.zip')" /> </v-col> <v-col cols="12" sm="6"> <zendo-forms-text-field v-model="formData.invoiceDetails.tax_id" name="invoice.tax_id" rules="max:40" color="accent" :placeholder="$t('modules.settings.finances.details.tax.placeholder')" :label="$t('modules.settings.finances.details.tax.label')" /> </v-col> </template> <template v-if="!$services.auth.isSignedIn"> <v-col cols="12" class="mt-5"> <h3 class="text-h5" v-text="$t('pages.order.index.slug.index.checkout.register_title')" /> <p class="mb-0" v-text="$t('pages.order.index.slug.index.checkout.register_subtitle')" /> </v-col> <v-col v-if="!showInvoiceDetails" cols="12" sm="6" > <zendo-forms-text-field v-model="formData.firstname" name="firstname" color="accent" rules="required" :label="$t('modules.settings.finances.details.first_name')" /> </v-col> <v-col v-if="!showInvoiceDetails" cols="12" sm="6" > <zendo-forms-text-field v-model="formData.lastname" name="lastname" color="accent" rules="required" :label="$t('modules.settings.finances.details.last_name')" /> </v-col> <v-col cols="12"> <zendo-forms-text-field v-model="formData.email" :label="$t('pages.register.index.form.email.label')" :placeholder="$t('pages.register.index.form.email.placeholder')" :rules="$constants.validation.register.email" color="accent" name="email" autocomplete="on" type="email" :disabled="loading || !!$route.query.email" :debounce="500" /> </v-col> <v-col cols="12" class="position-relative"> <zendo-forms-password-field v-model="formData.password" :label="$t('pages.register.index.form.password.label')" :placeholder="$t('pages.register.index.form.password.placeholder')" :rules="$constants.validation.register.password('@password_meter')" color="accent" name="password" autocomplete="new-password" type="password" :disabled="loading" :debounce="500" /> <zendo-forms-password-meter name="password_meter" :value="formData.password" class="mt-5" /> </v-col> <zendo-forms-text-field v-model="formData.honeypot" class="honeypot" name="honeypot" type="text" /> <v-col cols="12"> <zendo-forms-checkbox :input-value.sync="formData.terms" :rules="{ required: { allowFalse: false } }" color="accent" name="terms" :disabled="loading" class="terms" > <template #content> {{ $t('pages.register.index.form.toc.message') }} <zendo-link class="px-1" :href="$services.settingsWorkspace.termsOfServiceUrl" target="_blank" @click.stop v-text="$t('pages.register.index.form.toc.link')" /> </template> </zendo-forms-checkbox> </v-col> </template> <template v-if="$services.auth.isSignedIn && !$services.auth.current.access.isClient"> <zendo-alert v-if="orderForm.offer.type === Types.Subscription || (orderForm.offer.type === Types.Productized && orderForm.offer.settings.collect_payment === 'upfront')" inline type="warning" > {{ $t('modules.subcscriptions.components.premium_tokens.overlimit.owner') }} </zendo-alert> <v-col cols="12"> <h3 class="text-h5" v-text="$t('pages.order.index.slug.checkout.select_client_title')" /> <p class="mb-0" v-text="$t('pages.order.index.slug.checkout.select_client_subtitle')" /> </v-col> <v-col cols="12" class="position-relative"> <zendo-clients-form-search v-model="selectedUser" name="email" item-value="id" rules="required" :label="$t('pages.order.index.slug.checkout.select_client_label')" /> </v-col> </template> <v-col cols="12" class="d-sm-flex flex-wrap justify-end" > <zendo-btn block :disabled="invalid || (blockByFeatureToken && orderForm.offer.type === Types.Subscription) || ((orderForm.offer.type === Types.Subscription || (orderForm.offer.type === Types.Productized && orderForm.offer.settings.collect_payment === 'upfront')) && ($services.auth.isSignedIn && !$services.auth.current.access.isClient))" :loading="loading" type="submit" color="accent" class="mt-5 mt-sm-1 my-1" @click.prevent="! invalid ? submit(orderForm.offer.type === Types.Subscription ? createSubscriptionRequest : createTaskRequest) : null" > {{ orderForm.offer.type !== Types.Subscription ? $t('pages.order.submit_request') : $t('pages.order.index.slug.index.go_to_checkout_btn_text') }} </zendo-btn> </v-col> <v-col v-if="!$services.auth.isSignedIn" class="pt-0"> <p class="text-body-2 d-flex align-center"> {{ $t('pages.order.index.slug.checkout.login_text') }} <zendo-link-btn class="ml-1" color="accent" @click="onLogin" > {{ $t('pages.order.thank_you.log_in') }} </zendo-link-btn> </p> </v-col> </v-row> <div class="d-flex justify-end w-100 pr-2 pt-10 pb-5 mt-auto"> <zendo-signet /> </div> </div> </div> </v-col> </v-row> </v-container> </zendo-form> </template> <script lang="ts"> import { computed, defineComponent, onMounted, reactive, ref, useContext, useRoute, useRouter, watch, } from '@nuxtjs/composition-api' import MarkdownItVue from 'markdown-it-vue' import { Component } from 'vue' import OrderFormModel from '~/modules/orderpage/models/OrderForm' import { TaskGuestCredentials } from '~/modules/tasks/types/tasks' import { CustomFieldsResponse } from '~/modules/tasks/types/fields' import { Nullable } from '~/types/type-utils' import { LocalStorageRedirect } from '~/modules/core/types/localStorage' import Task from '~/modules/tasks/models/Task' import Item from '~/modules/items/models/Item' import countryItems from '~/config/countries' import headersConfig from '~/modules/items/config/table-headers/order-checkout' import { Types } from '~/modules/documents/types' import OrderForm from '~/modules/orderpage/types' import OfferResponse = OrderForm.OfferResponse import { CreateSubscriptionCredentials } from '~/modules/client-subscriptions/types' import Permissions from '~/modules/subscriptions/models/Permissions' interface Props { orderForm: OrderFormModel formImage: Nullable<string> } export default defineComponent<Props>({ components: { MarkdownItVue: MarkdownItVue as Component, }, setup (_, ctx) { const { app, $config, $services, $localforage } = useContext() const route = useRoute() const router = useRouter() const orderForm = ref<OrderFormModel>() const quantityArr = ref([]) // @ts-ignore const fields: CustomFieldsResponse = {} const offer = ref<OfferResponse>() const selectedUser = ref() const isInApp = computed(() => $services.auth.current?.access.isClient) const rewardful = $services.settingsWorkspace.integrations.rewardful // const serviceURL = /\/service\// const featureTokens = ref() const blockByFeatureToken = ref(false) const stripeStatus = $services.settingsWorkspace.payments.stripe_connect.status const isSubscriptionType = ref(null) $services.orderPage.get(route.value.params.slug).then(({ data }) => { offer.value = data.offer orderForm.value = data isSubscriptionType.value = orderForm.value?.offer.type === 'subscription' if (orderForm.value.fields) { orderForm.value.fields.forEach((field) => { // @ts-ignore fields[field.id] = field.value }) } if (!data.form_enabled) { setQuantityArr() orderForm.value.offer.services.forEach((item) => { updateLocalQuantityValues(item.quantity, item) }) } if (orderForm.value.offer.type) { console.log(orderForm.value.offer.type) } console.log(isSubscriptionType.value) }).catch(() => { router.push({ name: '404' }) }) const formData = reactive<TaskGuestCredentials>({ email: $services.auth.current?.access.isClient ? $services.auth.current.email : null, password: '', title: '', description: '', invoiceDetails: { firstname: '', lastname: '', company_name: '', country: '', st_address_1: '', st_address_2: '', city: '', state: '', zip: '', tax_id: '', }, fields: { title: '', }, services: [], // @ts-ignore selectedPackage: '', // @ts-ignore honeypot: '', }) const appendFields = (fd: FormData, fields: Record<string, any>) => { for (const [key, value] of Object.entries(fields)) { if (value !== null && value !== undefined) { fd.append(key, value) } } } const appendUserName = (fd: FormData) => { const firstname = orderForm.value.offer.type === Types.Free ? formData.firstname : formData.invoiceDetails.firstname const lastname = orderForm.value.offer.type === Types.Free ? formData.lastname : formData.invoiceDetails.lastname fd.append('firstname', firstname) fd.append('lastname', lastname) } const appendInvoiceDetails = (fd: FormData, isSubscription = false) => { const prefix = 'invoice' for (const [key, value] of Object.entries(formData.invoiceDetails)) { if (value) { fd.append(`${prefix}[${key}]`, value) } } } const appendServices = (fd: FormData) => { formData.services.forEach((service) => { if ((service.is_quantifiable && !service.is_addon) || (service.is_addon && formData.services.find(item => item.id === service.id))) { fd.append(`selected_services[${service.id}]`, String(service.quantity)) } }) } const appendFormDataFields = (fd: FormData, expectedFieldsIds: string[]) => { Object.entries(formData.fields) .filter(([key]) => expectedFieldsIds.includes(key)) .forEach(([key, value]: [string, string | string[]]) => { const fieldName = `order_submissions[${key}]` if (Array.isArray(value)) { value.forEach(item => fd.append(`${fieldName}[]`, item)) } else { fd.append(fieldName, value as string) } }) } const redirectToUrl = (url: string) => { if (url) { window.location.replace(url) } } const createTaskRequest = async () => { const fd = new FormData() as TaskGuestCredentials const expectedFieldsIds = orderForm.value.fields.map(({ id }) => id) const basicFields = { offer: orderForm.value?.offer.id as string, email: formData.email, client: formData.email, password: formData.password, title: formData.fields.title, // @ts-ignore honeypot: formData.honeypot, } if (formData.fields.title === '' || formData.fields.title === undefined) { formData.fields.title = orderForm.value.offer.title } if (!orderForm.value.form_enabled) { const selectedServices = orderForm.value.offer.services.map((service) => { if (service.is_addon && !formData.services.find(item => item.id === service.id)) { return null } service.quantity = parseInt(setQtyToSend(service)) service.price_total = service.quantity * service.price service.gross_price_total = service.price_total * (service.tax + 1) return service }).filter(el => el !== null) formData.services = selectedServices } appendFields(fd, basicFields) appendUserName(fd) appendInvoiceDetails(fd) appendServices(fd) appendFormDataFields(fd, expectedFieldsIds) if ($services.auth.isSignedIn) { if (orderForm.value.offer.settings.collect_payment === 'upfront') { return $services.tasks.createWithAuthorizedUpFront(fd) .then(({ data }) => { const url = data.url url && redirectToUrl(url) }) .catch(() => $services.alerts.error(app.i18n.t('pages.order.slug.form.alert.error') as string)) } else { return $services.tasks.create(fd) .then(({ data }) => onTaskCreated(data)) .catch(() => $services.alerts.error(app.i18n.t('pages.order.slug.form.alert.error') as string)) } } else if (orderForm.value.offer.settings.collect_payment === 'upfront') { return $services.tasks.createWithGuestUpFront(fd) .then(({ data }) => { const url = data.url url && redirectToUrl(url) }) .catch(() => $services.alerts.error(app.i18n.t('pages.order.slug.form.alert.error') as string)) } else { return $services.tasks.createAsGuest(fd) .then(({ data }) => onTaskCreated(data)) .catch(() => $services.alerts.error(app.i18n.t('pages.order.slug.form.alert.error') as string)) } } const createSubscriptionRequest = async () => { const fd = new FormData() as CreateSubscriptionCredentials const expectedFieldsIds = orderForm.value.fields.map(({ id }) => id) const basicSubscriptionFields = { offer_subscription_package: formData.selectedPackage.package.id, time_interval: formData.selectedPackage.billing_cycle, // Added here email: formData.email, client: formData.email, password: formData.password, title: formData.fields.title, // @ts-ignore honeypot: formData.honeypot, } appendFields(fd, basicSubscriptionFields) appendUserName(fd) appendInvoiceDetails(fd) appendFormDataFields(fd, expectedFieldsIds) if ($services.auth.isSignedIn) { return $services.clientSubscriptions.createSubscription(fd) .then(({ data }) => { if ( rewardful?.enabled && rewardful?.public_key && ($services.auth.current?.access.isClient || !$services.auth.isSignedIn) ) { window.rewardful('ready', () => { window.rewardful('convert', { email: formData.email }) }) } const url = data.url if (url) { redirectToUrl(url) } }) .catch(() => $services.alerts.error(app.i18n.t('pages.order.slug.form.alert.error') as string)) } else { return $services.clientSubscriptions.createSubscriptionGuest(fd) .then(({ data }) => { const url = data.url if (url) { redirectToUrl(url) } }) .catch(() => $services.alerts.error(app.i18n.t('pages.order.slug.form.alert.error') as string)) } } const hasPermission = (permission: Nullable<string>) => { if (!permission) { return true } return Permissions.have(permission) } const prepareRedirectionUrl = (task?: Task) => { $services.localStorage.remove('cache.redirect') let url = `${window.location.origin}/requests` if (task) { url = `${window.location.origin}/requests/${task.slug}` } const localStorageRedirectData: LocalStorageRedirect = { url, type: 'order' } $services.localStorage.set('cache.redirect', localStorageRedirectData) } const authPageRedirect = async (task: Task, checkout: boolean = false) => { let routeName = 'login' await $services.account.isRegistered({ hash: task.owner.getData().email_hash as string }) .then(({ data }) => { if (!data.registered) { routeName = 'register' } }) if (checkout) { $services.alerts.success(app.i18n.t('pages.order.alert.success') as string) } router.push({ name: routeName, query: { email: task.owner.email }, }) } const onTaskCreated = (data: any) => { $localforage.removeItem('checkout.order') if (data.token) { app.router?.push({ name: 'auth.confirmation.email', query: { type: 'email-verify', token: data.token, email: formData.email, }, }) } else { const task = new Task(data) if ($services.auth.isSignedIn) { $services.settingsProfile.fetch() router.push({ name: 'requests.id', params: { id: task.slug } }) } else { prepareRedirectionUrl(task) authPageRedirect(task) } } } // New const displayPrice = (price: string | number) => $services.utils.formatCurrency(offer.value.settings.currency, price) const setQuantityArr = () => { offer.value.services.forEach((item) => { quantityArr.value.push({ id: item.id, qty: item.quantity, }) }) } const setQtyToSend = (service: Item) => { return String(quantityArr.value.find(item => item.id === service.id).qty) } const totalPrice = computed(() => { let price = 0 if (orderForm.value.offer?.services?.length) { orderForm.value.offer.services.forEach((item) => { if (!item.is_addon) { if (item.is_quantifiable) { if (quantityArr.value.find(val => val.id === item.id)) { price += item.price * quantityArr.value.find(val => val.id === item.id).qty } else { price += item.price * 1 } } else { price += item.price * item.quantity } } else if (formData.services.includes(item)) { price += item.price * quantityArr.value.find(val => val.id === item.id).qty } }) } return price }) const updateLocalQuantityValues = (qtyValue: number, service: Item) => { if (quantityArr.value.find(item => item.id === service.id)) { quantityArr.value.find(item => item.id === service.id).qty = qtyValue } else { quantityArr.value.push({ id: service.id, qty: qtyValue, }) } } // End watch(selectedUser, (value) => { if (!value) { return } $services.clients.get(value).then(({ data }) => { Object.assign(formData, { invoiceDetails: data.settings.invoice }) formData.email = data.email }) }) onMounted(async () => { if ($services.auth.isSignedIn && $services.settingsProfile.data.invoice) { $services.settingsProfile.fetch().then((data) => { // @ts-ignore Object.assign(formData, { invoiceDetails: data.invoice }) }) } quantityArr.value = [] $localforage.getItem('checkout.order').then((data) => { if (data) { Object.assign(formData, data) } }) $services.settingsWorkspace.featureTokens().then((response) => { featureTokens.value = response.feature_tokens.premium_token if (stripeStatus !== 'connected') { blockByFeatureToken.value = true } if (featureTokens.value.remaining <= 0 && !hasPermission('subscriptions')) { blockByFeatureToken.value = true } }) }) const onLogin = () => { $services.localStorage.remove('cache.redirect') const url = orderForm.value.offer.type === Types.Free ? `${window.location.origin}/order/${route.value.params.slug}` : `${window.location.origin}/order/${route.value.params.slug}/checkout` const localStorageRedirectData: LocalStorageRedirect = { url, type: 'order' } $services.localStorage.set('cache.redirect', localStorageRedirectData) router.push({ name: 'login' }) } const onClickBackBtn = () => { // if ((serviceURL.test(route.value.path))) { // router.push({ path: `/service/${route.value.params.slug}` }) // } else { // router.push({ name: 'order.slug', params: { slug: route.value.params.slug } }) // } if (!orderForm.value.form_enabled) { router.push({ name: 'order' }) } else { history.back() } } const showInvoiceDetails = computed(() => { return orderForm.value?.offer.type !== Types.Free && (!$services.auth.isSignedIn || ($services.auth.isSignedIn && $services.auth.current.access.isClient)) }) return { isInApp, headersConfig, formData, orderForm, offer, quantityArr, currencyFormat: $services.settingsWorkspace.data.documents.currency, countryItems, selectedUser, onLogin, createTaskRequest, createSubscriptionRequest, onClickBackBtn, Types, showInvoiceDetails, blockByFeatureToken, displayPrice, isSubscriptionType, totalPrice, updateLocalQuantityValues, } }, }) </script> <style lang="sass"> .order-page__body .password-helper position: absolute left: 100% top: 2.75rem width: 14em .honeypot width: 0 height: 0 opacity: 0 .items-table-preview.v-data-table .v-data-table__wrapper border: none !important margin: 0 !important table border-collapse: collapse .v-data-table-header tr th height: 30px tr &:hover background: transparent !important td:first-child, th:first-child padding-left: 0 td:last-child, th:last-child padding-right: 0 table th background: #FFF !important border: none !important .theme--light.v-data-table tbody tr border-top: none !important border-bottom: 1px solid #ccc !important .item min-height: 40px .services-select .v-input--selection-controls .v-messages height: 0 display: none .services-select .v-messages__message font-size: 10px margin-top: 2px .services-select .v-input--selection-controls__input width: 1rem !important height: 1rem !important color: #FFF !important background: #FFF !important margin-top: 1px .services-select .v-input__slot margin-bottom: 0 .services-select .v-input__wrapper .theme--light.v-input__elem input height: 21px width: 55px text-align: right .services-select .v-input__wrapper .theme--light.v-input__elem .v-input__append-inner .v-input__icon height: 20px .v-label font-weight: bold !important .theme--light.v-btn.link-btn.v-btn--text:not([disabled]):not(.v-btn--active).link-btn.task-upload-btn color: #000 !important .terms .v-label font-weight: normal !important .partial-description flex: 1% 1 1 .partial-description-fade position: relative max-height: 11rem overflow: hidden &::after content: '' position: absolute bottom: 0 left: 0 height: 3rem width: 100% background: linear-gradient(0, var(--v-secondary-lighten5), transparent) </style>