/opt/mawid/apps/api/src/reminders
NameSizeModeActions
reminder-queue.ts5270644editdlrm
reminder-reply.service.ts34330644editdlrm
reminder-sender.service.ts21330644editdlrm
reminder.service.ts35900644editdlrm
reminder.worker.ts40600644editdlrm
reminders.e2e.spec.ts133040644editdlrm
reminders.module.ts10880644editdlrm
Edit: /opt/mawid/apps/api/src/reminders/reminder-sender.service.ts (2133B)
import { Injectable } from '@nestjs/common'; import { t, type Language } from '@mawid/shared'; import type { Appointment, Clinic, Patient, Service } from '@mawid/db'; import { formatLocal } from '../agent/tz'; import { WaSenderService } from '../whatsapp/wa-sender.service'; export type ReminderTone = 'first' | 'final' | 'nudge'; export interface ReminderTarget { appointment: Appointment; clinic: Clinic; patient: Patient; service: Service; } /** * Builds and sends the reminder template message with โœ… Confirm / โŒ Cancel / * ๐Ÿ” Reschedule quick-reply buttons. Template must be pre-approved in Meta as * "appointment_reminder" โ€” payload shape is stubbed until real credentials * exist (PROJECT_PLAN ยง7.6). */ @Injectable() export class ReminderSenderService { constructor(private readonly sender: WaSenderService) {} async send(target: ReminderTarget, tone: ReminderTone): Promise { const { appointment, clinic, patient, service } = target; const lang = this.lang(patient.language); const serviceName = ((service.name as Record)[lang] ?? (service.name as Record).en) || 'appointment'; const time = formatLocal(clinic.timezone, appointment.startsAt); const key = tone === 'first' ? 'reminderFirst' : tone === 'nudge' ? 'reminderNudge' : 'reminderFinal'; const bodyText = t(key, lang, { service: serviceName, time }); const components = [ { type: 'body', parameters: [{ type: 'text', text: serviceName }, { type: 'text', text: time }] }, ...['confirm', 'cancel', 'resched'].map((action, index) => ({ type: 'button', sub_type: 'quick_reply', index, parameters: [{ type: 'payload', payload: `${action}:${appointment.id}` }], })), ]; await this.sender.sendTemplate( appointment.clinicId, patient.id, 'appointment_reminder', lang, components, bodyText, ); } private lang(language: string): Language { return (['ar', 'tr', 'en'] as const).includes(language as Language) ? (language as Language) : 'en'; } }