Kaynağa Gözat

[update]

<ダッシュボード>
今年の年忌法要のカードを今月の法要に修正

<檀家一覧>
ページ遷移した時に全件が表示されるように修正
檀家登録のボタンをクリアに変更

<まとめて検索>
一覧へもどる削除
戻る・フォームを削除

<サイドメニュー>
選択済みはわかるように色付け
檀家一覧の下に檀家登録を追加
poohr 3 hafta önce
ebeveyn
işleme
aefb802b21

+ 2
- 2
src/app/pages/danka-list/danka-list.html Dosyayı Görüntüle

@@ -24,8 +24,8 @@
24 24
           検索
25 25
         </button>
26 26
 
27
-        <button type="button" class="new-button" routerLink="/danka-new">
28
-          新規登録
27
+        <button type="button" class="new-button" (click)="clearDanka()">
28
+          クリア
29 29
         </button>
30 30
       </div>
31 31
 

+ 10
- 2
src/app/pages/danka-list/danka-list.ts Dosyayı Görüntüle

@@ -5,7 +5,6 @@ import { AppHeader } from '../../share/header/app-header';
5 5
 import { AppSideMenu } from '../../share/side-menu/app-side-menu';
6 6
 import { Danka } from '../../models/danka';
7 7
 import { FormsModule } from '@angular/forms';
8
-import { findIndex } from 'rxjs';
9 8
 
