diff --git a/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js b/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js
index f3090b77d..815ff5e3f 100644
--- a/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js
+++ b/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js
@@ -17,6 +17,10 @@ import ResponsesIndex from './responses/Index.vue';
import ResponsesPendingIndex from './responses/Pending.vue';
import CustomToolsIndex from './tools/Index.vue';
import ReservationsIndex from './reservations/Index.vue';
+import LifecycleIndex from './lifecycle/Index.vue';
+import LifecycleRules from './lifecycle/Rules.vue';
+import LifecycleSettings from './lifecycle/Settings.vue';
+import LifecycleHistory from './lifecycle/History.vue';
const meta = {
permissions: ['administrator', 'agent'],
@@ -137,4 +141,30 @@ export const routes = [
name: 'captain_reservations_index',
meta,
},
+ {
+ path: frontendURL('accounts/:accountId/captain/lifecycle'),
+ component: LifecycleIndex,
+ meta,
+ redirect: { name: 'captain_lifecycle_rules' },
+ children: [
+ {
+ path: 'rules',
+ component: LifecycleRules,
+ name: 'captain_lifecycle_rules',
+ meta,
+ },
+ {
+ path: 'settings',
+ component: LifecycleSettings,
+ name: 'captain_lifecycle_settings',
+ meta,
+ },
+ {
+ path: 'history',
+ component: LifecycleHistory,
+ name: 'captain_lifecycle_history',
+ meta,
+ },
+ ],
+ },
];
diff --git a/app/javascript/dashboard/routes/dashboard/captain/lifecycle/History.vue b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/History.vue
new file mode 100644
index 000000000..9a522b601
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/History.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+ {{ t('CAPTAIN_LIFECYCLE.TABS.HISTORY') }}
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Index.vue b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Index.vue
new file mode 100644
index 000000000..582a53433
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Index.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Rules.vue b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Rules.vue
new file mode 100644
index 000000000..0a553c347
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Rules.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+ {{ t('CAPTAIN_LIFECYCLE.TABS.RULES') }}
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Settings.vue b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Settings.vue
new file mode 100644
index 000000000..3f8513a67
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/Settings.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+ {{ t('CAPTAIN_LIFECYCLE.TABS.SETTINGS') }}
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/lifecycle/constants.js b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/constants.js
new file mode 100644
index 000000000..e54c5e409
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/captain/lifecycle/constants.js
@@ -0,0 +1,92 @@
+export const EVENTS = [
+ {
+ value: 'reservation.confirmed',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.EVENTS.RESERVATION_CONFIRMED',
+ },
+ {
+ value: 'checkin.scheduled_at',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.EVENTS.CHECKIN_SCHEDULED_AT',
+ },
+ {
+ value: 'checkout.scheduled_at',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.EVENTS.CHECKOUT_SCHEDULED_AT',
+ },
+ {
+ value: 'reservation.cancelled',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.EVENTS.RESERVATION_CANCELLED',
+ },
+ {
+ value: 'reservation.no_show',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.EVENTS.RESERVATION_NO_SHOW',
+ },
+];
+
+export const MESSAGE_TYPES = [
+ {
+ value: 'text',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.MESSAGE_TYPES.TEXT',
+ },
+ {
+ value: 'buttons',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.MESSAGE_TYPES.BUTTONS',
+ },
+ {
+ value: 'list',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.MESSAGE_TYPES.LIST',
+ },
+ {
+ value: 'url_button',
+ labelKey: 'CAPTAIN_LIFECYCLE.RULES.WIZARD.MESSAGE_TYPES.URL_BUTTON',
+ },
+];
+
+export const OFFSET_UNITS = [
+ { value: 'minutes', factor: 1 },
+ { value: 'hours', factor: 60 },
+ { value: 'days', factor: 1440 },
+];
+
+export const AVAILABLE_VARIABLES = [
+ { key: 'customer.first_name', descKey: 'Primeiro nome do cliente' },
+ { key: 'customer.name', descKey: 'Nome completo' },
+ { key: 'customer.phone', descKey: 'Telefone' },
+ { key: 'reservation.suite', descKey: 'Suíte' },
+ { key: 'reservation.unit_name', descKey: 'Nome da unidade' },
+ { key: 'reservation.check_in_at', descKey: 'Check-in' },
+ { key: 'reservation.check_out_at', descKey: 'Check-out' },
+ { key: 'reservation.amount', descKey: 'Valor' },
+ { key: 'hotel.wifi_password', descKey: 'Senha do WiFi' },
+ { key: 'hotel.menu_link', descKey: 'Link do cardápio' },
+ { key: 'hotel.google_review_link', descKey: 'Link de review' },
+ { key: 'hotel.address', descKey: 'Endereço' },
+];
+
+export const RULE_TEMPLATES = [
+ {
+ id: 'precheckin_reminder',
+ name: 'Lembrete 10min antes do check-in',
+ event: 'checkin.scheduled_at',
+ offset_minutes: -10,
+ message_type: 'text',
+ message_body:
+ 'Oi {{ customer.first_name }}! Seu check-in é em 10 minutos na suíte {{ reservation.suite }}. Wifi: {{ hotel.wifi_password }}',
+ },
+ {
+ id: 'welcome_instay',
+ name: 'Boas-vindas após check-in',
+ event: 'checkin.scheduled_at',
+ offset_minutes: 15,
+ message_type: 'text',
+ message_body:
+ 'Seja bem-vindo(a), {{ customer.first_name }}! Qualquer coisa, só chamar. Cardápio: {{ hotel.menu_link }}',
+ },
+ {
+ id: 'review_request',
+ name: 'Pedido de review no Google',
+ event: 'checkout.scheduled_at',
+ offset_minutes: 120,
+ message_type: 'url_button',
+ message_body:
+ '{{ customer.first_name }}, adoraríamos saber como foi sua estadia. Se puder, deixa um review pra gente: {{ hotel.google_review_link }}',
+ },
+];