Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions app/controllers/app/dashboard_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
class App::DashboardController < ApplicationController
ONBOARDING_STEP_PATHS = {
"created_technician" => :app_technicians_path,
"created_customer" => :app_clients_path,
"created_first_work_order" => :app_order_services_path,
"moved_work_order_status" => :app_order_services_path,
"viewed_reports" => :app_reports_path
}.freeze

def index
authorize! :read, :dashboard

initialize_default_dashboard_variables
set_onboarding_welcome_modal

case current_user.role
when "admin"
Expand Down Expand Up @@ -142,4 +151,30 @@ def initialize_default_dashboard_variables
@overdue_count = 0
@budgets_total_value = 0
end

def set_onboarding_welcome_modal
@onboarding_progress = current_user.user_onboarding_progress
@show_onboarding_welcome_modal = onboarding_welcome_eligible?
@onboarding_start_path = next_onboarding_step_path
end

def onboarding_welcome_eligible?
return false if current_user.tecnico?
return true if @onboarding_progress.nil?
return false if @onboarding_progress.dismissed_at.present?
return false if @onboarding_progress.finished_at.present?

!@onboarding_progress.finished_all_steps?
end

def next_onboarding_step_path
completed_steps = @onboarding_progress&.completed_steps || {}

next_step = UserOnboardingProgress::STEP_KEYS.find do |step_key|
completed_steps.fetch(step_key, false) != true
end

route_name = ONBOARDING_STEP_PATHS[next_step] || :app_dashboard_path
send(route_name)
end
end
123 changes: 123 additions & 0 deletions app/javascript/controllers/onboarding_welcome_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ["modal", "startButton", "dismissButton"]
static values = {
autoShow: Boolean,
startPath: String
}

connect() {
this.modalInstance = null
this.fallbackBackdrop = null

if (!this.hasModalTarget) return

if (typeof window.bootstrap !== "undefined") {
this.modalInstance = new window.bootstrap.Modal(this.modalTarget)

if (this.autoShowValue) {
this.modalInstance.show()
}
return
}

if (this.autoShowValue) {
this.showFallback()
}
}

disconnect() {
if (this.modalInstance) {
this.modalInstance.hide()
this.modalInstance.dispose()
this.modalInstance = null
return
}

this.hideFallback()
}

async start() {
this.setButtonsDisabled(true)

await this.sendOperation("resume")
this.hideModal()

this.dispatch("started")

if (this.hasStartPathValue && this.startPathValue) {
window.location.href = this.startPathValue
return
}

this.setButtonsDisabled(false)
}

async dismiss() {
this.setButtonsDisabled(true)

await this.sendOperation("dismiss")
this.hideModal()
this.setButtonsDisabled(false)
}

hideModal() {
if (this.modalInstance) {
this.modalInstance.hide()
return
}

this.hideFallback()
}

async sendOperation(operation) {
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content")

try {
await fetch("/onboarding_progress", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"X-CSRF-Token": csrfToken || ""
},
credentials: "same-origin",
body: JSON.stringify({ operation })
})
} catch (error) {
console.warn("Falha ao atualizar onboarding:", error)
}
}

setButtonsDisabled(disabled) {
if (this.hasStartButtonTarget) this.startButtonTarget.disabled = disabled
if (this.hasDismissButtonTarget) this.dismissButtonTarget.disabled = disabled
}

showFallback() {
this.modalTarget.classList.add("show")
this.modalTarget.style.display = "block"
this.modalTarget.removeAttribute("aria-hidden")
this.modalTarget.setAttribute("aria-modal", "true")
this.modalTarget.setAttribute("role", "dialog")
document.body.classList.add("modal-open")

this.fallbackBackdrop = document.createElement("div")
this.fallbackBackdrop.className = "modal-backdrop fade show"
document.body.appendChild(this.fallbackBackdrop)
}

hideFallback() {
this.modalTarget.classList.remove("show")
this.modalTarget.style.display = "none"
this.modalTarget.setAttribute("aria-hidden", "true")
this.modalTarget.removeAttribute("aria-modal")
document.body.classList.remove("modal-open")

if (this.fallbackBackdrop) {
this.fallbackBackdrop.remove()
this.fallbackBackdrop = null
}
}
}
43 changes: 43 additions & 0 deletions app/views/app/dashboard/_onboarding_welcome_modal.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<div
data-controller="onboarding-welcome"
data-onboarding-welcome-auto-show-value="<%= @show_onboarding_welcome_modal %>"
data-onboarding-welcome-start-path-value="<%= @onboarding_start_path %>"
>
<div
class="modal fade"
tabindex="-1"
aria-hidden="true"
data-onboarding-welcome-target="modal"
data-bs-backdrop="static"
data-bs-keyboard="false"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Bem-vindo ao CatalystOps</h5>
</div>
<div class="modal-body">
<p class="mb-0">Em 2 minutos você configura o básico e já começa a operar.</p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-outline-secondary"
data-action="onboarding-welcome#dismiss"
data-onboarding-welcome-target="dismissButton"
>
Pular
</button>
<button
type="button"
class="btn btn-primary"
data-action="onboarding-welcome#start"
data-onboarding-welcome-target="startButton"
>
Começar
</button>
</div>
</div>
</div>
</div>
</div>
1 change: 1 addition & 0 deletions app/views/app/dashboard/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<div class="page-wrapper">
<div class="page-content">
<%= render "onboarding_welcome_modal" %>

<% flash.each do |type, message| %>
<% bootstrap_class = { notice: "alert-success", alert: "alert-danger", error: "alert-danger" }[type.to_sym] || "alert-info" %>
Expand Down
Loading