3 次代码提交

作者 SHA1 备注 提交日期
  poohr 342b671bd6 [add] 3 周前
  poohr 0e79b158a7 [add] 3 周前
  poohr f285bccffb [add] 3 周前

+ 48
- 1
src/app/pages/danka-detail/danka-detail.html 查看文件

480
                           <button
480
                           <button
481
                             type="button"
481
                             type="button"
482
                             class="member-chip"
482
                             class="member-chip"
483
-                            [class.active]="selectedFamily?.id === family.id"
483
+                            [class.active]="selectedFamily.id === family.id"
484
                             (click)="selectFamily(family)"
484
                             (click)="selectFamily(family)"
485
                           >
485
                           >
486
                             {{ family.name }}
486
                             {{ family.name }}
551
                       </div>
551
                       </div>
552
                     </div>
552
                     </div>
553
 
553
 
554
+                    <section class="marriage-summary-panel">
555
+                      <h4>配偶関係</h4>
556
+
557
+                      <div class="marriage-summary-block">
558
+                        <p class="marriage-summary-label">現在の配偶者</p>
559
+
560
+                        @if (getCurrentMarriage(selectedFamily); as currentMarriage) {
561
+                          @if (getMarriagePartner(currentMarriage, selectedFamily); as currentPartner) {
562
+                            <button
563
+                              type="button"
564
+                              class="marriage-person-button"
565
+                              (click)="selectFamily(currentPartner)"
566
+                            >
567
+                              {{ currentPartner.name }}
568
+                            </button>
569
+                          } @else {
570
+                            <p class="marriage-empty-text">未登録</p>
571
+                          }
572
+                        } @else {
573
+                          <p class="marriage-empty-text">未登録</p>
574
+                        }
575
+                      </div>
576
+
577
+                      <div class="marriage-summary-block">
578
+                        <p class="marriage-summary-label">過去の配偶者</p>
579
+
580
+                        @if (getPastMarriages(selectedFamily).length > 0) {
581
+                          <div class="marriage-history-list">
582
+                            @for (relation of getPastMarriages(selectedFamily); track relation.id) {
583
+                              @if (getMarriagePartner(relation, selectedFamily); as pastPartner) {
584
+                                <button
585
+                                  type="button"
586
+                                  class="marriage-person-button secondary"
587
+                                  (click)="selectFamily(pastPartner)"
588
+                                >
589
+                                  <span>{{ pastPartner.name }}</span>
590
+                                  <small>{{ getMarriageStatusLabel(relation.status) }}</small>
591
+                                </button>
592
+                              }
593
+                            }
594
+                          </div>
595
+                        } @else {
596
+                          <p class="marriage-empty-text">未登録</p>
597
+                        }
598
+                      </div>
599
+                    </section>
600
+
554
                     <div class="selected-person-actions">
601
                     <div class="selected-person-actions">
555
                       <a
602
                       <a
556
                         class="selected-person-button"
603
                         class="selected-person-button"

+ 71
- 0
src/app/pages/danka-detail/danka-detail.scss 查看文件

775
   font-weight: 800;
775
   font-weight: 800;
776
 }
776
 }
777
 
777
 
778
+.marriage-summary-panel {
779
+  margin-top: 18px;
780
+  padding: 14px 16px;
781
+  background: #fffaf3;
782
+  border: 2px solid #d8caba;
783
+  border-radius: 12px;
784
+  box-sizing: border-box;
785
+}
786
+
787
+.marriage-summary-panel h4 {
788
+  margin: 0 0 12px;
789
+  color: #2f2720;
790
+  font-size: 16px;
791
+  font-weight: 800;
792
+}
793
+
794
+.marriage-summary-block + .marriage-summary-block {
795
+  margin-top: 14px;
796
+}
797
+
798
+.marriage-summary-label {
799
+  margin: 0 0 8px;
800
+  color: #7b6b5c;
801
+  font-size: 13px;
802
+  font-weight: 800;
803
+}
804
+
805
+.marriage-history-list {
806
+  display: grid;
807
+  gap: 8px;
808
+}
809
+
810
+.marriage-person-button {
811
+  width: 100%;
812
+  min-height: 40px;
813
+  padding: 8px 10px;
814
+  border: 2px solid #8a6543;
815
+  border-radius: 8px;
816
+  background: #ffffff;
817
+  color: #2f2720;
818
+  font-size: 14px;
819
+  font-weight: 800;
820
+  cursor: pointer;
821
+  display: flex;
822
+  align-items: center;
823
+  justify-content: space-between;
824
+  gap: 8px;
825
+  box-sizing: border-box;
826
+}
827
+
828
+.marriage-person-button:hover {
829
+  background: #f6efe6;
830
+}
831
+
832
+.marriage-person-button small {
833
+  color: #7b6b5c;
834
+  font-size: 12px;
835
+  font-weight: 800;
836
+}
837
+
838
+.marriage-person-button.secondary {
839
+  border-color: #d8caba;
840
+}
841
+
842
+.marriage-empty-text {
843
+  margin: 0;
844
+  color: #7b6b5c;
845
+  font-size: 14px;
846
+  font-weight: 700;
847
+}
848
+
778
 .selected-person-actions {
849
 .selected-person-actions {
779
   display: grid;
850
   display: grid;
780
   gap: 10px;
851
   gap: 10px;

+ 6
- 13
src/app/pages/danka-detail/danka-detail.ts 查看文件

1
 import { Component } from '@angular/core';
1
 import { Component } from '@angular/core';
2
-import { ActivatedRoute, Router, RouterLink } from '@angular/router';
2
+import { ActivatedRoute, 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 { FamilyService } from '../../services/family-service';
5
 import { KakochoService } from '../../services/kakocho-service';
5
 import { KakochoService } from '../../services/kakocho-service';
34
     private marriageRelationService: MarriageRelationService,
34
     private marriageRelationService: MarriageRelationService,
35
     private route: ActivatedRoute,
35
     private route: ActivatedRoute,
36
   ) {
36
   ) {
37
-    //遷移先からタブ情報を取得
38
     const tab = this.route.snapshot.queryParams['tab'];
37
     const tab = this.route.snapshot.queryParams['tab'];
39
     if (tab === 'family') {
38
     if (tab === 'family') {
40
       this.selectedTab = 'family';
39
       this.selectedTab = 'family';
43
     } else if (tab === 'familyTree') {
42
     } else if (tab === 'familyTree') {
44
       this.selectedTab = 'familyTree';
43
       this.selectedTab = 'familyTree';
45
     }
44
     }
46
-    //遷移先のIDから該当の世帯と家族基本を取得
45
+
47
     const id = this.route.snapshot.params['id'];
46
     const id = this.route.snapshot.params['id'];
48
     if (id) {
47
     if (id) {
49
       this.danka = this.dankaService.getDankaById(id);
48
       this.danka = this.dankaService.getDankaById(id);
52
       this.selectedFamily = this.families[0];
51
       this.selectedFamily = this.families[0];
53
       this.kakocholist = this.kakochoService.getKakochoByDankaId(id);
52
       this.kakocholist = this.kakochoService.getKakochoByDankaId(id);
54
     }
53
     }
55
-    console.log(this.danka);
56
-    console.log(this.families);
57
-    console.log(tab);
58
   }
54
   }
59
 
55
 
60
-  //年齢計算の処理
61
-  getAge(birthDate: string) {
56
+  getAge(birthDate: string): string {
62
     if (birthDate === '') {
57
     if (birthDate === '') {
63
       return '-';
58
       return '-';
64
     }
59
     }
65
 
60
 
66
     const birth = new Date(birthDate);
61
     const birth = new Date(birthDate);
67
-    const today: Date = new Date();
62
+    const today = new Date();
68
     const thisYearBirthday = new Date(today.getFullYear(), birth.getMonth(), birth.getDate());
63
     const thisYearBirthday = new Date(today.getFullYear(), birth.getMonth(), birth.getDate());
69
 
64
 
70
     let age = today.getFullYear() - birth.getFullYear();
65
     let age = today.getFullYear() - birth.getFullYear();
72
     if (thisYearBirthday > today) {
67
     if (thisYearBirthday > today) {
73
       age--;
68
       age--;
74
     }
69
     }
70
+
75
     return age.toString();
71
     return age.toString();
76
-    console.log(this.kakocholist);
77
   }
72
   }
78
 
73
 
79
-  //回忌計算の処理
80
   getKaiki(deathDate: string): number {
74
   getKaiki(deathDate: string): number {
81
     return this.currentYear - new Date(deathDate).getFullYear() + 1;
75
     return this.currentYear - new Date(deathDate).getFullYear() + 1;
82
   }
76
   }
83
 
77
 
84
-  //家系図の処理
85
   selectFamily(family: Family): void {
78
   selectFamily(family: Family): void {
86
     this.selectedFamily = family;
79
     this.selectedFamily = family;
87
   }
80
   }
90
     if (!id) {
83
     if (!id) {
91
       return undefined;
84
       return undefined;
92
     }
85
     }
86
+
93
     return this.families.find((family) => family.id === id);
87
     return this.families.find((family) => family.id === id);
94
   }
88
   }
95
 
89
 
125
         relation.status !== 'current' &&
119
         relation.status !== 'current' &&
126
         (relation.person1Id === family.id || relation.person2Id === family.id),
120
         (relation.person1Id === family.id || relation.person2Id === family.id),
127
     );
121
     );
128
-
129
   }
122
   }
130
 
123
 
131
   getMarriagePartner(relation: MarriageRelation, family: Family): Family | undefined {
124
   getMarriagePartner(relation: MarriageRelation, family: Family): Family | undefined {

+ 20
- 0
src/app/pages/family-edit/family-edit.html 查看文件

141
                 </div>
141
                 </div>
142
               </div>
142
               </div>
143
 
143
 
144
+              <div class="form-row">
145
+                <label for="marriageStatus">配偶者の状態</label>
146
+                <div class="form-field">
147
+                  <select id="marriageStatus" formControlName="marriageStatus">
148
+                    <option value="current">現在の配偶者</option>
149
+                    <option value="divorced">離婚</option>
150
+                    <option value="widowed">死別</option>
151
+                    <option value="unknown">不明</option>
152
+                  </select>
153
+
154
+                  @if (marriageErrorMessages.length > 0) {
155
+                    <div class="error-message-list">
156
+                      @for (error of marriageErrorMessages; track error) {
157
+                        <p class="error-message">{{ error }}</p>
158
+                      }
159
+                    </div>
160
+                  }
161
+                </div>
162
+              </div>
163
+
144
               <div class="form-row">
164
               <div class="form-row">
145
                 <label for="note">備考</label>
165
                 <label for="note">備考</label>
146
                 <div class="form-field">
166
                 <div class="form-field">

+ 62
- 1
src/app/pages/family-edit/family-edit.ts 查看文件

10
 import { AppHeader } from '../../share/header/app-header';
10
 import { AppHeader } from '../../share/header/app-header';
11
 import { AppSideMenu } from '../../share/side-menu/app-side-menu';
11
 import { AppSideMenu } from '../../share/side-menu/app-side-menu';
12
 import { FamilyService } from '../../services/family-service';
12
 import { FamilyService } from '../../services/family-service';
13
+import { MarriageRelationService } from '../../services/marriage-relation-service';
13
 import { Danka } from '../../models/danka';
14
 import { Danka } from '../../models/danka';
14
 import { Family } from '../../models/family';
15
 import { Family } from '../../models/family';
16
+import { MarriageRelation } from '../../models/marriage-relation';
15
 
17
 
16
 @Component({
18
 @Component({
17
   selector: 'app-family-edit',
19
   selector: 'app-family-edit',
27
   familyId: string | null = null;
29
   familyId: string | null = null;
28
   relationMode: string = '';
30
   relationMode: string = '';
29
   baseFamilyId: string = '';
31
   baseFamilyId: string = '';
32
+  marriageErrorMessages: string[] = [];
30
 
33
 
31
   constructor(
34
   constructor(
32
     private familyService: FamilyService,
35
     private familyService: FamilyService,
36
+    private marriageRelationService: MarriageRelationService,
33
     private route: ActivatedRoute,
37
     private route: ActivatedRoute,
34
     private router: Router,
38
     private router: Router,
35
   ) {
39
   ) {
52
           spouseId: this.family.spouseId,
56
           spouseId: this.family.spouseId,
53
           gender: this.family.gender,
57
           gender: this.family.gender,
54
         });
58
         });
59
+        this.patchMarriageRelationFields(this.family.id);
55
       }
60
       }
56
     }
61
     }
57
 
62
 
58
     if (!this.familyId && this.relationMode === 'spouse') {
63
     if (!this.familyId && this.relationMode === 'spouse') {
59
       this.familyForm.patchValue({
64
       this.familyForm.patchValue({
60
         spouseId: this.baseFamilyId,
65
         spouseId: this.baseFamilyId,
66
+        marriageStatus: 'current',
61
       });
67
       });
62
     }
68
     }
63
 
69
 
87
     fatherId: new FormControl(''),
93
     fatherId: new FormControl(''),
88
     motherId: new FormControl(''),
94
     motherId: new FormControl(''),
89
     spouseId: new FormControl(''),
95
     spouseId: new FormControl(''),
96
+    marriageStatus: new FormControl<MarriageRelation['status']>('current'),
90
     gender: new FormControl('unknown'),
97
     gender: new FormControl('unknown'),
91
   });
98
   });
92
 
99
 
110
     return this.families.filter((family) => family.id !== this.familyId);
117
     return this.families.filter((family) => family.id !== this.familyId);
111
   }
118
   }
112
 
119
 
120
+  patchMarriageRelationFields(familyId: string): void {
121
+    const relations = this.marriageRelationService.getMarriageRelationsByFamilyId(familyId);
122
+    const relation =
123
+      relations.find((marriageRelation) => marriageRelation.status === 'current') ?? relations[0];
124
+
125
+    if (!relation) {
126
+      return;
127
+    }
128
+
129
+    this.familyForm.patchValue({
130
+      spouseId: relation.person1Id === familyId ? relation.person2Id : relation.person1Id,
131
+      marriageStatus: relation.status,
132
+    });
133
+  }
134
+
135
+  findMarriageRelation(person1Id: string, person2Id: string): MarriageRelation | undefined {
136
+    return this.marriageRelationService
137
+      .getMarriageRelationsByFamilyId(person1Id)
138
+      .find(
139
+        (relation) =>
140
+          (relation.person1Id === person1Id && relation.person2Id === person2Id) ||
141
+          (relation.person1Id === person2Id && relation.person2Id === person1Id),
142
+      );
143
+  }
144
+
113
   saveFamily() {
145
   saveFamily() {
114
     if (this.familyForm.invalid) {
146
     if (this.familyForm.invalid) {
115
       return;
147
       return;
116
     }
148
     }
117
 
149
 
150
+    this.marriageErrorMessages = [];
118
     const familyId = this.familyId ?? Date.now().toString();
151
     const familyId = this.familyId ?? Date.now().toString();
119
     const dankaId = this.dankaId;
152
     const dankaId = this.dankaId;
120
     const formValue = this.familyForm.value;
153
     const formValue = this.familyForm.value;
154
+    const spouseId = formValue.spouseId ?? '';
155
+    const marriageStatus = formValue.marriageStatus ?? 'current';
156
+    const currentSpouseId = marriageStatus === 'current' ? spouseId : '';
121
     const updatedFamily = {
157
     const updatedFamily = {
122
       id: familyId,
158
       id: familyId,
123
       dankaId: dankaId,
159
       dankaId: dankaId,
128
       note: formValue.note?.trim() ?? '',
164
       note: formValue.note?.trim() ?? '',
129
       fatherId: this.familyForm.value.fatherId ?? '',
165
       fatherId: this.familyForm.value.fatherId ?? '',
130
       motherId: this.familyForm.value.motherId ?? '',
166
       motherId: this.familyForm.value.motherId ?? '',
131
-      spouseId: this.familyForm.value.spouseId ?? '',
167
+      spouseId: currentSpouseId,
132
       gender: this.familyForm.value.gender ?? 'unknown',
168
       gender: this.familyForm.value.gender ?? 'unknown',
133
     };
169
     };
170
+
171
+    if (spouseId) {
172
+      const existingRelation = this.findMarriageRelation(familyId, spouseId);
173
+      const errors = this.marriageRelationService.saveMarriageRelation({
174
+        id: existingRelation?.id ?? Date.now().toString(),
175
+        dankaId,
176
+        person1Id: familyId,
177
+        person2Id: spouseId,
178
+        status: marriageStatus,
179
+        startDate: existingRelation?.startDate ?? '',
180
+        endDate: existingRelation?.endDate ?? '',
181
+        note: existingRelation?.note ?? '',
182
+      });
183
+
184
+      if (errors.length > 0) {
185
+        this.marriageErrorMessages = errors;
186
+        return;
187
+      }
188
+    } else {
189
+      const currentMarriage = this.marriageRelationService.getCurrentMarriageByFamilyId(familyId);
190
+      if (currentMarriage) {
191
+        this.marriageRelationService.deleteMarriageRelation(currentMarriage.id);
192
+      }
193
+    }
194
+
134
     this.familyService.saveFamily(updatedFamily);
195
     this.familyService.saveFamily(updatedFamily);
135
     this.router.navigate(['/danka-detail', dankaId], { queryParams: { tab: 'family' } });
196
     this.router.navigate(['/danka-detail', dankaId], { queryParams: { tab: 'family' } });
136
   }
197
   }

