Documentation Index
Fetch the complete documentation index at: https://wiki.vivla.com/llms.txt
Use this file to discover all available pages before exploring further.
Descripcion
- Ubicacion:
src/modules/surveys/
useToolsBackend). Las encuestas son completamente editables desde el backend sin necesidad de deploys de la app.
El motor de encuestas es generico y reutilizable. Actualmente soporta multiples tipos de encuesta:
Home Annual Review (
home-review), Arrival Review (arrival-review), Stay Review
(stay-review), y cualquier nuevo tipo definido desde el backend (ej: onboarding-review,
financial-review) sin necesidad de nuevas pantallas ni deploys.Tipos de encuesta
| Slug | Descripcion | scopeType | scopeId | Entry points |
|---|---|---|---|---|
home-review | Encuesta anual de satisfaccion del propietario | property | propertyId | Home card, deep link |
arrival-review | Revision del estado de la casa al llegar (1 dia post check-in) | booking | bookingId | Deep link, notification, dev button |
stay-review | Valoracion post-estancia (home rating + stay experience) | booking | bookingId | StayCard, auto-show modal, deep link, dev button |
onboarding-review | Feedback del proceso de onboarding | property | propertyId | Deep link, notification |
financial-review | Valoracion de la gestion financiera | property | propertyId | Deep link, notification |
Los tipos
onboarding-review y financial-review no tienen rutas especificas — usan la ruta
generica /survey que abre como modal. Solo necesitan que el backend defina la encuesta con ese
slug.Arquitectura
Motor generico
El
useSurveyEngine maneja navegacion, persistencia, resume y condicionales de forma
independiente del contenido de la encuesta.Backend-driven
La definicion completa (pasos, preguntas, opciones, condicionales) viene del backend. La app
solo renderiza y recopila respuestas.
Persistencia dual
Progreso guardado tanto en AsyncStorage (local) como en el backend. Resume automatico comparando
timestamps.
Analytics integrado
Callbacks de analytics en el engine permiten trackear cada paso sin acoplar el motor a PostHog.
API Endpoints
Todos los endpoints usan el backend de Vivla Tools (useToolsBackend: true). Definidos en src/shared/constants/api.ts:
| Metodo | Path | Descripcion |
|---|---|---|
GET | /surveys/mobile/{slug} | Obtener definicion de la encuesta |
POST | /surveys/mobile/{slug}/responses | Guardar progreso parcial |
POST | /surveys/mobile/{slug}/responses/complete | Marcar encuesta como completada |
POST | /surveys/mobile/{slug}/responses/resume | Obtener progreso guardado en el backend |
GET | /surveys/mobile/{slug}/results | Obtener resultados (si estan disponibles) |
POST | /surveys/mobile/{slug}/status | Consultar estado por scope IDs |
Hook principal: useSurveyEngine
Core de orquestacion. Recibe slug, scopeId y scopeType.
View States
El engine maneja las siguientes vistas:| Estado | Descripcion |
|---|---|
loading | Cargando definicion o restaurando progreso |
intro | Pantalla inicial de la encuesta |
stepIntro | Intro intermedia entre pasos (titulo, descripcion, CTA) |
questions | Renderizando preguntas del paso actual |
completion | Encuesta enviada exitosamente |
error | Error en carga o envio |
Flujo de navegacion
- Resume on mount
- Guardado automatico
Al montar el componente: 1. Carga progreso local desde AsyncStorage 2. POST
/resume al backend
3. Compara updatedAt timestamps, usa el mas reciente 4. Si el remoto dice completed →
muestra pantalla de completadoEvaluacion de condicionales
lt, lte, gt, gte, eq, neq, in
Modos de display:
display: 'inline'(default) — preguntas hijas aparecen debajo del padre en la misma pantalla. Al aparecer, auto-scroll posiciona el titulo de la primera condicional en la parte superior.display: 'next_screen'— preguntas hijas se muestran como pantallas independientes
Resolucion de idioma (I18nString)
Todos los campos de texto del backend (title, description, options.label, text_placeholder, cta_label) son I18nString (Record<string, string>, ej: { en: "Start", es: "Empezar" }).
Se resuelven usando resolveI18n() de src/core/i18n/index.ts, que selecciona el valor del idioma actual de la app con fallback a ingles. Todos los componentes de survey usan este helper en lugar de Object.values(...)[0].
Los textos de UI de la app (botones, validaciones, contadores) usan i18n keys via useTranslation(). No hay strings hardcodeados.
Progreso
totalQuestionsGlobal: cuenta de preguntas principales en TODOS los pasos (no condicionales)currentQuestionGlobal: calculado desdecurrentStepIndex+currentQuestionIndex- La barra de progreso muestra la posicion en el formulario, no la cantidad respondida
Answer Store
Archivo:src/modules/surveys/stores/surveyAnswerStore.ts
Store Zustand con persistencia en AsyncStorage.
survey_progress_{slug}_{scopeId}
Tipos de pregunta
Star Rating
Rating con estrellas interactivas. Muestra sublabel de feedback dinamico segun la calificacion
seleccionada (“Excelente en todo”, “Muy bien en general”, etc.).
Single Choice
Opciones con radio buttons. Filas full-width con indicador circular a la derecha. Opciones no
seleccionadas se atenuan cuando hay una seleccion.
Multi Choice
Opciones con checkboxes. Similar a single choice pero permite multiples selecciones. Respeta
max_selections del backend.Open Text
Campo de texto libre. Minimo 10 caracteres (sin whitespace). Contador progresivo de caracteres:
“Min. 10 caracteres” (gris) → “5/10 caracteres” (ambar) → “10 caracteres” (verde con checkmark).
Dispara scroll-to-end para visibilidad con teclado.
Componentes UI
SurveyScreen
Orquestador principal. UsauseSurveyEngine(slug, scopeId, scopeType) y enruta entre las pantallas segun viewState. Maneja estados de error/loading y la logica de analytics. Al cerrar, invalida el cache de survey-scope-status para que la home card refleje el estado actualizado (ej: “Continuar” en vez de “Completar”).
onClose permite usar SurveyScreen tanto como ruta standalone como embebido dentro de un <Modal> (usado por AutoShowReviewModal para stay-review).
SurveyStepScreen
Pantalla de preguntas con header (“Guardar y salir” + barra de progreso), ScrollView con question renderers, y footer con labels i18n (surveyScreen.continue / surveyScreen.submit). Auto-scroll a condicionales inline cuando aparecen. Tutorial de star rating en la primera pregunta de tipo estrella por sesion.
SurveyCompletionScreen
Pantalla de agradecimiento slug-aware con safe area insets para padding superior (notch/dynamic island).- Slugs con contenido custom (definidos en
COMPLETION_I18N_PREFIX): Renderizan su timeline de bullet points especifica. Actualmente solohome-reviewtiene contenido custom (homeScreen.home_review_completion.*). - Otros slugs: Renderizan una pantalla generica con icono de check, titulo “Gracias” y subtitulo “Tu respuesta ha sido enviada” (i18n keys
surveyScreen.completion.*).
COMPLETION_I18N_PREFIX y se crean los keys correspondientes en los archivos de idiomas.
QuestionProgressBar
Barra segmentada de progreso. Una linea delgada por pregunta total, animada conwithSpring. Sin contador numerico — la barra sola muestra la posicion.
FormFooter
Componente compartido (src/shared/components/FormFooter.tsx). Boton primario con labels i18n, soporte para boton de retroceso, mensaje de validacion y estados de loading/disabled.
Integracion con Home Screen
El Home Annual Review se integra en la pantalla home mediante:| Componente | Archivo | Feature Flag |
|---|---|---|
HomeReviewCard | src/modules/home/components/HomeReviewCard.tsx | home-review |
HomeReviewResultsCard | src/modules/home/components/HomeReviewResultsCard.tsx | home-review-results |
borderWidth eliminado). Entry points: card CTA y deep links.
Hooks de integracion
| Hook | Descripcion |
|---|---|
useHomeReview() | Lee feature flag, retorna { isEnabled, showCard } |
useHomeReviewResults() | Lee flag + fetch de endpoint de resultados via React Query |
useHomeReviewStatus() | POST /status con property IDs. Retorna statusMap: Record<string, ScopeStatusValue> para lookup O(1) |
Estados por propiedad
| Status | Card CTA |
|---|---|
not_started | ”Completar” / “Complete” |
in_progress | ”Continuar” / “Continue” |
completed | ”Completada” (no tappable) |
Rutas y navegacion
Rutas especificas (backward compatible)
| Ruta | Archivo | Params | Survey |
|---|---|---|---|
/property/home-review | app/property/home-review.tsx | propertyId, entryPoint? | home-review |
/property/arrival-review | app/property/arrival-review.tsx | propertyId, bookingId, entryPoint? | arrival-review |
/booking/review | app/booking/review.tsx | bookingId, entryPoint? | stay-review |
Ruta generica (extensible)
| Ruta | Archivo | Params | Presentacion |
|---|---|---|---|
/survey | app/survey.tsx | slug, scopeId, scopeType? (default: property), entryPoint? | Modal |
presentation: 'modal' en app/_layout.tsx. Permite abrir cualquier encuesta nueva sin crear archivos de ruta.
Deep links soportados
linkingService.ts infiere automaticamente el scopeType del deep link: si bookingId esta presente se usa 'booking', sino 'property'.
Configuracion
app/_layout.tsx—<Stack.Screen name="survey" options={{ presentation: 'modal' }} />src/shared/services/linkingService.ts— URL mapping para deep links (rutas especificas + generica/survey)src/modules/notifications/utils/notificationHelpers.ts— validacion de rutas
Analytics
El modulo trackea 7 eventos especificos del Home NPS con el prefijohome_nps_*. La documentacion completa de eventos, propiedades y guia de dashboard se encuentra en:
- Referencia de eventos:
docs/specs/home-annual-review/posthog-analytics.md - Pagina Mintlify: Eventos del Home NPS
Integracion con otros modulos
Stay Review (modulo Stays)
ElAutoShowReviewModal del modulo Stays embebe SurveyScreen directamente dentro de un <Modal> con slug="stay-review" y onClose callback. Cuando el feature flag home-review esta activo, useAutoShowReview.ts suprime los modales automaticos para no abrumar al usuario durante el periodo de revision anual.
El StayCard navega a /booking/review?bookingId={id} en vez de abrir un modal. La ruta booking/review.tsx renderiza SurveyScreen slug="stay-review" e invalida las queries de stays al volver.
Arrival Review (modulo Property)
La ruta/property/arrival-review renderiza SurveyScreen slug="arrival-review" con scopeType="booking". Las preguntas se definen en el backend por propiedad pero las respuestas se trackean por booking.
Dev Testing
En modo__DEV__:
- Active stays list: Boton “DEV Test Arrival Review” que navega a
/property/arrival-reviewcon IDs fake - Past stays list: Boton “DEV Test Stay Review” que navega a
/booking/reviewcon ID fake