/** * Chat Service Types * * Tipos compartidos para el sistema de chat en tiempo real. * Firestore paths: * /apps/{appId}/orgs/{orgId}/conversations/{convId}/messages/{msgId} * /apps/{appId}/orgs/{orgId}/conversations/{convId}/typing/{userId} */ import { FirestoreDocument } from '../firebase/types'; /** * Tipo de conversacion. Debe coincidir con el backend (services/conversation): * thread = comentarios en entidad · group = canal grupal · dm = 1:1 directo. */ export type ConversationType = 'thread' | 'group' | 'dm'; /** Visibilidad de una conversacion (quien puede unirse). */ export type ConvVisibility = 'org' | 'private' | 'public' | ''; /** Vinculo de la conversacion con una entidad del dominio. */ export interface EntityRef { /** Tipo de entidad ('post' | 'request' | 'org' | 'custom', etc.). */ type: string; /** ID de la entidad. */ id: string; } /** Configuracion de la conversacion. */ export interface ConvSettings { /** Si la conversacion esta abierta para enviar mensajes. */ isOpen: boolean; /** Quien puede unirse. */ visibility: ConvVisibility; /** Si admite participantes anonimos. */ allowAnonymous: boolean; /** Si requiere membresia de la org. */ requireMembership: boolean; /** Maximo de participantes (0 = sin limite). */ maxParticipants: number; } /** * Documento de conversacion. Refleja el contrato del backend * (services/conversation/types.go) — la fuente de verdad es DynamoDB y el doc se * proyecta a Firestore para las reglas de membresia. Por eso los campos son * `convId`/`name`/`participants: string[]` y NO el shape antiguo. */ export interface Conversation { /** ID de la conversacion. */ convId: string; /** Tipo de conversacion. */ type: ConversationType; /** ID de la app. */ appId: string; /** ID de la org. */ orgId: string; /** Nombre de la conversacion (para grupos). */ name?: string; /** Entidad asociada (para tipo thread). */ entityRef?: EntityRef; /** IDs de los participantes. */ participants: string[]; /** Configuracion. */ settings: ConvSettings; /** ID del usuario que la creo. */ createdBy: string; /** Fecha de creacion (ISO string). */ createdAt: string; /** Fecha de ultima actualizacion (ISO string). */ updatedAt: string; /** Fecha del ultimo mensaje (ISO string). */ lastMsgAt?: string; /** Preview del ultimo mensaje. */ lastMsgPreview?: string; } /** Tipo de mensaje. */ export type MessageType = 'text' | 'image' | 'file' | 'system'; /** * Estado de envio/entrega de un mensaje (para read receipts estilo WhatsApp): * sending → reloj · sent → ✓ · delivered → ✓✓ gris · read → ✓✓ primary · failed → alerta. * El backend hoy solo emite hasta `sent`; los demas estan soportados para el futuro. */ export type MessageStatus = 'sending' | 'sent' | 'delivered' | 'read' | 'failed'; /** Archivo adjunto en un mensaje. */ export interface MessageAttachment { /** Nombre del archivo. */ name: string; /** URL de descarga. */ url: string; /** Tipo MIME. */ mimeType: string; /** Tamano en bytes. */ size?: number; } /** Reaccion a un mensaje. */ export interface MessageReaction { /** Token del emoji (ej: 'like', 'heart'). */ token: string; /** Cantidad de usuarios que reaccionaron con este emoji. */ count: number; /** Si el usuario actual tiene activa esta reaccion. */ active: boolean; } /** Referencia al mensaje al que se responde. */ export interface MessageReplyTo { /** ID del mensaje original. */ msgId: string; /** Nombre del emisor del mensaje original. */ senderName: string; /** Texto del mensaje original (preview). */ body: string; } /** Documento de mensaje en Firestore. */ export interface Message extends FirestoreDocument { /** ID del emisor. */ senderId: string; /** Nombre visible del emisor. */ senderName: string; /** URL del avatar del emisor (opcional). */ senderAvatar?: string; /** Cuerpo del mensaje. */ body: string; /** Tipo de mensaje. */ type: MessageType; /** Fecha de creacion del mensaje. */ createdAt: Date; /** Si el mensaje fue eliminado. */ isDeleted?: boolean; /** Si el mensaje fue editado. */ isEdited?: boolean; /** Mensaje al que se responde. */ replyTo?: MessageReplyTo; /** Archivos adjuntos. */ attachments?: MessageAttachment[]; /** Reacciones del mensaje. */ reactions?: MessageReaction[]; /** Estado de envio (para mensajes optimistas del lado del cliente). */ status?: MessageStatus; } /** Documento de "escribiendo" en Firestore. */ export interface TypingDocument extends FirestoreDocument { /** Nombre visible del usuario que esta escribiendo. */ displayName: string; /** Timestamp de la ultima actualizacion. */ updatedAt: Date; } /** Request para crear una conversacion. */ export interface CreateConversationRequest { /** Tipo de conversacion. */ type: ConversationType; /** Nombre (para grupos). */ name?: string; /** Entidad asociada (para tipo thread). */ entityRef?: EntityRef; /** IDs de los participantes iniciales (ademas del creador). */ participants?: string[]; /** Configuracion inicial. */ settings?: Partial; } /** Request para actualizar una conversacion. */ export interface UpdateConversationRequest { /** Nuevo nombre (opcional). */ name?: string; /** Nueva configuracion (opcional). */ settings?: Partial; } /** Response que envuelve una sola conversacion (create / get / update / get-or-create). */ export interface ConversationResponse { /** ID de operacion para tracing. */ operationId: string; /** La conversacion. */ conversation: Conversation; /** Si fue creada en esta llamada (solo get-or-create). */ created?: boolean; } /** Response de listado de conversaciones. */ export interface ListConversationsResponse { /** ID de operacion para tracing. */ operationId: string; /** Lista de conversaciones. */ conversations: Conversation[]; /** Cursor para paginacion. */ nextCursor?: string; }