Работа над интерактивным обучением для дежурного и мед. сестры
This commit is contained in:
@@ -135,7 +135,11 @@ function delay(ms) {
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<TourOverlay
|
||||
v-if="onboarding.active && target"
|
||||
v-if="onboarding.active &&
|
||||
target &&
|
||||
onboarding.currentStep?.highlight !== false &&
|
||||
rect"
|
||||
:allow-interaction="onboarding.currentStep?.allowInteraction ?? true"
|
||||
:rect="rect"
|
||||
:padding="onboarding.currentStep.padding"
|
||||
/>
|
||||
@@ -148,7 +152,7 @@ function delay(ms) {
|
||||
:visible="onboarding.active"
|
||||
|
||||
:is-first="onboarding.stepIndex === 0"
|
||||
:is-last="onboarding.stepIndex === onboarding.tour.steps.length - 1"
|
||||
:is-last="onboarding.stepIndex === onboarding.tour?.steps.length - 1"
|
||||
|
||||
@next="onboarding.next"
|
||||
@previous="onboarding.previous"
|
||||
@@ -156,4 +160,4 @@ function delay(ms) {
|
||||
@close="onboarding.finish"
|
||||
/>
|
||||
</Teleport>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -5,16 +5,50 @@ const props = defineProps({
|
||||
rect: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
allowInteraction: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const style = computed(() => {
|
||||
const r = props.rect
|
||||
const overlayStyle = computed(() => {
|
||||
|
||||
if (!props.rect) return null;
|
||||
|
||||
const { top, left, width, height } = props.rect
|
||||
|
||||
return {
|
||||
"--top": `${r.top}px`,
|
||||
"--left": `${r.left}px`,
|
||||
"--width": `${r.width}px`,
|
||||
"--height": `${r.height}px`
|
||||
top: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100vw',
|
||||
height: `${top}px`
|
||||
},
|
||||
left: {
|
||||
top: `${top}px`,
|
||||
left: 0,
|
||||
width: `${left}px`,
|
||||
height: `${height}px`
|
||||
},
|
||||
right: {
|
||||
top: `${top}px`,
|
||||
left: `${left+width}px`,
|
||||
width: `calc(100vw - ${left+width}px)`,
|
||||
height: `${height}px`
|
||||
},
|
||||
bottom: {
|
||||
top: `${top+height}px`,
|
||||
left: 0,
|
||||
width: "100vw",
|
||||
height: `calc(100vh - ${top+height}px)`
|
||||
},
|
||||
highlight: {
|
||||
top: `${top}px`,
|
||||
left: `${left}px`,
|
||||
width: `${width}px`,
|
||||
height: `${height}px`
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -24,10 +58,32 @@ const style = computed(() => {
|
||||
|
||||
<Teleport to="body">
|
||||
<Transition name="tour-fade">
|
||||
<div
|
||||
class="tour-overlay"
|
||||
:style="style"
|
||||
/>
|
||||
<div v-if="rect && overlayStyle">
|
||||
<div
|
||||
class="tour-mask"
|
||||
:style="overlayStyle.top"
|
||||
/>
|
||||
<div
|
||||
class="tour-mask"
|
||||
:style="overlayStyle.left"
|
||||
/>
|
||||
<div
|
||||
class="tour-mask"
|
||||
:style="overlayStyle.right"
|
||||
/>
|
||||
<div
|
||||
class="tour-mask"
|
||||
:style="overlayStyle.bottom"
|
||||
/>
|
||||
<div
|
||||
class="tour-highlight"
|
||||
:style="overlayStyle.highlight"
|
||||
/>
|
||||
<div
|
||||
v-if="!allowInteraction"
|
||||
class="tour-blocker"
|
||||
/>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
|
||||
@@ -35,28 +91,27 @@ const style = computed(() => {
|
||||
|
||||
|
||||
<style scoped>
|
||||
.tour-mask {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
background: rgba(0,0,0,.55);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.tour-overlay {
|
||||
.tour-blocker {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9998;
|
||||
pointer-events: none;
|
||||
background: rgba(0,0,0,.55);
|
||||
background: transparent;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
вырезаем окно
|
||||
*/
|
||||
mask:
|
||||
linear-gradient(#000 0 0),
|
||||
linear-gradient(#000 0 0);
|
||||
mask-size:
|
||||
100% 100%,
|
||||
var(--width) var(--height);
|
||||
mask-position:
|
||||
0 0,
|
||||
var(--left) var(--top);
|
||||
mask-repeat:no-repeat;
|
||||
mask-composite: exclude;
|
||||
.tour-highlight {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
border: 2px solid white;
|
||||
border-radius: 8px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tour-fade-enter-active,
|
||||
@@ -68,4 +123,4 @@ const style = computed(() => {
|
||||
.tour-fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -23,6 +23,10 @@ const props = defineProps({
|
||||
type: [HTMLElement, String, Object],
|
||||
default: null
|
||||
},
|
||||
disabledControllers: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
@@ -53,83 +57,83 @@ const style = computed(() => ({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Transition name="tour-tooltip">
|
||||
<div
|
||||
ref="floating"
|
||||
v-if="visible && step"
|
||||
class="tour-tooltip"
|
||||
:style="style"
|
||||
<Transition name="tour-tooltip">
|
||||
<div
|
||||
ref="floating"
|
||||
v-if="visible && step"
|
||||
class="tour-tooltip"
|
||||
:style="style"
|
||||
>
|
||||
<NCard
|
||||
style="width:320px"
|
||||
size="small"
|
||||
>
|
||||
<NCard
|
||||
style="width:320px"
|
||||
size="small"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="font-semibold">
|
||||
{{ step.title }}
|
||||
</span>
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="font-semibold">
|
||||
{{ step.title }}
|
||||
</span>
|
||||
|
||||
<NTag
|
||||
v-if="step.tag"
|
||||
size="small"
|
||||
>
|
||||
{{ step.tag }}
|
||||
</NTag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="text-sm whitespace-pre-line">
|
||||
{{ step.description }}
|
||||
<NTag
|
||||
v-if="step.tag"
|
||||
size="small"
|
||||
>
|
||||
{{ step.tag }}
|
||||
</NTag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<slot />
|
||||
<div class="text-sm whitespace-pre-line">
|
||||
{{ step.description }}
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<NSpace justify="space-between">
|
||||
<div>
|
||||
<NButton
|
||||
quaternary
|
||||
size="small"
|
||||
@click="emit('close')"
|
||||
>
|
||||
Пропустить
|
||||
</NButton>
|
||||
</div>
|
||||
<slot />
|
||||
|
||||
<NSpace>
|
||||
<NButton
|
||||
v-if="!isFirst"
|
||||
size="small"
|
||||
@click="emit('previous')"
|
||||
>
|
||||
Назад
|
||||
</NButton>
|
||||
<template #footer>
|
||||
<NSpace justify="space-between">
|
||||
<div>
|
||||
<NButton
|
||||
quaternary
|
||||
size="small"
|
||||
@click="emit('close')"
|
||||
>
|
||||
Пропустить
|
||||
</NButton>
|
||||
</div>
|
||||
|
||||
<NButton
|
||||
v-if="!isLast"
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="step.manual"
|
||||
@click="emit('next')"
|
||||
>
|
||||
Далее
|
||||
</NButton>
|
||||
<NSpace>
|
||||
<NButton
|
||||
v-if="!isFirst"
|
||||
size="small"
|
||||
@click="emit('previous')"
|
||||
>
|
||||
Назад
|
||||
</NButton>
|
||||
|
||||
<NButton
|
||||
v-else
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="emit('finish')"
|
||||
>
|
||||
Завершить
|
||||
</NButton>
|
||||
</NSpace>
|
||||
<NButton
|
||||
v-if="!isLast"
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="step.manual"
|
||||
@click="emit('next')"
|
||||
>
|
||||
Далее
|
||||
</NButton>
|
||||
|
||||
<NButton
|
||||
v-else
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="emit('finish')"
|
||||
>
|
||||
Завершить
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</template>
|
||||
</NCard>
|
||||
</div>
|
||||
</Transition>
|
||||
</NSpace>
|
||||
</template>
|
||||
</NCard>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -151,4 +155,4 @@ const style = computed(() => ({
|
||||
transform:translateY(6px);
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -19,8 +19,8 @@ const onboarding = useOnboardingStore()
|
||||
const userStore = useAuthStore()
|
||||
const modalStore = useModalStore()
|
||||
|
||||
if (userStore.user.role.slug === 'dej')
|
||||
onboarding.start("welcomeDuty")
|
||||
// if (userStore.user.role.slug === 'nurse')
|
||||
// onboarding.start("welcomeNurse")
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const themeVars = useThemeVars()
|
||||
@@ -67,11 +67,12 @@ const isLockReportButton = computed(() => {
|
||||
return getHours(serverTime.value) < 6 || getHours(serverTime.value) >= 7
|
||||
})
|
||||
|
||||
const showSelectUserModal = ref(false)
|
||||
const showSelectDutyUserModal = ref(false)
|
||||
const showSelectNurseUserModal = ref(false)
|
||||
|
||||
const openReport = (path) => {
|
||||
modalStore.showSelectDutyUserModal = true
|
||||
showSelectDutyUserModal.value = true
|
||||
onboarding.emit('selectUser:opened')
|
||||
}
|
||||
|
||||
const openNurseReport = () => {
|
||||
@@ -80,7 +81,8 @@ const openNurseReport = () => {
|
||||
// } else {
|
||||
// router.visit('/nurse/report')
|
||||
// }
|
||||
modalStore.showSelectNurseUserModal = true
|
||||
showSelectNurseUserModal.value = true
|
||||
onboarding.emit('selectUser:opened')
|
||||
}
|
||||
|
||||
const cardColor = computed(() => themeVars.value.cardColor)
|
||||
@@ -90,7 +92,7 @@ const dividerColor = computed(() => themeVars.value.dividerColor)
|
||||
<template>
|
||||
<AppLayout>
|
||||
<div class="flex flex-col justify-center items-center" style="min-height: calc(100vh - 48px);">
|
||||
<NFlex vertical :size="10" class="max-w-2xl w-full" style="padding: 0 16px 24px;">
|
||||
<NFlex id="launcher" vertical :size="10" class="max-w-2xl w-full" style="padding: 0 16px 0 16px;">
|
||||
|
||||
<!-- Профиль -->
|
||||
<NEl id="user-panel" class="profile-card rounded-2xl" style="padding: 18px 22px;">
|
||||
@@ -192,9 +194,9 @@ const dividerColor = computed(() => themeVars.value.dividerColor)
|
||||
</NFlex>
|
||||
</div>
|
||||
|
||||
<SelectUserModal v-model:show="modalStore.showSelectDutyUserModal" :only-user-department="false" />
|
||||
<SelectUserModal v-model:show="showSelectDutyUserModal" :only-user-department="false" />
|
||||
<SelectUserModal
|
||||
v-model:show="modalStore.showSelectNurseUserModal"
|
||||
v-model:show="showSelectNurseUserModal"
|
||||
target-path="/nurse/report"
|
||||
submit-label="Перейти к журналу пациентов"
|
||||
:with-exists-check="false"
|
||||
|
||||
@@ -7,8 +7,11 @@ import {format} from "date-fns";
|
||||
import {router, usePage} from "@inertiajs/vue3";
|
||||
import AppPanel from "../../../Components/AppPanel.vue"
|
||||
import AppSearchAddress from '../../../Components/AppSearchAddress.vue';
|
||||
import {useOnboardingStore} from "../../../Stores/onboarding.js";
|
||||
|
||||
const show = defineModel('show', { default: false })
|
||||
|
||||
const onboarding = useOnboardingStore()
|
||||
const currentStep = ref(1)
|
||||
const currentStatus = ref('process')
|
||||
const isFinallyStep = computed(() => currentStep.value === 2)
|
||||
@@ -224,10 +227,16 @@ const onAfterLeave = () => {
|
||||
currentStep.value = 1
|
||||
searchOptions.value = []
|
||||
}
|
||||
|
||||
const onUpdatePatientSource = (v) => {
|
||||
if (v === 'mis') onboarding.emit('newPatientModal:patientTypeSelected')
|
||||
if (v === 'special') onboarding.emit('newPatientModal:patientTypeSelected')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NModal v-model:show="show"
|
||||
id="create-new-patient-modal"
|
||||
segmented
|
||||
preset="card"
|
||||
title="Добавление пациента"
|
||||
@@ -243,7 +252,7 @@ const onAfterLeave = () => {
|
||||
</NSteps>
|
||||
<NTabs tab-class="hidden!" :value="currentStep">
|
||||
<NTabPane :name="1" class="mt-4">
|
||||
<NRadioGroup class="w-full space-y-2!" v-model:value="form.patient_source">
|
||||
<NRadioGroup class="w-full space-y-2!" v-model:value="form.patient_source" @update:value="v => onUpdatePatientSource(v)">
|
||||
<AppRadio title="МИС" value="mis" description="Выберите, если пациента можно найти в системе МИС" />
|
||||
<AppRadio title="Спец. контингент" value="special" description="Выберите, если пациента нет в системе МИС" />
|
||||
</NRadioGroup>
|
||||
|
||||
@@ -17,6 +17,7 @@ import ActionsColumnDataTable from "../Components/ActionsColumnDataTable.vue";
|
||||
import {useAppDialog} from "../../../Composables/useAppDialog.js";
|
||||
import {format} from "date-fns";
|
||||
import DatePickerQuery from "../../../Components/DatePickerQuery.vue";
|
||||
import {useOnboardingStore} from "../../../Stores/onboarding.js";
|
||||
|
||||
const props = defineProps({
|
||||
patients: {
|
||||
@@ -53,6 +54,7 @@ const props = defineProps({
|
||||
|
||||
const canEdit = computed(() => props.canSaveReport || props.canEditPastReport)
|
||||
|
||||
const onboarding = useOnboardingStore()
|
||||
const showAddMedicalHistoryModal = shallowRef(false)
|
||||
const showEditMedicalHistoryModal = shallowRef(false)
|
||||
const editHistoryId = ref(null)
|
||||
@@ -210,18 +212,23 @@ const submit = () => {
|
||||
|
||||
const reportCreator = computed(() => {
|
||||
if (props.latestReport === null) return ''
|
||||
if (props.latestReport.doctor.LPUDoctorID === 0) return 'Отчет создан системой'
|
||||
if (props.latestReport.doctor?.LPUDoctorID === 0) return 'Отчет создан системой'
|
||||
else return `Отчет создан: ${props.latestReport.doctor.FAM_V} ${props.latestReport.doctor.IM_V} ${props.latestReport.doctor.OT_V}`
|
||||
})
|
||||
const reportCreatorType = computed(() => {
|
||||
if (props.latestReport === null) return 'warning'
|
||||
if (props.latestReport.doctor.LPUDoctorID === 0) return 'error'
|
||||
if (props.latestReport.doctor?.LPUDoctorID === 0) return 'error'
|
||||
else return 'warning'
|
||||
})
|
||||
|
||||
const formattedLabel = (word, count) => {
|
||||
return `${word} (${count})`
|
||||
}
|
||||
|
||||
const onShowCreatePatientModal = () => {
|
||||
showAddMedicalHistoryModal.value = true
|
||||
onboarding.emit('createNewPatientModal:opened')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -237,19 +244,19 @@ const formattedLabel = (word, count) => {
|
||||
{{ reportCreator }}
|
||||
</NTag>
|
||||
</NSpace>
|
||||
<DatePickerQuery :date="dates" :is-head-or-admin="true" class="text-lg!" hint />
|
||||
<DatePickerQuery id="date-selector" :date="dates" :is-head-or-admin="true" class="text-lg!" hint />
|
||||
</NFlex>
|
||||
</AppPanel>
|
||||
<AppPanel header="Журнал пациентов" header-include-body>
|
||||
<template v-if="canEdit" #header-extra>
|
||||
<NButton secondary :loading="loading" @click="showAddMedicalHistoryModal = true">
|
||||
<NButton id="add-new-patient" secondary :loading="loading" @click="onShowCreatePatientModal">
|
||||
<template #icon>
|
||||
<TbCirclePlus />
|
||||
</template>
|
||||
Добавить пациента
|
||||
</NButton>
|
||||
</template>
|
||||
<NTabs type="line">
|
||||
<NTabs id="view-tabs" type="line">
|
||||
<NTabPane name="all"
|
||||
:tab="formattedLabel('В отделении', patientsByGroup.in_department.length)"
|
||||
>
|
||||
|
||||
@@ -27,6 +27,8 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const reportStore = useReportStore()
|
||||
const onboarding = useOnboardingStore()
|
||||
|
||||
const formRef = ref()
|
||||
|
||||
const rawUsers = ref([])
|
||||
@@ -153,10 +155,15 @@ const onSubmit = (e) => {
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
if (reportExists.value) return
|
||||
|
||||
router.visit(props.targetPath, {
|
||||
data: {
|
||||
userId: reportStore.reportInfo.userId,
|
||||
departmentId: reportStore.reportInfo.departmentId
|
||||
},
|
||||
onSuccess: () => {
|
||||
onboarding.emit('navigate:report')
|
||||
show.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -177,22 +184,11 @@ const onChangeDepartment = (departmentId) => {
|
||||
usersLoaded.value = false
|
||||
fetchUsers(departmentId)
|
||||
}
|
||||
|
||||
const onboarding = useOnboardingStore()
|
||||
const onAfterEnter = async () => {
|
||||
// Если онбординг активен и текущий шаг имеет opensModal, переходим к следующему
|
||||
if (!onboarding.isActive) return
|
||||
|
||||
await nextTick()
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
onboarding.setStep(onboarding.activeStepIndex + 1)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NModal v-model:show="show"
|
||||
id="modal-select-user"
|
||||
preset="card"
|
||||
class="max-w-[420px]"
|
||||
:mask-closable="false"
|
||||
|
||||
@@ -271,10 +271,10 @@ watch(() => props, (newProps) => {
|
||||
{{ reportCreator }}
|
||||
</NTag>
|
||||
</NSpace>
|
||||
<DatePickerQuery :date="dates" :is-head-or-admin="true" class="text-lg!" />
|
||||
<DatePickerQuery id="date-selector" :date="dates" :is-head-or-admin="true" class="text-lg!" />
|
||||
</NFlex>
|
||||
<NDivider dashed class="my-4! mt-3!" />
|
||||
<NRow class="grow space-x-2 h-[82.78px]">
|
||||
<NRow id="statistic-widgets" class="grow space-x-2 h-[82.78px]">
|
||||
<NCol :span="3">
|
||||
<HeaderWidget label="Коек"
|
||||
:counter="stats.duty.beds" />
|
||||
@@ -305,7 +305,7 @@ watch(() => props, (newProps) => {
|
||||
</NRow>
|
||||
</AppPanel>
|
||||
<div class="grid grid-cols-[1fr_auto] gap-x-2">
|
||||
<AppPanel>
|
||||
<AppPanel id="input-widgets">
|
||||
<NFlex align="center" :wrap="false">
|
||||
<NFormItem label="Поступило" :show-feedback="false">
|
||||
<NInputNumber :disabled="!canSaveReport" :min="0" v-model:value="reportForm.recipient" />
|
||||
@@ -335,7 +335,7 @@ watch(() => props, (newProps) => {
|
||||
</NFlex>
|
||||
</div>
|
||||
<AppPanel>
|
||||
<NTabs type="segment">
|
||||
<NTabs id="view-tabs" type="segment">
|
||||
<NTabPane name="mis" tab="МИС" display-directive="show">
|
||||
<DutyPatientsPane :patients="patientCollection" :nurse-patients="nursePatientCollection" @create-observable="addObservablePatient" @remove-observable="removeObservablePatient" />
|
||||
</NTabPane>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import welcomeDuty from "./welcomeDuty"
|
||||
import welcomeNurse from "./welcomeNurse"
|
||||
|
||||
export default {
|
||||
welcomeDuty
|
||||
}
|
||||
welcomeDuty,
|
||||
welcomeNurse,
|
||||
}
|
||||
|
||||
@@ -3,83 +3,78 @@ export default {
|
||||
name: 'Знакомство с Метрикой',
|
||||
steps: [
|
||||
{
|
||||
id: 'wellcome',
|
||||
target: '#user-panel',
|
||||
route: 'start', // главная страница
|
||||
id: 'step-0',
|
||||
target: '#launcher',
|
||||
route: 'start',
|
||||
title: '👋 Добро пожаловать!',
|
||||
description: 'Это ваша панель управления. Сейчас мы покажем вам основные возможности.',
|
||||
popper: { placement: 'bottom-start' }, // опционально: позиция тултипа
|
||||
on: {
|
||||
afterStep: () => {
|
||||
const modalStore = useModalStore()
|
||||
modalStore.showSelectDutyUserModal = false
|
||||
},
|
||||
beforeStep: () => {
|
||||
const modalStore = useModalStore()
|
||||
modalStore.showSelectDutyUserModal = false
|
||||
},
|
||||
}
|
||||
description: 'Это ваша рабочая область. Сейчас мы покажем вам основные возможности.',
|
||||
highlight: true,
|
||||
scroll: false,
|
||||
allowInteraction: false,
|
||||
},
|
||||
{
|
||||
attachTo: { element: '#new-report-duty' },
|
||||
route: 'start', // переходим на страницу отчётов
|
||||
content: {
|
||||
title: '✏️ Создать отчёт',
|
||||
description: 'Нажмите эту кнопку, чтобы начать создание нового отчёта.'
|
||||
},
|
||||
on: {
|
||||
afterStep: () => {
|
||||
const modalStore = useModalStore()
|
||||
const onboarding = useOnboardingStore()
|
||||
|
||||
if (onboarding.activeStepIndex === 2) modalStore.showSelectDutyUserModal = true
|
||||
if (onboarding.activeStepIndex < 2) modalStore.showSelectDutyUserModal = false
|
||||
},
|
||||
beforeStep: () => {
|
||||
const modalStore = useModalStore()
|
||||
const onboarding = useOnboardingStore()
|
||||
|
||||
if (onboarding.activeStepIndex < 2) modalStore.showSelectDutyUserModal = false
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
attachTo: { element: '#modal-select-user-department' },
|
||||
id: 'step-1',
|
||||
target: '#new-report-duty',
|
||||
route: 'start',
|
||||
content: { title: 'Выберите отделение', description: 'Можете использовать список, либо ввести ФИО для поиска' },
|
||||
insideModal: true, // флаг, что этот шаг внутри модалки
|
||||
options: {
|
||||
disableInteraction: false
|
||||
}
|
||||
title: '✏️ Создать отчёт',
|
||||
description: 'Нажмите эту кнопку, чтобы начать создание нового отчёта.',
|
||||
manual: true,
|
||||
highlight: true,
|
||||
scroll: false,
|
||||
allowInteraction: true,
|
||||
nextEvent: 'selectUser:opened'
|
||||
},
|
||||
{
|
||||
attachTo: { element: '#modal-select-user-doctor' },
|
||||
id: 'step-2',
|
||||
target: '#modal-select-user',
|
||||
route: 'start',
|
||||
content: { title: 'Введите ответственного', description: 'Можете использовать список, либо ввести ФИО для поиска' },
|
||||
insideModal: true, // флаг, что этот шаг внутри модалки
|
||||
title: 'Выберите отделение и ответственного',
|
||||
description: 'Можете использовать список, либо ввести для поиска',
|
||||
manual: true,
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: true,
|
||||
nextEvent: 'navigate:report'
|
||||
},
|
||||
{
|
||||
attachTo: { element: '#modal-select-user-submit' },
|
||||
route: 'start',
|
||||
content: { title: 'Подтвердите ввод' },
|
||||
insideModal: true, // флаг, что этот шаг внутри модалки
|
||||
manual: true
|
||||
id: 'step-3',
|
||||
target: '#date-selector',
|
||||
route: 'report',
|
||||
title: 'Календарь',
|
||||
description: 'Здесь Вы можете просмотреть предыдущие отчеты, путем выбора даты в календаре.',
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: false,
|
||||
},
|
||||
{
|
||||
attachTo: { element: '#report-name-input' },
|
||||
route: 'report', // страница создания отчёта
|
||||
content: {
|
||||
title: '📝 Название отчёта',
|
||||
description: 'Введите название, чтобы легко находить отчёт позже.'
|
||||
}
|
||||
id: 'step-4',
|
||||
target: '#statistic-widgets',
|
||||
route: 'report',
|
||||
title: 'Основная статистика',
|
||||
description: 'Здесь отображается информация из МИС и журнала пациентов',
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: false,
|
||||
},
|
||||
{
|
||||
attachTo: { element: '#save-report-btn' },
|
||||
route: 'reports.create',
|
||||
content: {
|
||||
title: '💾 Сохранить',
|
||||
description: 'После заполнения всех полей нажмите "Сохранить", чтобы завершить.'
|
||||
}
|
||||
}
|
||||
id: 'step-5',
|
||||
target: '#input-widgets',
|
||||
route: 'report',
|
||||
title: 'Поля ввода',
|
||||
description: 'Поля заполняются данными из МИС автоматически. Но вы можете их изменить.',
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: false,
|
||||
},
|
||||
{
|
||||
id: 'step-6',
|
||||
target: '#view-tabs',
|
||||
route: 'report',
|
||||
title: 'Представления',
|
||||
description: 'Вы можете переключать представления. Вам доступны МИС и Журнал пациентов (заполняет старшая медицинская сестра отделения)',
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
94
resources/js/Tours/welcomeNurse.js
Normal file
94
resources/js/Tours/welcomeNurse.js
Normal file
@@ -0,0 +1,94 @@
|
||||
export default {
|
||||
id: 'welcome-nurse',
|
||||
name: 'Знакомство с Метрикой',
|
||||
steps: [
|
||||
{
|
||||
id: 'step-0',
|
||||
target: '#launcher',
|
||||
route: 'start',
|
||||
title: '👋 Добро пожаловать!',
|
||||
description: 'Это ваша рабочая область. Сейчас мы покажем вам основные возможности.',
|
||||
highlight: true,
|
||||
scroll: false,
|
||||
allowInteraction: false,
|
||||
},
|
||||
{
|
||||
id: 'step-1',
|
||||
target: '#new-report-nurse',
|
||||
route: 'start',
|
||||
title: '✏️ Создать отчёт',
|
||||
description: 'Нажмите эту кнопку, чтобы начать создание нового отчёта.',
|
||||
manual: true,
|
||||
highlight: true,
|
||||
scroll: false,
|
||||
allowInteraction: true,
|
||||
nextEvent: 'selectUser:opened'
|
||||
},
|
||||
{
|
||||
id: 'step-2',
|
||||
target: '#modal-select-user',
|
||||
route: 'start',
|
||||
title: 'Выберите отделение и ответственного',
|
||||
description: 'Можете использовать список, либо ввести для поиска',
|
||||
manual: true,
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: true,
|
||||
nextEvent: 'navigate:report'
|
||||
},
|
||||
{
|
||||
id: 'step-3',
|
||||
target: '#date-selector',
|
||||
route: 'nurse.report',
|
||||
title: 'Календарь',
|
||||
description: 'Здесь Вы можете просмотреть предыдущие отчеты, путем выбора даты в календаре.',
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: false,
|
||||
},
|
||||
{
|
||||
id: 'step-4',
|
||||
target: '#view-tabs',
|
||||
route: 'nurse.report',
|
||||
title: 'Представления',
|
||||
description: 'Вы можете переключать представления. Для удобства пациенты разделены на категории.',
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: false,
|
||||
},
|
||||
{
|
||||
id: 'step-5',
|
||||
target: '#add-new-patient',
|
||||
route: 'nurse.report',
|
||||
title: 'Добавление пациента',
|
||||
description: 'Нажмите эту кнопку, чтобы добавить пациента.',
|
||||
manual: true,
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: true,
|
||||
nextEvent: 'createNewPatientModal:opened'
|
||||
},
|
||||
{
|
||||
id: 'step-6',
|
||||
target: '#create-new-patient-modal',
|
||||
route: 'nurse.report',
|
||||
title: 'Форма создания',
|
||||
description: 'Для начала вам нужно выбрать тип пациента. Если пациент есть в МИС, то выберите МИС. Иначе Спец. контингент',
|
||||
manual: true,
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: true,
|
||||
nextEvent: 'newPatientModal:patientTypeSelected'
|
||||
},
|
||||
{
|
||||
id: 'step-7',
|
||||
target: '#create-new-patient-modal',
|
||||
route: 'nurse.report',
|
||||
title: 'Форма создания',
|
||||
description: 'Заполните все необходимые поля, и нажмите кнопку Добавить',
|
||||
highlight: true,
|
||||
scroll: true,
|
||||
allowInteraction: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user