방식 개편
This commit is contained in:
@@ -2,80 +2,83 @@
|
||||
<section class="faq-section">
|
||||
<div class="section-header">
|
||||
<span class="section-badge">궁금한 점을 풀어드립니다</span>
|
||||
<h2 class="section-title">{{ regionDong }} 1:1 과외 자주 묻는 질문</h2>
|
||||
<h2 class="section-title">{{ shortSidoName }} {{ gradeShortName }} {{ subjectName }} 과외 · {{ regionDong }} 1:1 과외 자주 묻는 질문</h2>
|
||||
<p class="section-desc">학부모님들께서 가장 많이 문의하시는 내용을 모았습니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-list">
|
||||
<div
|
||||
<details
|
||||
v-for="(faq, idx) in faqs"
|
||||
:key="idx"
|
||||
class="faq-item"
|
||||
:class="{ active: openIndex === idx }"
|
||||
class="faq-item qa"
|
||||
:open="idx === 0"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="faq-question"
|
||||
@click="toggle(idx)"
|
||||
:aria-expanded="openIndex === idx"
|
||||
>
|
||||
<summary class="faq-question">
|
||||
<span class="q-icon">Q</span>
|
||||
<span class="q-text">{{ faq.q }}</span>
|
||||
<span class="toggle-icon">{{ openIndex === idx ? '▲' : '▼' }}</span>
|
||||
</button>
|
||||
<div v-show="openIndex === idx" class="faq-answer">
|
||||
<span class="toggle-icon">▼</span>
|
||||
</summary>
|
||||
<div class="faq-answer ans">
|
||||
<span class="a-icon">A</span>
|
||||
<p class="a-text">{{ faq.a }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
regionDong: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
shortSido: {
|
||||
type: String,
|
||||
default: '서울'
|
||||
},
|
||||
grade: {
|
||||
type: String,
|
||||
default: '중학생'
|
||||
},
|
||||
gradeShort: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
subjectName: {
|
||||
type: String,
|
||||
default: '영어'
|
||||
default: '수학'
|
||||
}
|
||||
})
|
||||
|
||||
const openIndex = ref(0)
|
||||
|
||||
const toggle = (idx) => {
|
||||
openIndex.value = openIndex.value === idx ? -1 : idx
|
||||
}
|
||||
const shortSidoName = computed(() => props.shortSido || '서울')
|
||||
const gradeShortName = computed(() => {
|
||||
if (props.gradeShort) return props.gradeShort
|
||||
return (props.grade || '').includes('초등') ? '초등' : (props.grade || '').includes('고등') ? '고등' : '중등'
|
||||
})
|
||||
|
||||
const faqs = computed(() => [
|
||||
{
|
||||
q: `${props.regionDong} ${props.grade} ${props.subjectName} 방문 과외와 온라인 화상 과외 중 어떤 것이 가능한가요?`,
|
||||
a: `학생과 학부모님의 선호에 따라 100% 자택 방문 대면 과외 또는 실시간 쌍방향 비대면 화상 과외 중 자유롭게 선택하실 수 있습니다. ${props.regionDong} 전 지역 방문 수업이 가능합니다.`
|
||||
q: `${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외(${props.regionDong}), 방문 수업과 온라인 화상 수업 모두 가능한가요?`,
|
||||
a: `네, ${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외 및 ${shortSidoName.value} ${gradeShortName.value} 과외는 학생과 학부모님의 선호에 따라 ${props.regionDong} 100% 자택 방문 대면 과외 또는 실시간 쌍방향 화상 과외 중 자유롭게 선택하실 수 있습니다.`
|
||||
},
|
||||
{
|
||||
q: `${props.grade} ${props.subjectName} 전문 선생님이 학생과 잘 맞지 않으면 교체 가능한가요?`,
|
||||
a: '네, 1회 무료 모의수업을 통해 사전에 호흡을 맞추며, 정규 수업 시작 후에도 학생의 성향이나 요청에 따라 추가 비용 없이 100% 무료 교체 및 환불 규정을 보장합니다.'
|
||||
q: `${shortSidoName.value} ${gradeShortName.value} 과외 및 ${props.regionDong} ${gradeShortName.value} ${props.subjectName} 과외 선생님이 학생과 맞지 않으면 교체 가능한가요?`,
|
||||
a: `네, ${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외는 1회 무료 시범수업을 통해 사전에 호흡을 맞추며, 정규 수업 시작 후에도 학생 성향이나 요청에 따라 추가 비용 없이 100% 무료 교체 및 환불 규정을 보장합니다.`
|
||||
},
|
||||
{
|
||||
q: `${props.grade} ${props.subjectName} 과외 수업 비용은 어떻게 되나요?`,
|
||||
a: `${props.grade} 내신 단계, 주당 수업 횟수, 수업 시간(1회 60분/90분/120분)에 따라 표준 교육청 가이드라인에 맞춘 투명한 정찰제로 운영됩니다. 무료 상담 시 상세 견적표를 안내해 드립니다.`
|
||||
q: `${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외(${props.regionDong} ${props.grade} ${props.subjectName}과외) 수업 비용은 어떻게 되나요?`,
|
||||
a: `${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외 및 ${shortSidoName.value} ${gradeShortName.value} 과외 수업료는 ${props.grade} 내신 단계, 주당 횟수, 수업 시간(60분/90분/120분)에 따라 교육청 가이드라인에 맞춘 투명한 정찰제로 운영됩니다.`
|
||||
},
|
||||
{
|
||||
q: `${props.regionDong} 학교 중간·기말고사 직전 단기 ${props.subjectName} 족보 클리닉도 가능한가요?`,
|
||||
a: `네, 시험 3~4주 전 학교별 기출 족보 풀이 및 서술형 배점 방어를 위한 ${props.grade} ${props.subjectName} 단기 속성 킬러 클리닉 프로그램도 상시 운영 중입니다.`
|
||||
q: `${props.regionDong} 학교 중간·기말고사 대비 ${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외 단기 족보 클리닉도 가능한가요?`,
|
||||
a: `네, 시험 3~4주 전 ${props.regionDong} 인근 학교별 기출 족보 풀이 및 서술형 배점 방어를 위한 ${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외 단기 속성 킬러 클리닉 프로그램도 상시 운영 중입니다.`
|
||||
},
|
||||
{
|
||||
q: `${props.subjectName} 외에 다른 과목도 함께 상담받을 수 있나요?`,
|
||||
a: `${props.subjectName} 집중 신청은 물론, 국영수 또는 수탐 복합 패키지로 맞춤 구성하여 전 과목 플래너 관리와 함께 시간표를 편성하실 수 있습니다.`
|
||||
q: `${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외 외에 다른 과목도 함께 ${shortSidoName.value} ${gradeShortName.value} 과외 상담을 받을 수 있나요?`,
|
||||
a: `${shortSidoName.value} ${gradeShortName.value} ${props.subjectName} 과외 집중 신청은 물론, 국영수 또는 수탐 복합 ${shortSidoName.value} ${gradeShortName.value} 과외 패키지로 맞춤 구성하여 전 과목 플래너 관리와 함께 시간표를 편성하실 수 있습니다.`
|
||||
}
|
||||
])
|
||||
</script>
|
||||
@@ -143,11 +146,16 @@ const faqs = computed(() => [
|
||||
border: none;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
font-size: clamp(0.9rem, 2.2vw, 1.02rem);
|
||||
font-weight: 800;
|
||||
color: var(--text-color, #0f172a);
|
||||
}
|
||||
|
||||
.faq-question::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.q-icon {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
@@ -172,6 +180,11 @@ const faqs = computed(() => [
|
||||
font-size: 0.8rem;
|
||||
color: #94a3b8;
|
||||
flex-shrink: 0;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.faq-item[open] .toggle-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.faq-answer {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 네이버 5개 멀티 썸네일 스니펫 및 상담 링크 매칭용 5개 리스트 -->
|
||||
<!-- 네이버 5개 멀티 썸네일 스니펫 및 상담 링크 매칭용 가로 5열 캐러셀 리스트 -->
|
||||
<div class="focus-grid">
|
||||
<a
|
||||
v-for="(item, idx) in programList"
|
||||
@@ -21,27 +21,29 @@
|
||||
class="focus-card"
|
||||
:title="`${item.title} 상담 신청`"
|
||||
>
|
||||
<div class="focus-thumb-wrap">
|
||||
<img
|
||||
:src="item.image"
|
||||
:alt="`${item.title} 1:1 맞춤 지도`"
|
||||
width="500"
|
||||
height="500"
|
||||
loading="lazy"
|
||||
class="focus-img"
|
||||
/>
|
||||
<span class="step-tag">STEP 0{{ idx + 1 }}</span>
|
||||
</div>
|
||||
|
||||
<div class="focus-info">
|
||||
<div class="focus-item-tag">{{ item.tag }}</div>
|
||||
<strong class="focus-item-title">{{ item.title }}</strong>
|
||||
<p class="focus-item-desc">{{ item.desc }}</p>
|
||||
<div class="focus-cta-link">
|
||||
<span>1:1 상담 예약</span>
|
||||
<span class="arrow-sym">→</span>
|
||||
<figure class="focus-figure m-0 flex flex-col flex-1">
|
||||
<div class="focus-thumb-wrap">
|
||||
<img
|
||||
:src="item.image"
|
||||
:alt="item.title"
|
||||
width="1080"
|
||||
height="1080"
|
||||
decoding="async"
|
||||
loading="eager"
|
||||
class="focus-img"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<figcaption class="focus-info">
|
||||
<div class="focus-item-tag">{{ item.tag }}</div>
|
||||
<h3 class="focus-item-title m-0">{{ item.title }}</h3>
|
||||
<p class="focus-item-desc">{{ item.desc }}</p>
|
||||
<div class="focus-cta-link">
|
||||
<span>1:1 상담 예약</span>
|
||||
<span class="arrow-sym">→</span>
|
||||
</div>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,6 +58,14 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: '중학생'
|
||||
},
|
||||
gradeShort: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
shortSido: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
subjectName: {
|
||||
type: String,
|
||||
default: '수학'
|
||||
@@ -78,7 +88,7 @@ const displaySubject = computed(() => {
|
||||
return props.subjectName || '수학'
|
||||
})
|
||||
|
||||
// 초등 vs 중등/고등 5개 항목 분기
|
||||
// 초등 vs 중등/고등 5개 항목 분기 (실사 PNG 5종 적용)
|
||||
const programList = computed(() => {
|
||||
const dong = props.regionDong ? `${props.regionDong} ` : ''
|
||||
const sub = displaySubject.value
|
||||
@@ -90,31 +100,31 @@ const programList = computed(() => {
|
||||
tag: '개념 완성',
|
||||
title: `${dong}초등 ${sub}과외 - 기초학습`,
|
||||
desc: '개념 쏙쏙 이해와 튼튼한 연산 기본기 완성',
|
||||
image: '/images/focus/elem-1-basic.svg'
|
||||
image: '/img/math-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '학습 코칭',
|
||||
title: `${dong}초등 ${sub}과외 - 공부방법`,
|
||||
desc: '스스로 원리를 깨우치는 올바른 문제 해결력',
|
||||
image: '/images/focus/elem-2-method.svg'
|
||||
image: '/img/english-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '밀착 피드백',
|
||||
title: `${dong}초등 ${sub}과외 - 숙제검사`,
|
||||
desc: '매일 1:1 오답 점검과 꼼꼼한 피드백 클리닉',
|
||||
image: '/images/focus/elem-3-homework.svg'
|
||||
image: '/img/korean-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '자기주도',
|
||||
title: `${dong}초등 ${sub}과외 - 공부습관`,
|
||||
desc: '매일 스스로 책상에 앉는 주도적 학습 루틴',
|
||||
image: '/images/focus/elem-4-habit.svg'
|
||||
image: '/img/science-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '상위권 도약',
|
||||
title: `${dong}초등 ${sub}과외 - 중등대비`,
|
||||
desc: '중학교 내신 서술형과 심화 개념 선행 마스터',
|
||||
image: '/images/focus/elem-5-middleprep.svg'
|
||||
image: '/img/social-studies-tutoring.png'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -125,31 +135,31 @@ const programList = computed(() => {
|
||||
tag: '기출 정복',
|
||||
title: `${dong}${grd} 중간고사 ${sub}과외`,
|
||||
desc: '학교별 기출 족보 완벽 분석 및 서술형 킬러 대비',
|
||||
image: '/images/focus/sec-1-midterm.svg'
|
||||
image: '/img/math-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '학기말 총력',
|
||||
title: `${dong}${grd} 기말고사 ${sub}과외`,
|
||||
desc: '전 범위 오답 분석 및 취약 유형 완벽 클리닉',
|
||||
image: '/images/focus/sec-2-final.svg'
|
||||
image: '/img/english-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '수능·전국연합',
|
||||
title: `${dong}${grd} 모의고사 ${sub}과외`,
|
||||
desc: '수능형 사고력 확장 및 실전 시간 배분 특훈',
|
||||
image: '/images/focus/sec-3-mock.svg'
|
||||
image: '/img/korean-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '내신 만점',
|
||||
title: `${dong}${grd} 수행평가 ${sub}과외`,
|
||||
desc: '조건 감점 0점화 및 과제·보고서 완벽 케어',
|
||||
image: '/images/focus/sec-4-assessment.svg'
|
||||
image: '/img/science-tutoring.png'
|
||||
},
|
||||
{
|
||||
tag: '1등급 집중',
|
||||
title: `${dong}${grd} 내신대비 ${sub}과외`,
|
||||
desc: '관내 교과서·부교재 적중 1:1 맞춤 지도',
|
||||
image: '/images/focus/sec-5-schoolprep.svg'
|
||||
image: '/img/social-studies-tutoring.png'
|
||||
}
|
||||
]
|
||||
})
|
||||
@@ -202,10 +212,10 @@ const programList = computed(() => {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 5열 카드 그리드 */
|
||||
/* 데스크톱: 가로 1열 5칸 균등 그리드 */
|
||||
.focus-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
grid-template-columns: repeat(5, minmax(180px, 1fr));
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
@@ -313,52 +323,22 @@ const programList = computed(() => {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
|
||||
/* 태블릿 및 모바일 반응형 */
|
||||
@media (max-width: 960px) {
|
||||
/* 태블릿 및 모바일 반응형: 가로 스크롤 캐러셀 유지 */
|
||||
@media (max-width: 1024px) {
|
||||
.focus-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.focus-grid {
|
||||
grid-template-columns: 1fr;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
scroll-snap-type: x mandatory;
|
||||
gap: 12px;
|
||||
padding-bottom: 12px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.focus-card {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.focus-thumb-wrap {
|
||||
width: 105px;
|
||||
height: 105px;
|
||||
aspect-ratio: 1 / 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.focus-info {
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.focus-item-title {
|
||||
font-size: 0.88rem;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.focus-item-desc {
|
||||
font-size: 0.74rem;
|
||||
margin-bottom: 6px;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.focus-cta-link {
|
||||
padding-top: 4px;
|
||||
font-size: 0.72rem;
|
||||
flex: 0 0 220px;
|
||||
scroll-snap-align: start;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<header class="hero-banner-clean bg-white border-b border-slate-200/80 pt-10 sm:pt-14 pb-14 sm:pb-18 px-4 sm:px-6 relative overflow-hidden text-center">
|
||||
<section class="hero-banner hero-banner-clean bg-white border-b border-slate-200/80 pt-10 sm:pt-14 pb-14 sm:pb-18 px-4 sm:px-6 relative overflow-hidden text-center" itemscope itemtype="https://schema.org/Course">
|
||||
|
||||
<!-- 은은한 상단 엠비언트 라이트 -->
|
||||
<div class="absolute inset-0 bg-gradient-to-b from-blue-50/40 via-transparent to-transparent pointer-events-none"></div>
|
||||
@@ -12,16 +12,20 @@
|
||||
<span>{{ region.dong }} 학군 전담 | 서울대·연고대 및 베테랑 강사진 100% 신원 보증</span>
|
||||
</div>
|
||||
|
||||
<!-- SEO 메인 H1 (사용자 지정 롱테일 조합형: [지역] + [학년] + [과목]과외 + 검증된 전문 선생님 100% 매칭) -->
|
||||
<h1 class="text-2xl sm:text-4xl md:text-5xl font-extrabold tracking-tight text-slate-900 leading-[1.22] sm:leading-[1.18] mb-4">
|
||||
<span>{{ displayRegionName }} {{ grade }} {{ subjectName }}과외</span><br />
|
||||
<span class="text-blue-600">우리 아이 맞춤 검증된 전문 선생님 100% 매칭</span>
|
||||
<!-- 네이버 상위 노출 순서: 1. H1 ➔ 2. meta ➔ 3. H2 ➔ 4. 일반글 P -->
|
||||
<h1 itemprop="headline" class="text-2xl sm:text-4xl md:text-5xl font-extrabold tracking-tight text-slate-900 leading-[1.22] sm:leading-[1.18] mb-3">
|
||||
<span class="highlight text-blue-600">{{ shortSidoName }} {{ gradeShortName }} {{ subjectName }} 과외 · {{ region.dong }} {{ grade }} {{ subjectName }}과외</span><br />
|
||||
1:1 맞춤 학습으로 성적 역전!
|
||||
</h1>
|
||||
|
||||
<!-- 서브 카피 (비용 시세 비교 + 학교 기출 분석 + 무료 시범수업 신뢰 트리거) -->
|
||||
<p class="text-xs sm:text-base text-slate-600 font-normal max-w-2xl mx-auto leading-relaxed mb-7">
|
||||
{{ region.dong }} 인근 학교별 기출 분석부터 과외 비용·시세 비교, 취약 개념 클리닉까지.<br class="hidden sm:inline" />
|
||||
직접 수업받아보고 결정하는 <strong>1:1 무료 방문·화상 시범수업</strong>을 신청하세요.
|
||||
<meta itemprop="name" :content="`${shortSidoName} ${gradeShortName} ${subjectName} 과외 · ${shortSidoName} ${gradeShortName} 과외 (${region.dong})`" />
|
||||
<meta itemprop="description" :content="`${shortSidoName} ${gradeShortName} ${subjectName} 과외 및 ${shortSidoName} ${gradeShortName} 과외 전문 매칭. ${displayRegionName} ${grade} ${subjectName} 1:1 방문·화상 맞춤 수업`" />
|
||||
<meta itemprop="keywords" :content="`${shortSidoName} ${gradeShortName} ${subjectName} 과외, ${shortSidoName} ${gradeShortName} 과외, ${region.dong} ${gradeShortName} ${subjectName} 과외, ${region.dong} ${gradeShortName} 과외, ${displayRegionName} ${grade} ${subjectName}과외`" />
|
||||
<meta itemprop="image" content="/img/math-tutoring.png" />
|
||||
<h2 class="hero-subtitle">
|
||||
{{ shortSidoName }} {{ gradeShortName }} 과외 · {{ displayRegionName }} {{ gradeShortName }} {{ subjectName }} 과외 검증된 전문 선생님 1:1 매칭
|
||||
</h2>
|
||||
<p class="sub-headline text-xs sm:text-base text-slate-600 font-normal max-w-2xl mx-auto leading-relaxed mb-7">
|
||||
{{ shortSidoName }} {{ gradeShortName }} {{ subjectName }} 과외 및 {{ shortSidoName }} {{ gradeShortName }} 과외를 찾으시는 학부모님을 위해 {{ region.dong }} 인근 학교별 기출 족보 분석부터 개인별 취약 개념 완벽 보완, 투명한 과외비 안내와 무료 시범수업까지 1:1 밀착 커리큘럼을 제공합니다.
|
||||
</p>
|
||||
|
||||
<!-- 4대 핵심 신뢰 지표 바 -->
|
||||
@@ -84,15 +88,15 @@
|
||||
|
||||
<!-- 태그 목록 -->
|
||||
<div class="flex justify-center flex-wrap gap-1.5">
|
||||
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ shortSidoName }}{{ gradeShortName }}{{ subjectName }}과외</span>
|
||||
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ shortSidoName }}{{ gradeShortName }}과외</span>
|
||||
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ region.dong }}과외</span>
|
||||
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ region.dong }}{{ subjectName }}과외</span>
|
||||
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ grade }}내신대비</span>
|
||||
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#과외비용시세</span>
|
||||
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#1대1무료시범수업</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -111,12 +115,26 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: '중학생'
|
||||
},
|
||||
gradeShort: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
subjectName: {
|
||||
type: String,
|
||||
default: '수학'
|
||||
}
|
||||
})
|
||||
|
||||
const shortSidoName = computed(() => {
|
||||
const s = (props.region?.sido || '').replace(/특별시|광역시|특별자치시|도/g, '').trim()
|
||||
return s || '서울'
|
||||
})
|
||||
|
||||
const gradeShortName = computed(() => {
|
||||
if (props.gradeShort) return props.gradeShort
|
||||
return props.grade === '초등학생' ? '초등' : props.grade === '고등학생' ? '고등' : '중등'
|
||||
})
|
||||
|
||||
const noticeIdx = ref(0)
|
||||
let timer = null
|
||||
|
||||
@@ -171,4 +189,12 @@ const displayRegionName = computed(() => {
|
||||
.hero-banner-clean {
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
color: #334155;
|
||||
margin-bottom: 0.75rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -116,15 +116,15 @@ const nearbyDongs = computed(() => {
|
||||
}
|
||||
|
||||
// 만약 동일 구의 동이 부족하면 전체에서 다른 동 가져오기
|
||||
if (candidates.length < 5) {
|
||||
if (candidates.length < 12) {
|
||||
const others = allList
|
||||
.filter(r => r.dong !== curDong && !candidates.includes(r.dong))
|
||||
.map(r => r.dong)
|
||||
candidates = [...candidates, ...others]
|
||||
}
|
||||
|
||||
// 중복 제거 후 6개 반환
|
||||
return Array.from(new Set(candidates)).slice(0, 6)
|
||||
// 중복 제거 후 12개 반환
|
||||
return Array.from(new Set(candidates)).slice(0, 12)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
|
||||
<!-- 가로 1열 5칸 캐러셀 레이아웃 -->
|
||||
<div class="subject-grid-221">
|
||||
<div
|
||||
v-for="(item, idx) in subjectList"
|
||||
@@ -26,17 +26,18 @@
|
||||
:class="`card-item-${idx + 1}`"
|
||||
@click="openModal(item)"
|
||||
>
|
||||
<div class="card-inner">
|
||||
<figure class="card-inner m-0">
|
||||
<div class="img-wrap">
|
||||
<img
|
||||
:src="item.image"
|
||||
:alt="`${item.name} 1:1 맞춤 지도`"
|
||||
width="600"
|
||||
height="600"
|
||||
:src="item.path"
|
||||
:alt="`${shortSido || defaultSido} ${gradeShort || computedGradeShort} ${item.keyName} 과외 · ${regionDong || defaultDong} ${item.name}`"
|
||||
width="1080"
|
||||
height="1080"
|
||||
decoding="async"
|
||||
class="subject-img"
|
||||
loading="lazy"
|
||||
loading="eager"
|
||||
fetchpriority="high"
|
||||
/>
|
||||
<span class="subject-tag">{{ item.tag }}</span>
|
||||
<div class="zoom-overlay">
|
||||
<span class="zoom-btn">
|
||||
<i class="fa-solid fa-magnifying-glass-plus"></i>
|
||||
@@ -45,18 +46,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-info">
|
||||
<figcaption class="card-info">
|
||||
<div class="card-subject-name">
|
||||
<span class="sub-name">{{ item.name }}</span>
|
||||
<h3 class="sub-name m-0 text-inherit font-extrabold">{{ shortSido || defaultSido }} {{ gradeShort || computedGradeShort }} {{ item.name }}</h3>
|
||||
<span class="sub-grade">{{ grade }}</span>
|
||||
</div>
|
||||
<p class="card-subject-desc">{{ item.desc }}</p>
|
||||
<div class="card-action">
|
||||
<NuxtLink :to="getSubjectPageUrl(item.subjectKey)" class="card-action" @click.stop>
|
||||
<span>자세히 보기 & 신청</span>
|
||||
<i class="fa-solid fa-arrow-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -87,13 +88,13 @@
|
||||
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
|
||||
<div class="modal-img-col">
|
||||
<img
|
||||
:src="selectedItem.image"
|
||||
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
|
||||
width="600"
|
||||
height="600"
|
||||
:src="selectedItem.path"
|
||||
:alt="`${shortSido || defaultSido} ${gradeShort || computedGradeShort} ${selectedItem.keyName} 과외`"
|
||||
width="1080"
|
||||
height="1080"
|
||||
decoding="async"
|
||||
class="modal-main-img"
|
||||
/>
|
||||
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
|
||||
@@ -148,7 +149,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -156,9 +157,17 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
shortSido: {
|
||||
type: String,
|
||||
default: '서울'
|
||||
},
|
||||
grade: {
|
||||
type: String,
|
||||
default: '중·고등'
|
||||
default: '중학생'
|
||||
},
|
||||
gradeShort: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
currentSubject: {
|
||||
type: String,
|
||||
@@ -167,15 +176,21 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
const defaultDong = '대치동'
|
||||
const defaultSido = '서울'
|
||||
const computedGradeShort = computed(() => {
|
||||
if (props.gradeShort) return props.gradeShort
|
||||
return (props.grade || '').includes('초등') ? '초등' : (props.grade || '').includes('고등') ? '고등' : '중등'
|
||||
})
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const siteDomain = config.public?.siteDomain || 'https://aeseo.cloud'
|
||||
|
||||
// 5대 핵심 과목 (2 2 1 순서 배치)
|
||||
// 5대 핵심 과목 (가로 1열 5칸 캐러셀 배치)
|
||||
const subjectList = [
|
||||
// 1행: 수학, 영어
|
||||
{
|
||||
name: '수학과외',
|
||||
keyName: '수학',
|
||||
subjectKey: 'math',
|
||||
tag: '인기 1위',
|
||||
image: `${siteDomain}/img/math-tutoring.png`,
|
||||
@@ -190,6 +205,7 @@ const subjectList = [
|
||||
},
|
||||
{
|
||||
name: '영어과외',
|
||||
keyName: '영어',
|
||||
subjectKey: 'english',
|
||||
tag: '내신 필수',
|
||||
image: `${siteDomain}/img/english-tutoring.png`,
|
||||
@@ -202,9 +218,9 @@ const subjectList = [
|
||||
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
|
||||
]
|
||||
},
|
||||
// 2행: 국어, 과학
|
||||
{
|
||||
name: '국어과외',
|
||||
keyName: '국어',
|
||||
subjectKey: 'korean',
|
||||
tag: '문해력 완성',
|
||||
image: `${siteDomain}/img/korean-tutoring.png`,
|
||||
@@ -219,6 +235,7 @@ const subjectList = [
|
||||
},
|
||||
{
|
||||
name: '과학과외',
|
||||
keyName: '과학',
|
||||
subjectKey: 'science',
|
||||
tag: '통합과학',
|
||||
image: `${siteDomain}/img/science-tutoring.png`,
|
||||
@@ -231,9 +248,9 @@ const subjectList = [
|
||||
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
|
||||
]
|
||||
},
|
||||
// 3행: 사회 (1개 단독 센터 정렬)
|
||||
{
|
||||
name: '사회과외',
|
||||
keyName: '사회',
|
||||
subjectKey: 'social',
|
||||
tag: '통합사회',
|
||||
image: `${siteDomain}/img/social-studies-tutoring.png`,
|
||||
@@ -304,8 +321,9 @@ const applyWithSubject = (subjectName) => {
|
||||
|
||||
// 해당 과목 전용 페이지 URL 생성 (NuxtLink 바인딩용)
|
||||
const getSubjectPageUrl = (subjectKey) => {
|
||||
const dong = props.regionDong || '서울'
|
||||
const grade = props.grade || '중학생'
|
||||
const dong = props.regionDong || defaultDong
|
||||
const validGrades = ['초등학생', '중학생', '고등학생']
|
||||
const grade = validGrades.includes(props.grade) ? props.grade : '중학생'
|
||||
const subMap = {
|
||||
math: '수학',
|
||||
english: '영어',
|
||||
@@ -347,7 +365,7 @@ onUnmounted(() => {
|
||||
<style scoped>
|
||||
.subject-gallery-section {
|
||||
width: 100%;
|
||||
max-width: 1080px;
|
||||
max-width: 1120px;
|
||||
margin: 40px auto 60px;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
@@ -358,7 +376,7 @@ onUnmounted(() => {
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 28px;
|
||||
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
|
||||
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 32px);
|
||||
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
@@ -398,31 +416,29 @@ onUnmounted(() => {
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
/* 2 - 2 - 1 그리드 레이아웃 */
|
||||
/* 데스크톱: 가로 1열 5칸 균등 그리드 */
|
||||
.subject-grid-221 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20px;
|
||||
grid-template-columns: repeat(5, minmax(180px, 1fr));
|
||||
gap: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
|
||||
.card-item-5 {
|
||||
grid-column: 1 / -1;
|
||||
justify-self: center;
|
||||
grid-column: auto;
|
||||
width: 100%;
|
||||
max-width: calc(50% - 10px);
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.gallery-card {
|
||||
cursor: pointer;
|
||||
border-radius: 20px;
|
||||
border-radius: 18px;
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
|
||||
.card-inner {
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
border-radius: 18px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e2e8f0;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
|
||||
@@ -459,14 +475,14 @@ onUnmounted(() => {
|
||||
|
||||
.subject-tag {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: 14px;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
background: rgba(15, 23, 42, 0.85);
|
||||
backdrop-filter: blur(4px);
|
||||
color: #ffffff;
|
||||
font-size: 0.75rem;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 800;
|
||||
padding: 4px 12px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 9999px;
|
||||
z-index: 2;
|
||||
}
|
||||
@@ -490,9 +506,9 @@ onUnmounted(() => {
|
||||
.zoom-btn {
|
||||
background: #ffffff;
|
||||
color: #0f172a;
|
||||
font-size: 0.88rem;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 800;
|
||||
padding: 10px 18px;
|
||||
padding: 8px 14px;
|
||||
border-radius: 9999px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -507,7 +523,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.card-info {
|
||||
padding: 18px 20px;
|
||||
padding: 14px 14px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
@@ -516,59 +532,68 @@ onUnmounted(() => {
|
||||
.card-subject-name {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
justify-content: space-between;
|
||||
gap: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.sub-name {
|
||||
font-size: 1.2rem;
|
||||
font-size: 1.05rem;
|
||||
font-weight: 800;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.sub-grade {
|
||||
font-size: 0.78rem;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
color: #64748b;
|
||||
background: #f1f5f9;
|
||||
padding: 2px 8px;
|
||||
padding: 2px 7px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.card-subject-desc {
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.8rem;
|
||||
color: #475569;
|
||||
line-height: 1.45;
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 12px;
|
||||
flex: 1;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.card-action {
|
||||
font-size: 0.82rem;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary-color, #1e3a8a);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
gap: 5px;
|
||||
transition: gap 0.2s ease;
|
||||
}
|
||||
|
||||
.gallery-card:hover .card-action {
|
||||
gap: 10px;
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
/* 모바일 반응형 대응 */
|
||||
@media (max-width: 640px) {
|
||||
/* 태블릿/모바일: 가로 스크롤 캐러셀 */
|
||||
@media (max-width: 1024px) {
|
||||
.subject-grid-221 {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 16px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
scroll-snap-type: x mandatory;
|
||||
gap: 12px;
|
||||
padding-bottom: 12px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
|
||||
.gallery-card {
|
||||
flex: 0 0 220px;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
|
||||
.card-item-5 {
|
||||
grid-column: auto;
|
||||
max-width: 100%;
|
||||
justify-self: stretch;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user