feat: birthday tracking, dashboard KPIs, and app name customization (#88)

- Add Birthdays module: CRUD with calendar/reminder auto-sync, photo upload, age notes
- Add DB migration 18 (birthdays table with calendar_event_id, trigger, indexes)
- Add dashboard widgets: birthdays, family participants, budget overview
- Add Settings > General: admins can set a custom app name (reflected in title/sidebar/login)
- Improve service worker: network-first caching for mutable JS/CSS assets
- Add translations for 16 locales (birthday keys)

Fixes applied during integration:
- innerHTML replaced with insertAdjacentHTML/replaceChildren throughout birthdays.js and dashboard.js
- docker-compose.yml personal dev changes reverted

Co-authored-by: Rafael Foster <rafaelgfoster@gmail.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ulas Kalayci
2026-04-27 07:37:09 +02:00
39 changed files with 4026 additions and 156 deletions
+53
View File
@@ -38,6 +38,7 @@
"shopping": "買い物",
"notes": "メモ",
"contacts": "連絡先",
"birthdays": "誕生日",
"budget": "家計",
"settings": "設定",
"main": "メインナビゲーション",
@@ -82,6 +83,19 @@
"allDay": "終日",
"shoppingMore": "+{{count}} 件",
"weather": "天気",
"familyMembers": "家族メンバー",
"participantsAdded": "人が追加済み",
"upcomingBirthdays": "今後の誕生日",
"noBirthdays": "誕生日はまだありません",
"daysLeft": "{{count}}日",
"budgetOverview": "予算の概要",
"monthlyIncome": "収入",
"monthlyExpenses": "支出",
"monthlyBalance": "残高",
"savingsRate": "貯蓄率",
"topExpense": "最大の支出",
"budgetEntries": "記録",
"noBudgetData": "今月の予算データはありません。",
"customize": "カスタマイズ",
"customizeTitle": "ウィジェットのカスタマイズ",
"customizeReset": "デフォルト",
@@ -537,6 +551,7 @@
"tabAccount": "アカウント",
"tabsAriaLabel": "設定カテゴリー",
"sectionDesign": "デザイン",
"sectionAppName": "アプリ名",
"sectionShopping": "買い物",
"shoppingCategoriesLabel": "買い物カテゴリー",
"shoppingCategoriesHint": "カテゴリーの追加、名前変更、削除、並び替えができます。",
@@ -554,6 +569,16 @@
"sectionCalendarSync": "カレンダー同期",
"sectionFamily": "家族メンバー",
"cardAppearance": "外観",
"appNameTitle": "アプリ名",
"appNameLabel": "アプリ名",
"appNameHint": "この名前はサイドバー、ブラウザのタイトル、ログイン画面に表示されます。",
"appNamePlaceholder": "Oikos",
"appNameSavedToast": "アプリ名を保存しました。",
"sectionDate": "日付",
"dateFormatTitle": "日付形式",
"dateFormatLabel": "希望する日付形式",
"dateFormatHint": "アプリ内で日付をどう表示するかを選択します。",
"dateFormatSavedToast": "日付形式を保存しました。",
"themeSystem": "システム設定",
"themeSysLabel": "システム設定を使用",
"themeLight": "ライト",
@@ -760,6 +785,34 @@
"placeholder": "検索…",
"noResults": "結果が見つかりませんでした。"
},
"birthdays": {
"title": "誕生日",
"addButton": "誕生日を追加",
"searchPlaceholder": "誕生日を検索…",
"upcomingTitle": "次の誕生日",
"upcomingHint": "次に祝う誕生日。すでにカレンダーに同期されています。",
"peopleTitle": "人物",
"peopleHint": "保存されたすべての誕生日を検索、確認、編集できます。",
"emptyTitle": "まだ誕生日はありません",
"emptyDescription": "誕生日を追加すると、カレンダーとリマインダーに表示されます。",
"newTitle": "新しい誕生日",
"editTitle": "誕生日を編集",
"nameLabel": "名前",
"birthDateLabel": "生年月日",
"photoLabel": "プロフィール画像",
"removePhoto": "画像を削除",
"notesLabel": "メモ",
"notesPlaceholder": "プレゼント案、好きなケーキ、家族メモ…",
"calendarHint": "各誕生日は自動的にカレンダーとリマインダーシステムに追加されます。",
"requiredFields": "名前と生年月日は必須です。",
"createdToast": "誕生日を保存しました。",
"updatedToast": "誕生日を更新しました。",
"deletedToast": "誕生日を削除しました。",
"deleteConfirm": "「{{name}}」の誕生日を削除しますか?",
"ageNoteToday": "今日で{{age}}歳になります。",
"ageNoteTomorrow": "明日で{{age}}歳になります。",
"ageNoteDays": "{{days}}日後に{{age}}歳になります。"
},
"reminders": {
"sectionTitle": "リマインダー",
"enableLabel": "リマインダーを設定",