Files
web_6ea_educo/site4/components/SubjectMastery.vue
T
2026-10-07 11:08:05 +09:00

331 lines
8.1 KiB
Vue

<template>
<section class="mastery-section">
<div class="section-header">
<span class="section-badge">{{ curriculum.name }} 1:1 집중 클리닉</span>
<h2 class="section-title">{{ regionDong }} {{ grade }} {{ curriculum.name }} 1등급 커리큘럼</h2>
<p class="section-desc">{{ curriculum.slogan }}</p>
</div>
<!-- 오직 해당 학년(중학생이면 중학생, 고등학생이면 고등학생)의 커리큘럼만 단일 타겟팅 렌더링 -->
<div v-if="targetGradeData" class="grade-focus-grid single-grade-view">
<!-- 카드 1: 출제 패턴 및 핵심 목표 -->
<div class="grade-focus-card">
<div class="grade-header">
<span class="grade-pill">{{ grade }} {{ curriculum.name }} 집중 솔루션</span>
<h3 class="focus-title">{{ targetGradeData.focus }}</h3>
</div>
<p class="exam-pattern-box">
<span class="badge-tag">{{ regionDong }} 내신 실전 출제 패턴</span>
{{ targetGradeData.examPattern }}
</p>
<ul class="points-list">
<li v-for="(pt, pIdx) in targetGradeData.points" :key="pIdx">
<span class="check-bullet">•</span>
<span class="pt-text">{{ pt }}</span>
</li>
</ul>
</div>
<!-- 카드 2: 1:1 맞춤 지도 세부 실행 로드맵 -->
<div class="grade-focus-card roadmap-card">
<div class="grade-header">
<span class="grade-pill accent-pill">1:1 밀착 코칭 전략</span>
<h3 class="focus-title">{{ grade }} {{ curriculum.name }} 성적 역전 3단계</h3>
</div>
<div class="roadmap-steps">
<div class="rm-step">
<div class="rm-badge">STEP 1</div>
<div>
<strong>기초 개념 & 오답 4분류 태깅</strong>
<p>자주 틀리는 개념 구멍을 즉시 메우고 오답 원인을 정밀 추적합니다.</p>
</div>
</div>
<div class="rm-step">
<div class="rm-badge">STEP 2</div>
<div>
<strong>학교 기출 변형 & 서술형 킬러 완파</strong>
<p>{{ regionDong }} 학교별 기출 족보와 부교재 변형 문제를 반복 훈련합니다.</p>
</div>
</div>
<div class="rm-step">
<div class="rm-badge">STEP 3</div>
<div>
<strong>실전 타임어택 & 서술형 감점 0점화</strong>
<p>실제 시험 시간과 동일한 환경에서 서술형 채점표 기준 감점을 방지합니다.</p>
</div>
</div>
</div>
</div>
</div>
<!-- 핵심 솔루션 3단계 스킬 (해당 과목 고유 스킬) -->
<div class="skills-wrap">
<h3 class="skills-title">{{ grade }} {{ curriculum.name }} 1등급 도약을 위한 3대 핵심 솔루션</h3>
<div class="skills-grid">
<div v-for="(sk, sIdx) in curriculum.skills" :key="sIdx" class="skill-item">
<div class="skill-num">0{{ sIdx + 1 }}</div>
<h4 class="skill-name">{{ sk.title }}</h4>
<p class="skill-desc">{{ sk.desc }}</p>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
regionDong: {
type: String,
required: true
},
grade: {
type: String,
default: '중학생'
},
curriculum: {
type: Object,
required: true
}
})
// 고등학생이면 고등학생 데이터, 중학생이면 중학생 데이터만 100% 매칭하여 단일 추출
const targetGradeData = computed(() => {
if (!props.curriculum || !props.curriculum.grades) return null
const isHigh = (props.grade || '').includes('고등')
if (isHigh) {
const found = props.curriculum.grades.find(g => g.grade.includes('고등'))
return found || props.curriculum.grades[1] || props.curriculum.grades[0]
} else {
const found = props.curriculum.grades.find(g => g.grade.includes('중학'))
return found || props.curriculum.grades[0]
}
})
</script>
<style scoped>
.mastery-section {
max-width: 1080px;
margin: 0 auto 50px;
padding: 0 16px;
}
.section-header {
text-align: center;
margin-bottom: 28px;
}
.section-badge {
display: inline-block;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: var(--badge-bg, rgba(30, 58, 138, 0.08));
padding: 5px 12px;
border-radius: 9999px;
margin-bottom: 8px;
}
.section-title {
font-size: clamp(1.3rem, 3.8vw, 1.95rem);
font-weight: 800;
color: var(--text-color, #1e293b);
letter-spacing: -0.6px;
word-break: keep-all;
line-height: 1.35;
}
.section-desc {
font-size: clamp(0.85rem, 2.2vw, 0.98rem);
color: #64748b;
margin-top: 6px;
word-break: keep-all;
}
.grade-focus-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 18px;
margin-bottom: 30px;
}
.grade-focus-card {
background: var(--bg-card, #ffffff);
border: 1px solid var(--border-color, #e2e8f0);
border-radius: var(--card-radius, 14px);
padding: clamp(18px, 3.5vw, 24px);
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.04);
display: flex;
flex-direction: column;
}
.grade-header {
margin-bottom: 12px;
}
.grade-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 800;
color: #ffffff;
background: var(--primary-color, #1e3a8a);
padding: 3px 10px;
border-radius: 9999px;
margin-bottom: 6px;
}
.grade-pill.accent-pill {
background: var(--accent-color, #d97706);
}
.focus-title {
font-size: clamp(1.02rem, 2.5vw, 1.2rem);
font-weight: 800;
color: var(--text-color, #0f172a);
letter-spacing: -0.4px;
}
.exam-pattern-box {
background: #f8fafc;
border-left: 3px solid var(--accent-color, #d97706);
padding: 10px 12px;
border-radius: 4px;
font-size: clamp(0.78rem, 2vw, 0.86rem);
line-height: 1.55;
color: #334155;
margin-bottom: 14px;
word-break: keep-all;
}
.badge-tag {
display: block;
font-weight: 800;
color: var(--accent-color, #d97706);
margin-bottom: 3px;
font-size: 0.82em;
}
.points-list {
list-style: none;
display: flex;
flex-direction: column;
gap: 10px;
}
.points-list li {
display: flex;
align-items: flex-start;
gap: 8px;
font-size: clamp(0.8rem, 2vw, 0.88rem);
color: #475569;
line-height: 1.5;
word-break: keep-all;
}
.check-icon {
color: #10b981;
font-weight: 900;
flex-shrink: 0;
}
.roadmap-steps {
display: flex;
flex-direction: column;
gap: 12px;
margin-top: 6px;
}
.rm-step {
display: flex;
gap: 10px;
align-items: flex-start;
}
.rm-badge {
font-size: 0.7rem;
font-weight: 800;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 2px 6px;
border-radius: 4px;
flex-shrink: 0;
margin-top: 2px;
}
.rm-step strong {
display: block;
font-size: 0.86rem;
color: #1e293b;
margin-bottom: 2px;
}
.rm-step p {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.skills-wrap {
background: var(--skills-bg, #f8fafc);
border: 1px solid var(--border-color, #e2e8f0);
border-radius: var(--card-radius, 14px);
padding: clamp(20px, 4vw, 30px);
}
.skills-title {
font-size: clamp(1.05rem, 2.8vw, 1.3rem);
font-weight: 800;
color: var(--text-color, #0f172a);
text-align: center;
margin-bottom: 20px;
letter-spacing: -0.4px;
}
.skills-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
}
.skill-item {
background: #ffffff;
border: 1px solid var(--border-color, #e2e8f0);
border-radius: 10px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
}
.skill-num {
font-size: 1.1rem;
font-weight: 900;
color: var(--accent-color, #d97706);
margin-bottom: 4px;
}
.skill-name {
font-size: clamp(0.9rem, 2.2vw, 1rem);
font-weight: 800;
color: var(--text-color, #1e293b);
margin-bottom: 6px;
}
.skill-desc {
font-size: clamp(0.78rem, 1.9vw, 0.85rem);
color: #64748b;
line-height: 1.5;
word-break: keep-all;
}
@media (max-width: 768px) {
.grade-focus-grid {
grid-template-columns: 1fr;
}
.skills-grid {
grid-template-columns: 1fr;
}
}
</style>