From 8a497578828b9c97939104478dbeb73b6683e9e3 Mon Sep 17 00:00:00 2001 From: shinalok Date: Wed, 19 Aug 2026 17:13:33 +0900 Subject: [PATCH] enlarge journal calendar cells and pair day/title on one line - calendar-cell-journal: bump min-height 44px -> 76px, scale up date/dot/title font sizes - journal calendar titles were centered; left-align them - rework JournalCalendarDay: replace separate category_colors/titles lists (mismatched lengths, no way to pair a dot with its title) with a single entries list of (color, title) pairs so the dot and its title render on the same non-wrapping row per entry Co-Authored-By: Claude Sonnet 5 --- app/schemas/journal.py | 7 +++++- app/services/journal_service.py | 25 +++++++++++++------- app/static/css/style.css | 41 +++++++++++++++++++++++++++++---- app/templates/journal.html | 11 +++++---- tests/test_journal_service.py | 2 +- 5 files changed, 68 insertions(+), 18 deletions(-) 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) %}
{{ d.day }} {% if day_summary %} - - {% for color in day_summary.category_colors %} - + + {% for entry in day_summary.entries %} + + + {{ entry.title }} + {% endfor %} {% endif %} diff --git a/tests/test_journal_service.py b/tests/test_journal_service.py index 5ed230a..51079b6 100644 --- a/tests/test_journal_service.py +++ b/tests/test_journal_service.py @@ -285,7 +285,7 @@ def test_get_monthly_journal_summary_counts_entries_per_day(db_session, test_use summary = journal_service.get_monthly_journal_summary(db_session, test_user.id, today.year, today.month) assert summary[today].total_count == 2 - assert summary[today].category_colors == ["#ff0000"] + assert [e.color for e in summary[today].entries] == ["#ff0000", "#ff0000"] def test_get_day_entries_returns_entries_for_that_date(db_session, test_user): -- 2.54.0