Написание движка для интерактивного обучения
This commit is contained in:
@@ -1,40 +1,139 @@
|
||||
import {defineStore} from "pinia";
|
||||
import {computed, ref} from "vue";
|
||||
import {tours} from "../config/tours.js";
|
||||
import { defineStore } from "pinia";
|
||||
import { router } from "@inertiajs/vue3";
|
||||
import { route } from "ziggy-js";
|
||||
|
||||
export const useOnboardingStore = defineStore('onboarding', () => {
|
||||
const activeTourId = ref(null)
|
||||
const activeStepIndex = ref(0)
|
||||
const isActive = ref(false)
|
||||
import tours from "@/Tours";
|
||||
|
||||
const currentTourSteps = computed(() => {
|
||||
if (!activeTourId.value) return []
|
||||
return tours[activeTourId.value]?.steps || []
|
||||
})
|
||||
export const useOnboardingStore = defineStore("onboarding", {
|
||||
state: () => ({
|
||||
active: false,
|
||||
currentTourId: null,
|
||||
stepIndex: 0,
|
||||
waitingEvent: null,
|
||||
}),
|
||||
|
||||
const startTour = (tourId, startFrom = 0) => {
|
||||
activeTourId.value = tourId
|
||||
activeStepIndex.value = startFrom
|
||||
isActive.value = true
|
||||
}
|
||||
getters: {
|
||||
tour(state) {
|
||||
return tours[state.currentTourId] ?? null;
|
||||
},
|
||||
currentStep() {
|
||||
return this.tour?.steps[this.stepIndex] ?? null;
|
||||
},
|
||||
isFirst() {
|
||||
return this.stepIndex === 0;
|
||||
},
|
||||
isLast() {
|
||||
return this.stepIndex >= this.tour.steps.length - 1;
|
||||
}
|
||||
},
|
||||
|
||||
const setStep = (index) => {
|
||||
activeStepIndex.value = index
|
||||
}
|
||||
actions: {
|
||||
start(tourId) {
|
||||
|
||||
const finish = () => {
|
||||
activeTourId.value = null
|
||||
activeStepIndex.value = 0
|
||||
isActive.value = false
|
||||
}
|
||||
if (!tours[tourId]) {
|
||||
console.warn(`Tour "${tourId}" not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
activeTourId,
|
||||
activeStepIndex,
|
||||
isActive,
|
||||
currentTourSteps,
|
||||
startTour,
|
||||
finish,
|
||||
setStep
|
||||
this.currentTourId = tourId;
|
||||
this.stepIndex = 0;
|
||||
this.active = true;
|
||||
},
|
||||
|
||||
finish() {
|
||||
this.active = false;
|
||||
this.currentTourId = null;
|
||||
this.stepIndex = 0;
|
||||
this.waitingEvent = null;
|
||||
},
|
||||
|
||||
async next() {
|
||||
|
||||
if (!this.active)
|
||||
return;
|
||||
|
||||
const step = this.currentStep;
|
||||
|
||||
if (step?.afterLeave)
|
||||
await step.afterLeave();
|
||||
|
||||
if (this.isLast) {
|
||||
this.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
this.stepIndex++;
|
||||
await this.openStep();
|
||||
},
|
||||
|
||||
async previous() {
|
||||
|
||||
if (!this.active)
|
||||
return;
|
||||
|
||||
const step = this.currentStep;
|
||||
|
||||
if (step?.afterLeave)
|
||||
await step.afterLeave();
|
||||
|
||||
if (this.isFirst)
|
||||
return;
|
||||
|
||||
this.stepIndex--;
|
||||
await this.openStep();
|
||||
},
|
||||
|
||||
async goTo(index) {
|
||||
|
||||
if (
|
||||
index < 0 ||
|
||||
index >= this.tour.steps.length
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.stepIndex = index;
|
||||
await this.openStep();
|
||||
},
|
||||
|
||||
async openStep() {
|
||||
const step = this.currentStep;
|
||||
|
||||
if (!step)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Выполнить beforeEnter
|
||||
*/
|
||||
if (step.beforeEnter)
|
||||
await step.beforeEnter();
|
||||
|
||||
/*
|
||||
* Переход между страницами
|
||||
*/
|
||||
if (
|
||||
step.route &&
|
||||
step.route !== route().current()
|
||||
) {
|
||||
router.visit(route(step.route));
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
emit(event) {
|
||||
const step = this.currentStep;
|
||||
|
||||
if (!step)
|
||||
return;
|
||||
|
||||
if (
|
||||
step.nextEvent &&
|
||||
step.nextEvent === event
|
||||
) {
|
||||
|
||||
this.next();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user