diff --git a/app/schemas/journal.py b/app/schemas/journal.py index 9753a92..143ef78 100644 --- a/app/schemas/journal.py +++ b/app/schemas/journal.py @@ -116,10 +116,15 @@ class JournalAttachmentOut(BaseModel): has_thumbnail: bool +class JournalCalendarEntry(BaseModel): + color: str # 그 엔트리가 속한 카테고리 색상 (점 표시용) + title: str # 제목(없으면 내용 일부) + + class JournalCalendarDay(BaseModel): entry_date: date total_count: int - category_colors: list[str] # 그 날 엔트리가 있는 카테고리들의 색상(점 표시용, 중복 제거) + entries: list[JournalCalendarEntry] # 엔트리별 (색상, 제목) 쌍 — 점과 제목이 한 줄에 붙어 나오도록 1:1로 매칭 class JournalDayDetailItem(BaseModel): diff --git a/app/services/journal_service.py b/app/services/journal_service.py index a8e36fd..beeda15 100644 --- a/app/services/journal_service.py +++ b/app/services/journal_service.py @@ -23,6 +23,7 @@ from app.models.journal import ( from app.schemas.journal import ( JournalAttachmentOut, JournalCalendarDay, + JournalCalendarEntry, JournalCategoryCreate, JournalDayDetailItem, JournalEntryCreate, @@ -363,25 +364,33 @@ def get_monthly_journal_summary( last_day = date(year, month, days_in_month) stmt = ( - select(JournalEntry.entry_date, JournalCategory.color) + select(JournalEntry.entry_date, JournalCategory.color, JournalEntry.title, JournalEntry.content) .join(JournalCategory, JournalEntry.category_id == JournalCategory.id) .where(JournalEntry.user_id == user_id, JournalEntry.entry_date.between(first_day, last_day)) + .order_by(JournalEntry.entry_date, JournalEntry.created_at) ) if category_id is not None: stmt = stmt.where(JournalEntry.category_id == category_id) rows = db.execute(stmt).all() counts: dict[date, int] = {} - colors_by_date: dict[date, list[str]] = {} - for entry_date, color in rows: + entries_by_date: dict[date, list[JournalCalendarEntry]] = {} + for entry_date, color, title, content in rows: counts[entry_date] = counts.get(entry_date, 0) + 1 - colors = colors_by_date.setdefault(entry_date, []) - color = color or "var(--color-accent)" - if color not in colors: - colors.append(color) + entries = entries_by_date.setdefault(entry_date, []) + entries.append( + JournalCalendarEntry( + color=color or "var(--color-accent)", + title=title or (content[:12] + ("…" if len(content) > 12 else "")), + ) + ) return { - d: JournalCalendarDay(entry_date=d, total_count=counts[d], category_colors=colors_by_date[d]) + d: JournalCalendarDay( + entry_date=d, + total_count=counts[d], + entries=entries_by_date[d], + ) for d in counts } diff --git a/app/static/css/style.css b/app/static/css/style.css index 41c9812..88ccba0 100644 --- a/app/static/css/style.css +++ b/app/static/css/style.css @@ -872,15 +872,48 @@ label { } /* 저널링 */ -.journal-day-dots { +.calendar-cell-journal { + aspect-ratio: auto; + min-height: 76px; + padding: 6px 5px; + overflow: hidden; +} + +.calendar-cell-journal .calendar-date { + font-size: 13px; +} + +.journal-day-entries { display: flex; - gap: 2px; + flex-direction: column; + align-items: flex-start; + width: 100%; +} + +.journal-day-entry { + display: flex; + align-items: center; + gap: 4px; + width: 100%; + min-width: 0; } .journal-day-dot { - width: 5px; - height: 5px; + width: 6px; + height: 6px; border-radius: 50%; + flex-shrink: 0; +} + +.journal-day-title { + min-width: 0; + font-size: 10px; + line-height: 1.3; + color: var(--color-text-muted); + text-align: left; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .journal-prompt-card, diff --git a/app/templates/journal.html b/app/templates/journal.html index 02fcf04..91afdcc 100644 --- a/app/templates/journal.html +++ b/app/templates/journal.html @@ -252,16 +252,19 @@ {% for d in week %} {% set day_summary = summary_map.get(d) %}