feat: onboarding course type
This commit is contained in:
parent
4ac735c3be
commit
607789d599
|
|
@ -4,14 +4,15 @@ import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/vue";
|
|||
import type { AvailableLanguages } from "@/stores/user";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const props = defineProps({
|
||||
courseName: String,
|
||||
});
|
||||
const props = defineProps<{
|
||||
courseName: string;
|
||||
imageUrl: string;
|
||||
}>();
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
async function changeLocale(language: AvailableLanguages) {
|
||||
userStore.setUserLanguages(language);
|
||||
await userStore.setUserLanguages(language);
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
|
|
@ -70,12 +71,9 @@ async function changeLocale(language: AvailableLanguages) {
|
|||
</div>
|
||||
|
||||
<div class="max-w-xs text-white">
|
||||
<img
|
||||
src="/static/images/mood_uk.jpg"
|
||||
class="aspect-square rounded-full object-cover"
|
||||
alt=""
|
||||
/>
|
||||
<h3 class="mt-8 text-center">{{ props.courseName }}</h3>
|
||||
<img :src="imageUrl" class="aspect-square rounded-full object-cover" alt="" />
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<h3 class="mt-8 text-center" v-html="props.courseName"></h3>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-x-2 text-sm text-white">
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const props = withDefaults(
|
|||
<div class="relative">
|
||||
<img
|
||||
v-if="props?.imageUrl"
|
||||
class="aspect-square h-[172px] w-[172px] rounded-full object-cover"
|
||||
class="aspect-square w-[172px] rounded-full object-cover"
|
||||
:class="{ 'opacity-30': props.loading }"
|
||||
:src="props.imageUrl"
|
||||
alt="avatar"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import WizardPage from "@/components/onboarding/WizardPage.vue";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import { ref, watch } from "vue";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import AvatarImage from "@/components/ui/AvatarImage.vue";
|
||||
import { useFileUpload } from "@/composables";
|
||||
import { companies } from "@/pages/onboarding/companies";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const user = useUserStore();
|
||||
|
||||
const route = useRoute();
|
||||
const selectedCompany = ref(companies[0]);
|
||||
|
||||
const {
|
||||
|
|
@ -25,6 +26,16 @@ watch(avatarFileInfo, (info) => {
|
|||
watch(selectedCompany, (company) => {
|
||||
console.log("company changed", company);
|
||||
});
|
||||
|
||||
const nextRoute = computed(() => {
|
||||
if (route.params.courseType === "uk") {
|
||||
return "setupComplete";
|
||||
}
|
||||
if (route.params.courseType === "vv") {
|
||||
return "checkoutAddress";
|
||||
}
|
||||
return "";
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -69,7 +80,7 @@ watch(selectedCompany, (company) => {
|
|||
</template>
|
||||
|
||||
<template #footer>
|
||||
<router-link :to="{ name: 'setupComplete' }" class="btn-blue flex items-center">
|
||||
<router-link :to="{ name: nextRoute }" class="btn-blue flex items-center">
|
||||
Weiter
|
||||
<it-icon-arrow-right class="it-icon ml-2 h-6 w-6" />
|
||||
</router-link>
|
||||
|
|
@ -12,12 +12,5 @@ import WizardPage from "@/components/onboarding/WizardPage.vue";
|
|||
<p class="mb-4 mt-12">Hast du schon ein Konto?</p>
|
||||
<a href="/sso/login/" class="btn-secondary">Anmelden</a>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<button disabled class="btn-blue flex items-center">
|
||||
Weiter
|
||||
<it-icon-arrow-right class="it-icon ml-2 h-6 w-6" />
|
||||
</button>
|
||||
</template>
|
||||
</WizardPage>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<script setup lang="ts">
|
||||
import WizardSidePanel from "@/components/onboarding/WizardSidePanel.vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
courseType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
type CourseMetaType = {
|
||||
[key: string]: {
|
||||
name: string;
|
||||
imageUrl: string;
|
||||
};
|
||||
};
|
||||
|
||||
const courseMeta: CourseMetaType = {
|
||||
uk: {
|
||||
name: "Überbetriebliche Kurse",
|
||||
imageUrl: "/static/images/mood_uk.jpg",
|
||||
},
|
||||
vv: {
|
||||
name: "Versicherungs­vermittler/‑in",
|
||||
imageUrl: "/static/images/mood_vv.jpg",
|
||||
},
|
||||
};
|
||||
|
||||
const courseData = computed(() => {
|
||||
return courseMeta[props.courseType];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col lg:flex-row">
|
||||
<WizardSidePanel :image-url="courseData.imageUrl" :course-name="courseData.name" />
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import WizardSidePanel from "@/components/onboarding/WizardSidePanel.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col lg:flex-row">
|
||||
<WizardSidePanel course-name="Überbetriebliche Kurse" />
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
<script setup lang="ts">
|
||||
import WizardPage from "@/components/onboarding/WizardPage.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<WizardPage :step="2">
|
||||
<template #content>
|
||||
<h2 class="my-10">Lehrgang kaufen</h2>
|
||||
<p class="mb-4">
|
||||
Der Preis für diesen Lehrgang beträgt
|
||||
<b>300 CHF.</b>
|
||||
Mit dem Kauf erhältst du Zugang auf den gesamten Kurs (inkl. Prüfung).
|
||||
</p>
|
||||
<p>Hier kannst du ausschliesslich mit einer Kreditkarte bezahlen.</p>
|
||||
|
||||
<h3 class="mb-4 mt-10">Adresse</h3>
|
||||
<p>
|
||||
Um die Zahlung vornehmen zu können, benötigen wir deine Privatadresse. Optional
|
||||
kannst du die Rechnungsadresse deiner Gesellschaft hinzufügen.
|
||||
</p>
|
||||
|
||||
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-6 sm:grid-cols-6">
|
||||
<div class="sm:col-span-3">
|
||||
<label
|
||||
for="first-name"
|
||||
class="block text-sm font-medium leading-6 text-gray-900"
|
||||
>
|
||||
Vorname
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<input
|
||||
id="first-name"
|
||||
type="text"
|
||||
name="first-name"
|
||||
autocomplete="given-name"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sm:col-span-3">
|
||||
<label
|
||||
for="last-name"
|
||||
class="block text-sm font-medium leading-6 text-gray-900"
|
||||
>
|
||||
Last name
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<input
|
||||
id="last-name"
|
||||
type="text"
|
||||
name="last-name"
|
||||
autocomplete="family-name"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sm:col-span-4">
|
||||
<label for="email" class="block text-sm font-medium leading-6 text-gray-900">
|
||||
Email address
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
autocomplete="email"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sm:col-span-3">
|
||||
<label
|
||||
for="country"
|
||||
class="block text-sm font-medium leading-6 text-gray-900"
|
||||
>
|
||||
Country
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<select
|
||||
id="country"
|
||||
name="country"
|
||||
autocomplete="country-name"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:max-w-xs sm:text-sm sm:leading-6"
|
||||
>
|
||||
<option>United States</option>
|
||||
<option>Canada</option>
|
||||
<option>Mexico</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<label
|
||||
for="street-address"
|
||||
class="block text-sm font-medium leading-6 text-gray-900"
|
||||
>
|
||||
Street address
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<input
|
||||
id="street-address"
|
||||
type="text"
|
||||
name="street-address"
|
||||
autocomplete="street-address"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sm:col-span-2 sm:col-start-1">
|
||||
<label for="city" class="block text-sm font-medium leading-6 text-gray-900">
|
||||
City
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<input
|
||||
id="city"
|
||||
type="text"
|
||||
name="city"
|
||||
autocomplete="address-level2"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sm:col-span-2">
|
||||
<label for="region" class="block text-sm font-medium leading-6 text-gray-900">
|
||||
State / Province
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<input
|
||||
id="region"
|
||||
type="text"
|
||||
name="region"
|
||||
autocomplete="address-level1"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sm:col-span-2">
|
||||
<label
|
||||
for="postal-code"
|
||||
class="block text-sm font-medium leading-6 text-gray-900"
|
||||
>
|
||||
ZIP / Postal code
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<input
|
||||
id="postal-code"
|
||||
type="text"
|
||||
name="postal-code"
|
||||
autocomplete="postal-code"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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" />
|
||||
Zurück
|
||||
</router-link>
|
||||
<router-link to="/" class="btn-blue flex items-center">
|
||||
Mit Kreditkarte bezahlen
|
||||
<it-icon-arrow-right class="it-icon ml-2 h-6 w-6" />
|
||||
</router-link>
|
||||
</template>
|
||||
</WizardPage>
|
||||
</template>
|
||||
|
|
@ -7,7 +7,7 @@ import {
|
|||
updateLoggedIn,
|
||||
} from "@/router/guards";
|
||||
import { addToHistory } from "@/router/history";
|
||||
import { checkUKProcess } from "@/router/onboarding";
|
||||
import { onboardingRedirect } from "@/router/onboarding";
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
|
||||
const router = createRouter({
|
||||
|
|
@ -231,39 +231,40 @@ const router = createRouter({
|
|||
component: () => import("@/pages/AppointmentsPage.vue"),
|
||||
},
|
||||
{
|
||||
path: "/onboarding/uk",
|
||||
path: "/onboarding/:courseType",
|
||||
props: true,
|
||||
component: () => import("@/pages/onboarding/uk/WizardBase.vue"),
|
||||
component: () => import("@/pages/onboarding/WizardBase.vue"),
|
||||
meta: {
|
||||
public: true,
|
||||
hideChrome: true,
|
||||
},
|
||||
beforeEnter: checkUKProcess,
|
||||
beforeEnter: onboardingRedirect,
|
||||
children: [
|
||||
{
|
||||
path: "account/create",
|
||||
props: true,
|
||||
component: () => import("@/pages/onboarding/uk/AccountSetup.vue"),
|
||||
component: () => import("@/pages/onboarding/AccountSetup.vue"),
|
||||
name: "accountCreate",
|
||||
},
|
||||
{
|
||||
path: "account/confirm",
|
||||
props: true,
|
||||
component: () => import("@/pages/onboarding/uk/AccountConfirm.vue"),
|
||||
component: () => import("@/pages/onboarding/AccountConfirm.vue"),
|
||||
name: "accountConfirm",
|
||||
},
|
||||
{
|
||||
path: "account/profile",
|
||||
props: true,
|
||||
component: () => import("@/pages/onboarding/uk/AccountProfile.vue"),
|
||||
component: () => import("@/pages/onboarding/AccountProfile.vue"),
|
||||
name: "accountProfile",
|
||||
},
|
||||
{
|
||||
path: "account/complete",
|
||||
props: true,
|
||||
component: () => import("@/pages/onboarding/uk/SetupComplete.vue"),
|
||||
name: "setupComplete",
|
||||
},
|
||||
{
|
||||
path: "checkout/address",
|
||||
component: () => import("@/pages/onboarding/vv/CheckoutAddress.vue"),
|
||||
name: "checkoutAddress",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useUserStore } from "@/stores/user";
|
||||
import type { NavigationGuardNext, RouteLocationNormalized } from "vue-router";
|
||||
|
||||
export async function checkUKProcess(
|
||||
export async function onboardingRedirect(
|
||||
to: RouteLocationNormalized,
|
||||
from: RouteLocationNormalized,
|
||||
next: NavigationGuardNext
|
||||
|
|
@ -11,14 +11,14 @@ export async function checkUKProcess(
|
|||
// Guest
|
||||
if (!userStore.loggedIn) {
|
||||
if (to.name !== "accountCreate") {
|
||||
return next({ name: "accountCreate" });
|
||||
return next({ name: "accountCreate", params: to.params });
|
||||
}
|
||||
return next();
|
||||
}
|
||||
|
||||
// Logged in
|
||||
if (to.name === "accountCreate") {
|
||||
return next({ name: "accountConfirm" });
|
||||
return next({ name: "accountConfirm", params: to.params });
|
||||
}
|
||||
|
||||
return next();
|
||||
|
|
|
|||
Loading…
Reference in New Issue