Compare commits
3 Commits
c69a1babe5
...
bc9ce01d3f
| Author | SHA1 | Date | |
|---|---|---|---|
| bc9ce01d3f | |||
| 38051db180 | |||
| 36b747d267 |
+1
-1
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Banu</title>
|
||||
<title>مدرسه بانو</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 106.25%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@font-face {
|
||||
font-family: montserrat;
|
||||
src: url('../fonts/montserrat/Montserrat-ExtraLight.ttf') format('truetype');
|
||||
src: url('../fonts/montserrat/Montserrat-Regular.ttf') format('truetype');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
@font-face {
|
||||
font-family: aria;
|
||||
src: url('../fonts/aria/AriaWebFaNum-Light.woff2') format('woff2');
|
||||
font-weight: 300;
|
||||
src: url('../fonts/aria/AriaWeb-Normal.woff2') format('woff2');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
@font-face {
|
||||
font-family: aria;
|
||||
src: url('../fonts/aria/AriaWebFaNum-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@@ -33,6 +33,14 @@
|
||||
@font-face {
|
||||
font-family: aria;
|
||||
src: url('../fonts/aria/AriaWebFaNum-Medium.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: aria;
|
||||
src: url('../fonts/aria/AriaWebFaNum-SemiBold.woff2') format('woff2');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
@@ -46,25 +54,17 @@
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: aria;
|
||||
src: url('../fonts/aria/AriaWeb-Normal.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: iran-yekan;
|
||||
src: url('../fonts/iran-yekan/iranyekanwebregularfanum.woff') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: iran-yekan;
|
||||
src: url('../fonts/iran-yekan/iranyekanwebmediumfanum.woff') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: iran-yekan;
|
||||
src: url('../fonts/iran-yekan/iranyekanwebboldfanum.woff') format('woff');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: iran-yekan;
|
||||
src: url('../fonts/iran-yekan/iranyekanweblightfanum.woff') format('woff');
|
||||
src: url('../fonts/iran-yekan/iranyekanwebregularfanum.woff') format('woff');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
|
||||
@@ -15,6 +15,10 @@ export const fields = {
|
||||
lastName: 'نام خانوادگی',
|
||||
nationalCode: 'کد ملی',
|
||||
postalCode: 'کد پستی',
|
||||
virtualPhoneNumber: 'شماره تلفن مجازی',
|
||||
seminaryCode: 'کد حوزوی',
|
||||
seminaryServiceCenterCode: 'کد مرکز خدمات حوزه',
|
||||
childrenCount: 'تعداد فرزند',
|
||||
|
||||
birthDate: 'تاریخ تولد',
|
||||
birthday: 'تاریخ تولد',
|
||||
@@ -76,7 +80,6 @@ export const fields = {
|
||||
seminaryLevel: 'مقطع حوزه',
|
||||
universityLevel: 'مقطع دانشگاهی',
|
||||
universityName: 'نام حوزه علمیه / دانشگاه',
|
||||
workExperienceSummary: 'خلاصهٔ سوابق شغلی',
|
||||
hijabApproach: 'رویکرد حجاب',
|
||||
|
||||
prerequisites: 'پیشنیازها',
|
||||
|
||||
+2
-6
@@ -6,7 +6,7 @@ export const getEnumObject = (enumArray, key = 'value', value = 'label') =>
|
||||
|
||||
export const ROLES = Object.freeze([
|
||||
{ value: 'admin', label: 'مدیر', changeable: false },
|
||||
{ value: 'student', label: 'دانشجو', changeable: true },
|
||||
{ value: 'student', label: 'طلبه', changeable: true },
|
||||
{ value: 'teacher', label: 'استاد', changeable: true },
|
||||
{ value: 'counselor', label: 'مشاور', changeable: true },
|
||||
{ value: 'missionary', label: 'مبلغ', changeable: true },
|
||||
@@ -53,8 +53,6 @@ export const USER_STATUS = Object.freeze({
|
||||
export const MARITAL_STATUS = Object.freeze({
|
||||
single: 'مجرد',
|
||||
married: 'متاهل',
|
||||
divorced: 'مطلقه',
|
||||
widowed: 'بیوه',
|
||||
})
|
||||
|
||||
export const GENDER = Object.freeze({
|
||||
@@ -68,7 +66,6 @@ export const CHANGEABLE_ROLES = Object.freeze(ROLES.filter((r) => r.changeable).
|
||||
|
||||
export const EDUCATION_STATUS = Object.freeze({
|
||||
seminary_student: 'طلبه',
|
||||
seminary_and_university_student: 'طلبه و دانشجو',
|
||||
graduate: 'فارغ التحصیلی',
|
||||
})
|
||||
|
||||
@@ -76,14 +73,13 @@ export const SEMINARY_LEVEL = Object.freeze({
|
||||
level_2: 'سطح دو',
|
||||
level_3: 'سطح سه',
|
||||
level_4: 'سطح چهار',
|
||||
not_applicable: 'طلبه نیستم',
|
||||
})
|
||||
|
||||
export const UNIVERSITY_LEVEL = Object.freeze({
|
||||
bachelor: ' مقطع کارشناسی (لیسانس)',
|
||||
master: ' مقطع کارشناسی ارشد (فوق لیسانس)',
|
||||
phd: ' مقطع دکتری',
|
||||
not_applicable: 'دانشجو نیستم',
|
||||
not_applicable: 'طلبه نیستم',
|
||||
})
|
||||
|
||||
export const PROPAGATION_PLATFORM = Object.freeze({
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@
|
||||
</div>
|
||||
|
||||
<div class="submission-details__row">
|
||||
<LineInfoBlock title="پاسخ دانشجو" :desc="submission.userDescription || '—'" />
|
||||
<LineInfoBlock title="پاسخ طلبه" :desc="submission.userDescription || '—'" />
|
||||
</div>
|
||||
|
||||
<div v-if="submission.attachments?.length" class="submission-details__attachments">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="dashboard">
|
||||
<div class="dashboard__main">
|
||||
<!-- اطلاعات موسسه -->
|
||||
<!-- اطلاعات مدرسه -->
|
||||
<section class="dashboard__section">
|
||||
<BoxedIconTitleBlock title="اطلاعات موسسه" desc="آخرین اطلاعات موسسه شما.">
|
||||
<BoxedIconTitleBlock title="اطلاعات مدرسه" desc="آخرین اطلاعات مدرسه شما.">
|
||||
<template #icon>
|
||||
<SvgIcon name="heart" :size="24" color="var(--color-primary)" />
|
||||
</template>
|
||||
|
||||
@@ -7,7 +7,7 @@ export default [
|
||||
layout: 'admin',
|
||||
role: 'admin',
|
||||
title: 'سلام بر شما',
|
||||
subtitle: 'به سامانه موسسه بانو خوش آمدید.',
|
||||
subtitle: 'به سامانه مدرسه بانو خوش آمدید.',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
title="افزودن دانشجو"
|
||||
title-en="Add Student"
|
||||
title="افزودن طلبه"
|
||||
title-en="Add Seminarian"
|
||||
width="95%"
|
||||
max-width="42rem"
|
||||
min-width="auto"
|
||||
@@ -15,7 +15,7 @@
|
||||
v-model="searchInput"
|
||||
type="text"
|
||||
class="add-term-student__search-input"
|
||||
placeholder="اسم دانشجو را وارد نمایید"
|
||||
placeholder="اسم طلبه را وارد نمایید"
|
||||
@input="onSearchInput"
|
||||
/>
|
||||
</div>
|
||||
@@ -56,7 +56,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NoItems v-else title="بدون نتیجه" desc="دانشجویی یافت نشد." />
|
||||
<NoItems v-else title="بدون نتیجه" desc="طلبهای یافت نشد." />
|
||||
|
||||
<div class="add-term-student__divider" />
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
title="تاریخ پایان"
|
||||
:numeric-desc="formatJalaaliDate(term.endsAt) || '-'"
|
||||
/>
|
||||
<LineInfoBlock title="تعداد دانشجویان" :numeric-desc="term.studentsCount ?? 0" />
|
||||
<LineInfoBlock title="تعداد طلبهها" :numeric-desc="term.studentsCount ?? 0" />
|
||||
<LineInfoBlock title="تعداد دورهها" :numeric-desc="term.coursesCount ?? 0" />
|
||||
<LineInfoBlock title="وضعیت" :desc="term.isActive ? 'فعال' : 'غیرفعال'" />
|
||||
<div v-if="term.description" class="term-details__cell--full">
|
||||
@@ -41,9 +41,9 @@
|
||||
<TabsBlock :tabs="tabs" v-model="activeTab">
|
||||
<template #students>
|
||||
<div class="term-details__panel-header">
|
||||
<LineTitleBlock title="لیست دانشجویان این ترم" title-en="Students List" />
|
||||
<LineTitleBlock title="لیست طلبههای این ترم" title-en="Seminarians List" />
|
||||
<BaseButton
|
||||
text="افزودن دانشجو"
|
||||
text="افزودن طلبه"
|
||||
custom-class="term-details__panel-btn"
|
||||
@click="onOpenAddStudent"
|
||||
>
|
||||
@@ -76,7 +76,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NoItems v-else title="متاسفیم" desc="دانشجویی برای نمایش وجود ندارد." />
|
||||
<NoItems v-else title="متاسفیم" desc="طلبهای برای نمایش وجود ندارد." />
|
||||
|
||||
<PaginationBlock :pagination="studentPaginationMeta" @update:page="setStudentPage" />
|
||||
</template>
|
||||
@@ -161,7 +161,7 @@ const { data: term } = useAdminTermQuery(termId, {
|
||||
|
||||
const tabs = [
|
||||
{ name: 'courses', label: 'دورهها', icon: 'list-bullets' },
|
||||
{ name: 'students', label: 'دانشجویان', icon: 'users' },
|
||||
{ name: 'students', label: 'طلبهها', icon: 'users' },
|
||||
]
|
||||
const activeTab = ref('courses')
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@ export const termSchema = object().shape({
|
||||
})
|
||||
|
||||
export const addTermStudentSchema = object().shape({
|
||||
studentIds: array().of(mixed()).min(1, 'حداقل یک دانشجو را انتخاب کنید').required(),
|
||||
studentIds: array().of(mixed()).min(1, 'حداقل یک طلبه را انتخاب کنید').required(),
|
||||
})
|
||||
|
||||
-6
@@ -59,12 +59,6 @@
|
||||
<section class="user-verification-details__section">
|
||||
<LineTitleBlock title="اطلاعات شغلی" title-en="Job information" />
|
||||
<div class="user-verification-details__grid user-verification-details__grid--4">
|
||||
<div class="user-verification-details__cell user-verification-details__cell--full">
|
||||
<LineInfoBlock
|
||||
title="خلاصهای از سوابق شغلی"
|
||||
:desc="profile.workExperienceSummary || ''"
|
||||
/>
|
||||
</div>
|
||||
<div class="user-verification-details__cell user-verification-details__cell--full">
|
||||
<LineInfoBlock
|
||||
title="خلاصهای از فعالیتها در موقعیتهای شغلی"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="auth-heading">
|
||||
<img :src="logo" alt="banu" class="auth-heading__logo" />
|
||||
<img :src="logo" alt="مدرسه بانو" class="auth-heading__logo" />
|
||||
<h2 class="auth-heading__title">{{ title }}</h2>
|
||||
<p v-if="step === 'otp'" class="auth-heading__subtitle">
|
||||
<span class="auth-heading__phone-label">ارسال کد فعالسازی به شماره</span>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="pattern-section">
|
||||
<div class="pattern-section__bg" :style="{ backgroundImage: `url(${bgImage})` }" />
|
||||
<div class="pattern-section__front">
|
||||
<img :src="frontImage" alt="banu" />
|
||||
<img :src="frontImage" alt="مدرسه بانو" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -144,7 +144,7 @@ const onResend = async () => {
|
||||
const body = { phone: props.phoneNumber }
|
||||
if (props.mode === 'forgotPassword') await forgotMutation.mutateAsync(body)
|
||||
else if (props.mode === 'loginWithCode') await requestLoginOtpMutation.mutateAsync(body)
|
||||
else await resendCodeMutation.mutateAsync({ phoneNumber: props.phoneNumber })
|
||||
else await resendCodeMutation.mutateAsync(body)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<SelectField
|
||||
v-model="form.universityLevel"
|
||||
name="universityLevel"
|
||||
label="آخرین مدرک تحصیلی"
|
||||
label="آخرین مدرک تحصیلی دانشگاهی"
|
||||
:options="universityLevelOptions"
|
||||
option-label="label"
|
||||
option-value="value"
|
||||
@@ -65,20 +65,6 @@
|
||||
|
||||
<LineTitleBlock title="مشخصات شغلی" title-en="Job Details" />
|
||||
<div class="educational-info__row">
|
||||
<div class="educational-info__cell educational-info__cell--full">
|
||||
<TextareaField
|
||||
v-model="form.workExperienceSummary"
|
||||
name="workExperienceSummary"
|
||||
label="خلاصه ای از سوابق شغلی خود را ذکر بفرمایید."
|
||||
:row="isMobile ? 5 : 1"
|
||||
:error="errors.workExperienceSummary"
|
||||
@blur="validateAt('workExperienceSummary', form.workExperienceSummary)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="file" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextareaField>
|
||||
</div>
|
||||
<div class="educational-info__cell educational-info__cell--full">
|
||||
<TextareaField
|
||||
v-model="form.activitySummary"
|
||||
|
||||
@@ -75,6 +75,51 @@
|
||||
:error="errors.gender"
|
||||
/>
|
||||
</div>
|
||||
<div class="personal-info__cell">
|
||||
<TextField
|
||||
v-model="form.childrenCount"
|
||||
name="childrenCount"
|
||||
label="تعداد فرزند"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.childrenCount"
|
||||
@blur="validateAt('childrenCount', form.childrenCount)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="users-three" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="personal-info__cell">
|
||||
<TextField
|
||||
v-model="form.seminaryCode"
|
||||
name="seminaryCode"
|
||||
label="کد حوزوی"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.seminaryCode"
|
||||
@blur="validateAt('seminaryCode', form.seminaryCode)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="graduation-cap" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="personal-info__cell">
|
||||
<TextField
|
||||
v-model="form.seminaryServiceCenterCode"
|
||||
name="seminaryServiceCenterCode"
|
||||
label="کد مرکز خدمات حوزه"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.seminaryServiceCenterCode"
|
||||
@blur="validateAt('seminaryServiceCenterCode', form.seminaryServiceCenterCode)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="check-square" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<LineTitleBlock title="اطلاعات تماس" title-en="Contact Details" />
|
||||
@@ -95,6 +140,36 @@
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="personal-info__cell">
|
||||
<TextField
|
||||
v-model="form.virtualPhoneNumber"
|
||||
name="virtualPhoneNumber"
|
||||
label="شماره تلفن مجازی"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.virtualPhoneNumber"
|
||||
@blur="validateAt('virtualPhoneNumber', form.virtualPhoneNumber)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="phone" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="personal-info__cell">
|
||||
<TextField
|
||||
v-model="form.postalCode"
|
||||
name="postalCode"
|
||||
label="کد پستی"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.postalCode"
|
||||
@blur="validateAt('postalCode', form.postalCode)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="map-pin-simple-area" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="personal-info__cell">
|
||||
<SelectField
|
||||
v-model="form.provinceId"
|
||||
@@ -141,7 +216,11 @@
|
||||
|
||||
<StepActions
|
||||
:show-back="false"
|
||||
:loading="uploadMutation.isPending.value || updateProfileMutation.isPending.value"
|
||||
:loading="
|
||||
uploadMutation.isPending.value ||
|
||||
updateProfileMutation.isPending.value ||
|
||||
saveRegisterMutation.isPending.value
|
||||
"
|
||||
/>
|
||||
</form>
|
||||
</template>
|
||||
@@ -166,7 +245,12 @@ import { personalInformationSchema } from '@/features/auth/schema/student-regist
|
||||
import StepActions from '@/features/auth/components/studentRegister/StepActions.vue'
|
||||
import { useStudentRegistrationStore } from '@/features/auth/store/student-registration'
|
||||
import { useGetCitiesOfProvinceQuery, useGetProvincesQuery } from '@/services/query/common'
|
||||
import { authKeys, useUpdateProfileMutation, useUploadMediaMutation } from '@/services/query/auth'
|
||||
import {
|
||||
authKeys,
|
||||
useSaveRegisterDataMutation,
|
||||
useUpdateProfileMutation,
|
||||
useUploadMediaMutation,
|
||||
} from '@/services/query/auth'
|
||||
|
||||
const store = useStudentRegistrationStore()
|
||||
const { user } = useAuth()
|
||||
@@ -212,6 +296,11 @@ const form = ref({
|
||||
cityId: user.value?.cityId || store.personal.cityId || null,
|
||||
address:
|
||||
(typeof user.value?.address === 'string' && user.value.address) || store.personal.address || '',
|
||||
postalCode: store.personal.postalCode || '',
|
||||
virtualPhoneNumber: store.personal.virtualPhoneNumber || '',
|
||||
seminaryCode: store.personal.seminaryCode || '',
|
||||
seminaryServiceCenterCode: store.personal.seminaryServiceCenterCode || '',
|
||||
childrenCount: store.personal.childrenCount ?? '',
|
||||
avatar: initialAvatar,
|
||||
avatarId: store.personal.avatarId || '',
|
||||
})
|
||||
@@ -258,6 +347,7 @@ const onAvatarCropped = async (file) => {
|
||||
const onAvatarError = (msg) => toast.error(msg)
|
||||
|
||||
const updateProfileMutation = useUpdateProfileMutation()
|
||||
const saveRegisterMutation = useSaveRegisterDataMutation()
|
||||
|
||||
const onSubmit = async () => {
|
||||
const { isValid, payload } = await validate(form.value)
|
||||
@@ -280,6 +370,13 @@ const onSubmit = async () => {
|
||||
: {}),
|
||||
}
|
||||
await updateProfileMutation.mutateAsync(body)
|
||||
await saveRegisterMutation.mutateAsync({
|
||||
postalCode: payload.postalCode,
|
||||
virtualPhoneNumber: payload.virtualPhoneNumber,
|
||||
seminaryCode: payload.seminaryCode,
|
||||
seminaryServiceCenterCode: payload.seminaryServiceCenterCode,
|
||||
childrenCount: payload.childrenCount,
|
||||
})
|
||||
await queryClient.invalidateQueries({ queryKey: authKeys.me() })
|
||||
store.personal = { ...store.personal, ...next }
|
||||
store.markStepAsCompleted(STUDENT_REGISTRATION.PERSONAL_INFORMATION)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<form class="professional-info" @submit.prevent="onSubmit">
|
||||
<LineTitleBlock title="مشخصات شغلی" title-en="Job Details" />
|
||||
<LineTitleBlock title="مشخصات تبلیغی" title-en="Propagation Details" />
|
||||
<div class="professional-info__row">
|
||||
<div class="professional-info__cell professional-info__cell--5">
|
||||
<TextField
|
||||
@@ -49,7 +49,7 @@
|
||||
<SelectField
|
||||
v-model="form.propagationPlatforms"
|
||||
name="propagationPlatforms"
|
||||
label="در چه بستر هایی فعالیت تبلیغی داشته اید؟"
|
||||
label="در چه بستر هایی فعالیت تبلیغی داشته اید؟ (امکان انتخاب چند گزینه وجود دارد)"
|
||||
:options="platformOptions"
|
||||
option-label="label"
|
||||
option-value="value"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<aside class="sidebar-steps">
|
||||
<div class="sidebar-steps__mobile-logo">
|
||||
<img :src="logoPinkishRed" alt="banu" />
|
||||
<img :src="logoPinkishRed" alt="مدرسه بانو" />
|
||||
</div>
|
||||
<div class="sidebar-steps__panel">
|
||||
<div class="sidebar-steps__logo">
|
||||
<img :src="logoWhite" alt="banu" />
|
||||
<img :src="logoWhite" alt="مدرسه بانو" />
|
||||
</div>
|
||||
<ul class="sidebar-steps__list">
|
||||
<li
|
||||
|
||||
@@ -93,8 +93,8 @@ const STEP_LABELS = {
|
||||
desc: 'لطفاً اطلاعات تحصیلی و شغلی خود را بهصورت کامل و دقیق وارد کنید',
|
||||
},
|
||||
[STUDENT_REGISTRATION.PROFESSIONAL_INFORMATION]: {
|
||||
title: 'اطلاعات فعالیت تبلیغاتی و حرفهای',
|
||||
desc: 'لطفاً اطلاعات تبلیغاتی و حرفهای خود را بهصورت کامل و دقیق وارد کنید',
|
||||
title: 'اطلاعات فعالیتهای تبلیغی',
|
||||
desc: 'لطفاً اطلاعات فعالیتهای تبلیغی خود را بهصورت کامل و دقیق وارد کنید',
|
||||
},
|
||||
[STUDENT_REGISTRATION.SKILL_ASSESSMENT_PART_1]: {
|
||||
title: 'بخش مهارت (بخش اول)',
|
||||
|
||||
@@ -20,6 +20,15 @@ export const personalInformationSchema = object().shape({
|
||||
provinceId: mixed().required(),
|
||||
cityId: mixed().required(),
|
||||
address: requiredString(10),
|
||||
postalCode: string()
|
||||
.required()
|
||||
.matches(/^\d{10}$/, 'کد پستی باید ۱۰ رقم باشد'),
|
||||
virtualPhoneNumber: string()
|
||||
.required()
|
||||
.matches(/^\d{10,15}$/, 'شماره تلفن مجازی نامعتبر است'),
|
||||
seminaryCode: requiredString(),
|
||||
seminaryServiceCenterCode: requiredString(),
|
||||
childrenCount: number().typeError('تعداد فرزند باید عدد باشد').required().min(0).max(20),
|
||||
})
|
||||
|
||||
export const educationalInformationSchema = object().shape({
|
||||
@@ -28,7 +37,6 @@ export const educationalInformationSchema = object().shape({
|
||||
universityLevel: string().required(),
|
||||
universityName: requiredString(5),
|
||||
fieldOfStudy: requiredString(5),
|
||||
workExperienceSummary: requiredString(10),
|
||||
activitySummary: requiredString(10),
|
||||
})
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ const emptyState = () => ({
|
||||
provinceId: null,
|
||||
cityId: null,
|
||||
address: '',
|
||||
postalCode: '',
|
||||
virtualPhoneNumber: '',
|
||||
seminaryCode: '',
|
||||
seminaryServiceCenterCode: '',
|
||||
childrenCount: '',
|
||||
},
|
||||
educational: {
|
||||
educationStatus: '',
|
||||
@@ -25,7 +30,6 @@ const emptyState = () => ({
|
||||
universityLevel: '',
|
||||
universityName: '',
|
||||
fieldOfStudy: '',
|
||||
workExperienceSummary: '',
|
||||
activitySummary: '',
|
||||
},
|
||||
professional: {
|
||||
@@ -83,6 +87,11 @@ const SECTION_FIELDS = {
|
||||
'provinceId',
|
||||
'cityId',
|
||||
'address',
|
||||
'postalCode',
|
||||
'virtualPhoneNumber',
|
||||
'seminaryCode',
|
||||
'seminaryServiceCenterCode',
|
||||
'childrenCount',
|
||||
],
|
||||
educational: [
|
||||
'educationStatus',
|
||||
@@ -90,7 +99,6 @@ const SECTION_FIELDS = {
|
||||
'universityLevel',
|
||||
'universityName',
|
||||
'fieldOfStudy',
|
||||
'workExperienceSummary',
|
||||
'activitySummary',
|
||||
],
|
||||
professional: [
|
||||
|
||||
@@ -7,7 +7,7 @@ export default [
|
||||
layout: 'counselor',
|
||||
role: 'counselor',
|
||||
title: 'سلام بر شما',
|
||||
subtitle: 'به پنل مشاوره بانو خوش آمدید.',
|
||||
subtitle: 'به پنل مشاوره مدرسه بانو خوش آمدید.',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<template #default="{ data, close }">
|
||||
<form class="sample-modal__form" @submit.prevent="onSubmit(close)">
|
||||
<p class="sample-modal__intro">
|
||||
این مودال الگوی استاندارد بنو است: عنوان با
|
||||
این مودال الگوی استاندارد مدرسه بانو است: عنوان با
|
||||
<code>LineTitleBlock</code>
|
||||
در راست، دکمهٔ بستن داخلی در چپ.
|
||||
</p>
|
||||
@@ -82,6 +82,7 @@ const onSubmit = async (close) => {
|
||||
close()
|
||||
form.value = { subject: '', note: '' }
|
||||
resetErrors()
|
||||
// eslint-disable-next-line no-console
|
||||
console.info('SampleModal submit', payload)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
/>
|
||||
<BaseButton
|
||||
variant="secondary"
|
||||
text="نمایش مودال نمونه (الگوی بنو)"
|
||||
text="نمایش مودال نمونه (الگوی مدرسه بانو)"
|
||||
customClass="global-components__btn-wide"
|
||||
@click="openModal('SampleModal', { context: 'پیشنمایش' })"
|
||||
/>
|
||||
|
||||
@@ -7,7 +7,7 @@ export default [
|
||||
layout: 'missionary',
|
||||
role: 'missionary',
|
||||
title: 'سلام بر شما',
|
||||
subtitle: 'به پنل اعزام بانو خوش آمدید.',
|
||||
subtitle: 'به پنل اعزام مدرسه بانو خوش آمدید.',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div v-else class="se__empty">
|
||||
<SvgIcon name="scroll" :size="128" color="#c3c3c3" />
|
||||
<p class="se__empty-title">دانشجوی گرامی</p>
|
||||
<p class="se__empty-title">طلبه گرامی</p>
|
||||
<p class="se__empty-desc">شما تاکنون هیچ آزمونی را به شروع نکرده اید.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -101,6 +101,66 @@
|
||||
option-value="value"
|
||||
/>
|
||||
</div>
|
||||
<div class="edit-profile__cell edit-profile__cell--third">
|
||||
<TextField
|
||||
v-model="form.childrenCount"
|
||||
name="childrenCount"
|
||||
label="تعداد فرزند"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.childrenCount"
|
||||
@blur="validateAt('childrenCount', form.childrenCount)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="users-three" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="edit-profile__cell edit-profile__cell--third">
|
||||
<TextField
|
||||
v-model="form.virtualPhoneNumber"
|
||||
name="virtualPhoneNumber"
|
||||
label="شماره تلفن مجازی"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.virtualPhoneNumber"
|
||||
@blur="validateAt('virtualPhoneNumber', form.virtualPhoneNumber)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="phone" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="edit-profile__cell edit-profile__cell--third">
|
||||
<TextField
|
||||
v-model="form.seminaryCode"
|
||||
name="seminaryCode"
|
||||
label="کد حوزوی"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.seminaryCode"
|
||||
@blur="validateAt('seminaryCode', form.seminaryCode)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="graduation-cap" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="edit-profile__cell edit-profile__cell--third">
|
||||
<TextField
|
||||
v-model="form.seminaryServiceCenterCode"
|
||||
name="seminaryServiceCenterCode"
|
||||
label="کد مرکز خدمات حوزه"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.seminaryServiceCenterCode"
|
||||
@blur="validateAt('seminaryServiceCenterCode', form.seminaryServiceCenterCode)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="check-square" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<LineTitleBlock title="مشخصات محل سکونت" title-en="Address Details" />
|
||||
@@ -127,6 +187,21 @@
|
||||
:disabled="!form.provinceId"
|
||||
/>
|
||||
</div>
|
||||
<div class="edit-profile__cell edit-profile__cell--third">
|
||||
<TextField
|
||||
v-model="form.postalCode"
|
||||
name="postalCode"
|
||||
label="کد پستی"
|
||||
inputmode="numeric"
|
||||
:convert-digits="true"
|
||||
:error="errors.postalCode"
|
||||
@blur="validateAt('postalCode', form.postalCode)"
|
||||
>
|
||||
<template #appendIcon>
|
||||
<SvgIcon name="map-pin-simple-area" :size="20" color="var(--color-thd-gray)" />
|
||||
</template>
|
||||
</TextField>
|
||||
</div>
|
||||
<div class="edit-profile__cell edit-profile__cell--full">
|
||||
<TextareaField
|
||||
v-model="form.address"
|
||||
@@ -227,6 +302,8 @@ import { studentProfileSchema, studentResetPasswordSchema } from '@/features/stu
|
||||
import {
|
||||
authKeys,
|
||||
useGetMeQuery,
|
||||
useGetRegisterDataQuery,
|
||||
useSaveRegisterDataMutation,
|
||||
useUpdateProfileMutation,
|
||||
useUploadMediaMutation,
|
||||
} from '@/services/query/auth'
|
||||
@@ -262,6 +339,11 @@ const form = ref({
|
||||
provinceId: '',
|
||||
cityId: '',
|
||||
address: '',
|
||||
postalCode: '',
|
||||
virtualPhoneNumber: '',
|
||||
seminaryCode: '',
|
||||
seminaryServiceCenterCode: '',
|
||||
childrenCount: '',
|
||||
avatarMediaId: null,
|
||||
})
|
||||
|
||||
@@ -326,6 +408,24 @@ watch(
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const { data: registerData } = useGetRegisterDataQuery()
|
||||
|
||||
watch(
|
||||
registerData,
|
||||
(data) => {
|
||||
if (!data) return
|
||||
form.value = {
|
||||
...form.value,
|
||||
postalCode: data.postalCode || '',
|
||||
virtualPhoneNumber: data.virtualPhoneNumber || '',
|
||||
seminaryCode: data.seminaryCode || '',
|
||||
seminaryServiceCenterCode: data.seminaryServiceCenterCode || '',
|
||||
childrenCount: data.childrenCount ?? '',
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const uploadMutation = useUploadMediaMutation()
|
||||
|
||||
const onAvatarCropped = async (file) => {
|
||||
@@ -343,6 +443,7 @@ const onAvatarCropped = async (file) => {
|
||||
const onAvatarError = (msg) => toast.error(msg)
|
||||
|
||||
const updateMutation = useUpdateProfileMutation()
|
||||
const saveRegisterDataMutation = useSaveRegisterDataMutation()
|
||||
const resetPasswordMutation = useUpdateProfileMutation()
|
||||
|
||||
const onSubmit = async () => {
|
||||
@@ -359,7 +460,18 @@ const onSubmit = async () => {
|
||||
...(payload.avatarMediaId ? { avatarMediaId: payload.avatarMediaId } : {}),
|
||||
}
|
||||
await updateMutation.mutateAsync(body)
|
||||
await saveRegisterDataMutation.mutateAsync({
|
||||
postalCode: payload.postalCode || '',
|
||||
virtualPhoneNumber: payload.virtualPhoneNumber || '',
|
||||
seminaryCode: payload.seminaryCode || '',
|
||||
seminaryServiceCenterCode: payload.seminaryServiceCenterCode || '',
|
||||
childrenCount:
|
||||
payload.childrenCount == null || payload.childrenCount === ''
|
||||
? ''
|
||||
: Number(payload.childrenCount),
|
||||
})
|
||||
await queryClient.invalidateQueries({ queryKey: authKeys.me() })
|
||||
await queryClient.invalidateQueries({ queryKey: authKeys.registerData() })
|
||||
toast.success('پروفایل با موفقیت بهروز شد')
|
||||
router.push({ name: 'student-dashboard' })
|
||||
}
|
||||
|
||||
@@ -15,6 +15,20 @@ export const studentProfileSchema = object().shape({
|
||||
provinceId: string().nullable().notRequired(),
|
||||
cityId: string().nullable().notRequired(),
|
||||
address: string().nullable().notRequired(),
|
||||
postalCode: string()
|
||||
.nullable()
|
||||
.notRequired()
|
||||
.matches(/^\d{10}$/, { message: 'کد پستی باید ۱۰ رقم باشد', excludeEmptyString: true }),
|
||||
virtualPhoneNumber: string()
|
||||
.nullable()
|
||||
.notRequired()
|
||||
.matches(/^\d{10,15}$/, { message: 'شماره تلفن مجازی نامعتبر است', excludeEmptyString: true }),
|
||||
seminaryCode: string().nullable().notRequired(),
|
||||
seminaryServiceCenterCode: string().nullable().notRequired(),
|
||||
childrenCount: string()
|
||||
.nullable()
|
||||
.notRequired()
|
||||
.matches(/^\d+$/, { message: 'تعداد فرزند باید عدد باشد', excludeEmptyString: true }),
|
||||
})
|
||||
|
||||
export const studentResetPasswordSchema = object().shape({
|
||||
|
||||
@@ -7,7 +7,7 @@ export default [
|
||||
layout: 'student',
|
||||
role: 'student',
|
||||
title: 'سلام بر شما',
|
||||
subtitle: 'به سامانه موسسه بانو خوش آمدید.',
|
||||
subtitle: 'به سامانه مدرسه بانو خوش آمدید.',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<aside class="admin-sidebar">
|
||||
<div class="admin-sidebar__logo">
|
||||
<img :src="logo" alt="banu" />
|
||||
<img :src="logo" alt="مدرسه بانو" />
|
||||
</div>
|
||||
<nav class="admin-sidebar__nav">
|
||||
<ul>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<aside class="counselor-sidebar">
|
||||
<div class="counselor-sidebar__logo">
|
||||
<img :src="logo" alt="banu" />
|
||||
<img :src="logo" alt="مدرسه بانو" />
|
||||
</div>
|
||||
<nav class="counselor-sidebar__nav">
|
||||
<ul>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<aside class="student-sidebar" :style="{ backgroundImage: `url(${bgPattern})` }">
|
||||
<div class="student-sidebar__logo">
|
||||
<img :src="logo" alt="banu" />
|
||||
<img :src="logo" alt="مدرسه بانو" />
|
||||
</div>
|
||||
<nav class="student-sidebar__nav">
|
||||
<ul>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ROLE_HOME_ROUTES } from '@/enums'
|
||||
import { useAuthStore } from '@/store/auth'
|
||||
import { tokenService } from '@/services/api/token-service'
|
||||
|
||||
const APP_TITLE = 'بنو'
|
||||
const APP_TITLE = 'مدرسه بانو'
|
||||
|
||||
const isPublic = (to) => to.meta?.public === true
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export const endpoints = {
|
||||
verifyForgotPasswordCode: '/auth/password/verify-otp',
|
||||
resetPassword: '/auth/password/reset',
|
||||
|
||||
resendVerificationCodeForRegister: '/resend-verification-code',
|
||||
resendVerificationCodeForRegister: '/auth/login/otp/request',
|
||||
verifyCode: '/auth/login/otp/verify',
|
||||
completeProfile: '/complete-profile',
|
||||
getRegistrationQuestionVideo: '/verification-registration-media',
|
||||
|
||||
@@ -32,7 +32,6 @@ const makeStudent = (i) => {
|
||||
universityLevel: 'not_applicable',
|
||||
universityName: 'حوزه علمیه قم',
|
||||
fieldOfStudy: 'فقه و اصول',
|
||||
workExperienceSummary: 'پنج سال تدریس در مدرسه دینی.',
|
||||
activitySummary: 'برگزاری جلسات قرآن و حدیث به صورت هفتگی.',
|
||||
propagationExperienceYears: 6,
|
||||
propagationMethodDescription: 'محوریت بیان داستانهای قرآنی و قرابتهای اخلاقی.',
|
||||
|
||||
@@ -207,7 +207,7 @@ export const adminTickets = [
|
||||
type: 'service',
|
||||
category: 'insurance',
|
||||
status: 'answered',
|
||||
subject: 'درخواست بیمه دانشجویی',
|
||||
subject: 'درخواست بیمه طلبگی',
|
||||
createdAt: '2026-05-10T08:20:00.000Z',
|
||||
media: [],
|
||||
student: studentJane,
|
||||
|
||||
@@ -38,7 +38,7 @@ export const missionaryRequests = [
|
||||
requesterPhone: '09354445566',
|
||||
requesterEmail: 'fatemeh@example.com',
|
||||
title: 'جلسه پرسش و پاسخ اعتقادی دانشگاه',
|
||||
description: 'برگزاری نشست پرسش و پاسخ برای دانشجویان خوابگاه.',
|
||||
description: 'برگزاری نشست پرسش و پاسخ برای طلبههای خوابگاه.',
|
||||
location: 'اصفهان، ایران',
|
||||
requestedDate: '2026-06-02',
|
||||
status: 'accepted',
|
||||
|
||||
@@ -49,7 +49,6 @@ register('GET', endpoints.getUserRegisterData, ({ params }) => {
|
||||
{ key: 'universityLevel', value: 'not_applicable' },
|
||||
{ key: 'universityName', value: 'حوزه علمیه قم' },
|
||||
{ key: 'fieldOfStudy', value: 'فقه و اصول' },
|
||||
{ key: 'workExperienceSummary', value: 'پنج سال تدریس در مدرسه دینی.' },
|
||||
{ key: 'activitySummary', value: 'برگزاری جلسات قرآن و حدیث به صورت هفتگی.' },
|
||||
{ key: 'specializedTopics', value: 'تربیت دینی نوجوانان' },
|
||||
{ key: 'propagationExperienceYears', value: 6 },
|
||||
|
||||
@@ -27,10 +27,6 @@ register('POST', endpoints.register, ({ data }) => ({
|
||||
data: { user: { ...currentMe, ...data }, token: fakeToken },
|
||||
}))
|
||||
|
||||
register('POST', endpoints.resendVerificationCodeForRegister, () => ({
|
||||
data: { message: 'کد جدید ارسال شد' },
|
||||
}))
|
||||
|
||||
register('POST', endpoints.forgotPassword, () => ({
|
||||
success: true,
|
||||
message: 'If the phone is registered, a code has been sent.',
|
||||
|
||||
Reference in New Issue
Block a user