import { AfterViewInit, Component, OnDestroy, OnInit, Renderer2, } from '@angular/core'; import * as L from 'leaflet'; import 'leaflet.markercluster'; import { Subscription, take } from 'rxjs'; import { SocketService } from '../../../shared/services/socket.service'; import { MatDialog } from '@angular/material/dialog'; import { AlarmSoundService } from '../../../shared/services/alarm-sound.service'; import { CameraDialogComponent } from '../../../shared/component/camera-dialog/camera-dialog.component'; import { alarmData, alarmDemo } from '../data/fake-data'; import { ConfirmDialogService } from '../../../shared/services/confirm-dialog.service'; @Component({ selector: 'app-centralized-security-management', templateUrl: './centralized-security-management.component.html', styleUrls: ['./centralized-security-management.component.scss'], }) export class CentralizedSecurityManagementComponent implements OnInit, AfterViewInit, OnDestroy { private map!: L.Map; private markers!: L.MarkerClusterGroup; private statusSubscription?: Subscription; private messageSubscription?: Subscription; data = alarmData; alarmDemo = alarmDemo; state1 = false; state2 = false; state5 = false; state6 = false; isReady = true; constructor( private socketService$: SocketService, private dialog: MatDialog, private renderer: Renderer2, private alarmSoundService$: AlarmSoundService, private confirmDialogService$: ConfirmDialogService, ) {} ngOnInit() { this.statusSubscription = this.socketService$.status$.subscribe( (isConnected) => { if (isConnected) { this.socketService$.sendMessage({ id: '0', type: 'get' }); this.messageSubscription = this.socketService$.messages$.subscribe( (message) => { this.onMessage(message); }, ); } }, ); } openDialog(): void { this.dialog.open(CameraDialogComponent, { width: '80vw', data: '', }); } ngAfterViewInit(): void { this.initMap(); } ngOnDestroy(): void { this.statusSubscription?.unsubscribe(); this.messageSubscription?.unsubscribe(); this.socketService$.close(); this.alarmSoundService$.stopAlarm(); } initMap(): void { const mapContainer = document.getElementById('map'); if (mapContainer) { this.map = L.map('map', { center: [10.7483, 106.7537], zoom: 12, }); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 15, minZoom: 3, attribution: '© OpenStreetMap', }).addTo(this.map); this.addIconsToMap(); } else { console.error('Map container not found'); } } onMessage(message: any) { if (message.id == '0' && message.type === 'get') { this.state1 = message.state1 === '0'; // 1 OFF // alarm 12h this.state2 = message.state2 === '0'; // 1 OFF // alarm 1h this.state5 = message.state5 === '1'; // 1 ON, 0 OFF this.isReady = message.ready === '1'; // this.alarmSoundService$.startAlarm(true, true, true, this.state2); this.updateIcons(); } } addIconsToMap(): void { this.markers = L.markerClusterGroup(); this.data.forEach((item) => this.addMarker(item)); this.addMarker(this.alarmDemo, true); this.map.addLayer(this.markers); } addMarker(item: any, isDemo: boolean = false): void { const icon = isDemo ? this.getIcon(this.state5, this.isReady, this.state1, this.state2) : this.createIcon(item.warning); const marker = L.marker( [item.detail.coordinates.lat, item.detail.coordinates.lng], { icon }, ).bindPopup(this.popupDetail(item)); marker.on('popupopen', (event) => this.bindPopupEvents(event)); this.markers.addLayer(marker); } bindPopupEvents(event: any): void { const popupContainer = event.popup.getElement(); const button = popupContainer?.querySelector('.dynamic-button'); if (button) { this.renderer.listen(button, 'click', () => this.openDialog()); } } updateIcons(): void { this.markers.clearLayers(); this.addIconsToMap(); } popupDetail(item: any): string { return `
${item.title}
Địa điểm: ${item.detail.position}
Tọa độ: ${item.detail.coordinates.lat}, ${item.detail.coordinates.lng}
Thời gian: ${item.detail.time}
Xem chi tiết
`; } createIcon( active: boolean, className: string = '', text: any = [], ): L.Icon | L.DivIcon { if (text.length < 1) { return L.icon({ iconUrl: active ? '../../../../assets/images/sensor-on.png' : '../../../../assets/images/sensor-off.png', iconSize: [30, 30], className: className, }); } else { let htmlContent = ''; text.forEach((item: any) => { htmlContent += `${item}
`; }); return L.divIcon({ html: `
icon-alarm
${htmlContent}
`, iconSize: [200, 30], className: className, }); } } getIcon( isTurnOn: boolean, isReady: boolean, fireArm: boolean, fenceArm: boolean, ): L.Icon | L.DivIcon { if (isTurnOn && isReady) { let text = []; if (fireArm && fenceArm) { text.push('FIRE ALARM', 'FENCE ALARM'); } else if (fireArm) { text.push('FIRE ALARM'); } else if (fenceArm) { text.push('FENCE ALARM'); } return this.createIcon(true, '', text); } return this.createIcon(false); } }