Comentarios de Usuarios — Referencia Técnica
← Volver a Comentarios de Usuarios
Dónde vive esto
Backend
apps/backend/graphql/types/user-feedback.type.js— el tipoUserFeedback,SubmitFeedbackInput, y las queries/mutations descritas a continuaciónapps/backend/graphql/resolvers/user-feedback.resolver.js— resolvers que respaldan ese esquema, delegando en el managerapps/backend/managers/user-managers/user-feedback.manager.js— lógica de negocio (submitFeedback,submitBugReport,submitFeatureRequest,getUserFeedback,getFeedback,getPublicFeedback,upvoteFeedback,downvoteFeedback,getMyVotesFor,getAllFeedback,getFeedbackStats,updateStatus,setPriority,markAsResolved,getMostUpvoted, etc.). Solo un subconjunto está conectado a GraphQL — consulta la checklist a continuación.apps/backend/data-access-services/user/user-feedback.access-service.js— capa de base de datos para la tablauser_feedbackapps/backend/data-access-services/user/user-feedback-vote.access-service.js— capa de base de datos para la tabla de deduplicaciónuser_feedback_voteapps/backend/database/models/UserFeedback.js/ migración20220122175043-create-user-feedback.js— la tablauser_feedback(title,description,feedback_type,category,platform,status,priority,admin_response,upvotes,downvotes, etc.)apps/backend/database/models/UserFeedbackVote.js/ migración20260718140000-create-user-feedback-vote.js— la tablauser_feedback_vote(una fila por usuario por elemento de comentario, única enfeedback_id+user_id) además de las columnasupvotes/downvotesenuser_feedback
Frontend
apps/frontend-nextjs/src/page-components/settings/FeedbackPage.tsx(enrutado enapps/frontend-nextjs/src/app/settings/feedback/page.tsx, enlazado desdeSettings → Send feedback) — el formulario de envío, el historial de "Your submissions" (myFeedback), y el tablero votable de "Community feature requests" (publicFeedback+upvoteFeedback/downvoteFeedback). Las operaciones de GraphQL se declaran de forma inline en el componente (aún sin hooks generados, mismo patrón queSocialLinksPage.tsx).apps/frontend-admin/src/app/feedback/page.tsx+FeedbackContent.tsx— la cola de priorización de administración (/feedback, requiereMANAGE_FEEDBACK). Ver Comentarios de usuarios (administración) para toda la superficie de GraphQL de administración y los detalles del permiso.
Checklist de implementación técnica
-
submitFeedback— conectado:SubmitFeedbackInput→ resolver →user-feedback.manager.js#submitFeedback; usado porFeedbackPage.tsx -
myFeedback— conectado, autenticado; usado por la lista "Your submissions" deFeedbackPage.tsx -
feedbackById— conectado, autenticado, solo para el propietario (resuelve anullsi quien llama no es dueño del elemento) -
publicFeedback— conectado; tablero votable, por defectofeedbackType: feature_request; usado por "Community feature requests" deFeedbackPage.tsx -
upvoteFeedback/downvoteFeedback— conectados, deduplicados por usuario medianteuser_feedback_vote; usados porFeedbackPage.tsx - Los atajos
submitBugReport/submitFeatureRequest— existen solo como métodos del manager; no se exponen como mutations de GraphQL -
getMostUpvoted— existe solo como método del manager; no se expone como query de GraphQL (la querypublicFeedbackya ordena por votos a favor y sirve como la tabla de clasificación pública) - Revisión de administrador (
adminGetFeedback,adminGetFeedbackStats,adminUpdateFeedbackStatus,adminSetFeedbackPriority,adminRespondToFeedback) — conectados en el schema de administración, protegidos porMANAGE_FEEDBACK, con un frontend de administración real en/feedback. Ver Comentarios de usuarios (administración).markAsResolved/getMostUpvoted/getByStatus/getByPrioritysiguen existiendo solo en el manager (sin uso por ningún resolver - los dos últimos son código muerto que quedó de antes de quegetAllFeedback/getAllincorporaran soporte de filtros).
Tipos de comentarios
| Tipo | Descripción |
|---|---|
bug | Algo está roto o no funciona como se espera |
feature_request | Solicitud de una nueva funcionalidad |
general | Comentario general |
complaint | Queja sobre la plataforma u otro usuario |
suggestion | Idea de mejora |
Enviar comentarios
submitFeedback crea un nuevo elemento de comentario. feedbackType determina cómo se enruta. title es el resumen de una línea; description es el texto completo. La respuesta incluye el status inicial (pending).
mutation SubmitFeedback($input: SubmitFeedbackInput!) {
submitFeedback(input: $input) {
id feedbackType title status createdAt
}
}
Campos de SubmitFeedbackInput: feedbackType (requerido — bug | feature_request | general | complaint | suggestion), title (requerido), description (requerido), category (opcional, p. ej. ui_ux | performance | feature | content | security | privacy | other; por defecto other), platform (opcional; por defecto web), satisfactionRating (entero opcional de 1 a 5).
El manager también expone los envoltorios de conveniencia submitBugReport(userId, title, description) / submitFeatureRequest(userId, title, description) que establecen feedbackType automáticamente, pero no se exponen como mutations de GraphQL — en su lugar, el cliente establece feedbackType directamente en SubmitFeedbackInput (ver el selector de tipo de FeedbackPage.tsx).
Consultas de usuario
myFeedback muestra el historial de envíos del usuario actual con actualizaciones de estado en vivo, incluyendo cualquier adminResponse.
query MyFeedback($limit: Int, $offset: Int) {
myFeedback(limit: $limit, offset: $offset) {
id feedbackType title description status priority upvotes adminResponse createdAt
}
}
feedbackById obtiene un solo elemento por id — quien llama debe ser el propietario, de lo contrario resuelve a null.
query FeedbackById($id: ID!) {
feedbackById(id: $id) {
id feedbackType title description status priority adminResponse createdAt
}
}
Votación
Los miembros de la comunidad pueden señalar qué solicitudes de funcionalidades o reportes de errores les importan más. upvoteFeedback / downvoteFeedback se deduplican por usuario mediante la tabla user_feedback_vote (una fila por usuario por elemento de comentario): votar de nuevo desactiva el voto, y votar en sentido contrario lo cambia. Los conteos desnormalizados upvotes/downvotes viven en user_feedback, y UserFeedback.myVote refleja el voto actual de quien llama ('up' | 'down' | null).
publicFeedback es el tablero público y votable — ordena por upvotes de forma descendente, por defecto usa feedbackType: feature_request, y acepta 'all' para explorar todos los tipos. No existe una query separada mostUpvotedFeedback; el orden de publicFeedback ya sirve como tabla de clasificación.
mutation UpvoteFeedback($feedbackId: ID!) { upvoteFeedback(feedbackId: $feedbackId) { id upvotes downvotes myVote } }
mutation DownvoteFeedback($feedbackId: ID!) { downvoteFeedback(feedbackId: $feedbackId) { id upvotes downvotes myVote } }
query PublicFeedback($feedbackType: String, $limit: Int, $offset: Int) {
publicFeedback(feedbackType: $feedbackType, limit: $limit, offset: $offset) {
id title description feedbackType status upvotes downvotes myVote createdAt
user { id username }
}
}
Ciclo de vida del estado
pending → in_review → in_progress → resolved
↘ rejected
↘ duplicate
Este es el conjunto validado por el método updateStatus del manager, expuesto como adminUpdateFeedbackStatus en el schema de administración (ver "Gestión de administrador" a continuación).
Gestión de administrador
graphql/resolvers/admin/user-feedback-admin.resolver.js conecta las operaciones orientadas a administración, protegidas por context.admin + el permiso MANAGE_FEEDBACK (ver Comentarios de usuarios (administración) para la checklist completa, los detalles del permiso y la referencia de GraphQL):
adminGetFeedback→user-feedback.manager.js#getAllFeedback— lista comentarios con filtros opcionales destatus/priority/feedbackType, paginadosadminUpdateFeedbackStatus→updateStatus— mueve un elemento a través del ciclo de vida anterioradminSetFeedbackPriority→setPriority— asigna urgencia (low/medium/high/critical)adminRespondToFeedback→ el nuevo método del managerrespondToFeedback— estableceadminResponse,reviewedBy(el id del administrador que llama) yreviewedAtjuntos en una sola acciónadminGetFeedbackStats→getFeedbackStats— desglose por tipo, estado y prioridad, además de los totales de votos
markAsResolved (establece status: 'resolved', resolvedAt, y un campo resolution de texto libre que en realidad no es una columna de UserFeedback - un no-op preexistente) no tiene resolver y no lo usa el frontend de administración, que maneja el estado por completo a través de adminUpdateFeedbackStatus.
adminResponse está expuesta en myFeedback / feedbackById / publicFeedback, además del schema de administración, por lo que una respuesta escrita mediante adminRespondToFeedback aparece de inmediato en FeedbackPage.tsx.
Niveles de prioridad
| Prioridad | Descripción |
|---|---|
low | Problema menor, sin urgencia |
medium | Prioridad predeterminada |
high | Impacto significativo |
critical | Bloqueante / urgente |