Files
web_6ea_educo/seoul/components/SuccessStories.vue
T
2026-11-11 12:31:47 +09:00

386 lines
14 KiB
Vue

<template>
<section id="stories-section" class="stories-section">
<div class="stories-inner">
<div class="section-header">
<span class="section-badge">REVIEWS &amp; SUCCESS STORIES</span>
<h2 class="section-title">{{ regionDong }} {{ grade }}들의 놀라운 {{ subjectName }} 성적 변화</h2>
<p class="section-desc">공부 방법만 1:1로 정확히 교정해도 성적은 반드시 오릅니다. 실제 수강생들의 리얼 후기와 상승 지표를 확인하세요.</p>
</div>
<!-- 시안 5번째 섹션 레이아웃: 좌측 리뷰 카드 + 우측 98% 성적 상승 그래프 카드 -->
<div class="reviews-layout-grid">
<div class="reviews-stack">
<div v-for="(story, idx) in matchedStories.slice(0, 2)" :key="idx" class="story-card">
<div class="story-top">
<div>
<span class="student-info">{{ story.student }}</span>
<div class="grade-jump">
<span class="before">{{ story.before }}</span>
<span class="arrow">➔</span>
<span class="after">{{ story.after }}</span>
</div>
</div>
<div class="stars" aria-label="별점 5점 만점">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
</div>
</div>
<p class="story-review">"{{ story.review }}"</p>
<div class="story-sub">수강 기간: {{ story.period }} / {{ regionDong }} 1:1 맞춤 {{ subjectName }} 수업</div>
</div>
</div>
<!-- 우측: 세 번째 스토리 + 98% 상승 그래프 카드 -->
<div class="graph-story-card">
<div v-if="matchedStories[2]" class="graph-story-head">
<div class="story-top">
<div>
<span class="student-info">{{ matchedStories[2].student }}</span>
<div class="grade-jump">
<span class="before">{{ matchedStories[2].before }}</span>
<span class="arrow">➔</span>
<span class="after">{{ matchedStories[2].after }}</span>
</div>
</div>
<div class="stars" aria-label="별점 5점 만점">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
</div>
</div>
<p class="story-review mb-4">"{{ matchedStories[2].review }}"</p>
</div>
<div class="chart-wrap">
<div class="chart-caption">
<strong>{{ regionDong }} {{ subjectName }} 수강생 평균 성적 향상 추이</strong>
<span class="chart-highlight">성적 향상도 98%</span>
</div>
<svg viewBox="0 0 500 190" class="chart-svg" role="img" :aria-label="`${regionDong} ${subjectName} 1개월부터 6개월까지 98% 성적 향상 그래프`">
<line x1="30" y1="30" x2="470" y2="30" stroke="#e5dec9" stroke-dasharray="3 3" />
<line x1="30" y1="75" x2="470" y2="75" stroke="#e5dec9" stroke-dasharray="3 3" />
<line x1="30" y1="120" x2="470" y2="120" stroke="#e5dec9" stroke-dasharray="3 3" />
<line x1="30" y1="160" x2="470" y2="160" stroke="#cbbba0" stroke-width="1.5" />
<rect x="52" y="122" width="26" height="38" rx="4" fill="#d9cebe" />
<rect x="128" y="95" width="26" height="65" rx="4" fill="#cfc1ab" />
<rect x="204" y="108" width="26" height="52" rx="4" fill="#cfc1ab" />
<rect x="280" y="72" width="26" height="88" rx="4" fill="#c2ae8e" />
<rect x="356" y="84" width="26" height="76" rx="4" fill="#b89f78" />
<rect x="430" y="32" width="30" height="128" rx="4" fill="#10192b" />
<polyline
fill="none"
stroke="#c49b50"
stroke-width="3"
points="65,118 141,88 217,102 293,65 369,78 445,26"
/>
<circle cx="65" cy="118" r="4" fill="#ffffff" stroke="#c49b50" stroke-width="2.5" />
<circle cx="141" cy="88" r="4" fill="#ffffff" stroke="#c49b50" stroke-width="2.5" />
<circle cx="217" cy="102" r="4" fill="#ffffff" stroke="#c49b50" stroke-width="2.5" />
<circle cx="293" cy="65" r="4" fill="#ffffff" stroke="#c49b50" stroke-width="2.5" />
<circle cx="369" cy="78" r="4" fill="#ffffff" stroke="#c49b50" stroke-width="2.5" />
<circle cx="445" cy="26" r="5.5" fill="#e2c687" stroke="#10192b" stroke-width="2.5" />
<rect x="418" y="2" width="54" height="19" rx="5" fill="#10192b" />
<text x="445" y="15" text-anchor="middle" fill="#e2c687" font-size="11" font-weight="800">98%</text>
<text x="65" y="180" text-anchor="middle" fill="#64748b" font-size="11" font-weight="600">1개월</text>
<text x="141" y="180" text-anchor="middle" fill="#64748b" font-size="11" font-weight="600">2개월</text>
<text x="217" y="180" text-anchor="middle" fill="#64748b" font-size="11" font-weight="600">3개월</text>
<text x="293" y="180" text-anchor="middle" fill="#64748b" font-size="11" font-weight="600">4개월</text>
<text x="369" y="180" text-anchor="middle" fill="#64748b" font-size="11" font-weight="600">5개월</text>
<text x="445" y="180" text-anchor="middle" fill="#10192b" font-size="11" font-weight="800">6개월</text>
</svg>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { computed } from 'vue'
import { getRegionByDong } from '../utils/dataHelper'
const props = defineProps({
regionDong: {
type: String,
required: true
},
grade: {
type: String,
default: '중학생'
},
subjectName: {
type: String,
default: '영어'
}
})
const surnames = ['김', '이', '박', '최', '정', '강', '조', '윤', '장', '임', '한', '오', '서', '신', '권', '황', '안', '송']
// 동네·학년·과목에 100% 매칭되는 고유 성적 향상 스토리 동적 생성 (유사문서 방지)
const matchedStories = computed(() => {
const isHigh = (props.grade || '').includes('고등')
const isElem = (props.grade || '').includes('초등')
const dong = props.regionDong || '관내'
const regInfo = getRegionByDong(dong)
const gu = regInfo?.sigungu ? `${regInfo.sigungu} ` : ''
const sub = props.subjectName || '수학'
const seed = Array.from(dong + sub).reduce((acc, ch, i) => acc + ch.charCodeAt(0) * (i + 2), 0)
const s1 = surnames[seed % surnames.length]
const s2 = surnames[(seed + 5) % surnames.length]
const s3 = surnames[(seed + 11) % surnames.length]
if (isHigh) {
const beforeScore = 52 + (seed % 14)
const afterScore = 94 + (seed % 6)
const rankNum = 2 + (seed % 5)
return [
{
student: `${gu}${dong} 고2 ${s1}○○ 학생`,
before: `${sub} 내신 4등급 (${beforeScore}점)`,
after: `내신 1등급 (${afterScore}점)`,
period: `${3 + (seed % 2)}개월`,
review: `학원에서는 진도 따라가기 바빴는데, 선생님께서 ${gu}${dong} 인근 고교 부교재 킬러 변형 문항과 서술형 채점 조건을 1:1로 집중 지도해 주신 덕분에 생애 첫 1등급(${afterScore}점)을 받았습니다!`
},
{
student: `${gu}${dong} 고1 ${s2}○○ 학생`,
before: `중간고사 3등급`,
after: `기말고사 전교 ${rankNum}등 (1등급)`,
period: `${4 + (seed % 2)}개월`,
review: `고등학교 첫 ${sub} 시험에서 서술형 감점이 심해 좌절했었어요. 선생님과 ${dong} 기출 1:1 오답 역추적 노트를 작성하며 출제 의도를 파악하는 훈련을 하니 시험 시간이 10분이나 남았습니다.`
},
{
student: `${gu}${dong} 고3 ${s3}○○ 학부모님`,
before: `${sub} 모의고사 3등급`,
after: `수능 1등급 최저 충족`,
period: '6개월',
review: `수시 최저를 맞춰야 하는 절박한 상황에서 ${gu}${dong} 방문 1:1 과외를 시작했습니다. 취약한 킬러 유형만 집중 공략해 주셔서 원하는 목표 대학에 당당히 합격했습니다!`
}
]
} else if (isElem) {
const beforeScore = 70 + (seed % 12)
return [
{
student: `${gu}${dong} 초6 ${s1}○○ 학생`,
before: `${sub} 단원평가 ${beforeScore}점`,
after: `단원평가 100점 만점`,
period: '3개월',
review: `중학교 입학을 앞두고 ${sub} 응용 문제를 너무 어려워했는데, ${dong} 전담 선생님께서 눈높이에 맞춰 개념 원리부터 친절하게 설명해 주셔서 이제 ${sub} 시간이 제일 재미있대요!`
},
{
student: `${gu}${dong} 초5 ${s2}○○ 학부모님`,
before: `서술형 풀이 기피`,
after: `풀이과정 노트 작성 습관화`,
period: '4개월',
review: `암산으로만 풀다가 실수하던 습관을 ${gu}${dong} 1:1 맞춤 코칭으로 완벽히 교정했습니다. 스스로 식을 세우고 검산하는 습관이 잡혀 중등 선행도 시작했습니다.`
},
{
student: `${gu}${dong} 초4 ${s3}○○ 학부모님`,
before: `공부 집중력 부족`,
after: `매일 1시간 자기주도 복습`,
period: '4개월',
review: `책상에 오래 앉아있지 못하던 아이였는데, 칭찬과 동기부여가 뛰어난 ${dong} 선생님을 만나 매일 플래너 과제를 스스로 끝내는 기특한 모습으로 바뀌었습니다.`
}
]
} else {
const beforeScore = 62 + (seed % 14)
const afterScore = 96 + (seed % 5)
return [
{
student: `${gu}${dong} 중2 ${s1}○○ 학생`,
before: `${sub} ${beforeScore}점 (C등급)`,
after: `중간·기말 ${afterScore}점 (A등급)`,
period: `${3 + (seed % 2)}개월`,
review: `중학교 첫 지필고사에서 ${sub} 시험이 너무 어려워 ${beforeScore}점이었는데, 선생님께서 ${gu}${dong} 관내 중학교 교과서 핵심 개념과 서술형 풀이법을 1:1로 짚어주셔서 ${afterScore}점으로 올랐어요!`
},
{
student: `${gu}${dong} 중3 ${s2}○○ 학생`,
before: `서술형 감점 다수 (74점)`,
after: `100점 만점 달성`,
period: '4개월',
review: `알면서도 계산 실수나 조건 누락으로 틀리던 나쁜 습관을 ${dong} 1:1 밀착 검토법으로 완벽히 고쳤습니다. 이번 기말고사에서 100점 만점 맞고 고등 선행도 자신 있게 나가는 중입니다.`
},
{
student: `${gu}${dong} 중1 ${s3}○○ 학부모님`,
before: `자유학기 학습 습관 부족`,
after: `스스로 매일 2시간 복습`,
period: '5개월',
review: `중학교 입학 후 스마트폰만 해서 걱정이었는데, ${gu}${dong} 전담 선생님께서 매일 스터디 플래너를 점검하고 ${sub} 기본기를 탄탄하게 잡아주셔서 자기주도학습 습관이 완전히 잡혔습니다.`
}
]
}
})
</script>
<style scoped>
.stories-section {
background: #f4ece0;
border-top: 1px solid #e4d9c5;
border-bottom: 1px solid #e4d9c5;
padding: clamp(48px, 6vw, 72px) 16px;
margin: 0 auto 50px;
}
.stories-inner {
max-width: 1080px;
margin: 0 auto;
}
.section-header {
text-align: center;
margin-bottom: 32px;
}
.section-badge {
display: inline-block;
font-size: 0.76rem;
font-weight: 800;
letter-spacing: 0.2em;
color: #9e7a32;
margin-bottom: 6px;
}
.section-title {
font-size: clamp(1.35rem, 3.8vw, 2rem);
font-weight: 900;
color: #10192b;
letter-spacing: -0.6px;
word-break: keep-all;
line-height: 1.35;
}
.section-desc {
font-size: clamp(0.85rem, 2.2vw, 0.98rem);
color: #475569;
margin-top: 6px;
word-break: keep-all;
}
.reviews-layout-grid {
display: grid;
grid-template-columns: 5fr 7fr;
gap: 20px;
align-items: stretch;
}
.reviews-stack {
display: flex;
flex-direction: column;
gap: 18px;
}
.story-card,
.graph-story-card {
background: #ffffff;
border: 1.5px solid #dec492;
border-radius: 16px;
padding: 22px 24px;
box-shadow: 0 8px 22px rgba(16, 25, 43, 0.05);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.story-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 10px;
margin-bottom: 12px;
}
.stars {
color: #d4a038;
font-size: 0.78rem;
flex-shrink: 0;
}
.student-info {
display: block;
font-size: 0.92rem;
font-weight: 800;
color: #10192b;
margin-bottom: 4px;
}
.grade-jump {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.before {
font-size: 0.8rem;
color: #94a3b8;
text-decoration: line-through;
}
.arrow {
color: #b58e43;
font-weight: 900;
}
.after {
font-size: 0.95rem;
font-weight: 900;
color: #9e7a32;
}
.story-review {
font-size: 0.86rem;
line-height: 1.65;
color: #334155;
margin-bottom: 12px;
word-break: keep-all;
}
.story-sub {
font-size: 0.75rem;
color: #94a3b8;
border-top: 1px dashed #e4d9c5;
padding-top: 10px;
}
.chart-wrap {
background: #fbf8f3;
border: 1px solid #e4d9c5;
border-radius: 12px;
padding: 16px 18px;
}
.chart-caption {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 8px;
font-size: 0.84rem;
color: #10192b;
}
.chart-highlight {
font-size: 0.75rem;
font-weight: 800;
color: #e2c687;
background: #10192b;
padding: 3px 10px;
border-radius: 9999px;
}
.chart-svg {
width: 100%;
height: auto;
overflow: visible;
}
@media (max-width: 860px) {
.reviews-layout-grid {
grid-template-columns: 1fr;
}
}
</style>