kuni 3 週之前
父節點
當前提交
5b696f87f5
共有 3 個文件被更改,包括 118 次插入75 次删除
  1. 50
    47
      src/app/pages/danka-list/danka-list.ts
  2. 20
    16
      src/app/pages/dashboard/dashboard.ts
  3. 48
    12
      src/app/services/dankaService.ts

+ 50
- 47
src/app/pages/danka-list/danka-list.ts 查看文件

@@ -1,4 +1,4 @@
1
-import { Component } from '@angular/core';
1
+import { Component, OnInit } from '@angular/core';
2 2
 import { RouterLink } from '@angular/router';
3 3
 import { DankaService } from '../../services/dankaService';
4 4
 import { FamilyService } from '../../services/family-service';
@@ -26,13 +26,14 @@ type KanaRowValue =
26 26
   templateUrl: './danka-list.html',
27 27
   styleUrl: './danka-list.scss',
28 28
 })
29
-export class DankaList {
29
+export class DankaList implements OnInit {
30 30
   dankaList: Danka[] = [];
31 31
   filterDankaList: Danka[] = [];
32 32
   searchKeyword: string = '';
33 33
   dankaDisplay: number = 0;
34 34
   selectedFilter = 'all';
35 35
   selectedKanaRow: KanaRowValue = 'all';
36
+
36 37
   kanaRows: { label: string; value: KanaRowValue }[] = [
37 38
     { label: '全件', value: 'all' },
38 39
     { label: 'あ行', value: 'a' },
@@ -48,27 +49,33 @@ export class DankaList {
48 49
   ];
49 50
 
50 51
   private readonly kanaRowMap: Record<Exclude<KanaRowValue, 'all'>, string[]> = {
51
-    a: ['あ', 'い', 'う', 'え', 'お', 'ア', 'イ', 'ウ', 'エ', 'オ'],
52
-    ka: ['か', 'き', 'く', 'け', 'こ', 'が', 'ぎ', 'ぐ', 'げ', 'ご', 'カ', 'キ', 'ク', 'ケ', 'コ', 'ガ', 'ギ', 'グ', 'ゲ', 'ゴ'],
53
-    sa: ['さ', 'し', 'す', 'せ', 'そ', 'ざ', 'じ', 'ず', 'ぜ', 'ぞ', 'サ', 'シ', 'ス', 'セ', 'ソ', 'ザ', 'ジ', 'ズ', 'ゼ', 'ゾ'],
54
-    ta: ['た', 'ち', 'つ', 'て', 'と', 'だ', 'ぢ', 'づ', 'で', 'ど', 'タ', 'チ', 'ツ', 'テ', 'ト', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド'],
55
-    na: ['な', 'に', 'ぬ', 'ね', 'の', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ'],
56
-    ha: ['は', 'ひ', 'ふ', 'へ', 'ほ', 'ば', 'び', 'ぶ', 'べ', 'ぼ', 'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ'],
57
-    ma: ['ま', 'み', 'む', 'め', 'も', 'マ', 'ミ', 'ム', 'メ', 'モ'],
58
-    ya: ['や', 'ゆ', 'よ', 'ヤ', 'ユ', 'ヨ'],
59
-    ra: ['ら', 'り', 'る', 'れ', 'ろ', 'ラ', 'リ', 'ル', 'レ', 'ロ'],
60
-    wa: ['わ', 'を', 'ん', 'ワ', 'ヲ', 'ン'],
52
+    a: ['あ','い','う','え','お','ア','イ','ウ','エ','オ'],
53
+    ka: ['か','き','く','け','こ','が','ぎ','ぐ','げ','ご','カ','キ','ク','ケ','コ','ガ','ギ','グ','ゲ','ゴ'],
54
+    sa: ['さ','し','す','せ','そ','ざ','じ','ず','ぜ','ぞ','サ','シ','ス','セ','ソ','ザ','ジ','ズ','ゼ','ゾ'],
55
+    ta: ['た','ち','つ','て','と','だ','ぢ','づ','で','ど','タ','チ','ツ','テ','ト','ダ','ヂ','ヅ','デ','ド'],
56
+    na: ['な','に','ぬ','ね','の','ナ','ニ','ヌ','ネ','ノ'],
57
+    ha: ['は','ひ','ふ','へ','ほ','ば','び','ぶ','べ','ぼ','ぱ','ぴ','ぷ','ぺ','ぽ','ハ','ヒ','フ','ヘ','ホ','バ','ビ','ブ','ベ','ボ','パ','ピ','プ','ペ','ポ'],
58
+    ma: ['ま','み','む','め','も','マ','ミ','ム','メ','モ'],
59
+    ya: ['や','ゆ','よ','ヤ','ユ','ヨ'],
60
+    ra: ['ら','り','る','れ','ろ','ラ','リ','ル','レ','ロ'],
61
+    wa: ['わ','を','ん','ワ','ヲ','ン'],
61 62
   };
62 63
 
63 64
   constructor(
64 65
     private dankaService: DankaService,
65 66
     private familyService: FamilyService,
66
-  ) {
67
-    this.dankaList = this.dankaService.getDankaList();
67
+  ) {}
68
+
69
+  // 非同期初期化
70
+  ngOnInit(): void {
71
+    this.init();
72
+  }
73
+
74
+  async init(): Promise<void> {
75
+    this.dankaList = await this.dankaService.getDankaList();
68 76
     this.showAllDanka();
69 77
   }
70 78
 
71
-  //全件タグで絞り込み
72 79
   showAllDanka() {
73 80
     this.selectedFilter = 'all';
74 81
     this.selectedKanaRow = 'all';
@@ -77,44 +84,39 @@ export class DankaList {
77 84
     this.dankaDisplay = this.filterDankaList.length;
78 85
   }
79 86
 
80
-  //電話番号タグで絞り込み
81 87
   filterPhoneAvailable() {
82 88
     this.selectedFilter = 'phone';
83 89
     this.selectedKanaRow = 'all';
84
-    //電話番号タブに該当する檀家を表示
85
-    this.filterDankaList = this.dankaList.filter((danka) => {
86
-      return danka.phones.some((phone) => phone.tel.trim() !== '');
87
-    });
90
+
91
+    this.filterDankaList = this.dankaList.filter((danka) =>
92
+      danka.phones.some((phone) => phone.tel.trim() !== '')
93
+    );
94
+
88 95
     this.dankaDisplay = this.filterDankaList.length;
89 96
   }
90 97
 
91
-  //検索処理
92 98
   searchDanka() {
93 99
     this.selectedFilter = 'search';
94 100
     this.selectedKanaRow = 'all';
95
-    //検索欄に入力された値から余白を削除
101
+
96 102
     const keyword = this.searchKeyword.trim();
97
-    //検索欄が空の場合は檀家の一覧を表示
103
+
98 104
     if (keyword === '') {
99
-      this.filterDankaList = this.dankaList;
100
-      this.dankaDisplay = this.filterDankaList.length;
105
+      this.showAllDanka();
101 106
       return;
102 107
     }
103 108
 
104
-    //検索欄に値がある場合は値に該当する内容を表示
105
-    this.filterDankaList = this.dankaList.filter((danka) => {
106
-      return (
107
-        danka.householdName.includes(keyword) ||
108
-        danka.householdFurigana.includes(keyword) ||
109
-        danka.householder.includes(keyword) ||
110
-        danka.householderFurigana.includes(keyword) ||
111
-        danka.postalCode.includes(keyword) ||
112
-        danka.address.includes(keyword) ||
113
-        danka.phones.some((phone) => phone.tel.includes(keyword) || phone.note.includes(keyword))
114
-      );
115
-    });
109
+    this.filterDankaList = this.dankaList.filter((danka) =>
110
+      danka.householdName.includes(keyword) ||
111
+      danka.householdFurigana.includes(keyword) ||
112
+      danka.householder.includes(keyword) ||
113
+      danka.householderFurigana.includes(keyword) ||
114
+      danka.postalCode.includes(keyword) ||
115
+      danka.address.includes(keyword) ||
116
+      danka.phones.some((p) => p.tel.includes(keyword) || p.note.includes(keyword))
117
+    );
118
+
116 119
     this.dankaDisplay = this.filterDankaList.length;
117
-    console.log(this.dankaDisplay);
118 120
   }
119 121
 
120 122
   filterByKanaRow(row: KanaRowValue): void {
@@ -123,15 +125,15 @@ export class DankaList {
123 125
     this.searchKeyword = '';
124 126
 
125 127
     if (row === 'all') {
126
-      this.filterDankaList = this.dankaList;
127
-      this.dankaDisplay = this.filterDankaList.length;
128
+      this.showAllDanka();
128 129
       return;
129 130
     }
130 131
 
131
-    this.filterDankaList = this.dankaList.filter((danka) => {
132
-      const firstKana = this.getDankaSortText(danka).charAt(0);
132
+    this.filterDankaList = this.dankaList.filter(async (danka) => {
133
+      const firstKana = (await this.getDankaSortText(danka)).charAt(0);
133 134
       return this.kanaRowMap[row].includes(firstKana);
134 135
     });
136
+
135 137
     this.dankaDisplay = this.filterDankaList.length;
136 138
   }
137 139
 
@@ -143,11 +145,12 @@ export class DankaList {
143 145
     this.dankaDisplay = 0;
144 146
   }
145 147
 
146
-  private getDankaSortText(danka: Danka): string {
148
+  private async getDankaSortText(danka: Danka): Promise<string> {
147 149
     const householderName = this.normalizeName(danka.householder);
148
-    const householderFamily = this.familyService
149
-      .getFamiliesByDankaId(danka.id)
150
-      .find((family) => this.normalizeName(family.name) === householderName);
150
+
151
+    const householderFamily = (await this.familyService
152
+      .getFamiliesByDankaId(danka.id))
153
+      .find((f) => this.normalizeName(f.name) === householderName);
151 154
 
152 155
     return (householderFamily?.furigana || danka.householder).trim();
153 156
   }
@@ -155,4 +158,4 @@ export class DankaList {
155 158
   private normalizeName(name: string): string {
156 159
     return name.replace(/\s/g, '');
157 160
   }
158
-}
161
+}

+ 20
- 16
src/app/pages/dashboard/dashboard.ts 查看文件

@@ -49,19 +49,23 @@ export class Dashboard {
49 49
     this.setUpcomingMemorials();
50 50
   }
51 51
 
52
-  private setRecentDankaList(): void {
53
-    this.recentDankaList = this.dankaService.getRecentDankaList(5).map((danka) => ({
54
-      danka,
55
-      nextMemorialLabel: this.getNextMemorialLabel(danka.id),
56
-      updatedAtLabel: this.formatUpdatedAt(danka.updatedAt),
57
-    }));
52
+  private async setRecentDankaList(): Promise<void> {
53
+    const dankaList = await this.dankaService.getRecentDankaList(5);
54
+
55
+    this.recentDankaList = await Promise.all(
56
+      dankaList.map(async (danka) => ({
57
+        danka,
58
+        nextMemorialLabel: await this.getNextMemorialLabel(danka.id),
59
+        updatedAtLabel: this.formatUpdatedAt(danka.updatedAt),
60
+      }))
61
+    );
58 62
   }
59 63
 
60
-  private setWeeklyMemorialSummary(): void {
64
+  private async setWeeklyMemorialSummary(): Promise<void> {
61 65
     const today = this.toDateOnly(new Date());
62 66
     const weekEnd = this.addDays(this.getWeekStart(today), 6);
63 67
 
64
-    const weeklyMemorials = this.kakochoService.getKakochoList().filter((kakocho) => {
68
+    const weeklyMemorials = (await this.kakochoService.getKakochoList()).filter((kakocho) => {
65 69
       const deathDate = this.parseDate(kakocho.deathDate);
66 70
       if (!deathDate) {
67 71
         return false;
@@ -83,10 +87,10 @@ export class Dashboard {
83 87
     this.upcomingWeeklyMemorialCount = this.weeklyMemorialCount - this.todayMemorialCount;
84 88
   }
85 89
 
86
-  private setMonthlyMemorialSummary(): void {
90
+  private async setMonthlyMemorialSummary(): Promise<void> {
87 91
     const today = this.toDateOnly(new Date());
88 92
 
89
-    this.monthlyMemorialCount = this.kakochoService.getKakochoList().filter((kakocho) => {
93
+    this.monthlyMemorialCount = (await this.kakochoService.getKakochoList()).filter((kakocho) => {
90 94
       const deathDate = this.parseDate(kakocho.deathDate);
91 95
       if (!deathDate || !this.isMemorialTarget(deathDate)) {
92 96
         return false;
@@ -96,12 +100,12 @@ export class Dashboard {
96 100
     }).length;
97 101
   }
98 102
 
99
-  private setUpcomingMemorials(): void {
103
+  private async setUpcomingMemorials(): Promise<void> {
100 104
     const today = this.toDateOnly(new Date());
101 105
     const endDate = this.addDays(today, 30);
102 106
 
103
-    this.upcomingMemorials = this.kakochoService
104
-      .getKakochoList()
107
+    this.upcomingMemorials = (await this.kakochoService
108
+      .getKakochoList())
105 109
       .map((kakocho): UpcomingMemorial | null => {
106 110
         const deathDate = this.parseDate(kakocho.deathDate);
107 111
         if (!deathDate) {
@@ -167,10 +171,10 @@ export class Dashboard {
167 171
     return `${date.getMonth() + 1}月${date.getDate()}日`;
168 172
   }
169 173
 
170
-  private getNextMemorialLabel(dankaId: string): string {
174
+  private async getNextMemorialLabel(dankaId: string): Promise<string> {
171 175
     const today = this.toDateOnly(new Date());
172
-    const nextMemorial = this.kakochoService
173
-      .getKakochoByDankaId(dankaId)
176
+    const nextMemorial = (await this.kakochoService
177
+      .getKakochoByDankaId(dankaId))
174 178
       .map((kakocho) => {
175 179
         const deathDate = this.parseDate(kakocho.deathDate);
176 180
         if (!deathDate) {

+ 48
- 12
src/app/services/dankaService.ts 查看文件

@@ -60,33 +60,69 @@ export class DankaService {
60 60
     await deleteDoc(ref);
61 61
   }
62 62
 
63
+  // -----------------------------
64
+  // 最近開いた檀家
65
+  // -----------------------------
66
+
63 67
   private getRecentDankaIds(): string[] {
64
-    if (!this.canUseLocalStorage()) {
65
-      return [];
66
-    }
68
+    if (!this.canUseLocalStorage()) return [];
67 69
 
68 70
     const value = localStorage.getItem(this.recentDankaStorageKey);
69
-    if (!value) {
70
-      return [];
71
-    }
71
+    if (!value) return [];
72 72
 
73 73
     try {
74 74
       const parsed = JSON.parse(value);
75
-      return Array.isArray(parsed) ? parsed.filter((id): id is string => typeof id === 'string') : [];
75
+      return Array.isArray(parsed)
76
+        ? parsed.filter((id): id is string => typeof id === 'string')
77
+        : [];
76 78
     } catch {
77 79
       return [];
78 80
     }
79 81
   }
80 82
 
81 83
   private saveRecentDankaIds(ids: string[]): void {
82
-    if (!this.canUseLocalStorage()) {
83
-      return;
84
-    }
85
-
84
+    if (!this.canUseLocalStorage()) return;
86 85
     localStorage.setItem(this.recentDankaStorageKey, JSON.stringify(ids));
87 86
   }
88 87
 
89 88
   private canUseLocalStorage(): boolean {
90 89
     return typeof localStorage !== 'undefined';
91 90
   }
92
-}
91
+
92
+  // ★ここが重要:async化
93
+  async recordDankaOpened(id: string): Promise<void> {
94
+    const danka = await this.getDankaById(id);
95
+    if (!danka) return;
96
+
97
+    const recentIds = [
98
+      id,
99
+      ...this.getRecentDankaIds().filter(rid => rid !== id),
100
+    ].slice(0, 5);
101
+
102
+    this.saveRecentDankaIds(recentIds);
103
+  }
104
+
105
+  // ★ここも async 必須
106
+  async getRecentDankaList(limit = 5): Promise<Danka[]> {
107
+    const ids = this.getRecentDankaIds().slice(0, limit);
108
+
109
+    const list = await Promise.all(
110
+      ids.map(id => this.getDankaById(id))
111
+    );
112
+
113
+    const filtered = list.filter((d): d is Danka => d !== undefined);
114
+
115
+    if (filtered.length > 0) {
116
+      return filtered;
117
+    }
118
+
119
+    // fallback(updatedAtがある前提なら)
120
+    const all = await this.getDankaList();
121
+
122
+    return [...all]
123
+      .sort((a: any, b: any) =>
124
+        (b.updatedAt ?? '').localeCompare(a.updatedAt ?? '')
125
+      )
126
+      .slice(0, limit);
127
+  }
128
+}

Loading…
取消
儲存