Chore App Build, Test, and Push Docker Images / build-and-push (push) Has been cancelled
130 lines
3.6 KiB
Vue
130 lines
3.6 KiB
Vue
<template>
|
|
<button
|
|
v-if="visible"
|
|
type="button"
|
|
class="help-fab"
|
|
aria-label="Show help for this screen"
|
|
@click="onClick"
|
|
title="Show help"
|
|
>
|
|
?
|
|
</button>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
import { activeStep, maybeShow, clearChainProgress, modalTutorialStepId, helpButtonHidden, sessionSkipped } from './controller'
|
|
|
|
// Map route names to the tutorial step that should re-fire when the user taps `?`.
|
|
// Keep this list lean — only routes that have a tutorial step actually wired.
|
|
const routeToStep: Record<string, string> = {
|
|
ParentChildrenListView: 'parent-children-list',
|
|
ChoreView: 'list-chore-help',
|
|
KindnessView: 'list-kindness-help',
|
|
PenaltyView: 'list-penalty-help',
|
|
RewardView: 'list-reward-help',
|
|
RoutineView: 'list-routine-help',
|
|
NotificationView: 'notification-click',
|
|
ParentView: 'select-child',
|
|
CreateChore: 'edit-chore-name',
|
|
EditChore: 'edit-chore-name',
|
|
CreateKindness: 'edit-kindness-name',
|
|
EditKindness: 'edit-kindness-name',
|
|
CreatePenalty: 'edit-penalty-name',
|
|
EditPenalty: 'edit-penalty-name',
|
|
CreateRoutine: 'edit-routine-name',
|
|
EditRoutine: 'edit-routine-name',
|
|
CreateReward: 'edit-reward-name',
|
|
EditReward: 'edit-reward-name',
|
|
CreateChild: 'edit-child-name',
|
|
ChildEditView: 'edit-child-name',
|
|
ChoreAssignView: 'assign-chore-list',
|
|
KindnessAssignView: 'assign-kindness-list',
|
|
PenaltyAssignView: 'assign-penalty-list',
|
|
RewardAssignView: 'assign-reward-list',
|
|
RoutineAssignView: 'assign-routine-list',
|
|
}
|
|
|
|
const route = useRoute()
|
|
|
|
const targetStepId = computed<string | null>(() => {
|
|
// Modals (e.g. ScheduleModal) can override the route-based step.
|
|
if (modalTutorialStepId.value) return modalTutorialStepId.value
|
|
const name = typeof route.name === 'string' ? route.name : String(route.name ?? '')
|
|
return routeToStep[name] ?? null
|
|
})
|
|
|
|
const visible = computed(() => {
|
|
if (helpButtonHidden.value) return false
|
|
return targetStepId.value !== null
|
|
})
|
|
|
|
function onClick() {
|
|
const id = targetStepId.value
|
|
if (!id) return
|
|
// Clear any active step so the manual re-fire wins.
|
|
activeStep.value = null
|
|
// A previous Cancel/Skip would otherwise permanently block manual help.
|
|
sessionSkipped.value = false
|
|
// Temporarily clear local "seen" state for the whole chain so every step replays.
|
|
// The server state is left alone; on dismiss `markStepSeen` simply no-ops.
|
|
clearChainProgress(id)
|
|
maybeShow(id, null, true)
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.help-fab {
|
|
position: fixed;
|
|
bottom: 2rem;
|
|
left: 2rem;
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: 50%;
|
|
border: 0;
|
|
background: var(--btn-secondary, rgba(255, 255, 255, 0.92));
|
|
color: var(--btn-primary, #667eea);
|
|
font-weight: 700;
|
|
font-size: 1.5rem;
|
|
line-height: 1;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
z-index: 1300;
|
|
transition:
|
|
background 0.18s,
|
|
box-shadow 0.18s,
|
|
transform 0.18s;
|
|
}
|
|
.help-fab:hover {
|
|
background: var(--btn-secondary-hover, #e2e8f0);
|
|
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25);
|
|
transform: scale(1.05);
|
|
}
|
|
.help-fab:focus-visible {
|
|
outline: 2px solid var(--primary, #667eea);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
.help-fab {
|
|
bottom: 1rem;
|
|
left: 1rem;
|
|
width: 44px;
|
|
height: 44px;
|
|
font-size: 1.15rem;
|
|
background: rgba(255, 255, 255, 0.78);
|
|
backdrop-filter: blur(4px);
|
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
|
}
|
|
.help-fab:hover {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2);
|
|
transform: scale(1.05);
|
|
}
|
|
}
|
|
</style>
|