Przeglądaj źródła

[add]

<檀家一覧>
タブについて全件は残して、行順タブを追加

<檀家一覧(家族)>
氏名・ふりがな・生年月日・年齢・関係・備考
poohr 3 tygodni temu
rodzic
commit
2c5ae879e4

+ 4
- 4
src/app/pages/danka-detail/danka-detail.html Wyświetl plik

210
                   <div class="family-table-header">
210
                   <div class="family-table-header">
211
                     <div>氏名</div>
211
                     <div>氏名</div>
212
                     <div>ふりがな</div>
212
                     <div>ふりがな</div>
213
-                    <div>関係</div>
214
-                    <div>年齢</div>
215
                     <div>生年月日</div>
213
                     <div>生年月日</div>
214
+                    <div>年齢</div>
215
+                    <div>関係</div>
216
                     <div>備考</div>
216
                     <div>備考</div>
217
                     <div>操作</div>
217
                     <div>操作</div>
218
                   </div>
218
                   </div>
228
                       </div>
228
                       </div>
229
 
229
 
230
                       <div>
230
                       <div>
231
-                        {{ family.relationship || '未登録' }}
231
+                        {{ family.birthDate || '未登録' }}
232
                       </div>
232
                       </div>
233
 
233
 
234
                       <div>
234
                       <div>
236
                       </div>
236
                       </div>
237
 
237
 
238
                       <div>
238
                       <div>
239
-                        {{ family.birthDate || '未登録' }}
239
+                        {{ family.relationship || '未登録' }}
240
                       </div>
240
                       </div>
241
 
241
 
242
                       <div>
242
                       <div>

+ 10
- 17
src/app/pages/danka-list/danka-list.html Wyświetl plik

31
 
31
 
32
       <div class="filter-row">
32
       <div class="filter-row">
33
         <div class="filter-button-list">
33
         <div class="filter-button-list">
34
-          <button type="button" class="filter-button" [class.active]="selectedFilter === 'all'"
35
-                  (click)="showAllDanka()">
36
-            全件
37
-          </button>
38
-
39
-          <button type="button" class="filter-button">
40
-            過去帳あり
41
-          </button>
42
-
43
-          <button type="button" class="filter-button">
44
-            法要あり
45
-          </button>
46
-
47
-          <button type="button" class="filter-button" [class.active]="selectedFilter === 'phone'"
48
-                  (click)="filterPhoneAvailable()">
49
-            電話番号あり
50
-          </button>
34
+          @for (kanaRow of kanaRows; track kanaRow.value) {
35
+            <button
36
+              type="button"
37
+              class="filter-button"
38
+              [class.active]="selectedKanaRow === kanaRow.value"
39
+              (click)="filterByKanaRow(kanaRow.value)"
40
+            >
41
+              {{ kanaRow.label }}
42
+            </button>
43
+          }
51
         </div>
44
         </div>
52
 
45
 
53
         <p class="result-count">
46
         <p class="result-count">

+ 11
- 75
src/app/pages/danka-list/danka-list.scss Wyświetl plik

126
   display: flex;
126
   display: flex;
127
   align-items: center;
127
   align-items: center;
128
   justify-content: space-between;
128
   justify-content: space-between;
129
+  gap: 16px;
129
   margin-bottom: 14px;
130
   margin-bottom: 14px;
130
-  padding-right: 24px;
131
+  padding: 12px 14px;
132
+  background: #fffdf9;
133
+  border: 2px solid #d8caba;
134
+  border-radius: 10px;
131
 }
135
 }
132
 
136
 
133
 .filter-button-list {
137
 .filter-button-list {
134
   display: flex;
138
   display: flex;
135
   align-items: center;
139
   align-items: center;
140
+  flex-wrap: wrap;
136
   gap: 8px;
141
   gap: 8px;
137
 }
142
 }
138
 
143
 
139
 .filter-button {
144
 .filter-button {
140
-  min-width: 140px;
145
+  min-width: 56px;
141
   height: 40px;
146
   height: 40px;
142
-  padding: 0 18px;
147
+  padding: 0 14px;
143
   border: 2px solid #d8caba;
148
   border: 2px solid #d8caba;
144
-  border-radius: 6px;
149
+  border-radius: 8px;
145
   background: #f4eee4;
150
   background: #f4eee4;
146
   color: #2f2720;
151
   color: #2f2720;
147
   font-size: 16px;
152
   font-size: 16px;
148
-  font-weight: 700;
153
+  font-weight: 800;
149
   cursor: pointer;
154
   cursor: pointer;
150
   box-sizing: border-box;
155
   box-sizing: border-box;
151
 }
156
 }
