Commit graph

612 commits

Author SHA1 Message Date
0b730405a6 fix(x-bot): 만료되는 트위터 카드 이미지를 원본 OG 이미지로 대체
Nitter가 주는 pbs.twimg.com/card_img 이미지는 시간이 지나면 404로
만료됨. resolveCard에서 카드 이미지가 없거나 해당 만료성 URL이면
원본 URL의 OG 이미지(i.ytimg 등 안정적)로 대체.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 09:30:59 +09:00
134f5836b7 fix(x-bot): OG 카드 엔티티 디코딩 + YouTube 이미지 보강
- 스크래퍼가 Nitter HTML 엔티티(&#x2F; &amp; 등)를 디코딩하지 않아
  본문/카드 제목에 [JP&#x2F;EN]처럼 노출되던 문제 수정 (extractCard,
  extractTextFromHtml에 decodeEntities 적용)
- resolveCard가 Nitter 카드에 제목만 있고 이미지가 없을 때 OG로 이미지를
  보강하도록 변경 (YouTube 카드 이미지 누락 복구)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 09:26:54 +09:00
3ba27c0100 style(festival-bot): 봇 관리 페이지 축제 섹션 색상 amber로 변경
typeConfig.festival 색상을 emerald → amber로 변경해 다이얼로그·축제
카테고리 색감과 통일.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:06:07 +09:00
de6e56047c style(festival-bot): 다이얼로그 색상 축제 카테고리 톤(amber)으로 변경
초록(emerald) → amber 계열로 변경해 행사/축제 색감과 통일.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:04:38 +09:00
543371db23 feat(festival-bot): 비활성 월일 때 '대기 중' 상태 표시
봇 목록 API에 active_months 노출. 봇이 켜져 있어도 현재 달이 활성
월이 아니면 카드 상태를 초록 '실행 중' 대신 amber '대기 중'으로 표시.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:04:38 +09:00
d24f8cabe3 docs(api): 축제 봇 active_months 필드 문서화
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:59:03 +09:00
2af3af9345 feat(festival-bot): 다이얼로그에 활성 월 선택 UI
축제 봇 추가/수정 다이얼로그에 1~12월 토글 그리드 + 전체 선택/해제
추가. 신규 봇은 전체 월(항상 실행) 기본. 전체 선택은 active_months
null로 저장.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:58:13 +09:00
8b36e9b5f7 feat(festival-bot): active_months API + 축제 봇 전용으로 한정
- botMonths 유틸(parse/serialize) 추가, 빈배열·전체선택은 NULL 정규화
- 축제 봇 라우트 조회/생성/수정에 active_months 반영 (수정 시 봇 재시작으로 즉시 적용)
- 봇별 설정이 이미 분리돼 있어 x/youtube에는 미적용 — DB 컬럼/스케줄러 매퍼에서 제외
- 스케줄러 isActiveMonth 게이트는 범용 유지(미설정 봇은 항상 실행)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:56:26 +09:00
fa37891ab3 feat(bots): 스케줄러에 활성 월 게이트 추가
봇 매퍼에 activeMonths 파싱 추가. cron 콜백·즉시 실행 시 현재 KST
월이 활성 월에 포함될 때만 동기화 실행(매 실행 시점 재평가). NULL/
빈배열/12개 전체는 항상 실행. date.js에 monthKST() 헬퍼 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:52:26 +09:00
604142672e feat(bots): active_months 컬럼 추가 (시즌성 봇 실행 월 제한)
bot_festival/bot_x/bot_youtube에 active_months JSON 컬럼 추가.
NULL=전체 월(항상 실행), 정수 배열이면 해당 월에만 동기화.
대학 축제 봇처럼 시즌에만 도는 봇의 불필요한 API 호출 절약.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:49:35 +09:00
39a6225897 feat(schedule-mobile): 날짜 미정 일정 렌더링 (B안)
모바일 일정 페이지에 date_precision='month' 일정을 점선 "N월 중"
카드(UndatedScheduleListCard)로 표시. 선택 날짜와 무관하게 해당
달이면 확정 일정 아래 "날짜 미정" 구분선과 함께 배치.
캘린더/날짜 점은 1일에 찍지 않도록 PC·모바일 dot 목록에서 제외.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 20:27:07 +09:00
39aadf50e6 feat(schedule-pc): 날짜 미정 일정 렌더링 (B안)
date_precision='month' 일정을 점선 "N월 중" 카드(UndatedScheduleCard)로
표시. 선택 날짜와 무관하게 해당 월이면 확정 일정 아래에 배치하고
사이에 "날짜 미정" 구분선 추가. 카운트에도 포함.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 20:10:26 +09:00
44d30d48f6 feat(schedule): 조회 응답에 datePrecision 포함
목록(SCHEDULE_LIST_SQL)·상세(getScheduleDetail) 쿼리/포맷터가
date_precision을 반환하도록 추가. 기본값 'day'. 공개 페이지에서
'month'인 일정을 날짜 미정으로 렌더링하기 위한 읽기 지원.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 18:44:08 +09:00
17746581e1 feat(schedule): date_precision 컬럼 추가 (날짜 미정 일정 지원)
월만 확정된 일정을 위해 schedules에 date_precision ENUM('day','month')
추가. 기본값 'day'로 기존 일정/쿼리에 영향 없음. month인 경우
date는 해당 월 1일로 저장하고 확정 시 수정에서 정확한 날짜 입력.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 18:34:24 +09:00
01cf1cfe9a fix(mobile-schedule): 카테고리 칩 자동 숨김 제거
스크롤 방향 감지 자동 숨김이 sticky 바의 transform 전환과
충돌해 리스트 상단에서 위로 스크롤 시 떨림 발생.
항상 보이는 단순 sticky 칩 바로 변경.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 15:04:45 +09:00
f6ba4c8183 feat(mobile-members): 매거진 풀블리드 스티키 스택 디자인
- 멤버를 화면 폭 전체 화보 카드로 (한글명 + 생일/나이 + 인스타)
- 스티키 스택: 스크롤 시 다음 카드가 이전 카드를 덮으며 흐려짐/축소
- 스크롤 멈추면 가장 가까운 카드를 상단에 자석처럼 스냅
- 마지막 카드도 상단까지 올라오도록 동적 하단 여유 공간

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 14:47:37 +09:00
9b2e4e190d feat(mobile-schedule): 카테고리 필터 추가 + 리스트 카드 플랫화
- 일정 리스트 위에 카테고리 필터 칩 추가 (해당 달 전체 카테고리)
- 스크롤 방향 감지 자동 숨김 (내리면 숨고 올리면 보임), 상단 여백 일관
- 카테고리 선택 시 일정 목록 + 날짜 점 필터링 (공개 PC와 store 공유)
- 일정 리스트 카드: 그림자 제거, 1.5px 테두리로 플랫하게

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 14:10:16 +09:00
381461c25e fix(event): 모바일 축제 포스터 클릭 시 라이트박스로 열기
새 창(target=_blank) → MobileLightbox로 변경 (메인/추가 포스터 모두).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 13:48:57 +09:00
1a50f93d65 feat(event): 축제 상세 페이지 디자인 개편
- 골드 그라데이션 단일 히어로로 통합 (타입/학교/제목/날짜/장소/멤버/링크)
- 장소는 히어로에서 클릭 → 지도 다이얼로그(PC 모달/모바일 바텀시트)
- 칩(타입·학교·멤버·링크)을 흰 배경 + 앰버 글자로, 텍스트 그림자 추가
- 모바일: 포스터를 카드와 분리해 크게 표시 + 스크롤 패럴랙스/페이드

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 13:46:20 +09:00
c0ac18060d fix(admin-schedule): 카테고리 필터를 공개 페이지와 통일
- categoryCounts를 선택 날짜와 무관하게 해당 달 전체 기준으로 변경
- 달력 점도 카테고리 필터 반영

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 12:54:47 +09:00
70fb6527fe fix(event): 학교 축제 상세 날짜 옆 배지를 학교명 → 축제 타입으로
학교명은 이미 제목에 포함되어 중복이므로 '대학 축제' 타입 표시로 변경.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 12:50:32 +09:00
2ddc16d532 feat(concert): 콘서트 상세 페이지 추가 (몰입형 디자인)
기존 DefaultSection으로 빈약하게 표시되던 콘서트를 전용 상세 페이지로.

백엔드:
- getScheduleDetail 콘서트 분기: 포스터/장소/세트리스트(곡별 멤버)/굿즈/다른 회차

프론트엔드:
- ConcertSection(PC) / MobileConcertSection(모바일) 신규
- 블러 포스터 히어로 + 회차 드롭다운 + 장소 지도 다이얼로그
- 세트리스트 펼치기/접기 애니메이션, 유닛/솔로만 멤버 태그
- 굿즈 masonry 갤러리(라이트박스), 회차 전환은 history replace
- 모바일은 세로 중앙형 전용 히어로 + 바텀시트
- Lightbox/MobileLightbox를 createPortal로 변경 (오버레이 전체화면 보장)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 23:20:48 +09:00
dd5ef48592 feat(schedule): 검색 결과 없음 UI 추가 및 빈 상태 위치 개선
- PC: 검색 모드에서 결과 0개일 때 아무것도 안 나오던 문제 수정
  (돋보기 아이콘 + 검색어 표시), 검색 중 로딩 구분
- 모바일: 검색/날짜별 빈 상태를 아이콘 포함 디자인으로 통일
- 빈 상태/로딩을 일정 영역 기준으로 배치
  (PC: 상단 30% 지점, 모바일: 중앙)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 22:15:10 +09:00
8b8b9a7f53 feat(x-schedule): 링크 미리보기(OG) 카드 추가 - 하이브리드
트윗의 외부 링크에 대해 미리보기 카드 표시.
- Nitter가 렌더링한 카드 우선 사용 (extractCard)
- Nitter 카드가 비어있으면 본문 URL로 OG 직접 추출 (og.js)
  - YouTube/Instagram 등 복구, HTML 엔티티 디코딩 포함
  - TikTok 등 봇 차단 사이트는 Nitter 카드로 커버
- schedule_x.card_data 컬럼 + getScheduleDetail 응답에 card 포함
- 가로 레이아웃 카드 (왼쪽 이미지 + 오른쪽 텍스트)
- CardImage: 이미지 로드 실패 시 fallback 아이콘 (인스타 CDN 만료 대비)
- 자체 영상/이미지가 있으면 OG 카드 숨김 (중복 방지)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 19:34:42 +09:00
d3d3c9cf75 feat(x-schedule): 트윗 네이티브 영상 썸네일 표시
Nitter는 영상 파일을 제공하지 않으므로 썸네일만 추출해 표시하고,
재생 시 원본 트윗으로 이동.

- scraper: extractVideoThumbnails 추가 (amplify_video_thumb 등)
- schedule_x.video_thumbnails 컬럼 + saveTweet 저장
- getScheduleDetail 응답에 videoThumbnails 포함
- PC/모바일 X 상세: 썸네일 + 재생버튼 + 'X에서 재생' 배지

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 19:02:29 +09:00
4cfa4ffc00 fix(x-bot): 리트윗 이중 저장 방지
같은 리트윗이 타임라인에서 래퍼 id / 원본 id 두 형태로 번갈아 나타나
post_id 중복 체크를 통과해 두 번 저장되던 문제 수정.

리트윗 저장 시 동일 내용 + (원작자 또는 봇계정) username이 이미 있으면
중복으로 간주해 건너뜀. hydration으로 양쪽 모두 전체 내용을 갖추므로
내용 기반 매칭이 안정적으로 동작.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 18:02:22 +09:00
2cfc580283 fix(x-bot): 잘린 긴 리트윗 전체 내용 복원 (hydration)
X long tweet(280자 초과)을 Nitter 타임라인이 간헐적으로 …로 잘라서
주는 경우, 개별 상태 페이지에서 재요청해 전체 내용으로 교체.

- parseTweets: …로 끝나는 트윗에 truncated 플래그 부여
- hydrateTruncatedTweets: 잘린 트윗 status 페이지 재요청 후 교체 (best-effort)
- fetchTweets/fetchAllTweets에 적용
- fetchSingleTweet을 timeout-safe하게 변경

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 18:00:14 +09:00
6a24b997dd feat(logs): 활동 로그 다이얼로그 상세 정보 표시 + 에러 정보 보강
- logs API: longtext로 저장된 details를 JSON 객체로 파싱해 반환
- 응답 스키마에 additionalProperties: true 추가 (fast-json-stringify가
  스키마 미정의 키를 제거하던 문제 해결)
- scheduler 에러 로그: err.cause / err.code / err.causeCode 함께 기록
  (fetch failed 등 모호한 메시지의 진짜 원인 식별 가능)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 17:02:53 +09:00
9e3bff9762 feat(schedule): 카테고리 필터 개선 및 달력 오늘 버튼 추가
- 카테고리 카운트를 선택 날짜와 무관하게 해당 달 전체 기준으로 변경
- 카테고리 섹션이 길어지면 카드 내부 스크롤 (평소엔 콘텐츠 크기 유지)
- 달력 하단에 오늘 날짜로 이동하는 버튼 추가
- 달력 하단 여백 24px → 20px

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 22:47:13 +09:00
51e8f17cc1 feat(schedule): 카테고리 선택 시 달력 점도 필터링
카테고리 필터가 일정 목록만 필터링하던 것을 달력 점에도 적용.
날짜 필터는 제외하여 달력은 한 달 전체 점을 유지.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 22:35:12 +09:00
d530822a68 feat(festival-bot): 대학 축제 크롤러 봇 구현 (3단계)
검색 페이지(memogipost)를 크롤링하여 프로미스나인 출연 대학 축제를
Gemini url_context로 추출, 행사 일정을 자동 생성하는 봇.

백엔드:
- services/event.js: 이벤트 생성 로직 공유화 (upsertVenue, createEventSchedule, 카카오 검색)
- services/festival/: scraper(검색 페이지 크롤) + gemini(추출) + index(봇 플러그인)
- routes/admin/festival-bots.js: 축제 봇 CRUD API
- scheduler.js: festival 타입 지원, 시간 단위 cron(0 */H * * *) 변환
- 처리한 글 URL은 festival_crawl_log에 기록, 새 글 없으면 Gemini 미호출
- 학교명 부분일치 중복 감지, 활동 멤버 전체 자동 등록
- Gemini 503/500/429 재시도 로직

기타 수정:
- 행사 상세 페이지 관련 링크 줄바꿈 (truncate → break-all)
- 대학 축제 아이콘 변경 (GraduationCap → PartyPopper)
- docs/api.md, CLAUDE.md 환경변수 문서화

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 22:28:24 +09:00
3827a23d75 feat(festival-bot): 축제 봇 관리 UI 추가 (2단계)
- bot_festival, festival_crawl_log 테이블 SQL
- FestivalBotDialog: 봇 이름/크롤링 URL/동기화 간격(1~24시간) 입력
- 봇 관리 페이지에 '축제' 섹션 추가 (emerald, PartyPopper)
- BotCard: festival 타입 수정/삭제 버튼 표시
- API 클라이언트 함수 추가 (백엔드 라우트는 3단계)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 22:09:07 +09:00
2e459995c3 fix(event): 세부 타입 라벨 '학교 축제' → '대학 축제'
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 21:50:12 +09:00
bcc8555193 feat(youtube-bot): 제목에서 멤버 추출 옵션 추가
- bot_youtube에 extract_members_from_title 컬럼 추가 (기본값 0)
- services/youtube/index.js: 설명과 제목에서 각각 멤버 이름 검색, 합집합으로 중복 제거
- YouTubeBotDialog 고급 설정에 토글 추가 (설명 추출 토글 아래)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:50:02 +09:00
678e228bc5 feat(x-bot): 관리 YouTube 채널 영상 제외 옵션 추가
- bot_x에 exclude_managed_channels 컬럼 추가 (기본값 1, 기존 동작 유지)
- X 봇이 트윗에서 YouTube 링크를 추출할 때 이미 등록된 YouTube 봇 채널의 영상을 중복 추가할지 옵션으로 제어
- XBotDialog에 토글 추가 (extract_youtube 활성 시만 노출, 왼쪽 border로 하위 옵션 시각화)
- services/x/index.js processYoutubeLinks 시그니처에 옵션 파라미터 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:45:45 +09:00
9e87549ca3 style(admin): 곡 검색 다이얼로그 선택 순서 번호 표시
- 체크 아이콘 대신 선택 순서(1, 2, 3...) 숫자 뱃지 표시
- 선택 해제 시 남은 곡 번호 자동 재계산
- 숫자 시각 중심 보정 (leading-none + translate-y)
- 순서는 이미 클릭 순서대로 세트리스트에 추가됨 (selectedTracks push 순서 유지)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:25:42 +09:00
18efd952c4 style(admin): 세트리스트 드래그앤드롭 재정렬 추가
- framer-motion의 Reorder를 사용해 세트리스트 곡 순서를 드래그로 변경 가능
- 카드 왼쪽에 GripVertical 핸들 영역 분리, 오른쪽에 기존 폼 필드
- 내부 input/버튼은 드래그 임계값 덕분에 자유롭게 조작 가능

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:22:14 +09:00
5472725e9c style(admin): 콘서트 굿즈 섹션 UI 개선 + 드래그앤드롭 재정렬
- 그리드 4열 레이아웃으로 전환해 카드 공백감 해소
- 세로 이미지 잘림 방지: aspect-[3/4] + object-contain + 회색 배경
- 호버 시 삭제 버튼 노출, 순서 뱃지 상시 표시
- 마지막 칸에 '+ 추가' 점선 타일 추가 (다중 업로드 가능)
- @dnd-kit 기반 드래그앤드롭 재정렬 도입 (DragOverlay, rectSortingStrategy)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:13:20 +09:00
2564e1ddef style(admin): 콘서트/예능 수정 폼 너비를 추가 폼과 통일
수정 폼이 화면 전체 너비를 쓰던 문제를 max-w-4xl 컨테이너로 감싸 추가 페이지와 동일하게 맞춤.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:04:17 +09:00
7c20e9bb17 feat(schedule): 행사 수정 폼 + 공개 상세 페이지 + 지도
- Admin: EventEditForm 추가 (기존 포스터 유지 + 신규 추가 조합), ScheduleItem 편집 경로에 '행사' 분기
- PC 공개 상세: EventSection 추가 - 포스터 Swiper 슬라이드 + 호버 화살표, 클릭 시 Lightbox, 카카오맵 + 마커 + 장소명 오버레이, 관련 링크는 중간점+primary 색상, max-w-5xl 및 text-2xl로 크기 확대
- Mobile 공개 상세: MobileEventSection 추가 (포스터/장소/지도/링크)
- KakaoMap 공용 컴포넌트 신규 (SDK 1회 로드 공유), VITE_KAKAO_JS_KEY 사용
- .gitignore: frontend/.env 제외
- routes/admin/events.js: PUT 핸들러의 addOrUpdateSchedule → syncScheduleById 정정
- 관련 문서(api/architecture/development) 업데이트

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 12:24:01 +09:00
d9836d2f5d feat(schedule): 행사 카테고리 추가 (학교 행사)
- schedule_categories에 '행사' 카테고리(id=11) 시드, CATEGORY_IDS.EVENT 상수 추가
- event_venues / schedule_event 테이블 생성 (subtype, school_name, venue_id, post_urls, poster_image_ids)
- routes/admin/events.js 신설: multipart 기반 CRUD + 다중 포스터 업로드 + 카카오맵 venue upsert
- services/image.js에 uploadEventPoster 추가 (event/{scheduleId}/poster/...)
- 공개 /schedules 서비스의 SCHEDULE_LIST_SQL / getScheduleDetail에 행사 JOIN 및 응답(subtype, schoolName, venue, posters, postUrls)
- buildSource에 EVENT 분기 추가 → source.name = 학교명
- Meilisearch 동기화: source_name에 school_name 포함, 부분 검색 대응을 위한 resolveSchoolNames 추가
- 프론트: form/index.jsx에 '행사' 분기, EventForm 컴포넌트 신설 (LocationSearchDialog 재사용, 다중 포스터/URL)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 09:04:42 +09:00
f2a15e07d6 feat(youtube-bot): 주간 지정 시간 폴링 모드 추가
- bot_youtube에 weekly_schedule_config JSON 컬럼 추가, cron_interval nullable로 변경
- weekly 모드: 지정 요일/시각에만 cron 트리거 → setInterval로 intervalSeconds 간격 폴링
- 종료 조건: 새 영상 1개 발견(stopOnFound) 또는 durationMinutes 경과
- 평상시 API 호출 없어 주 1회 업로드 채널(워크맨 등)의 할당량 낭비 최소화
- 프론트 폼에 상시/주간 모드 토글 추가, 요일 드롭다운 월~일 순서로 정렬
- 관련 문서(api/development/architecture) 갱신

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 20:56:54 +09:00
39bb6f77f9 feat(admin): 활동 로그 페이지에 페이지 번호 직접 입력 기능 추가
- 페이지네이션을 3-column grid로 배치해 버튼 그룹은 중앙 정렬, 오른쪽 구석에 입력 박스 추가
- 숫자만 입력, Enter 또는 blur 시 페이지 이동 (1~totalPages로 clamp)
- Enter 시 blur() 호출로 포커스 자동 해제

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 11:47:59 +09:00
8ece4b1850 feat(backend): 봇 연속 오류 시 자동 정지 로직 추가
- consecutiveErrors 카운터로 실패 횟수 추적 (성공 시 0으로 리셋)
- 동일 에러 루프에서 sync/error 로그는 첫 1회만 기록하여 스팸 방지
- 10회 연속 실패 시 stopBot 호출 및 bot/stop 로그 1건 남김
- docs/logs.md, docs/development.md 관련 설명 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 11:38:37 +09:00
f73314d5dc feat(app): 예능 일정 상세 화면 추가
- ScheduleDetail 모델: broadcaster, replayUrl, varietyThumbnailUrl 필드 추가
- 예능 섹션: 썸네일(블러 배경 + contain) + 정보 카드
- 방송사 뱃지(카테고리 색상), 날짜/시간, 제목, 멤버, 다시보기 버튼
- 썸네일 없을 때 카테고리 색상 배경 + Tv 아이콘 표시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:06:06 +09:00
aae606725f feat(mobile): 앨범/곡/컨셉포토 상세 페이지 뒤로가기 버튼 추가
- MobileHeader에 showBack prop 추가 (ChevronLeft + history.back)
- Layout에 showBack 전달
- 라우터에서 상세 페이지에 showBack 적용
- 개별 페이지의 중복 액션바 제거

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:16:19 +09:00
901d788d9a feat(mobile): 일정 상세 페이지 액션바에 뒤로가기 버튼 추가
- ChevronLeft 아이콘 + history.back()
- 오른쪽 w-9 빈 영역으로 제목 중앙 정렬 유지

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:11:35 +09:00
1626091539 style(mobile): 일정 상세 액션바 카테고리 텍스트 font-bold로 변경
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:09:38 +09:00
aaec7fa071 style(mobile): 예능 썸네일 블러 배경 + 높이 축소
- 높이 h-52로 고정
- 배경에 동일 이미지를 scale-110 blur-2xl로 깔아서 빈 공간 채움
- 메인 이미지는 object-contain으로 원본 비율 유지

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:07:46 +09:00
45819f7a01 style(pc): 예능 상세 썸네일/정보 가로 배치, 높이 독립
- 썸네일: w-52 h-72 고정, object-cover
- 정보 카드: flex-1, 콘텐츠에 따라 높이 자유
- items-start로 서로 높이 영향 없음

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:05:37 +09:00