using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; namespace TaxBaik.Web.Hubs; /// /// Real-time notification hub for admin dashboard /// SOLID: Single Responsibility - Only broadcasts change notifications /// No state management - stateless broadcast pattern /// [Authorize] public class NotificationHub : Hub { private const string AdminGroup = "admins"; public override async Task OnConnectedAsync() { await Groups.AddToGroupAsync(Context.ConnectionId, AdminGroup); await base.OnConnectedAsync(); } /// /// Broadcast inquiry status changed to all connected admins /// Clients should re-fetch from API to verify /// public async Task NotifyInquiryStatusChanged(int inquiryId, string newStatus) { await Clients.Group(AdminGroup).SendAsync("InquiryStatusChanged", new { InquiryId = inquiryId, Status = newStatus, ChangedAt = DateTime.UtcNow }); } /// /// Broadcast inquiry submitted (new inquiry created) /// public async Task NotifyInquiryCreated(int inquiryId, string name) { await Clients.Group(AdminGroup).SendAsync("InquiryCreated", new { InquiryId = inquiryId, Name = name, CreatedAt = DateTime.UtcNow }); } /// /// Broadcast client created /// public async Task NotifyClientCreated(int clientId, string name) { await Clients.Group(AdminGroup).SendAsync("ClientCreated", new { ClientId = clientId, Name = name, CreatedAt = DateTime.UtcNow }); } /// /// Broadcast announcement published /// public async Task NotifyAnnouncementPublished(int announcementId, string title) { await Clients.Group(AdminGroup).SendAsync("AnnouncementPublished", new { AnnouncementId = announcementId, Title = title, PublishedAt = DateTime.UtcNow }); } /// /// Broadcast tax filing completed /// public async Task NotifyFilingCompleted(int filingId, string filingType) { await Clients.Group(AdminGroup).SendAsync("FilingCompleted", new { FilingId = filingId, FilingType = filingType, CompletedAt = DateTime.UtcNow }); } }