feat(tutorial): implement comprehensive tutorial system with step guidance
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 3m9s
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 3m9s
- Added tutorial controller to manage tutorial state and progress. - Introduced HelpButton component for contextual help throughout the application. - Created various tutorial steps for onboarding and feature guidance. - Integrated tutorial prompts in multiple components (ChildrenListView, LoginButton, ScheduleModal, etc.) to enhance user experience. - Implemented logic to show tutorials based on user actions and state. - Added functionality to dismiss and skip tutorial sessions. - Established a mechanism to hydrate tutorial state from user profile.
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
|
||||
import { ref, onMounted, onBeforeUnmount, onUnmounted, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getCachedImageUrl, revokeAllImageUrls } from '../../common/imageCache'
|
||||
import { isParentAuthenticated } from '../../stores/auth'
|
||||
import { eventBus } from '@/common/eventBus'
|
||||
import {
|
||||
maybeShow as tutorialMaybeShow,
|
||||
markStepSeen as tutorialMark,
|
||||
tutorialReady,
|
||||
} from '@/tutorial/controller'
|
||||
import type {
|
||||
Child,
|
||||
ChildModifiedEventPayload,
|
||||
@@ -150,6 +155,22 @@ const createChild = () => {
|
||||
router.push({ name: 'CreateChild' })
|
||||
}
|
||||
|
||||
function maybeTriggerCreateChildTutorial() {
|
||||
if (!isParentAuthenticated.value) return
|
||||
if (loading.value) return
|
||||
if (!tutorialReady.value) return
|
||||
if (children.value.length === 0) {
|
||||
tutorialMaybeShow('create-child', () => document.querySelector('.fab') as HTMLElement | null)
|
||||
} else {
|
||||
void tutorialMark('has-created-child')
|
||||
}
|
||||
}
|
||||
|
||||
watch([tutorialReady, loading, children, isParentAuthenticated], maybeTriggerCreateChildTutorial, {
|
||||
immediate: false,
|
||||
deep: true,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
eventBus.on('child_modified', handleChildModified)
|
||||
eventBus.on('child_task_triggered', handleChildTaskTriggered)
|
||||
@@ -158,6 +179,7 @@ onMounted(async () => {
|
||||
const listPromise = fetchChildren()
|
||||
listPromise.then((list) => {
|
||||
children.value = list
|
||||
maybeTriggerCreateChildTutorial()
|
||||
})
|
||||
// listen for outside clicks to auto-close any open kebab menu
|
||||
document.addEventListener('click', onDocClick, true)
|
||||
@@ -214,6 +236,10 @@ const selectChild = (childId: string | number) => {
|
||||
const openMenu = (childId: string | number, evt?: Event) => {
|
||||
evt?.stopPropagation()
|
||||
activeMenuFor.value = childId
|
||||
tutorialMaybeShow(
|
||||
'child-kebab',
|
||||
() => document.querySelector('.kebab-menu') as HTMLElement | null,
|
||||
)
|
||||
}
|
||||
const closeMenu = () => {
|
||||
activeMenuFor.value = null
|
||||
|
||||
Reference in New Issue
Block a user