/** * Use Case: RecordEngagementUseCase * * Records an engagement event when a visitor interacts with an entity. */ import type { AsyncUseCase } from '@gridpilot/shared/application'; import { EngagementEvent, type EngagementAction, type EngagementEntityType } from '../../domain/entities/EngagementEvent'; import type { IEngagementRepository } from '../../domain/repositories/IEngagementRepository'; export interface RecordEngagementInput { action: EngagementAction; entityType: EngagementEntityType; entityId: string; actorId?: string; actorType: 'anonymous' | 'driver' | 'sponsor'; sessionId: string; metadata?: Record; } export interface RecordEngagementOutput { eventId: string; engagementWeight: number; } export class RecordEngagementUseCase implements AsyncUseCase { constructor(private readonly engagementRepository: IEngagementRepository) {} async execute(input: RecordEngagementInput): Promise { const eventId = `eng-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const baseProps: Omit[0], 'timestamp'> = { id: eventId, action: input.action, entityType: input.entityType, entityId: input.entityId, actorType: input.actorType, sessionId: input.sessionId, }; const event = EngagementEvent.create({ ...baseProps, ...(input.actorId !== undefined ? { actorId: input.actorId } : {}), ...(input.metadata !== undefined ? { metadata: input.metadata } : {}), }); await this.engagementRepository.save(event); return { eventId, engagementWeight: event.getEngagementWeight(), }; } }