This commit is contained in:
Vendored
+1
@@ -22,6 +22,7 @@ declare module 'vue' {
|
|||||||
CreatePredefinedMessagesSection: typeof import('./src/components/create/CreatePredefinedMessagesSection.vue')['default']
|
CreatePredefinedMessagesSection: typeof import('./src/components/create/CreatePredefinedMessagesSection.vue')['default']
|
||||||
CreateReadySection: typeof import('./src/components/create/CreateReadySection.vue')['default']
|
CreateReadySection: typeof import('./src/components/create/CreateReadySection.vue')['default']
|
||||||
CreateSection: typeof import('./src/components/create/CreateSection.vue')['default']
|
CreateSection: typeof import('./src/components/create/CreateSection.vue')['default']
|
||||||
|
CreateSectionManager: typeof import('./src/components/create/CreateSectionManager.vue')['default']
|
||||||
CreateSummarySection: typeof import('./src/components/create/CreateSummarySection.vue')['default']
|
CreateSummarySection: typeof import('./src/components/create/CreateSummarySection.vue')['default']
|
||||||
DownloadImageButton: typeof import('./src/components/manage/DownloadImageButton.vue')['default']
|
DownloadImageButton: typeof import('./src/components/manage/DownloadImageButton.vue')['default']
|
||||||
DownloadPng: typeof import('./src/components/manage/DownloadImageButton.vue')['default']
|
DownloadPng: typeof import('./src/components/manage/DownloadImageButton.vue')['default']
|
||||||
|
|||||||
@@ -13,13 +13,14 @@ const sectionRef = useTemplateRef('section')
|
|||||||
|
|
||||||
// плавная прокрутка при активации секции
|
// плавная прокрутка при активации секции
|
||||||
watch(
|
watch(
|
||||||
() => props.isNextActiveSection,
|
() => sectionRef.value && props.isNextActiveSection,
|
||||||
(isNextActiveSection) => {
|
(isNextActiveSection) => {
|
||||||
if (isNextActiveSection) {
|
if (isNextActiveSection) {
|
||||||
sectionRef.value?.querySelector('input[type="text"]')?.focus()
|
sectionRef.value?.querySelector('input[type="text"]')?.focus()
|
||||||
sectionRef.value?.scrollIntoView({ behavior: 'smooth' })
|
sectionRef.value?.scrollIntoView({ behavior: 'smooth' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<div class="max-w-prose mx-auto py-6 px-4 md:px-6">
|
||||||
|
<section class="content">
|
||||||
|
<div class="max-w-prose mx-auto py-8">
|
||||||
|
<!-- Вывод секций через цикл -->
|
||||||
|
<CreateSection
|
||||||
|
v-for="{ name, isActive, isNextActiveSection } in visibleSections"
|
||||||
|
:key="name"
|
||||||
|
:isActive
|
||||||
|
:isNextActiveSection
|
||||||
|
>
|
||||||
|
<slot :name="name" />
|
||||||
|
</CreateSection>
|
||||||
|
|
||||||
|
<p v-if="error" class="text-red-500 mt-4">Ошибка создания QR‑кода: {{ error }}</p>
|
||||||
|
|
||||||
|
<div class="h-[30dvh] md:h-[10dvh] overflow-hidden"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from 'vue'
|
||||||
|
import type { QRCodeDocument } from '@/types/DBDocumentTypes'
|
||||||
|
|
||||||
|
// Пропсы, которые будут передаваться из родительского компонента
|
||||||
|
const props = defineProps<{
|
||||||
|
placement: null | QRCodeDocument['placement']
|
||||||
|
selectedActions: QRCodeDocument['actions']
|
||||||
|
messageDeliveryMethod: null | QRCodeDocument['messageDeliveryMethod']
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// Локальные состояния
|
||||||
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
|
// Доступные шаги и их условия
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
name: 'placement',
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actions',
|
||||||
|
get isActive() {
|
||||||
|
return !!props.placement
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'delivery',
|
||||||
|
get isHidden() {
|
||||||
|
return !props.placement || !props.selectedActions.includes('sendMessage')
|
||||||
|
},
|
||||||
|
get isActive() {
|
||||||
|
return props.selectedActions.length > 0 && props.selectedActions.includes('sendMessage')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'messages',
|
||||||
|
get isHidden() {
|
||||||
|
return (
|
||||||
|
!props.placement ||
|
||||||
|
!props.selectedActions.includes('sendMessage') ||
|
||||||
|
props.messageDeliveryMethod === 'telegram'
|
||||||
|
)
|
||||||
|
},
|
||||||
|
get isActive() {
|
||||||
|
return props.messageDeliveryMethod && props.selectedActions.includes('sendMessage')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'summary',
|
||||||
|
get isActive() {
|
||||||
|
return props.selectedActions.includes('sendMessage')
|
||||||
|
? !!props.messageDeliveryMethod && props.messageDeliveryMethod !== 'telegram'
|
||||||
|
: props.selectedActions.length > 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const activeSections = computed(() => {
|
||||||
|
const result = []
|
||||||
|
for (const step of steps) {
|
||||||
|
const isActive = !step.isHidden && step.isActive
|
||||||
|
if (isActive) {
|
||||||
|
result.push(step.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
|
const nextActiveSectionName = ref<string>('')
|
||||||
|
|
||||||
|
watch(
|
||||||
|
activeSections,
|
||||||
|
(newActiveSections, oldActiveSteps) => {
|
||||||
|
nextActiveSectionName.value =
|
||||||
|
(oldActiveSteps && newActiveSections[oldActiveSteps.length]) ?? newActiveSections.at(-1)!
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Выводимые секции
|
||||||
|
const visibleSections = computed(() => {
|
||||||
|
const result = []
|
||||||
|
for (const step of steps) {
|
||||||
|
if (step.isHidden) continue
|
||||||
|
result.push({
|
||||||
|
name: step.name,
|
||||||
|
isActive: activeSections.value.includes(step.name),
|
||||||
|
isNextActiveSection: nextActiveSectionName.value === step.name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
</script>
|
||||||
+26
-90
@@ -1,69 +1,42 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="max-w-prose mx-auto py-6 px-4 md:px-6">
|
<CreateSectionManager
|
||||||
<section class="content">
|
:placement="placement"
|
||||||
<div class="max-w-prose mx-auto py-8">
|
:selectedActions="selectedActions"
|
||||||
<!-- Секция выбора размещения -->
|
:messageDeliveryMethod="messageDeliveryMethod"
|
||||||
<CreateSection
|
>
|
||||||
:isActive="activeSteps.includes('placement')"
|
<template #placement>
|
||||||
:isNextActiveSection="nextActiveSection === 'placement'"
|
<CreatePlacementSection v-model="placement" />
|
||||||
>
|
</template>
|
||||||
<CreatePlacementSection v-model="placement" />
|
|
||||||
</CreateSection>
|
|
||||||
|
|
||||||
<!-- Секция выбора доступных действий -->
|
<template #actions>
|
||||||
<CreateSection
|
<CreateActionsSection v-model="selectedActions" />
|
||||||
:isActive="activeSteps.includes('actions')"
|
</template>
|
||||||
:isNextActiveSection="nextActiveSection === 'actions'"
|
|
||||||
>
|
|
||||||
<CreateActionsSection v-model="selectedActions" />
|
|
||||||
</CreateSection>
|
|
||||||
|
|
||||||
<!-- Секция выбора способа доставки -->
|
<template #delivery>
|
||||||
<CreateSection
|
<CreateMessageDeliveryMethodSection v-model="messageDeliveryMethod" />
|
||||||
v-if="activeSteps.includes('delivery')"
|
</template>
|
||||||
:isActive="true"
|
|
||||||
:isNextActiveSection="nextActiveSection === 'delivery'"
|
|
||||||
>
|
|
||||||
<CreateMessageDeliveryMethodSection v-model="messageDeliveryMethod" />
|
|
||||||
</CreateSection>
|
|
||||||
|
|
||||||
<!-- Секция сообщений для отправки -->
|
<template #messages>
|
||||||
<CreateSection
|
<CreatePredefinedMessagesSection :placement="placement" v-model="messages" />
|
||||||
v-if="selectedActions.includes('sendMessage')"
|
</template>
|
||||||
:isActive="activeSteps.includes('messages')"
|
|
||||||
:isNextActiveSection="nextActiveSection === 'messages'"
|
|
||||||
>
|
|
||||||
<CreatePredefinedMessagesSection :placement="placement" v-model="messages" />
|
|
||||||
</CreateSection>
|
|
||||||
|
|
||||||
<!-- Секция итогового резюме -->
|
<template #summary>
|
||||||
<CreateSection
|
<CreateSummarySection
|
||||||
:isActive="activeSteps.includes('summary')"
|
v-model:name="name"
|
||||||
:isNextActiveSection="nextActiveSection === 'summary'"
|
buttonLabel="Создать QR‑код"
|
||||||
>
|
@nextStep="createQrCode"
|
||||||
<CreateSummarySection
|
/>
|
||||||
v-model:name="name"
|
</template>
|
||||||
buttonLabel="Создать QR‑код"
|
</CreateSectionManager>
|
||||||
@nextStep="createQrCode"
|
|
||||||
/>
|
|
||||||
</CreateSection>
|
|
||||||
|
|
||||||
<p v-if="error" class="text-red-500 mt-4">Ошибка создания QR‑кода: {{ error }}</p>
|
|
||||||
|
|
||||||
<div class="h-[30dvh] md:h-[10dvh] overflow-hidden"></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { createQrCodeDocument } from '@/api/qrCode'
|
import { createQrCodeDocument } from '@/api/qrCode'
|
||||||
import type { QRCodeDocument } from '@/types/DBDocumentTypes'
|
import type { QRCodeDocument } from '@/types/DBDocumentTypes'
|
||||||
import { ROUTE_NAMES } from '@/constants/routes'
|
import { ROUTE_NAMES } from '@/constants/routes'
|
||||||
|
|
||||||
// Состояния шагов
|
|
||||||
const placement = ref<null | QRCodeDocument['placement']>(null)
|
const placement = ref<null | QRCodeDocument['placement']>(null)
|
||||||
const selectedActions = ref<QRCodeDocument['actions']>([])
|
const selectedActions = ref<QRCodeDocument['actions']>([])
|
||||||
const messageDeliveryMethod = ref<null | QRCodeDocument['messageDeliveryMethod']>(null)
|
const messageDeliveryMethod = ref<null | QRCodeDocument['messageDeliveryMethod']>(null)
|
||||||
@@ -73,7 +46,6 @@ const error = ref<string | null>(null)
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// Логика создания QR-кода
|
|
||||||
async function createQrCode() {
|
async function createQrCode() {
|
||||||
try {
|
try {
|
||||||
const qrCodeDocument = await createQrCodeDocument({
|
const qrCodeDocument = await createQrCodeDocument({
|
||||||
@@ -93,40 +65,4 @@ async function createQrCode() {
|
|||||||
error.value = (err as Error).message || 'Неизвестная ошибка'
|
error.value = (err as Error).message || 'Неизвестная ошибка'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция для определения доступных шагов
|
|
||||||
const activeSteps = computed(() => {
|
|
||||||
const steps = ['placement', 'actions', 'delivery', 'messages', 'summary'] as const
|
|
||||||
const isStepValid = {
|
|
||||||
placement: !!placement.value,
|
|
||||||
actions: !!placement.value,
|
|
||||||
delivery:
|
|
||||||
!!placement.value &&
|
|
||||||
selectedActions.value.length > 0 &&
|
|
||||||
selectedActions.value.includes('sendMessage'),
|
|
||||||
messages:
|
|
||||||
!!messageDeliveryMethod.value && messageDeliveryMethod.value === 'webPushSubscription',
|
|
||||||
summary:
|
|
||||||
!!placement.value &&
|
|
||||||
selectedActions.value.length > 0 &&
|
|
||||||
(selectedActions.value.includes('sendMessage')
|
|
||||||
? messageDeliveryMethod.value === 'webPushSubscription'
|
|
||||||
: !!selectedActions.value.length),
|
|
||||||
}
|
|
||||||
|
|
||||||
const active = []
|
|
||||||
for (const step of steps) {
|
|
||||||
if (active.length === 0 || isStepValid[step]) {
|
|
||||||
active.push(step)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return active
|
|
||||||
})
|
|
||||||
|
|
||||||
const nextActiveSection = ref<string>('placement')
|
|
||||||
|
|
||||||
watch(activeSteps, (newActiveSteps, oldActiveSteps) => {
|
|
||||||
nextActiveSection.value =
|
|
||||||
(oldActiveSteps && newActiveSteps[oldActiveSteps.length]) ?? newActiveSteps.at(-1)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user