exxtract CreateSectionManager component
Main daploy / deploy (push) Successful in 48s

This commit is contained in:
2024-11-20 11:26:28 +02:00
parent fc66b779ae
commit a149b9d261
4 changed files with 147 additions and 91 deletions
+1
View File
@@ -22,6 +22,7 @@ declare module 'vue' {
CreatePredefinedMessagesSection: typeof import('./src/components/create/CreatePredefinedMessagesSection.vue')['default']
CreateReadySection: typeof import('./src/components/create/CreateReadySection.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']
DownloadImageButton: typeof import('./src/components/manage/DownloadImageButton.vue')['default']
DownloadPng: typeof import('./src/components/manage/DownloadImageButton.vue')['default']
+2 -1
View File
@@ -13,13 +13,14 @@ const sectionRef = useTemplateRef('section')
// плавная прокрутка при активации секции
watch(
() => props.isNextActiveSection,
() => sectionRef.value && props.isNextActiveSection,
(isNextActiveSection) => {
if (isNextActiveSection) {
sectionRef.value?.querySelector('input[type="text"]')?.focus()
sectionRef.value?.scrollIntoView({ behavior: 'smooth' })
}
},
{ immediate: true },
)
</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
View File
@@ -1,69 +1,42 @@
<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
:isActive="activeSteps.includes('placement')"
:isNextActiveSection="nextActiveSection === 'placement'"
>
<CreatePlacementSection v-model="placement" />
</CreateSection>
<CreateSectionManager
:placement="placement"
:selectedActions="selectedActions"
:messageDeliveryMethod="messageDeliveryMethod"
>
<template #placement>
<CreatePlacementSection v-model="placement" />
</template>
<!-- Секция выбора доступных действий -->
<CreateSection
:isActive="activeSteps.includes('actions')"
:isNextActiveSection="nextActiveSection === 'actions'"
>
<CreateActionsSection v-model="selectedActions" />
</CreateSection>
<template #actions>
<CreateActionsSection v-model="selectedActions" />
</template>
<!-- Секция выбора способа доставки -->
<CreateSection
v-if="activeSteps.includes('delivery')"
:isActive="true"
:isNextActiveSection="nextActiveSection === 'delivery'"
>
<CreateMessageDeliveryMethodSection v-model="messageDeliveryMethod" />
</CreateSection>
<template #delivery>
<CreateMessageDeliveryMethodSection v-model="messageDeliveryMethod" />
</template>
<!-- Секция сообщений для отправки -->
<CreateSection
v-if="selectedActions.includes('sendMessage')"
:isActive="activeSteps.includes('messages')"
:isNextActiveSection="nextActiveSection === 'messages'"
>
<CreatePredefinedMessagesSection :placement="placement" v-model="messages" />
</CreateSection>
<template #messages>
<CreatePredefinedMessagesSection :placement="placement" v-model="messages" />
</template>
<!-- Секция итогового резюме -->
<CreateSection
:isActive="activeSteps.includes('summary')"
:isNextActiveSection="nextActiveSection === 'summary'"
>
<CreateSummarySection
v-model:name="name"
buttonLabel="Создать QR‑код"
@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 #summary>
<CreateSummarySection
v-model:name="name"
buttonLabel="Создать QR‑код"
@nextStep="createQrCode"
/>
</template>
</CreateSectionManager>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { createQrCodeDocument } from '@/api/qrCode'
import type { QRCodeDocument } from '@/types/DBDocumentTypes'
import { ROUTE_NAMES } from '@/constants/routes'
// Состояния шагов
const placement = ref<null | QRCodeDocument['placement']>(null)
const selectedActions = ref<QRCodeDocument['actions']>([])
const messageDeliveryMethod = ref<null | QRCodeDocument['messageDeliveryMethod']>(null)
@@ -73,7 +46,6 @@ const error = ref<string | null>(null)
const router = useRouter()
// Логика создания QR-кода
async function createQrCode() {
try {
const qrCodeDocument = await createQrCodeDocument({
@@ -93,40 +65,4 @@ async function createQrCode() {
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>