168
   margin: 0;
173
   margin: 0;
169
   color: #8a7d6d;
174
   color: #8a7d6d;
170
   font-size: 15px;
175
   font-size: 15px;
176
+  white-space: nowrap;
171
 }
177
 }
172
 
178
 
173
 .list-content {
179
 .list-content {
232
   text-align: center;
238
   text-align: center;
233
 }
239
 }
234
 
240
 
235
-.help-panel {
236
-  position: absolute;
237
-  top: 0;
238
-  right: 18px;
239
-  width: 158px;
240
-  min-height: 446px;
241
-  padding: 28px 14px 18px;
242
-  background: #fffdf9;
243
-  border: 2px solid #d8caba;
244
-  border-radius: 24px;
245
-  box-sizing: border-box;
246
-}
247
-
248
-.help-panel h2 {
249
-  margin: 0 0 16px;
250
-  color: #2f2720;
251
-  font-size: 20px;
252
-  font-weight: 800;
253
-}
254
-
255
-.help-panel ol {
256
-  margin: 0;
257
-  padding-left: 22px;
258
-  color: #6f6257;
259
-  font-size: 14px;
260
-  line-height: 1.45;
261
-}
262
-
263
-.help-title-secondary {
264
-  margin-top: 28px !important;
265
-}
266
-
267
-.help-button-list {
268
-  display: flex;
269
-  flex-direction: column;
270
-  gap: 8px;
271
-}
272
-
273
-.help-button {
274
-  min-height: 46px;
275
-  padding: 0 8px;
276
-  border: 2px solid #d8caba;
277
-  border-radius: 8px;
278
-  background: #ffffff;
279
-  color: #2f2720;
280
-  font-size: 16px;
281
-  font-weight: 800;
282
-  text-decoration: none;
283
-  display: flex;
284
-  align-items: center;
285
-  justify-content: center;
286
-  text-align: center;
287
-  box-sizing: border-box;
288
-}
289
-
290
-.help-button:hover {
291
-  background: #f6efe6;
292
-}
293
-
294
-.bottom-note {
295
-  width: 700px;
296
-  margin: 18px 0 22px 36px;
297
-  padding: 4px 12px;
298
-  border: 2px solid #d8caba;
299
-  border-radius: 4px;
300
-  background: #eadfce;
301
-  color: #7b6b5c;
302
-  font-size: 14px;
303
-  box-sizing: border-box;
304
-}

+ 80
- 1
src/app/pages/danka-list/danka-list.ts Wyświetl plik

1
 import { Component } from '@angular/core';
1
 import { Component } from '@angular/core';
2
 import { RouterLink } from '@angular/router';
2
 import { RouterLink } from '@angular/router';
3
 import { DankaService } from '../../services/dankaService';
3
 import { DankaService } from '../../services/dankaService';
4
+import { FamilyService } from '../../services/family-service';
4
 import { AppHeader } from '../../share/header/app-header';
5
 import { AppHeader } from '../../share/header/app-header';
5
 import { AppSideMenu } from '../../share/side-menu/app-side-menu';
6
 import { AppSideMenu } from '../../share/side-menu/app-side-menu';
6
 import { Danka } from '../../models/danka';
7
 import { Danka } from '../../models/danka';
7
 import { FormsModule } from '@angular/forms';
8
 import { FormsModule } from '@angular/forms';
8
 
9
 
