학습자 레슨 뷰 — Learn 네임스페이스 컨트롤러 + 뷰 + 진행 추적 + 완료 버튼 + 테스트

ID: 87846442-92d3-4a86-9125-e4346a3ec8b2

높음 리뷰

## 목표
Learn 네임스페이스에서 학습자용 커리큘럼/레슨 뷰 구현. UserLessonProgress 생성. 완료 버튼.

## 현재 상태
- Learn::CurriculaController 스텁 (index, show)
- Learn::LessonsController 스텁 (show, complete)
- Learn::HomeController 스텁 (index)
- 라우트: `namespace :learn { get "/", to: "home#index"; resources :curricula, only: [:index, :show] do resources :lessons, only: [:show] do post :complete, on: :member end end }`
- Curriculum 모델: has_many :lessons, scope :published
- Lesson 모델: belongs_to :curriculum, has_many :user_lesson_progresses, scope :published
- UserLessonProgress 모델: belongs_to :user, belongs_to :lesson, completed(boolean), completed_at, started_at, time_spent_seconds
- User: has_many :user_lesson_progresses, has_many :lessons(through)

## 구현 사항

### 1. Learn::HomeController
```ruby
def index
@curricula = Curriculum.published.order(:position).includes(:lessons)
end
```

### 2. Learn::CurriculaController
```ruby
def index
@curricula = Curriculum.published.order(:position).includes(:lessons)
end

def show
@curriculum = Curriculum.published.find(params[:id])
@lessons = @curriculum.lessons.published.order(:position)
# 현재 유저의 진행 상태 로드
@progresses = Current.user.user_lesson_progresses
.where(lesson_id: @lessons.pluck(:id))
.index_by(&:lesson_id)
end
```

### 3. Learn::LessonsController
```ruby
def show
@curriculum = Curriculum.published.find(params[:curriculum_id])
@lesson = @curriculum.lessons.published.find(params[:id])
@progress = Current.user.user_lesson_progresses.find_or_initialize_by(lesson: @lesson)
# started_at 기록
@progress.update(started_at: Time.current) if @progress.started_at.nil?
end

def complete
@curriculum = Curriculum.published.find(params[:curriculum_id])
@lesson = @curriculum.lessons.published.find(params[:id])
progress = Current.user.user_lesson_progresses.find_or_initialize_by(lesson: @lesson)
progress.update!(completed: true, completed_at: Time.current)
redirect_to learn_curriculum_lesson_path(@curriculum, @lesson), notice: "레슨을 완료했습니다!"
end
```

### 4. 뷰
- **다크 테마** (bg-bg, bg-surface, text-text-primary, bg-accent)
- 기존 Partial 활용 (_button, _card)

**learn/home/index.html.erb**: 커리큘럼 카드 목록 + 각 커리큘럼의 진행률

**learn/curricula/index.html.erb**: 커리큘럼 목록 (published만), week 범위 표시

**learn/curricula/show.html.erb**: 커리큘럼 상세 + 레슨 목록
- 각 레슨에 완료 체크 표시 (UserLessonProgress 기반)
- content_type 아이콘 (article/video/guide)
- read_time_minutes 표시

**learn/lessons/show.html.erb**: 레슨 상세
- content_type별 렌더링 (article→simple_format, video→iframe, guide→simple_format)
- "완료" 버튼 (POST complete)
- 이미 완료된 경우 "완료됨" 표시
- 이전/다음 레슨 네비게이션

### 5. role 기반 접근 제어 (선택사항)
- Lesson의 required_role 확인: 0=free(모두 접근), 1=cohort(cohort/admin만), 2=admin
- 접근 불가 시 Flash + 리다이렉트

### ⚠️ 주의
- learn/ 범위만 수정 (developer-2는 build/ 작업 중)
- 모델 수정 불필요
- N+1 방지: includes, index_by 활용
- 한국어 Flash 메시지

### 테스트 (TDD)
- Learn::CurriculaController: index(published만), show
- Learn::LessonsController: show, complete(progress 생성), 이미 완료 시
- Learn::HomeController: index
- 인증 필요 확인
- fixture 활용

### 완료 기준
- 커리큘럼/레슨 목록 페이지
- 레슨 상세 컨텐츠 표시
- "완료" 버튼 → progress 레코드 생성
- 완료 레슨 체크 표시
- bin/rails test 전체 통과

첨부 이미지

이미지 추가 (Ctrl+V로 붙여넣기 또는 클릭)

JPEG, PNG, GIF, WebP / 최대 10MB

담당자: developer-1
생성일: 2026년 03월 26일 09:31

활동 로그

  • D
    developer-1 상태 변경: 할 일 → 리뷰

    2026년 03월 26일 09:35:40