Skip to content

feat(kanban): calendar view (month grid + agenda)#35

Merged
cnjack merged 2 commits into
mainfrom
feat/kanban-c3-calendar
Jun 23, 2026
Merged

feat(kanban): calendar view (month grid + agenda)#35
cnjack merged 2 commits into
mainfrom
feat/kanban-c3-calendar

Conversation

@cnjack

@cnjack cnjack commented Jun 22, 2026

Copy link
Copy Markdown
Owner

What

Adds a third board view alongside Board and Table — a month grid and an agenda list, keyed off each card's due date. Implements C3 from the kanban roadmap (design §2).

Because both the desktop file board and the web DB board render the shared BoardSurface, the calendar lands on both platforms for free.

Scope

Pure presentational layer over the existing shared board model — no backend, no migration, no WebSocket changes. All data (due) already rides the document-sync pipeline / DB; the remembered sub-mode (calendarMode) persists in the board config like viewType.

Changes

  • shared/lib/board.ts — widen BoardViewType with "calendar", add CalendarMode + calendarMode, and pure helpers isIsoDate / currentMonth / shiftMonth / groupCardsByDay / monthMatrix (zero-padded ISO strings, no date library — consistent with sortCards/todayStr).
  • shared/components/board/BoardCalendar.tsx (new) — month grid + agenda. Overdue (due < today and not in the done column) renders red; today is highlighted; out-of-month and undated cards are handled; a card click opens the same BoardPeek (so due editing reuses the existing date input — no new edit UI).
  • BoardSurface — Calendar toggle, third render branch, hide the sort dropdown in calendar mode (group-by was already board-only).
  • Thread viewType: "calendar" + calendarMode through all three config types (desktop BoardConfig, web file-board BoardConfigJSON, web DB-board view).
  • Fix a stale setConfig persistence comment in board/types.ts.
  • tests/unit/boardCalendar.spec.ts — cover the calendar helpers (6 tests).
  • i18n: extract new shared strings, add zh translations, compile.

Verification

  • tsc --noEmit clean for both the root (desktop+shared) and web-frontend projects.
  • 9/9 unit tests pass (pnpm test:unit).
  • Web frontend vite build succeeds.
  • A throwaway in-browser harness confirmed: month grid with correct day placement, overdue red (non-done past-due only), today highlight, out-of-month greyed cells, the Month/Agenda toggle (exercising setConfig), and card-click → BoardPeek with the Due input.
Month Agenda
today highlighted, overdue red, out-of-month greyed due-sorted with date headers + Unscheduled section

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Calendar view for boards with Month and Agenda display modes.
    • Introduced month navigation controls (Previous/Next/Today buttons).
    • Cards now display organized by due dates in calendar format.
    • Added mode switching between Calendar Month and Agenda views.
  • Tests

    • Added unit tests for calendar date utility functions.
  • Chores

    • Added calendar-related localization strings for multiple languages (English, Japanese, Korean, Chinese).

Add a third board view alongside Board/Table — a month grid and an agenda
list keyed off each card's `due`. Pure presentational layer over the shared
board model; no backend, migration, or WS changes. Because both the desktop
file board and the web DB board render the shared BoardSurface, the calendar
lands on both for free.

- shared/lib/board.ts: widen BoardViewType with "calendar", add CalendarMode +
  calendarMode config field, and pure helpers isIsoDate / currentMonth /
  shiftMonth / groupCardsByDay / monthMatrix (zero-padded ISO strings, no date
  library — matches sortCards/todayStr).
- shared/components/board/BoardCalendar.tsx: new month-grid + agenda component.
  Overdue (due < today && not in done column) shows red; today is highlighted;
  out-of-month and undated cards handled; card click opens the same BoardPeek.
- BoardSurface: Calendar toggle button, third render branch, hide sort in
  calendar mode (group-by was already board-only); persist calendarMode via
  setConfig.
- Thread calendar viewType + calendarMode through all three config types
  (desktop BoardConfig, web file-board BoardConfigJSON, web DB-board view).