10 9
 @Component({
11 10
   selector: 'app-danka-list',
@@ -22,6 +21,7 @@ export class DankaList {
22 21
 
23 22
   constructor(private dankaService: DankaService) {
24 23
     this.dankaList = this.dankaService.getDankaList();
24
+    this.showAllDanka();
25 25
   }
26 26
 
27 27
   //全件タグで絞り込み
@@ -44,12 +44,13 @@ export class DankaList {
44 44
 
45 45
   //検索処理
46 46
   searchDanka() {
47
-        this.selectedFilter = 'search';
47
+    this.selectedFilter = 'search';
48 48
     //検索欄に入力された値から余白を削除
49 49
     const keyword = this.searchKeyword.trim();
50 50
     //検索欄が空の場合は檀家の一覧を表示
51 51
     if (keyword === '') {
52 52
       this.filterDankaList = this.dankaList;
53
+      this.dankaDisplay = this.filterDankaList.length;
53 54
       return;
54 55
     }
55 56
 
@@ -66,4 +67,11 @@ export class DankaList {
66 67
     this.dankaDisplay = this.filterDankaList.length;
67 68
     console.log(this.dankaDisplay);
68 69
   }
70
+
71
+  clearDanka() {
72
+    this.selectedFilter = '';
73
+    this.searchKeyword = '';
74
+    this.filterDankaList = [];
75
+    this.dankaDisplay = 0;
76
+  }
69 77
 }

+ 32
- 32
src/app/pages/dashboard/dashboard.html Dosyayı Görüntüle

@@ -15,14 +15,15 @@
15 15
       <section class="overview" aria-label="概要">
16 16
         <a class="card primary" href="#">
17 17
           <div class="card-label">今週の法要</div>
18
-          <div class="metric"><strong>4</strong><span>件</span></div>
19
-          <p class="card-text">本日 1件、明日以降 3件。準備状況を確認できます。</p>
18
+          <div class="metric"><strong>{{ weeklyMemorialCount }}</strong><span>件</span></div>
19
+          <p class="card-text">
20
+            本日 {{ todayMemorialCount }}件、明日以降 {{ upcomingWeeklyMemorialCount }}件。
21
+          </p>
20 22
         </a>
21 23
 
22 24
         <a class="card" href="#">
23 25
           <div class="card-label">今月の年忌法要</div>
24
-          <div class="metric"><strong>12</strong><span>名</span></div>
25
-          <p class="card-text">未確認 3名 / 案内済 7名 / 完了 2名</p>
26
+          <div class="metric"><strong>{{ monthlyMemorialCount }}</strong><span>名</span></div>
26 27
         </a>
27 28
 
28 29
         <div class="search-card">
@@ -92,35 +93,34 @@
92 93
         </div>
93 94
 
94 95
         <div class="upcoming-list">
95
-          <a class="upcoming-item important" href="#">
96
-            <div class="upcoming-date">今日</div>
97
-            <div class="upcoming-main">
98
-              <div class="upcoming-title">鈴木家 美咲様 三回忌</div>
99
-              <div class="upcoming-sub">市内 1-2-3 / 連絡先確認済</div>
96
+          @if (upcomingMemorials.length > 0) {
97
+            @for (memorial of upcomingMemorials; track memorial.id) {
98
+              <a
99
+                class="upcoming-item"
100
+                [class.important]="memorial.dateLabel === '今日'"
101
+                [routerLink]="['/danka-detail', memorial.dankaId]"
102
+                [queryParams]="{tab: 'kakocho'}"
103
+              >
104
+                <div class="upcoming-date">{{ memorial.dateLabel }}</div>
105
+                <div class="upcoming-main">
106
+                  <div class="upcoming-title">{{ memorial.title }}</div>
107
+                  <div class="upcoming-sub">{{ memorial.subText }}</div>
108
+                </div>
109
+                <div class="upcoming-type">{{ memorial.type }}</div>
110
+                <div class="upcoming-status">{{ memorial.status }}</div>
111
+              </a>
112
+            }
113
+          } @else {
114
+            <div class="upcoming-item">
115
+              <div class="upcoming-date">なし</div>
116
+              <div class="upcoming-main">
117
+                <div class="upcoming-title">近日の法要・命日はありません</div>
118
+                <div class="upcoming-sub">過去帳に登録された命日から自動表示します。</div>
119
+              </div>
120
+              <div class="upcoming-type">-</div>
121
+              <div class="upcoming-status">-</div>
100 122
             </div>
101
-            <div class="upcoming-type">年忌法要</div>
102
-            <div class="upcoming-status">準備確認</div>
103
-          </a>
104
-
105
-          <a class="upcoming-item" href="#">
106
-            <div class="upcoming-date">6月2日</div>
107
-            <div class="upcoming-main">
108
-              <div class="upcoming-title">佐藤家 恵夫様 七回忌</div>
109
-              <div class="upcoming-sub">市内 2-8-1 / 案内状送付済</div>
110
-            </div>
111
-            <div class="upcoming-type">年忌法要</div>
112
-            <div class="upcoming-status">案内済</div>
113
-          </a>
114
-
115
-          <a class="upcoming-item" href="#">
116
-            <div class="upcoming-date">6月7日</div>
117
-            <div class="upcoming-main">
118
-              <div class="upcoming-title">田中家 雪音様 祥月命日</div>
119
-              <div class="upcoming-sub">市内 3-4-6 / 法要日は未設定</div>
120
-            </div>
121
-            <div class="upcoming-type">命日</div>
122
-            <div class="upcoming-status">要確認</div>
123
-          </a>
123
+          }
124 124
         </div>
125 125
       </section>
126 126
     </section>

+ 167
- 2
src/app/pages/dashboard/dashboard.ts Dosyayı Görüntüle

@@ -1,11 +1,176 @@
1 1
 import { Component } from '@angular/core';
2
+import { RouterLink } from '@angular/router';
3
+import { KakochoService } from '../../services/kakocho-service';
4
+import { DankaService } from '../../services/dankaService';
2 5
 import { AppHeader } from '../../share/header/app-header';
3 6
 import { AppSideMenu } from '../../share/side-menu/app-side-menu';
4 7
 
8
+interface UpcomingMemorial {
9
+  id: string;
10
+  dankaId: string;
11
+  date: Date;
12
+  dateLabel: string;
13
+  title: string;
14
+  subText: string;
15
+  type: '年忌法要' | '命日';
16
+  status: '準備確認' | '要確認';
17
+}
18
+
5 19
 @Component({
6 20
   selector: 'app-dashboard',
7
-  imports: [AppHeader, AppSideMenu],
21
+  imports: [AppHeader, AppSideMenu, RouterLink],
8 22
   templateUrl: './dashboard.html',
9 23
   styleUrl: './dashboard.scss',
10 24
 })
11
-export class Dashboard {}
25
+export class Dashboard {
26
+  weeklyMemorialCount = 0;
27
+  todayMemorialCount = 0;
28
+  upcomingWeeklyMemorialCount = 0;
29
+  monthlyMemorialCount = 0;
30
+  upcomingMemorials: UpcomingMemorial[] = [];
31
+
32
+  private readonly targetYear = new Date().getFullYear();
33
+
34
+  constructor(
35
+    private kakochoService: KakochoService,
36
+    private dankaService: DankaService,
37
+  ) {
38
+    this.setWeeklyMemorialSummary();
39
+    this.setMonthlyMemorialSummary();
40
+    this.setUpcomingMemorials();
41
+  }
42
+
43
+  private setWeeklyMemorialSummary(): void {
44
+    const today = this.toDateOnly(new Date());
45
+    const weekEnd = this.addDays(this.getWeekStart(today), 6);
46
+
47
+    const weeklyMemorials = this.kakochoService.getKakochoList().filter((kakocho) => {
48
+      const deathDate = this.parseDate(kakocho.deathDate);
49
+      if (!deathDate) {
50
+        return false;
51
+      }
52
+
53
+      if (!this.isMemorialTarget(deathDate)) {
54
+        return false;
55
+      }
56
+
57
+      const memorialDate = new Date(this.targetYear, deathDate.getMonth(), deathDate.getDate());
58
+      return memorialDate >= today && memorialDate <= weekEnd;
59
+    });
60
+
61
+    this.weeklyMemorialCount = weeklyMemorials.length;
62
+    this.todayMemorialCount = weeklyMemorials.filter((kakocho) => {
63
+      const deathDate = this.parseDate(kakocho.deathDate);
64
+      return deathDate?.getMonth() === today.getMonth() && deathDate.getDate() === today.getDate();
65
+    }).length;
66
+    this.upcomingWeeklyMemorialCount = this.weeklyMemorialCount - this.todayMemorialCount;
67
+  }
68
+
69
+  private setMonthlyMemorialSummary(): void {
70
+    const today = this.toDateOnly(new Date());
71
+
72
+    this.monthlyMemorialCount = this.kakochoService.getKakochoList().filter((kakocho) => {
73
+      const deathDate = this.parseDate(kakocho.deathDate);
74
+      if (!deathDate || !this.isMemorialTarget(deathDate)) {
75
+        return false;
76
+      }
77
+
78
+      return deathDate.getMonth() === today.getMonth();
79
+    }).length;
80
+  }
81
+
82
+  private setUpcomingMemorials(): void {
83
+    const today = this.toDateOnly(new Date());
84
+    const endDate = this.addDays(today, 30);
85
+
86
+    this.upcomingMemorials = this.kakochoService
87
+      .getKakochoList()
88
+      .map((kakocho): UpcomingMemorial | null => {
89
+        const deathDate = this.parseDate(kakocho.deathDate);
90
+        if (!deathDate) {
91
+          return null;
92
+        }
93
+
94
+        const eventDate = new Date(this.targetYear, deathDate.getMonth(), deathDate.getDate());
95
+        if (eventDate < today || eventDate > endDate) {
96
+          return null;
97
+        }
98
+
99
+        const memorialType = this.getMemorialType(deathDate);
100
+        const danka = this.dankaService.getDankaById(kakocho.dankaId);
101
+        const type = memorialType ? '年忌法要' : '命日';
102
+        const status = memorialType ? '準備確認' : '要確認';
103
+
104
+        return {
105
+          id: kakocho.id,
106
+          dankaId: kakocho.dankaId,
107
+          date: eventDate,
108
+          dateLabel: this.formatDateLabel(eventDate, today),
109
+          title: `${danka?.householdName ?? '不明'} ${kakocho.name}様 ${memorialType || '祥月命日'}`,
110
+          subText: `${danka?.address ?? '住所未登録'} / ${kakocho.kaimyo || '戒名未登録'}`,
111
+          type,
112
+          status,
113
+        };
114
+      })
115
+      .filter((memorial): memorial is UpcomingMemorial => memorial !== null)
116
+      .sort((a, b) => a.date.getTime() - b.date.getTime() || a.title.localeCompare(b.title, 'ja'))
117
+      .slice(0, 3);
118
+  }
119
+
120
+  private isMemorialTarget(deathDate: Date): boolean {
121
+    return this.getMemorialType(deathDate) !== '';
122
+  }
123
+
124
+  private getMemorialType(deathDate: Date): string {
125
+    const yearDiff = this.targetYear - deathDate.getFullYear();
126
+
127
+    switch (yearDiff) {
128
+      case 1:
129
+        return '一周忌';
130
+      case 2:
131
+        return '三回忌';
132
+      case 6:
133
+        return '七回忌';
134
+      case 12:
135
+        return '十三回忌';
136
+      case 16:
137
+        return '十七回忌';
138
+      case 22:
139
+        return '二十三回忌';
140
+      default:
141
+        return '';
142
+    }
143
+  }
144
+
145
+  private formatDateLabel(date: Date, today: Date): string {
146
+    if (date.getTime() === today.getTime()) {
147
+      return '今日';
148
+    }
149
+
150
+    return `${date.getMonth() + 1}月${date.getDate()}日`;
151
+  }
152
+
153
+  private getWeekStart(date: Date): Date {
154
+    const day = date.getDay();
155
+    const diff = day === 0 ? -6 : 1 - day;
156
+    return this.addDays(date, diff);
157
+  }
158
+
159
+  private addDays(date: Date, days: number): Date {
160
+    const result = new Date(date);
161
+    result.setDate(result.getDate() + days);
162
+    return result;
163
+  }
164
+
165
+  private toDateOnly(date: Date): Date {
166
+    return new Date(date.getFullYear(), date.getMonth(), date.getDate());
167
+  }
168
+
169
+  private parseDate(value: string): Date | null {
170
+    const [year, month, day] = value.split('-').map(Number);
171
+    if (!year || !month || !day) {
172
+      return null;
173
+    }
174
+    return new Date(year, month - 1, day);
175
+  }
176
+}

+ 0
- 11
src/app/pages/search/search.html Dosyayı Görüntüle

@@ -11,14 +11,6 @@
11 11
     <section class="search-panel">
12 12
       <div class="page-title-row">
13 13
         <h1>まとめて検索</h1>
14
-        <div class="top-action-list">
15
-          <button type="button" class="top-button" onclick="history.back()">
16
-            戻る
17
-          </button>
18
-          <a routerLink="/" class="top-button">
19
-            ホーム
20
-          </a>
21
-        </div>
22 14
       </div>
23 15
 
24 16
       <section class="search-condition-area">
@@ -35,9 +27,6 @@
35 27
           <button type="button" class="filter-button-main" (click)="clearSearch()">
36 28
             クリア
37 29
           </button>
38
-          <a routerLink="/danka-list" class="back-list-button">
39
-            一覧へ戻る
40
-          </a>
41 30
         </div>
42 31
 
43 32
         <div class="search-filter-list">

+ 4
- 4
src/app/share/side-menu/app-side-menu.html Dosyayı Görüntüle

@@ -11,6 +11,10 @@
11 11
         檀家一覧
12 12
       </a>
13 13
 
14
+      <a routerLink="/danka-new" routerLinkActive="active" class="menu-button">
15
+        檀家登録
16
+      </a>
17
+
14 18
       <a routerLink="/memorial-list" routerLinkActive="active" class="menu-button">
15 19
         年次法要
16 20
       </a>
@@ -19,10 +23,6 @@
19 23
         まとめて検索
20 24
       </a>
21 25
 
22
-      <a routerLink="/family-tree" routerLinkActive="active" class="menu-button">
23
-        家系図
24
-      </a>
25
-
26 26
 <!--  ユーザー数が増えた際に実装    -->
27 27
 <!--      <a routerLink="/user-setting" routerLinkActive="active" class="menu-button">-->
28 28
 <!--        利用者設定-->

+ 2
- 3
src/app/share/side-menu/app-side-menu.ts Dosyayı Görüntüle

@@ -1,10 +1,9 @@
1 1
 import { Component } from '@angular/core';
2
-import { RouterLink } from '@angular/router';
3
-import { DankaList } from '../../pages/danka-list/danka-list';
2
+import { RouterLink, RouterLinkActive } from '@angular/router';
4 3
 
5 4
 @Component({
6 5
   selector: 'app-side-menu',
7
-  imports: [RouterLink, ],
6
+  imports: [RouterLink, RouterLinkActive],
8 7
   templateUrl: './app-side-menu.html',
9 8
   styleUrl: './app-side-menu.scss',
10 9
 })

Loading…
İptal
Kaydet