// 行事予定データを月ごとに集計する(ビルド時専用)。 // // 注意: このモジュールは JSON を import するため、ブラウザ用スクリプトからは読み込まないこと。 // (カレンダー側が必要とする日付計算は src/lib/schedule-dates.ts にある) import meetings from '@/data/schedule/meetings.json'; import events from '@/data/schedule/events.json'; import { entryDates } from './schedule-dates'; export type Row = { date: string; title: string; place: string; note: string; source: string }; export type Item = { type: 'meeting' | 'event'; row: Row }; export const items: Item[] = [ ...(meetings.rows as Row[]).map((row) => ({ type: 'meeting' as const, row })), ...(events.rows as Row[]).map((row) => ({ type: 'event' as const, row })), ]; const datesOf = (item: Item) => entryDates(item.type, item.row.date, item.row.place); /** 月ごとの件数(会議・イベントの合計) */ export const monthCounts: Record = (() => { const counts: Record = {}; for (const item of items) { for (const date of new Set(datesOf(item).map((d) => d.slice(0, 7)))) { counts[date] = (counts[date] ?? 0) + 1; } } return counts; })(); /** データに存在する月(YYYY-MM、昇順) */ export const monthKeys: string[] = Object.keys(monthCounts).sort(); /** 指定した月に開催される行だけを返す */ export function rowsInMonth(month: string, type: 'meeting' | 'event'): Row[] { return items .filter((item) => item.type === type && datesOf(item).some((d) => d.startsWith(month))) .map((item) => item.row); } /** 年月の表示(2026-11 → 2026年11月) */ export function monthLabel(key: string): string { const [y, m] = key.split('-').map(Number); return `${y}年${m}月`; } /** 月キー → 年度キー(令和8年度は r8。4月〜翌年3月) */ export function fiscalYearOf(month: string): string { const [y, m] = month.split('-').map(Number); const startYear = m >= 4 ? y : y - 1; return `r${startYear - 2018}`; } /** データに存在する年度(昇順) */ export const fiscalYearKeys: string[] = [...new Set(monthKeys.map(fiscalYearOf))].sort(); /** 年度に含まれる月キー(データにある月だけ) */ export function monthsInFiscalYear(fy: string): string[] { return monthKeys.filter((month) => fiscalYearOf(month) === fy); } /** 年度の表示(r8 → 令和8年度) */ export function fiscalYearLabel(fy: string): string { return `令和${Number(fy.slice(1))}年度`; } /** 複数の月のいずれかに開催される行を返す */ export function rowsInMonths(months: string[], type: 'meeting' | 'event'): Row[] { const inMonths = (item: Item) => datesOf(item).some((date) => months.includes(date.slice(0, 7))); return items .filter((item) => item.type === type && inMonths(item)) .map((item) => item.row); } /** 年度に開催される行を返す */ export function rowsInFiscalYear(fy: string, type: 'meeting' | 'event'): Row[] { return rowsInMonths(monthsInFiscalYear(fy), type); }