- Fix stale setConfig persistence comment in board/types.ts.
- tests/unit/boardCalendar.spec.ts: cover the calendar helpers.
- i18n: extract new shared strings, add zh translations, compile.

Verified: both tsc projects clean, 9 unit tests pass, web build succeeds, and
a throwaway harness render confirmed month grid, agenda, overdue styling,
today highlight, mode toggle, and peek-on-click.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new Calendar view is added to the board system alongside the existing Board and Table views. It supports month-grid and agenda sub-modes, controlled via a new calendarMode config field. Pure date utility functions (isIsoDate, currentMonth, shiftMonth, groupCardsByDay, monthMatrix) back the rendering. Unit tests and i18n strings for four locales are included.

Changes

Board Calendar View

Layer / File(s) Summary
Calendar types and date utility functions
shared/lib/board.ts, src/lib/types.ts, services/jtype-web/frontend/src/pages/WebBoardView.tsx
BoardViewType gains "calendar", CalendarMode type is introduced, BoardViewConfig gets calendarMode?, desktop/web BoardConfig types are updated, and five exported calendar helpers (isIsoDate, currentMonth, shiftMonth, groupCardsByDay, monthMatrix) are added.
BoardCalendar component
shared/components/board/BoardCalendar.tsx, shared/components/board/index.ts
New component renders month-grid and agenda views. Includes localized weekday header, month navigation, mode toggle, card chip renderer with priority/selection/overdue support, agenda mode with per-day headers and Unscheduled section, and month grid with 6×7 matrix and "+N" overflow. Exported from the board module index.
BoardSurface calendar integration
shared/components/board/BoardSurface.tsx, shared/components/board/types.ts
Adds Calendar button to the view switcher, hides sort dropdown when viewType === "calendar", renders BoardCalendar with config.calendarMode wired to actions.setConfig. setConfig doc comment is expanded.
App-level calendarMode propagation
services/jtype-web/frontend/src/pages/Kanban.tsx, services/jtype-web/frontend/src/pages/WebBoardView.tsx, src/components/BoardView.tsx
Kanban, WebBoardView, and BoardView each forward calendarMode from their config/state into the viewConfig object passed to BoardSurface.
Calendar helper unit tests
tests/unit/boardCalendar.spec.ts
Playwright unit tests cover isIsoDate, shiftMonth, currentMonth, monthMatrix (grid shape, week-start, day contiguity, month coverage), and groupCardsByDay (valid grouping, null/invalid due exclusion).
i18n strings for calendar UI
shared/i18n/locales/*/messages.po, shared/i18n/locales/*/messages.mjs
Adds Agenda, Calendar, Month, Next month, Previous month, Today, and Unscheduled entries across English (translated), Japanese, Korean (empty), and Chinese (translated) locale files, with compiled .mjs bundles updated.

Sequence Diagram

sequenceDiagram
  participant User
  participant BoardSurface
  participant BoardCalendar
  participant board_ts as board.ts helpers
  participant actions as setConfig

  User->>BoardSurface: click "Calendar" in view switcher
  BoardSurface->>actions: setConfig({ viewType: "calendar" })
  BoardSurface->>BoardCalendar: render(cards, today, doneKey, calendarMode="month")
  BoardCalendar->>board_ts: monthMatrix(currentMonth())
  board_ts-->>BoardCalendar: 6×7 ISO day strings
  BoardCalendar->>board_ts: groupCardsByDay(cards)
  board_ts-->>BoardCalendar: Map<due, cards[]>
  BoardCalendar-->>User: month grid with card chips
  User->>BoardCalendar: toggle "Agenda" mode
  BoardCalendar->>actions: setConfig({ calendarMode: "agenda" })
  BoardCalendar->>board_ts: sort cards by due, split dated/undated
  board_ts-->>BoardCalendar: sorted + grouped cards
  BoardCalendar-->>User: agenda list with day headers and Unscheduled section
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hop, hop, hip hooray!
The calendar blooms today —
Month grids and agenda lines,
Each due date perfectly aligns.
Cards chip by in rows so neat,
A bunny's board is now complete! 📅

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(kanban): calendar view (month grid + agenda)' directly and accurately describes the main change: adding a calendar view feature with month grid and agenda modes to the kanban board.
Docstring Coverage ✅ Passed Docstring coverage is 92.31% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/kanban-c3-calendar

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