+ 13
- 0
src/app/services/family-service.ts 查看文件

110
       spouseId: '',
110
       spouseId: '',
111
       gender: 'male',
111
       gender: 'male',
112
     },
112
     },
113
+    {
114
+      id: '9',
115
+      dankaId: '1',
116
+      furigana: 'やまだ はなこ',
117
+      name: '山田 花子',
118
+      relationship: '長男の前妻',
119
+      birthDate: '2005-04-02',
120
+      note: '',
121
+      fatherId: '',
122
+      motherId: '',
123
+      spouseId: '',
124
+      gender: 'female',
125
+    },
113
   ];
126
   ];
114
 
127
 
115
   //檀家と紐づいている家族情報の取得
128
   //檀家と紐づいている家族情報の取得

+ 4
- 4
src/app/services/marriage-relation-service.ts 查看文件

9
     {
9
     {
10
       id: '1',
10
       id: '1',
11
       dankaId: '1',
11
       dankaId: '1',
12
-      person1Id: '2', // 太郎
13
-      person2Id: '8', // 花子
12
+      person1Id: '2',
13
+      person2Id: '9',
14
       status: 'divorced',
14
       status: 'divorced',
15
       startDate: '',
15
       startDate: '',
16
       endDate: '',
16
       endDate: '',
19
     {
19
     {
20
       id: '2',
20
       id: '2',
21
       dankaId: '1',
21
       dankaId: '1',
22
-      person1Id: '2', // 太郎
23
-      person2Id: '7', // 美咲
22
+      person1Id: '2',
23
+      person2Id: '7',
24
       status: 'current',
24
       status: 'current',
25
       startDate: '',
25
       startDate: '',
26
       endDate: '',
26
       endDate: '',

正在加载...
取消
保存