하이라이트 Stimulus 컨트롤러 + UI
ID: 7ee09279-4408-42be-a612-5b1882a5e413
## 목표
bible_passage_controller.js를 확장하여 성경 절 하이라이트 기능 구현
## 의존성
- highlight-backend 에이전트가 모델 + API를 먼저 완성해야 함
- API 엔드포인트: GET/POST/DELETE /api/bible/highlights
## 구현 내용
### 1. bible_passage_controller.js 수정
기존 bible_passage_controller.js에 하이라이트 기능을 직접 추가합니다.
#### 새 Stimulus values 추가
```javascript
static values = {
passage: String,
highlightable: { type: Boolean, default: false } // 하이라이트 활성화 여부
}
```
#### 새 Stimulus targets 추가
```javascript
static targets = ["content", "loading", "error", "colorPopover"]
```
#### 주요 메서드
1. **renderVerses() 수정** - 기존 절 렌더링에 하이라이트 CSS 적용
- 각 verse를 `` 으로 감싸기
- 기존 하이라이트가 있으면 배경색 클래스 적용
2. **loadHighlights()** - 페이지 로드 시 API에서 기존 하이라이트 조회
```javascript
async loadHighlights() {
if (!this.highlightableValue) return
const resp = await fetch(`/api/bible/highlights?book=${this.bookAbbrev}&chapter=${this.chapter}`)
const highlights = await resp.json()
highlights.forEach(h => this.applyHighlight(h.verse, h.color))
}
```
3. **toggleHighlight(event)** - 절 클릭 시 색상 팝오버 표시
```javascript
toggleHighlight(event) {
if (!this.highlightableValue) return
const verse = event.currentTarget.dataset.verse
this.showColorPopover(event.currentTarget, verse)
}
```
4. **showColorPopover(target, verse)** - 색상 선택 팝오버
- 5색 버튼: yellow, green, blue, pink, purple
- 이미 하이라이트된 절이면 "삭제" 버튼도 표시
- 절 위에 popover로 표시 (position: absolute)
- 외부 클릭 시 닫기
5. **selectColor(event)** - 색상 선택 → API 호출
```javascript
async selectColor(event) {
const color = event.currentTarget.dataset.color
const verse = this.currentVerse
const resp = await fetch('/api/bible/highlights', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.csrfToken },
body: JSON.stringify({ highlight: { book_abbrev: this.bookAbbrev, chapter: this.chapter, verse: parseInt(verse), color } })
})
if (resp.ok) {
this.applyHighlight(verse, color)
this.hideColorPopover()
}
}
```
6. **removeHighlight(event)** - 하이라이트 삭제
```javascript
async removeHighlight() {
const highlightId = this.highlightMap.get(parseInt(this.currentVerse))
await fetch(`/api/bible/highlights/${highlightId}`, {
method: 'DELETE',
headers: { 'X-CSRF-Token': this.csrfToken }
})
this.clearHighlight(this.currentVerse)
this.hideColorPopover()
}
```
7. **applyHighlight(verse, color)** - DOM에 배경색 적용
- 색상 매핑:
- yellow: bg-yellow-100 dark:bg-yellow-900/30
- green: bg-emerald-100 dark:bg-emerald-900/30
- blue: bg-blue-100 dark:bg-blue-900/30
- pink: bg-pink-100 dark:bg-pink-900/30
- purple: bg-purple-100 dark:bg-purple-900/30
### 2. 색상 팝오버 UI
```html
```
### 3. qt/today.html.erb 수정
기존 bible_passage 파셜 사용 부분에 `highlightable: true` 추가:
```erb
```
### 4. 색상 팝오버 파셜 (선택)
- 동적 JS 생성이면 파셜 불필요
- 정적 파셜이면 `app/views/shared/_color_popover.html.erb`
## 주의사항
- CSRF 토큰: `document.querySelector('meta[name="csrf-token"]').content`
- 기존 bible_passage_controller.js의 parsePassageReference()에서 bookAbbrev 추출 필요
- 하이라이트 Map으로 verse→{id, color} 매핑 관리
- 다크모드 대응 필수 (bg-yellow-100 + dark:bg-yellow-900/30)
- 모바일: 탭으로 절 선택 (hover 없음)
- 기존 테스트 전체 통과 확인
첨부 이미지
이미지 추가 (Ctrl+V로 붙여넣기 또는 클릭)
JPEG, PNG, GIF, WebP / 최대 10MB
활동 로그
-
팀팀리드 상태 변경: 할 일 → 완료
2026년 03월 03일 04:08:49