# Conflicts:
#	services/jtype-web/frontend/src/pages/Kanban.tsx
#	services/jtype-web/frontend/src/pages/WebBoardView.tsx
#	shared/components/board/BoardSurface.tsx
#	shared/components/board/index.ts
#	shared/i18n/locales/en/messages.mjs
#	shared/i18n/locales/en/messages.po
#	shared/i18n/locales/ja/messages.mjs
#	shared/i18n/locales/ja/messages.po
#	shared/i18n/locales/ko/messages.mjs
#	shared/i18n/locales/ko/messages.po
#	shared/i18n/locales/zh/messages.mjs
#	shared/i18n/locales/zh/messages.po
#	shared/lib/board.ts
#	src/components/BoardView.tsx
#	src/lib/types.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
tests/unit/boardCalendar.spec.ts (1)

19-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add impossible-date cases to isIsoDate tests.

Please include calendar-invalid inputs (e.g., 2026-02-31, 2026-13-01) so the validation contract is enforced by tests.

Suggested test additions
 test("isIsoDate accepts only zero-padded YYYY-MM-DD", () => {
   expect(isIsoDate("2026-06-22")).toBe(true);
   expect(isIsoDate("2026-6-2")).toBe(false); // not zero-padded
   expect(isIsoDate("2026/06/22")).toBe(false);
+  expect(isIsoDate("2026-02-31")).toBe(false); // impossible day
+  expect(isIsoDate("2026-13-01")).toBe(false); // impossible month
   expect(isIsoDate("")).toBe(false);
   expect(isIsoDate(null)).toBe(false);
   expect(isIsoDate(undefined)).toBe(false);
   expect(isIsoDate("garbage")).toBe(false);
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/boardCalendar.spec.ts` around lines 19 - 27, The test function
isIsoDate needs additional test cases to validate that impossible calendar dates
are rejected, not just format validation. Add test assertions within the
existing test block that check edge cases like February 31st (2026-02-31) and
invalid month numbers (2026-13-01) to ensure the validation logic properly
rejects dates that are syntactically correct ISO format but semantically invalid
on a calendar.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@shared/components/board/BoardCalendar.tsx`:
- Line 1: The BoardCalendar component uses useState on line 45 to manage month
cursor state internally, violating the Props-in/Callbacks-out pattern required
for shared components. Remove the useState hook for month cursor from
BoardCalendar and replace it with props passed from the parent component.
Convert the state mutations occurring at lines 90, 93, and 100 into callback
props (such as onMonthChange or similar) that invoke parent-provided handlers
instead of directly updating state. The parent component should be responsible
for managing the month cursor state and passing both the current value and
update callbacks as props to BoardCalendar.

In `@shared/i18n/locales/ja/messages.po`:
- Around line 63-66: The Japanese translation file contains empty msgstr values
for new translation entries, including the "Agenda" entry and others at the
specified line ranges (109-112, 305-317, 373-376, 499-502, 515-518), which will
cause these labels to fall back to English when displayed to Japanese users.
Fill in all empty msgstr values with appropriate Japanese translations for each
corresponding msgid entry before shipping, or remove these incomplete
translation entries from the file.

In `@shared/i18n/locales/ko/messages.po`:
- Around line 63-66: The Korean translation file (messages.po) contains empty
msgstr values for multiple translation entries including "Agenda" and others at
the specified line ranges. Fill in each empty msgstr field with the appropriate
Korean translation for the corresponding msgid. Ensure all empty msgstr entries
at lines 63-66, 109-112, 305-317, 373-376, 499-502, and 515-518 are populated
with valid Korean translations before releasing to prevent the UI from falling
back to English text in Korean locale.

In `@shared/lib/board.ts`:
- Around line 356-359: The isIsoDate function only validates the format of the
date string using a regex pattern, but does not check whether the date
represents a valid calendar date. This allows impossible dates like 2026-02-31
or 2026-13-01 to pass validation. Strengthen the isIsoDate function by parsing
the month and day components from the matched string and validating that they
represent valid calendar values (month between 1 and 12, day between 1 and the
maximum days for that month). Consider using JavaScript's Date object to
validate the actual date after confirming the format matches the regex pattern.

In `@src/lib/types.ts`:
- Around line 22-25: The BoardConfig definition is currently using the type
keyword, but per the frontend coding guidelines, object shapes should be
declared as interfaces instead. Convert the BoardConfig from a type declaration
to an interface declaration to ensure consistency with the typing policy for
object shape definitions.

---

Nitpick comments:
In `@tests/unit/boardCalendar.spec.ts`:
- Around line 19-27: The test function isIsoDate needs additional test cases to
validate that impossible calendar dates are rejected, not just format
validation. Add test assertions within the existing test block that check edge
cases like February 31st (2026-02-31) and invalid month numbers (2026-13-01) to
ensure the validation logic properly rejects dates that are syntactically
correct ISO format but semantically invalid on a calendar.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d896357c-4131-4ab5-99c0-61b676276b60

📥 Commits

Reviewing files that changed from the base of the PR and between 1e78c6a and 01e4303.

📒 Files selected for processing (18)
  • services/jtype-web/frontend/src/pages/Kanban.tsx
  • services/jtype-web/frontend/src/pages/WebBoardView.tsx
  • shared/components/board/BoardCalendar.tsx
  • shared/components/board/BoardSurface.tsx
  • shared/components/board/index.ts
  • shared/components/board/types.ts
  • shared/i18n/locales/en/messages.mjs
  • shared/i18n/locales/en/messages.po
  • shared/i18n/locales/ja/messages.mjs
  • shared/i18n/locales/ja/messages.po
  • shared/i18n/locales/ko/messages.mjs
  • shared/i18n/locales/ko/messages.po
  • shared/i18n/locales/zh/messages.mjs
  • shared/i18n/locales/zh/messages.po
  • shared/lib/board.ts
  • src/components/BoardView.tsx
  • src/lib/types.ts
  • tests/unit/boardCalendar.spec.ts

@@ -0,0 +1,203 @@
import { useState } from "react";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -path "*shared/components/board/BoardCalendar.tsx" -type f

Repository: cnjack/jtype

Length of output: 194


🏁 Script executed:

if [ -f shared/components/board/BoardCalendar.tsx ]; then
  wc -l shared/components/board/BoardCalendar.tsx
fi

Repository: cnjack/jtype

Length of output: 196


🏁 Script executed:

cat -n shared/components/board/BoardCalendar.tsx

Repository: cnjack/jtype

Length of output: 9469


Hoist month cursor state out of the shared component.

Line 45 introduces local useState, and Lines 90/93/100 mutate it internally. In shared/components, this should be controlled via props/callbacks so the component stays Props-in/Callbacks-out.

Suggested refactor
-import { useState } from "react";
 import { t } from "`@lingui/core/macro`";
 import { Trans } from "`@lingui/react/macro`";
@@
 export function BoardCalendar({
   cards,
   today,
   doneKey,
+  month,
+  onMonthChange,
   mode,
   onModeChange,
   selectedId,
   onSelect,
 }: {
   cards: BoardViewCard[];
   today: string;
   doneKey: string;
+  month: string;
+  onMonthChange: (month: string) => void;
   mode: CalendarMode;
   onModeChange: (mode: CalendarMode) => void;
   selectedId?: string;
   onSelect: (card: BoardViewCard) => void;
 }) {
-  const [month, setMonth] = useState(() => currentMonth());
   const byDay = groupCardsByDay(cards);
@@
-          <button type="button" className={navBtn} title={t`Previous month`} aria-label={t`Previous month`} onClick={() => setMonth((m) => shiftMonth(m, -1))}>
+          <button type="button" className={navBtn} title={t`Previous month`} aria-label={t`Previous month`} onClick={() => onMonthChange(shiftMonth(month, -1))}>
@@
-          <button type="button" className={navBtn} title={t`Next month`} aria-label={t`Next month`} onClick={() => setMonth((m) => shiftMonth(m, 1))}>
+          <button type="button" className={navBtn} title={t`Next month`} aria-label={t`Next month`} onClick={() => onMonthChange(shiftMonth(month, 1))}>
@@
-            onClick={() => setMonth(currentMonth())}
+            onClick={() => onMonthChange(currentMonth())}

Per coding guidelines: "Shared React components in shared/ must follow Props-in/Callbacks-out pattern and must not depend on useReducer, useState, or any specific state pattern."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/components/board/BoardCalendar.tsx` at line 1, The BoardCalendar
component uses useState on line 45 to manage month cursor state internally,
violating the Props-in/Callbacks-out pattern required for shared components.
Remove the useState hook for month cursor from BoardCalendar and replace it with
props passed from the parent component. Convert the state mutations occurring at
lines 90, 93, and 100 into callback props (such as onMonthChange or similar)
that invoke parent-provided handlers instead of directly updating state. The
parent component should be responsible for managing the month cursor state and
passing both the current value and update callbacks as props to BoardCalendar.

Source: Coding guidelines

Comment on lines +63 to +66
#: shared/components/board/BoardCalendar.tsx
msgid "Agenda"
msgstr ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fill the new Japanese translations before shipping.

All added msgstr values are empty, so the new Calendar/Agenda labels will fall back to English in Japanese. Please populate these entries or keep the locale update out until they’re ready.

Also applies to: 109-112, 305-317, 373-376, 499-502, 515-518

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/i18n/locales/ja/messages.po` around lines 63 - 66, The Japanese
translation file contains empty msgstr values for new translation entries,
including the "Agenda" entry and others at the specified line ranges (109-112,
305-317, 373-376, 499-502, 515-518), which will cause these labels to fall back
to English when displayed to Japanese users. Fill in all empty msgstr values
with appropriate Japanese translations for each corresponding msgid entry before
shipping, or remove these incomplete translation entries from the file.

Comment on lines +63 to +66
#: shared/components/board/BoardCalendar.tsx
msgid "Agenda"
msgstr ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fill the new Korean translations before shipping.

All added msgstr values are empty, so the new Calendar/Agenda labels will fall back to English in Korean, and the generated runtime bundle will inherit the same fallback. Please populate these entries before release.

Also applies to: 109-112, 305-317, 373-376, 499-502, 515-518

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/i18n/locales/ko/messages.po` around lines 63 - 66, The Korean
translation file (messages.po) contains empty msgstr values for multiple
translation entries including "Agenda" and others at the specified line ranges.
Fill in each empty msgstr field with the appropriate Korean translation for the
corresponding msgid. Ensure all empty msgstr entries at lines 63-66, 109-112,
305-317, 373-376, 499-502, and 515-518 are populated with valid Korean
translations before releasing to prevent the UI from falling back to English
text in Korean locale.

Comment thread shared/lib/board.ts
Comment on lines +356 to +359
/** True when `s` is a well-formed zero-padded ISO date (`YYYY-MM-DD`). */
export function isIsoDate(s: string | null | undefined): s is string {
return !!s && /^\d{4}-\d{2}-\d{2}$/.test(s);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Strengthen isIsoDate to reject impossible calendar dates.

The regex-only check accepts values like 2026-02-31 and 2026-13-01, so invalid due values can still be bucketed as scheduled days.

Suggested fix
 export function isIsoDate(s: string | null | undefined): s is string {
-  return !!s && /^\d{4}-\d{2}-\d{2}$/.test(s);
+  if (!s || !/^\d{4}-\d{2}-\d{2}$/.test(s)) return false;
+  const [ys, ms, ds] = s.split("-");
+  const y = Number(ys);
+  const m = Number(ms);
+  const d = Number(ds);
+  const parsed = new Date(y, m - 1, d);
+  return parsed.getFullYear() === y && parsed.getMonth() === m - 1 && parsed.getDate() === d;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/lib/board.ts` around lines 356 - 359, The isIsoDate function only
validates the format of the date string using a regex pattern, but does not
check whether the date represents a valid calendar date. This allows impossible
dates like 2026-02-31 or 2026-13-01 to pass validation. Strengthen the isIsoDate
function by parsing the month and day components from the matched string and
validating that they represent valid calendar values (month between 1 and 12,
day between 1 and the maximum days for that month). Consider using JavaScript's
Date object to validate the actual date after confirming the format matches the
regex pattern.

Comment thread src/lib/types.ts
Comment on lines +22 to +25
/** Which renderer this board shows: kanban columns, a flat table, or a calendar. Defaults to "board". */
viewType?: "board" | "table" | "calendar";
/** Calendar sub-mode (month grid vs agenda list) when viewType === "calendar". Defaults to "month". */
calendarMode?: "month" | "agenda";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify object-shape type aliases under src frontend code.
rg -nP --iglob 'src/**/*.{ts,tsx}' '^\s*export\s+type\s+\w+\s*=\s*\{'

Repository: cnjack/jtype

Length of output: 150


🏁 Script executed:

cat -n src/lib/types.ts | head -50

Repository: cnjack/jtype

Length of output: 2391


Use interface for BoardConfig to match frontend typing policy.

BoardConfig should be declared as an interface per the coding guideline "Use interface for defining object shapes in TypeScript frontend code".

Suggested fix
-export type BoardConfig = {
+export interface BoardConfig {
   id: string;
   title: string;
   groupBy: string;
   columns: BoardColumn[];
   /** Column key treated as terminal/done (suppresses overdue styling). Defaults to "done". */
   doneColumn?: string;
   /** When true, tint each column header by its column color. */
   colorColumns?: boolean;
   /** Which renderer this board shows: kanban columns, a flat table, or a calendar. Defaults to "board". */
   viewType?: "board" | "table" | "calendar";
   /** Calendar sub-mode (month grid vs agenda list) when viewType === "calendar". Defaults to "month". */
   calendarMode?: "month" | "agenda";
   /** User-defined custom fields shown/edited on this board's cards. */
   fields?: { key: string; label: string; type?: "text" | "number" | "date" }[];
   /** Optional second grouping dimension rendered as swimlane rows in the board view. */
   swimlaneBy?: "status" | "priority" | "assignee";
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** Which renderer this board shows: kanban columns, a flat table, or a calendar. Defaults to "board". */
viewType?: "board" | "table" | "calendar";
/** Calendar sub-mode (month grid vs agenda list) when viewType === "calendar". Defaults to "month". */
calendarMode?: "month" | "agenda";
export interface BoardConfig {
id: string;
title: string;
groupBy: string;
columns: BoardColumn[];
/** Column key treated as terminal/done (suppresses overdue styling). Defaults to "done". */
doneColumn?: string;
/** When true, tint each column header by its column color. */
colorColumns?: boolean;
/** Which renderer this board shows: kanban columns, a flat table, or a calendar. Defaults to "board". */
viewType?: "board" | "table" | "calendar";
/** Calendar sub-mode (month grid vs agenda list) when viewType === "calendar". Defaults to "month". */
calendarMode?: "month" | "agenda";
/** User-defined custom fields shown/edited on this board's cards. */
fields?: { key: string; label: string; type?: "text" | "number" | "date" }[];
/** Optional second grouping dimension rendered as swimlane rows in the board view. */
swimlaneBy?: "status" | "priority" | "assignee";
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/types.ts` around lines 22 - 25, The BoardConfig definition is
currently using the type keyword, but per the frontend coding guidelines, object
shapes should be declared as interfaces instead. Convert the BoardConfig from a
type declaration to an interface declaration to ensure consistency with the
typing policy for object shape definitions.

Source: Coding guidelines

@cnjack cnjack merged commit a891cc9 into main Jun 23, 2026
3 checks passed
@cnjack cnjack deleted the feat/kanban-c3-calendar branch June 23, 2026 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant