295 lines
8.8 KiB
Vue
295 lines
8.8 KiB
Vue
<script setup lang="ts">
|
|
import WizardPage from "@/components/onboarding/WizardPage.vue";
|
|
import { computed, ref } from "vue";
|
|
import { type User, useUserStore } from "@/stores/user";
|
|
import PersonalAddress from "@/components/onboarding/PersonalAddress.vue";
|
|
import OrganisationAddress from "@/components/onboarding/OrganisationAddress.vue";
|
|
import { itPost } from "@/fetchHelpers";
|
|
import { useEntities } from "@/services/entities";
|
|
import { useRoute } from "vue-router";
|
|
import { useTranslation } from "i18next-vue";
|
|
import { getVVCourseName } from "./composables";
|
|
|
|
const props = defineProps({
|
|
courseType: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
const user = useUserStore();
|
|
const route = useRoute();
|
|
const { organisations, countries } = useEntities();
|
|
|
|
const userOrganisationName = computed(() => {
|
|
if (!user.organisation) {
|
|
return null;
|
|
}
|
|
|
|
// Those IDs do not represent a company
|
|
// 1: Other broker
|
|
// 2: Other insurance
|
|
// 3: Other private insurance
|
|
// 31: No company relation
|
|
if ([1, 2, 3, 31].includes(user.organisation)) {
|
|
return null;
|
|
}
|
|
|
|
return organisations.value?.find((c) => c.id === user.organisation)?.name;
|
|
});
|
|
|
|
const paymentError = computed(() => {
|
|
return "error" in route.query;
|
|
});
|
|
|
|
const address = ref({
|
|
first_name: user.first_name,
|
|
last_name: user.last_name,
|
|
street: user.street,
|
|
street_number: user.street_number,
|
|
postal_code: user.postal_code,
|
|
city: user.city,
|
|
country_code: user.country?.country_code ?? "CH",
|
|
organisation_detail_name: user.organisation_detail_name,
|
|
organisation_street: user.organisation_street,
|
|
organisation_street_number: user.organisation_street_number,
|
|
organisation_postal_code: user.organisation_postal_code,
|
|
organisation_city: user.organisation_city,
|
|
organisation_country_code: user.organisation_country?.country_code ?? "CH",
|
|
invoice_address: user.invoice_address ?? "prv",
|
|
});
|
|
|
|
const useCompanyAddress = ref(user.invoice_address === "org");
|
|
|
|
const setUseCompanyAddress = (value: boolean) => {
|
|
useCompanyAddress.value = value;
|
|
address.value.invoice_address = value ? "org" : "prv";
|
|
};
|
|
|
|
type FormErrors = {
|
|
personal: string[];
|
|
company: string[];
|
|
};
|
|
|
|
const formErrors = ref<FormErrors>({
|
|
personal: [],
|
|
company: [],
|
|
});
|
|
|
|
const { t } = useTranslation();
|
|
|
|
function validateAddress() {
|
|
formErrors.value.personal = [];
|
|
formErrors.value.company = [];
|
|
|
|
if (!address.value.first_name) {
|
|
formErrors.value.personal.push(t("a.Vorname"));
|
|
}
|
|
|
|
if (!address.value.last_name) {
|
|
formErrors.value.personal.push(t("a.Nachname"));
|
|
}
|
|
|
|
if (!address.value.street) {
|
|
formErrors.value.personal.push(t("a.Strasse"));
|
|
}
|
|
|
|
if (!address.value.street_number) {
|
|
formErrors.value.personal.push(t("a.Hausnummmer"));
|
|
}
|
|
|
|
if (!address.value.postal_code) {
|
|
formErrors.value.personal.push(t("a.PLZ"));
|
|
}
|
|
|
|
if (!address.value.city) {
|
|
formErrors.value.personal.push(t("a.Ort"));
|
|
}
|
|
|
|
if (!address.value.country_code) {
|
|
formErrors.value.personal.push(t("a.Land"));
|
|
}
|
|
|
|
if (useCompanyAddress.value) {
|
|
if (!address.value.organisation_detail_name) {
|
|
formErrors.value.company.push(t("a.Name"));
|
|
}
|
|
|
|
if (!address.value.organisation_street) {
|
|
formErrors.value.company.push(t("a.Strasse"));
|
|
}
|
|
|
|
if (!address.value.organisation_street_number) {
|
|
formErrors.value.company.push(t("a.Hausnummmer"));
|
|
}
|
|
|
|
if (!address.value.organisation_postal_code) {
|
|
formErrors.value.company.push(t("a.PLZ"));
|
|
}
|
|
|
|
if (!address.value.organisation_city) {
|
|
formErrors.value.company.push(t("a.Ort"));
|
|
}
|
|
|
|
if (!address.value.organisation_country_code) {
|
|
formErrors.value.company.push(t("a.Land"));
|
|
}
|
|
}
|
|
}
|
|
|
|
async function saveAddress() {
|
|
const { country_code, organisation_country_code, ...profileData } = address.value;
|
|
const typedProfileData: Partial<User> = { ...profileData };
|
|
|
|
typedProfileData.country = countries.value.find(
|
|
(c) => c.country_code === country_code
|
|
);
|
|
typedProfileData.organisation_country = countries.value.find(
|
|
(c) => c.country_code === organisation_country_code
|
|
);
|
|
|
|
await user.updateUserProfile(typedProfileData);
|
|
}
|
|
|
|
const executePayment = async () => {
|
|
validateAddress();
|
|
if (formErrors.value.personal.length > 0 || formErrors.value.company.length > 0) {
|
|
return;
|
|
}
|
|
|
|
await saveAddress();
|
|
|
|
// Where the payment page will redirect to after the payment is done:
|
|
// The reason why this is here is convenience: We could also do this in the backend
|
|
// then we'd need to configure this for all environments (including Caprover).
|
|
// /server/transactions/redirect?... will just redirect to the frontend to the right page
|
|
// anyway, so it seems fine to do it here.
|
|
const fullHost = `${window.location.protocol}//${window.location.host}`;
|
|
|
|
itPost("/api/shop/vv/checkout/", {
|
|
redirect_url: fullHost,
|
|
address: address.value,
|
|
product: props.courseType,
|
|
}).then((res: any) => {
|
|
console.log("Going to next page", res.next_step_url);
|
|
window.location.href = res.next_step_url;
|
|
});
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<WizardPage :step="2">
|
|
<template #content>
|
|
<h2 class="my-10">{{ $t("a.Lehrgang kaufen") }}</h2>
|
|
<p class="mb-4">
|
|
<i18next
|
|
:translation="$t('a.Der Preis für den Lehrgang {course} beträgt {price}.')"
|
|
>
|
|
<template #course>
|
|
<b>«{{ getVVCourseName(props.courseType) }}»</b>
|
|
</template>
|
|
<template #price>
|
|
<b class="whitespace-nowrap">300 CHF</b>
|
|
</template>
|
|
</i18next>
|
|
{{
|
|
$t("a.Mit dem Kauf erhältst du Zugang auf den gesamten Kurs (inkl. Prüfung).")
|
|
}}
|
|
</p>
|
|
<p>
|
|
{{ $t("a.Hier kannst du ausschliesslich mit einer Kreditkarte bezahlen.") }}
|
|
</p>
|
|
|
|
<p v-if="paymentError" class="text-bold mt-12 text-lg text-red-700">
|
|
{{
|
|
$t("a.Fehler bei der Zahlung. Bitte versuche es erneut oder kontaktiere uns")
|
|
}}:
|
|
<a href="mailto:vermittler@vbv-afa.ch" class="underline">
|
|
vermittler@vbv-afa.ch
|
|
</a>
|
|
</p>
|
|
|
|
<h3 class="mb-4 mt-10">{{ $t("a.Adresse") }}</h3>
|
|
<p class="mb-2">
|
|
{{
|
|
$t(
|
|
"a.Um die Zahlung vornehmen zu können, benötigen wir deine Privatadresse. Optional kannst du die Rechnungsadresse deiner Gesellschaft hinzufügen."
|
|
)
|
|
}}
|
|
</p>
|
|
<p>
|
|
{{
|
|
$t(
|
|
"Wichtig: wird die Rechnung von deinem Arbeitgeber bezahlt, dann kannst du zusätzlich die Rechnungsadresse deines Arbeitsgebers erfassen."
|
|
)
|
|
}}
|
|
</p>
|
|
<PersonalAddress v-model="address" />
|
|
|
|
<p v-if="formErrors.personal.length" class="mb-10 text-red-700">
|
|
{{ $t("a.Bitte folgende Felder ausfüllen") }}:
|
|
{{ formErrors.personal.join(", ") }}
|
|
</p>
|
|
|
|
<button
|
|
v-if="!useCompanyAddress"
|
|
class="underline"
|
|
@click="setUseCompanyAddress(true)"
|
|
>
|
|
<template v-if="userOrganisationName">
|
|
{{
|
|
$t("a.Rechnungsadresse von {organisation} hinzufügen", {
|
|
organisation: userOrganisationName,
|
|
})
|
|
}}
|
|
</template>
|
|
<template v-else>{{ $t("a.Rechnungsadresse hinzufügen") }}</template>
|
|
</button>
|
|
|
|
<transition
|
|
enter-active-class="transition ease-out duration-100"
|
|
enter-from-class="transform opacity-0 scale-y-95"
|
|
enter-to-class="transform opacity-100 scale-y-100"
|
|
leave-active-class="transition ease-in duration-75"
|
|
leave-from-class="transform opacity-100 scale-y-100"
|
|
leave-to-class="transform opacity-0 scale-y-95"
|
|
>
|
|
<div v-if="useCompanyAddress">
|
|
<div class="flex items-center justify-between">
|
|
<h3 v-if="userOrganisationName">
|
|
{{
|
|
$t("a.Rechnungsadresse von {organisation}", {
|
|
organisation: userOrganisationName,
|
|
})
|
|
}}
|
|
</h3>
|
|
<h3 v-else>{{ $t("a.Rechnungsadresse") }}</h3>
|
|
<button class="underline" @click="setUseCompanyAddress(false)">
|
|
{{ $t("a.Entfernen") }}
|
|
</button>
|
|
</div>
|
|
<OrganisationAddress v-model="address" />
|
|
<p v-if="formErrors.company.length" class="text-red-700">
|
|
{{ $t("a.Bitte folgende Felder ausfüllen") }}:
|
|
{{ formErrors.company.join(", ") }}
|
|
</p>
|
|
</div>
|
|
</transition>
|
|
</template>
|
|
|
|
<template #footer>
|
|
<router-link
|
|
:to="{ name: 'accountProfile' }"
|
|
class="btn-secondary flex items-center"
|
|
>
|
|
<it-icon-arrow-left class="it-icon mr-2 h-6 w-6" />
|
|
{{ $t("general.back") }}
|
|
</router-link>
|
|
<button class="btn-blue flex items-center" @click="executePayment">
|
|
{{ $t("a.Mit Kreditkarte bezahlen") }}
|
|
<it-icon-arrow-right class="it-icon ml-2 h-6 w-6" />
|
|
</button>
|
|
</template>
|
|
</WizardPage>
|
|
</template>
|