fix: raise registration form to reduce scrolling.

Fold the page title into the card header, tighten vertical spacing, and hide the footer on registration routes.
This commit is contained in:
2026-08-16 08:48:49 +03:30
parent 6d76a90d9b
commit 8f67f27b36
3 changed files with 95 additions and 52 deletions
+6 -2
View File
@@ -4,14 +4,18 @@
<main> <main>
<RouterView /> <RouterView />
</main> </main>
<SiteFooter /> <SiteFooter v-if="!hideFooter" />
</div> </div>
</template> </template>
<script setup> <script setup>
import { RouterView } from 'vue-router' import { computed } from 'vue'
import { RouterView, useRoute } from 'vue-router'
import SiteHeader from '@/components/SiteHeader.vue' import SiteHeader from '@/components/SiteHeader.vue'
import SiteFooter from '@/components/SiteFooter.vue' import SiteFooter from '@/components/SiteFooter.vue'
const route = useRoute()
const hideFooter = computed(() => Boolean(route.meta.hideFooter))
</script> </script>
<style scoped> <style scoped>
+2 -2
View File
@@ -22,13 +22,13 @@ const routes = [
path: 'register/upcoming/:classId', path: 'register/upcoming/:classId',
name: 'register-upcoming', name: 'register-upcoming',
component: () => import('@/views/ClassRegistrationView.vue'), component: () => import('@/views/ClassRegistrationView.vue'),
meta: { title: 'ثبت‌نام در کلاس | گام نو', registrationType: 'enrollment' } meta: { title: 'ثبت‌نام در کلاس | گام نو', registrationType: 'enrollment', hideFooter: true }
}, },
{ {
path: 'register/request/:classId', path: 'register/request/:classId',
name: 'register-request', name: 'register-request',
component: () => import('@/views/ClassRegistrationView.vue'), component: () => import('@/views/ClassRegistrationView.vue'),
meta: { title: 'درخواست تشکیل کلاس | گام نو', registrationType: 'class_request' } meta: { title: 'درخواست تشکیل کلاس | گام نو', registrationType: 'class_request', hideFooter: true }
} }
] ]
}, },
+87 -48
View File
@@ -1,16 +1,6 @@
<template> <template>
<div class="registration-page"> <div class="registration-page">
<div class="container"> <div class="container registration-wrap">
<header class="page-head">
<RouterLink to="/" class="back-link">
<span aria-hidden="true"></span>
بازگشت به صفحه اصلی
</RouterLink>
<p class="page-eyebrow">{{ isClassRequest ? 'درخواست تشکیل کلاس' : 'ثبت‌نام در کلاس' }}</p>
<h1>{{ pageTitle }}</h1>
<p v-if="cls" class="page-lead">{{ cls.course?.title || cls.name }}</p>
</header>
<div v-if="loading" class="state-card loading-block"> <div v-if="loading" class="state-card loading-block">
<div class="spinner" aria-label="در حال بارگذاری"></div> <div class="spinner" aria-label="در حال بارگذاری"></div>
</div> </div>
@@ -18,6 +8,19 @@
<div v-else-if="loadError" class="state-card alert" role="alert">{{ loadError }}</div> <div v-else-if="loadError" class="state-card alert" role="alert">{{ loadError }}</div>
<div v-else-if="cls" class="registration-card"> <div v-else-if="cls" class="registration-card">
<header class="card-topbar">
<RouterLink to="/" class="back-link">
<span aria-hidden="true"></span>
بازگشت
</RouterLink>
<div class="card-topbar-title">
<p class="page-eyebrow">{{ isClassRequest ? 'درخواست تشکیل کلاس' : 'ثبت‌نام در کلاس' }}</p>
<h1>{{ pageTitle }}</h1>
</div>
<p v-if="cls.course?.title" class="card-topbar-course">{{ cls.course.title }}</p>
</header>
<div class="card-columns">
<aside class="summary-panel"> <aside class="summary-panel">
<div class="summary-inner"> <div class="summary-inner">
<p class="summary-label">خلاصه کلاس</p> <p class="summary-label">خلاصه کلاس</p>
@@ -250,6 +253,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script setup> <script setup>
@@ -391,14 +395,44 @@ onMounted(async () => {
<style scoped> <style scoped>
.registration-page { .registration-page {
min-height: 100vh; min-height: calc(100vh - var(--header-h));
padding: calc(var(--header-h) + 2rem) 0 3.5rem; padding: calc(var(--header-h) + 0.65rem) 0 2rem;
background: background:
radial-gradient(circle at 12% 0%, rgba(45, 106, 79, 0.1), transparent 42%), radial-gradient(circle at 12% 0%, rgba(45, 106, 79, 0.1), transparent 42%),
radial-gradient(circle at 88% 8%, rgba(232, 163, 23, 0.1), transparent 38%), radial-gradient(circle at 88% 8%, rgba(232, 163, 23, 0.1), transparent 38%),
linear-gradient(180deg, var(--canvas) 0%, var(--canvas-deep) 100%); linear-gradient(180deg, var(--canvas) 0%, var(--canvas-deep) 100%);
} }
.registration-wrap {
max-width: 960px;
}
.card-topbar {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 1rem 1.25rem;
padding: 0.85rem 1.5rem;
border-bottom: 1px solid rgba(20, 53, 43, 0.08);
background: rgba(45, 106, 79, 0.03);
}
.card-topbar-title {
min-width: 0;
}
.card-topbar-course {
font-size: 0.85rem;
font-weight: 700;
color: var(--ink-soft);
white-space: nowrap;
}
.card-columns {
display: grid;
grid-template-columns: minmax(220px, 280px) 1fr;
}
.page-head { .page-head {
max-width: 42rem; max-width: 42rem;
margin-bottom: 2rem; margin-bottom: 2rem;
@@ -408,11 +442,11 @@ onMounted(async () => {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 0.35rem; gap: 0.35rem;
margin-bottom: 1rem; font-size: 0.82rem;
font-size: 0.875rem;
font-weight: 600; font-weight: 600;
color: var(--ink-soft); color: var(--ink-soft);
transition: color 0.2s ease; transition: color 0.2s ease;
white-space: nowrap;
} }
.back-link:hover { .back-link:hover {
@@ -420,22 +454,18 @@ onMounted(async () => {
} }
.page-eyebrow { .page-eyebrow {
font-size: 0.8rem; font-size: 0.72rem;
font-weight: 800; font-weight: 800;
letter-spacing: 0.02em; letter-spacing: 0.02em;
color: var(--saffron-deep); color: var(--saffron-deep);
margin-bottom: 0.5rem; margin-bottom: 0.15rem;
} }
.card-topbar-title h1,
.page-head h1 { .page-head h1 {
font-family: var(--font-display); font-family: var(--font-display);
font-size: clamp(1.75rem, 3.2vw, 2.25rem); font-size: 1.15rem;
margin-bottom: 0.5rem; line-height: 1.3;
}
.page-lead {
font-size: 1.05rem;
color: var(--ink-soft);
} }
.state-card { .state-card {
@@ -447,12 +477,12 @@ onMounted(async () => {
} }
.registration-card { .registration-card {
display: grid; display: flex;
grid-template-columns: minmax(240px, 300px) 1fr; flex-direction: column;
gap: 0; gap: 0;
max-width: 960px; max-width: 960px;
margin-inline: auto; margin-inline: auto;
border-radius: 1.5rem; border-radius: 1.25rem;
overflow: hidden; overflow: hidden;
border: 1px solid rgba(20, 53, 43, 0.08); border: 1px solid rgba(20, 53, 43, 0.08);
box-shadow: var(--shadow); box-shadow: var(--shadow);
@@ -466,9 +496,9 @@ onMounted(async () => {
} }
.summary-inner { .summary-inner {
padding: 2rem 1.75rem; padding: 1.35rem 1.5rem;
position: sticky; position: sticky;
top: calc(var(--header-h) + 1.5rem); top: calc(var(--header-h) + 0.5rem);
} }
.summary-label { .summary-label {
@@ -481,9 +511,9 @@ onMounted(async () => {
} }
.summary-title { .summary-title {
font-size: 1.15rem; font-size: 1.05rem;
line-height: 1.45; line-height: 1.45;
margin-bottom: 1.5rem; margin-bottom: 1rem;
} }
.summary-list { .summary-list {
@@ -528,15 +558,15 @@ onMounted(async () => {
} }
.form-panel { .form-panel {
padding: 2rem 2.25rem 2.25rem; padding: 1.35rem 1.75rem 1.5rem;
} }
.stepper { .stepper {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.75rem; gap: 0.75rem;
margin-bottom: 2rem; margin-bottom: 1.25rem;
padding-bottom: 1.5rem; padding-bottom: 1rem;
border-bottom: 1px solid rgba(20, 53, 43, 0.08); border-bottom: 1px solid rgba(20, 53, 43, 0.08);
} }
@@ -587,25 +617,25 @@ onMounted(async () => {
} }
.step-header { .step-header {
margin-bottom: 1.75rem; margin-bottom: 1.15rem;
} }
.step-header h2 { .step-header h2 {
font-size: 1.25rem; font-size: 1.1rem;
margin-bottom: 0.5rem; margin-bottom: 0.35rem;
} }
.step-header p { .step-header p {
color: var(--ink-soft); color: var(--ink-soft);
font-size: 0.925rem; font-size: 0.875rem;
line-height: 1.75; line-height: 1.6;
max-width: 36rem; max-width: 36rem;
} }
.fields-grid { .fields-grid {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1.25rem 1.5rem; gap: 0.9rem 1.25rem;
} }
.field-wide { .field-wide {
@@ -657,8 +687,8 @@ onMounted(async () => {
} }
.form-actions { .form-actions {
margin-top: 2rem; margin-top: 1.35rem;
padding-top: 0.25rem; padding-top: 0;
} }
.form-actions--split { .form-actions--split {
@@ -875,8 +905,21 @@ onMounted(async () => {
} }
@media (max-width: 820px) { @media (max-width: 820px) {
.registration-card { .card-topbar {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: 0.5rem;
padding: 0.85rem 1.25rem;
}
.card-topbar-course {
white-space: normal;
}
.card-columns {
grid-template-columns: 1fr;
}
.registration-card {
max-width: 520px; max-width: 520px;
} }
@@ -915,11 +958,7 @@ onMounted(async () => {
@media (max-width: 560px) { @media (max-width: 560px) {
.registration-page { .registration-page {
padding-top: calc(var(--header-h) + 1.25rem); padding-top: calc(var(--header-h) + 0.4rem);
}
.page-head {
margin-bottom: 1.5rem;
} }
.fields-grid { .fields-grid {