This commit is contained in:
@@ -2,16 +2,26 @@
|
||||
<div class="student-register">
|
||||
<div class="student-register__container">
|
||||
<aside class="student-register__sidebar">
|
||||
<SideBarSteps :tabs="tabs" :active-tab="activeTab" @update:active-tab="goToStep" />
|
||||
<SideBarSteps :tabs="tabs" :active-step="store.currentStep" @select-step="goToStep" />
|
||||
</aside>
|
||||
|
||||
<main class="student-register__main">
|
||||
<header class="student-register__heading">
|
||||
<div class="student-register__step-meta">
|
||||
<span>مرحله {{ currentStepNumber }} از {{ totalSteps }}</span>
|
||||
<span>{{ progressPercent }}٪</span>
|
||||
</div>
|
||||
<div class="student-register__progress" aria-hidden="true">
|
||||
<span :style="{ width: `${progressPercent}%` }" />
|
||||
</div>
|
||||
<h1 class="student-register__title">{{ stepLabel.title }}</h1>
|
||||
<p class="student-register__desc">{{ stepLabel.desc }}</p>
|
||||
</header>
|
||||
|
||||
<component :is="currentComponent" />
|
||||
<div v-if="isRegistrationDataPending" class="student-register__loading" aria-live="polite">
|
||||
در حال بازیابی اطلاعات ثبتنام…
|
||||
</div>
|
||||
<component :is="currentComponent" v-else />
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -23,10 +33,10 @@
|
||||
import useModal from '@/composables/useModal'
|
||||
import { computed, markRaw, watch } from 'vue'
|
||||
import { STUDENT_REGISTRATION } from '@/enums'
|
||||
import { useGetRegisterDataQuery } from '@/services/query/auth'
|
||||
import SideBarSteps from '@/features/auth/components/studentRegister/SideBarSteps.vue'
|
||||
import SuccessModal from '@/features/auth/components/studentRegister/SuccessModal.vue'
|
||||
import { useStudentRegistrationStore } from '@/features/auth/store/student-registration'
|
||||
import { useGetRegisterDataQuery, useGetRegistrationVideoQuery } from '@/services/query/auth'
|
||||
import PersonalInformation from '@/features/auth/components/studentRegister/PersonalInformation.vue'
|
||||
import SkillAssessmentPart1 from '@/features/auth/components/studentRegister/SkillAssessmentPart1.vue'
|
||||
import SkillAssessmentPart2 from '@/features/auth/components/studentRegister/SkillAssessmentPart2.vue'
|
||||
@@ -41,15 +51,21 @@ import ProfessionalInformation from '@/features/auth/components/studentRegister/
|
||||
const store = useStudentRegistrationStore()
|
||||
const { isModal, openModal } = useModal()
|
||||
|
||||
const { data: registerData } = useGetRegisterDataQuery()
|
||||
const { data: registerData, isPending: isRegistrationDataPending } = useGetRegisterDataQuery()
|
||||
watch(
|
||||
registerData,
|
||||
(value) => {
|
||||
if (value && Object.keys(value).length > 0) store.hydrateFromRegisterData(value)
|
||||
},
|
||||
{ immediate: true }
|
||||
{ immediate: true, flush: 'sync' }
|
||||
)
|
||||
|
||||
const { data: registrationMedia } = useGetRegistrationVideoQuery({ retry: false })
|
||||
watch(registrationMedia, (value) => store.setRegistrationMedia(value), {
|
||||
immediate: true,
|
||||
flush: 'sync',
|
||||
})
|
||||
|
||||
const STEP_TO_COMPONENT = {
|
||||
[STUDENT_REGISTRATION.PERSONAL_INFORMATION]: markRaw(PersonalInformation),
|
||||
[STUDENT_REGISTRATION.EDUCATIONAL_INFORMATION]: markRaw(EducationalInformation),
|
||||
@@ -63,26 +79,6 @@ const STEP_TO_COMPONENT = {
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_7]: markRaw(SkillAssessmentPart7),
|
||||
}
|
||||
|
||||
const STEP_TO_TAB = {
|
||||
[STUDENT_REGISTRATION.PERSONAL_INFORMATION]: 'personal',
|
||||
[STUDENT_REGISTRATION.EDUCATIONAL_INFORMATION]: 'educational',
|
||||
[STUDENT_REGISTRATION.PROFESSIONAL_INFORMATION]: 'professional',
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_1]: 'skill',
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_2]: 'skill',
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_3]: 'skill',
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_4]: 'skill',
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_5]: 'skill',
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_6]: 'skill',
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_7]: 'skill',
|
||||
}
|
||||
|
||||
const TAB_TO_STEP = {
|
||||
personal: STUDENT_REGISTRATION.PERSONAL_INFORMATION,
|
||||
educational: STUDENT_REGISTRATION.EDUCATIONAL_INFORMATION,
|
||||
professional: STUDENT_REGISTRATION.PROFESSIONAL_INFORMATION,
|
||||
skill: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_1,
|
||||
}
|
||||
|
||||
const STEP_LABELS = {
|
||||
[STUDENT_REGISTRATION.PERSONAL_INFORMATION]: {
|
||||
title: 'اطلاعـــــات شخصـــــی',
|
||||
@@ -126,14 +122,33 @@ const STEP_LABELS = {
|
||||
},
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
{ key: 'personal', icon: 'user' },
|
||||
{ key: 'educational', icon: 'book' },
|
||||
{ key: 'professional', icon: 'file' },
|
||||
{ key: 'skill', icon: 'check-square' },
|
||||
const STEP_NAVIGATION = [
|
||||
{ step: STUDENT_REGISTRATION.PERSONAL_INFORMATION, title: 'مشخصات فردی', icon: 'user' },
|
||||
{ step: STUDENT_REGISTRATION.EDUCATIONAL_INFORMATION, title: 'اطلاعات تحصیلی', icon: 'book' },
|
||||
{ step: STUDENT_REGISTRATION.PROFESSIONAL_INFORMATION, title: 'فعالیتهای تبلیغی', icon: 'file' },
|
||||
{ step: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_1, title: 'مهارت ۱', icon: 'check-square' },
|
||||
{ step: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_2, title: 'مهارت ۲', icon: 'check-square' },
|
||||
{ step: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_3, title: 'مهارت ۳', icon: 'check-square' },
|
||||
{ step: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_4, title: 'مهارت ۴', icon: 'check-square' },
|
||||
{ step: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_5, title: 'مهارت ۵', icon: 'check-square' },
|
||||
{ step: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_6, title: 'مهارت ۶', icon: 'check-square' },
|
||||
{ step: STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_7, title: 'مهارت ۷', icon: 'check-square' },
|
||||
]
|
||||
|
||||
const activeTab = computed(() => STEP_TO_TAB[store.currentStep] || 'personal')
|
||||
const tabs = computed(() =>
|
||||
STEP_NAVIGATION.map((tab) => ({
|
||||
...tab,
|
||||
completed: store.completedSteps.includes(tab.step),
|
||||
disabled: !store.canGoToStep(tab.step),
|
||||
}))
|
||||
)
|
||||
|
||||
const totalSteps = STEP_NAVIGATION.length
|
||||
const currentStepNumber = computed(() => {
|
||||
const index = STEP_NAVIGATION.findIndex((item) => item.step === store.currentStep)
|
||||
return index >= 0 ? index + 1 : 1
|
||||
})
|
||||
const progressPercent = computed(() => Math.round((currentStepNumber.value / totalSteps) * 100))
|
||||
|
||||
const currentComponent = computed(
|
||||
() =>
|
||||
@@ -145,12 +160,8 @@ const stepLabel = computed(
|
||||
() => STEP_LABELS[store.currentStep] || STEP_LABELS[STUDENT_REGISTRATION.PERSONAL_INFORMATION]
|
||||
)
|
||||
|
||||
const goToStep = (tabKey) => {
|
||||
const targetStep = TAB_TO_STEP[tabKey]
|
||||
if (!targetStep) return
|
||||
if (store.canGoToStep(targetStep)) {
|
||||
store.updateCurrentStep(targetStep)
|
||||
}
|
||||
const goToStep = (step) => {
|
||||
store.updateCurrentStep(step)
|
||||
}
|
||||
|
||||
watch(
|
||||
@@ -188,9 +199,8 @@ watch(
|
||||
width: 100%;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
width: 8.333%;
|
||||
min-width: 5rem;
|
||||
max-width: 6.5rem;
|
||||
width: 13.5rem;
|
||||
min-width: 13.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,23 +216,97 @@ watch(
|
||||
}
|
||||
|
||||
&__heading {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
&__step-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.375rem;
|
||||
color: #6f6f6f;
|
||||
font-family: var(--font-family-number-fa);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&__progress {
|
||||
width: 100%;
|
||||
height: 0.35rem;
|
||||
margin-bottom: 1rem;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
background: #f2f2f2;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: var(--color-primary);
|
||||
transition: width 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-family: var(--font-family-fa);
|
||||
font-weight: 500;
|
||||
font-size: 1.125rem;
|
||||
color: #4c4c4c;
|
||||
margin: 0 0 0.25rem;
|
||||
font-weight: 600;
|
||||
font-size: 1.375rem;
|
||||
color: #3f3f3f;
|
||||
margin: 0 0 0.375rem;
|
||||
}
|
||||
|
||||
&__desc {
|
||||
font-family: var(--font-family-fa);
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
color: #adadad;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.8;
|
||||
color: #747474;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__loading {
|
||||
padding: 3rem 1rem;
|
||||
color: #747474;
|
||||
font-family: var(--font-family-fa);
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__main :deep(.text-field__label),
|
||||
&__main :deep(.textarea-field__label),
|
||||
&__main :deep(.select-field__label),
|
||||
&__main :deep(.datepicker-field__label) {
|
||||
color: #626262;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&__main :deep(.text-field__input),
|
||||
&__main :deep(.textarea-field__input),
|
||||
&__main :deep(.select-field__trigger),
|
||||
&__main :deep(.datepicker-field__trigger) {
|
||||
min-height: 2.6rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&__main :deep(.line-title__fa) {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__main :deep(.line-title__en) {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&__main :deep(.text-field__error),
|
||||
&__main :deep(.textarea-field__error),
|
||||
&__main :deep(.select-field__error),
|
||||
&__main :deep(.datepicker-field__error) {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user