10
+type KanaRowValue =
11
+  | 'all'
12
+  | 'a'
13
+  | 'ka'
14
+  | 'sa'
15
+  | 'ta'
16
+  | 'na'
17
+  | 'ha'
18
+  | 'ma'
19
+  | 'ya'
20
+  | 'ra'
21
+  | 'wa';
22
+
9
 @Component({
23
 @Component({
10
   selector: 'app-danka-list',
24
   selector: 'app-danka-list',
11
   imports: [AppHeader, AppSideMenu, RouterLink, FormsModule],
25
   imports: [AppHeader, AppSideMenu, RouterLink, FormsModule],
18
   searchKeyword: string = '';
32
   searchKeyword: string = '';
19
   dankaDisplay: number = 0;
33
   dankaDisplay: number = 0;
20
   selectedFilter = 'all';
34
   selectedFilter = 'all';
35
+  selectedKanaRow: KanaRowValue = 'all';
36
+  kanaRows: { label: string; value: KanaRowValue }[] = [
37
+    { label: '全件', value: 'all' },
38
+    { label: 'あ行', value: 'a' },
39
+    { label: 'か行', value: 'ka' },
40
+    { label: 'さ行', value: 'sa' },
41
+    { label: 'た行', value: 'ta' },
42
+    { label: 'な行', value: 'na' },
43
+    { label: 'は行', value: 'ha' },
44
+    { label: 'ま行', value: 'ma' },
45
+    { label: 'や行', value: 'ya' },
46
+    { label: 'ら行', value: 'ra' },
47
+    { label: 'わ行', value: 'wa' },
48
+  ];
49
+
50
+  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: ['わ', 'を', 'ん', 'ワ', 'ヲ', 'ン'],
61
+  };
21
 
62
 
22
-  constructor(private dankaService: DankaService) {
63
+  constructor(
64
+    private dankaService: DankaService,
65
+    private familyService: FamilyService,
66
+  ) {
23
     this.dankaList = this.dankaService.getDankaList();
67
     this.dankaList = this.dankaService.getDankaList();
24
     this.showAllDanka();
68
     this.showAllDanka();
25
   }
69
   }
27
   //全件タグで絞り込み
71
   //全件タグで絞り込み
28
   showAllDanka() {
72
   showAllDanka() {
29
     this.selectedFilter = 'all';
73
     this.selectedFilter = 'all';
74
+    this.selectedKanaRow = 'all';
30
     this.searchKeyword = '';
75
     this.searchKeyword = '';
31
     this.filterDankaList = this.dankaList;
76
     this.filterDankaList = this.dankaList;
32
     this.dankaDisplay = this.filterDankaList.length;
77
     this.dankaDisplay = this.filterDankaList.length;
35
   //電話番号タグで絞り込み
80
   //電話番号タグで絞り込み
36
   filterPhoneAvailable() {
81
   filterPhoneAvailable() {
37
     this.selectedFilter = 'phone';
82
     this.selectedFilter = 'phone';
83
+    this.selectedKanaRow = 'all';
38
     //電話番号タブに該当する檀家を表示
84
     //電話番号タブに該当する檀家を表示
39
     this.filterDankaList = this.dankaList.filter((danka) => {
85
     this.filterDankaList = this.dankaList.filter((danka) => {
40
       return danka.phones.some((phone) => phone.tel.trim() !== '');
86
       return danka.phones.some((phone) => phone.tel.trim() !== '');
45
   //検索処理
91
   //検索処理
46
   searchDanka() {
92
   searchDanka() {
47
     this.selectedFilter = 'search';
93
     this.selectedFilter = 'search';
94
+    this.selectedKanaRow = 'all';
48
     //検索欄に入力された値から余白を削除
95
     //検索欄に入力された値から余白を削除
49
     const keyword = this.searchKeyword.trim();
96
     const keyword = this.searchKeyword.trim();
50
     //検索欄が空の場合は檀家の一覧を表示
97
     //検索欄が空の場合は檀家の一覧を表示
68
     console.log(this.dankaDisplay);
115
     console.log(this.dankaDisplay);
69
   }
116
   }
70
 
117
 
118
+  filterByKanaRow(row: KanaRowValue): void {
119
+    this.selectedFilter = 'kana';
120
+    this.selectedKanaRow = row;
121
+    this.searchKeyword = '';
122
+
123
+    if (row === 'all') {
124
+      this.filterDankaList = this.dankaList;
125
+      this.dankaDisplay = this.filterDankaList.length;
126
+      return;
127
+    }
128
+
129
+    this.filterDankaList = this.dankaList.filter((danka) => {
130
+      const firstKana = this.getDankaSortText(danka).charAt(0);
131
+      return this.kanaRowMap[row].includes(firstKana);
132
+    });
133
+    this.dankaDisplay = this.filterDankaList.length;
134
+  }
135
+
71
   clearDanka() {
136
   clearDanka() {
72
     this.selectedFilter = '';
137
     this.selectedFilter = '';
138
+    this.selectedKanaRow = 'all';
73
     this.searchKeyword = '';
139
     this.searchKeyword = '';
74
     this.filterDankaList = [];
140
     this.filterDankaList = [];
75
     this.dankaDisplay = 0;
141
     this.dankaDisplay = 0;
76
   }
142
   }
143
+
144
+  private getDankaSortText(danka: Danka): string {
145
+    const householderName = this.normalizeName(danka.householder);
146
+    const householderFamily = this.familyService
147
+      .getFamiliesByDankaId(danka.id)
148
+      .find((family) => this.normalizeName(family.name) === householderName);
149
+
150
+    return (householderFamily?.furigana || danka.householder).trim();
151
+  }
152
+
153
+  private normalizeName(name: string): string {
154
+    return name.replace(/\s/g, '');
155
+  }
77
 }
156
 }

Ładowanie…
Anuluj
Zapisz