설명 없음
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

event.ts 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import { Component } from '@angular/core';
  2. import { FormsModule } from '@angular/forms';
  3. import { DankaService } from '../../services/dankaService';
  4. import { FamilyService } from '../../services/family-service';
  5. import { EventStatus, EventTarget, EventType } from '../../models/event';
  6. import { AppHeader } from '../../share/header/app-header';
  7. import { AppSideMenu } from '../../share/side-menu/app-side-menu';
  8. @Component({
  9. selector: 'app-event',
  10. imports: [AppHeader, AppSideMenu, FormsModule],
  11. templateUrl: './event.html',
  12. styleUrl: './event.scss',
  13. })
  14. export class EventPage {
  15. eventTargets: EventTarget[] = [];
  16. targetYear: number = new Date().getFullYear();
  17. selectedEventType: EventType | 'all' = 'all';
  18. selectedStatus: EventStatus | 'all' = 'all';
  19. searchKeyword = '';
  20. eventStatuses: EventStatus[] = ['未案内', '案内済'];
  21. yearOptions: number[] = [
  22. this.targetYear - 1,
  23. this.targetYear,
  24. this.targetYear + 1,
  25. this.targetYear + 2,
  26. ];
  27. eventTypeFilters: { label: string; value: EventType | 'all' }[] = [
  28. { label: 'すべて', value: 'all' },
  29. { label: '稚児行列', value: '稚児行列' },
  30. { label: '七五三', value: '七五三' },
  31. { label: '成人式', value: '成人式' },
  32. { label: '米寿', value: '米寿' },
  33. ];
  34. statusFilters: { label: string; value: EventStatus | 'all' }[] = [
  35. { label: 'すべて', value: 'all' },
  36. { label: '未案内', value: '未案内' },
  37. { label: '案内済', value: '案内済' },
  38. ];
  39. private statusByTargetId: Record<string, EventStatus> = {};
  40. constructor(
  41. private dankaService: DankaService,
  42. private familyService: FamilyService,
  43. ) {
  44. this.createEventTargetList();
  45. }
  46. createEventTargetList(): void {
  47. this.eventTargets = [];
  48. this.familyService.getFamilyList().forEach((family) => {
  49. const birthDate = this.parseDate(family.birthDate);
  50. if (!birthDate) {
  51. return;
  52. }
  53. const age = this.targetYear - birthDate.getFullYear();
  54. const eventTypes = this.getEventTypes(age);
  55. if (eventTypes.length === 0) {
  56. return;
  57. }
  58. const danka = this.dankaService.getDankaById(family.dankaId);
  59. eventTypes.forEach((eventType) => {
  60. if (this.selectedEventType !== 'all' && this.selectedEventType !== eventType) {
  61. return;
  62. }
  63. const id = `${family.id}-${eventType}`;
  64. this.eventTargets.push({
  65. id,
  66. dankaId: family.dankaId,
  67. name: family.name,
  68. furigana: family.furigana,
  69. householdName: danka?.householdName ?? '不明',
  70. relationship: family.relationship || '未登録',
  71. birthDate: family.birthDate,
  72. age,
  73. eventType,
  74. note: family.note,
  75. status: this.statusByTargetId[id] ?? (Number(family.id) % 2 === 0 ? '案内済' : '未案内'),
  76. });
  77. });
  78. });
  79. this.eventTargets.sort(
  80. (a, b) =>
  81. this.getEventSortOrder(a.eventType) - this.getEventSortOrder(b.eventType) ||
  82. a.age - b.age ||
  83. a.name.localeCompare(b.name, 'ja'),
  84. );
  85. }
  86. changeEventType(eventType: EventType | 'all'): void {
  87. this.selectedEventType = eventType;
  88. this.createEventTargetList();
  89. }
  90. get filteredEventTargets(): EventTarget[] {
  91. const keyword = this.searchKeyword.trim();
  92. return this.eventTargets.filter((target) => {
  93. const matchesStatus = this.selectedStatus === 'all' || target.status === this.selectedStatus;
  94. const matchesKeyword =
  95. !keyword ||
  96. [
  97. target.name,
  98. target.furigana,
  99. target.householdName,
  100. target.relationship,
  101. target.birthDate,
  102. target.eventType,
  103. target.note,
  104. target.status,
  105. ].some((value) => value.includes(keyword));
  106. return matchesStatus && matchesKeyword;
  107. });
  108. }
  109. changeStatus(target: EventTarget, status: EventStatus): void {
  110. target.status = status;
  111. this.statusByTargetId[target.id] = status;
  112. }
  113. private getEventTypes(age: number): EventType[] {
  114. const eventTypes: EventType[] = [];
  115. if (age >= 3 && age <= 12) {
  116. eventTypes.push('稚児行列');
  117. }
  118. if ([3, 5, 7].includes(age)) {
  119. eventTypes.push('七五三');
  120. }
  121. if (age === 20) {
  122. eventTypes.push('成人式');
  123. }
  124. if (age === 88) {
  125. eventTypes.push('米寿');
  126. }
  127. return eventTypes;
  128. }
  129. private getEventSortOrder(eventType: EventType): number {
  130. return ['稚児行列', '七五三', '成人式', '米寿'].indexOf(eventType);
  131. }
  132. private parseDate(value: string): Date | null {
  133. const [year, month, day] = value.split('-').map(Number);
  134. if (!year || !month || !day) {
  135. return null;
  136. }
  137. return new Date(year, month - 1, day);
  138. }
  139. }