import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { DankaService } from '../../services/dankaService'; import { FamilyService } from '../../services/family-service'; import { EventStatus, EventTarget, EventType } from '../../models/event'; import { AppHeader } from '../../share/header/app-header'; import { AppSideMenu } from '../../share/side-menu/app-side-menu'; @Component({ selector: 'app-event', imports: [AppHeader, AppSideMenu, FormsModule], templateUrl: './event.html', styleUrl: './event.scss', }) export class EventPage { eventTargets: EventTarget[] = []; targetYear: number = new Date().getFullYear(); selectedEventType: EventType | 'all' = 'all'; selectedStatus: EventStatus | 'all' = 'all'; searchKeyword = ''; eventStatuses: EventStatus[] = ['未案内', '案内済']; yearOptions: number[] = [ this.targetYear - 1, this.targetYear, this.targetYear + 1, this.targetYear + 2, ]; eventTypeFilters: { label: string; value: EventType | 'all' }[] = [ { label: 'すべて', value: 'all' }, { label: '稚児行列', value: '稚児行列' }, { label: '七五三', value: '七五三' }, { label: '成人式', value: '成人式' }, { label: '米寿', value: '米寿' }, ]; statusFilters: { label: string; value: EventStatus | 'all' }[] = [ { label: 'すべて', value: 'all' }, { label: '未案内', value: '未案内' }, { label: '案内済', value: '案内済' }, ]; private statusByTargetId: Record = {}; constructor( private dankaService: DankaService, private familyService: FamilyService, ) { this.createEventTargetList(); } createEventTargetList(): void { this.eventTargets = []; this.familyService.getFamilyList().forEach((family) => { const birthDate = this.parseDate(family.birthDate); if (!birthDate) { return; } const age = this.targetYear - birthDate.getFullYear(); const eventTypes = this.getEventTypes(age); if (eventTypes.length === 0) { return; } const danka = this.dankaService.getDankaById(family.dankaId); eventTypes.forEach((eventType) => { if (this.selectedEventType !== 'all' && this.selectedEventType !== eventType) { return; } const id = `${family.id}-${eventType}`; this.eventTargets.push({ id, dankaId: family.dankaId, name: family.name, furigana: family.furigana, householdName: danka?.householdName ?? '不明', relationship: family.relationship || '未登録', birthDate: family.birthDate, age, eventType, note: family.note, status: this.statusByTargetId[id] ?? (Number(family.id) % 2 === 0 ? '案内済' : '未案内'), }); }); }); this.eventTargets.sort( (a, b) => this.getEventSortOrder(a.eventType) - this.getEventSortOrder(b.eventType) || a.age - b.age || a.name.localeCompare(b.name, 'ja'), ); } changeEventType(eventType: EventType | 'all'): void { this.selectedEventType = eventType; this.createEventTargetList(); } get filteredEventTargets(): EventTarget[] { const keyword = this.searchKeyword.trim(); return this.eventTargets.filter((target) => { const matchesStatus = this.selectedStatus === 'all' || target.status === this.selectedStatus; const matchesKeyword = !keyword || [ target.name, target.furigana, target.householdName, target.relationship, target.birthDate, target.eventType, target.note, target.status, ].some((value) => value.includes(keyword)); return matchesStatus && matchesKeyword; }); } changeStatus(target: EventTarget, status: EventStatus): void { target.status = status; this.statusByTargetId[target.id] = status; } private getEventTypes(age: number): EventType[] { const eventTypes: EventType[] = []; if (age >= 3 && age <= 12) { eventTypes.push('稚児行列'); } if ([3, 5, 7].includes(age)) { eventTypes.push('七五三'); } if (age === 20) { eventTypes.push('成人式'); } if (age === 88) { eventTypes.push('米寿'); } return eventTypes; } private getEventSortOrder(eventType: EventType): number { return ['稚児行列', '七五三', '成人式', '米寿'].indexOf(eventType); } private parseDate(value: string): Date | null { const [year, month, day] = value.split('-').map(Number); if (!year || !month || !day) { return null; } return new Date(year, month - 1, day); } }