diff --git a/app/assets/stylesheets/css/app.css b/app/assets/stylesheets/css/app.css index c9420a2..913b6a3 100644 --- a/app/assets/stylesheets/css/app.css +++ b/app/assets/stylesheets/css/app.css @@ -15,7 +15,7 @@ File: app.css -body { +body { font-size: 14px; @@ -27,15 +27,15 @@ body { overflow-x: hidden; - font-family: Roboto, sans-serif - -} - -html.page-pending .wrapper, -html.page-pending .page-footer { - opacity: 0; - visibility: hidden; -} + font-family: Roboto, sans-serif + +} + +html.page-pending .wrapper, +html.page-pending .page-footer { + opacity: 0; + visibility: hidden; +} @@ -519,7 +519,7 @@ input[type="file"].form-control.bg-dark::file-selector-button { -.metismenu .has-arrow:after { +.metismenu .has-arrow:after { position: absolute; @@ -5624,132 +5624,394 @@ payment-methods { align-items: stretch; } #knowledgeBaseModalBody li { margin-bottom: 0.4em; } -#knowledgeBaseModalBody p { - margin-bottom: 1em; -} - -/* Calendar page - technician filter */ -.calendar-filter-card { - background: linear-gradient(180deg, #f8fafc 0%, #eef3f8 100%); - border: 1px solid #d9e2ec; -} - -.calendar-tech-filter-group { - flex-wrap: nowrap; -} - -.calendar-tech-filter-icon { - border-right: 0; - min-height: 38px; - display: flex; - align-items: center; - justify-content: center; -} - -.calendar-tech-filter-group > .select2-container { - flex: 1 1 auto; - width: 1% !important; -} - -.calendar-tech-filter-group > .select2-container .select2-selection { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.calendar-filter-card .select2-container--bootstrap-5 .select2-selection { - min-height: 38px; -} - -.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple { - min-height: 38px; - max-height: 112px; - overflow-y: auto; - padding: 4px 6px; - border-color: #b6c2cf; -} - -.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__rendered { +#knowledgeBaseModalBody p { + margin-bottom: 1em; +} + +/* Calendar page - technician filter */ +.calendar-filter-card { + background: linear-gradient(180deg, #f8fafc 0%, #eef3f8 100%); + border: 1px solid #d9e2ec; +} + +.calendar-tech-filter-group { + flex-wrap: nowrap; +} + +.calendar-tech-filter-icon { + border-right: 0; + min-height: 38px; + display: flex; + align-items: center; + justify-content: center; +} + +.calendar-tech-filter-group > .select2-container { + flex: 1 1 auto; + width: 1% !important; +} + +.calendar-tech-filter-group > .select2-container .select2-selection { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.calendar-filter-card .select2-container--bootstrap-5 .select2-selection { + min-height: 38px; +} + +.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple { + min-height: 38px; + max-height: 112px; + overflow-y: auto; + padding: 4px 6px; + border-color: #b6c2cf; +} + +.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__rendered { + display: flex; + flex-wrap: wrap; + gap: 6px; + align-items: center; + margin: 0; + padding: 0; +} + +.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__choice { + margin: 0; + padding: 2px 8px; + border: 1px solid #bfd7ff; + background: #eaf2ff; + color: #24416b; + border-radius: 999px; + font-size: 12px; + line-height: 1.4; +} + +.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__choice__remove { + margin-right: 6px; + color: #24416b; +} + +.calendar-filter-card .select2-container--bootstrap-5.select2-container--focus .select2-selection { + border-color: #86b7fe; + box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.15); +} + +.audit-date-group .form-control { + background-color: #0f1a26; + color: #e8edf3; + border-color: #4a5562; +} + +.audit-date-group .form-control::placeholder { + color: #a8b3bf; + opacity: 1; +} + +.audit-date-group .input-group-text { + background-color: #132235; + border-color: #4a5562; + color: #e8edf3; + cursor: pointer; +} + +.logs-filters-bar { + background: rgba(12, 21, 32, 0.85); + border: 1px solid rgba(124, 136, 149, 0.25); + border-radius: 12px; + padding: 12px; +} + +.logs-filter-input { + min-height: 40px; +} + +.logs-filter-input.form-select, +.logs-filter-input.form-control { + background-color: #0f1a26; + color: #e8edf3; + border-color: #4a5562; +} + +.logs-filter-input.form-select:focus, +.logs-filter-input.form-control:focus { + border-color: #6ea8fe; + box-shadow: 0 0 0 0.2rem rgba(110, 168, 254, 0.2); +} + +.logs-filter-addon { + background-color: #132235; + border-color: #4a5562; + color: #9fb2c5; +} + +.logs-apply-btn { + min-width: 150px; +} + +.logs-clear-btn { + min-width: 90px; +} + +/* Onboarding tour (Intro.js) */ +.introjs-tooltip { + position: relative; +} + +.introjs-tooltip .introjs-tooltip-header { + position: relative; + padding-right: 72px; +} + +.introjs-tooltip .introjs-skipbutton { + position: absolute !important; + top: 8px !important; + right: 10px !important; + left: auto !important; + display: inline-block !important; + width: auto !important; + height: auto !important; + line-height: 1.2 !important; + padding: 4px 9px !important; + border-radius: 999px !important; + text-align: center !important; + text-decoration: none !important; + z-index: 10 !important; +} + +.introjs-tooltip.introjs-tooltip-onboarding { + min-width: 320px; + max-width: 372px; + border: 1px solid #d8e1ed; + border-radius: 16px; + background: #f8faff; + box-shadow: 0 18px 42px rgba(15, 23, 42, 0.18); + padding: 14px 16px 14px; + position: relative; + overflow: hidden; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-tooltip-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 10px; + margin-bottom: 10px; + position: static !important; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-tooltip-title { + margin: 0; + color: #1f2937; + font-size: 0.9rem; + font-weight: 800; + line-height: 1.35; + letter-spacing: 0.01em; + padding-right: 72px; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-tooltiptext { + color: #4b5563; + font-size: 0.9rem; + line-height: 1.5; + font-weight: 500; + padding: 0 0 6px; + margin: 0; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-progress { + background: #e3e9f2; + border-radius: 999px; + height: 8px; + margin: 10px 0 14px; + overflow: hidden; + box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.06); +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-progressbar { + background: linear-gradient(90deg, #3f8bd2 0%, #2d79bc 100%); + border-radius: 999px; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-tooltipbuttons { + border-top: 1px solid #dfe6f0; + margin-top: 6px; + padding-top: 12px; display: flex; - flex-wrap: wrap; - gap: 6px; align-items: center; - margin: 0; - padding: 0; -} - -.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__choice { - margin: 0; - padding: 2px 8px; - border: 1px solid #bfd7ff; - background: #eaf2ff; - color: #24416b; - border-radius: 999px; - font-size: 12px; - line-height: 1.4; -} - -.calendar-filter-card .select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__choice__remove { - margin-right: 6px; - color: #24416b; -} - -.calendar-filter-card .select2-container--bootstrap-5.select2-container--focus .select2-selection { - border-color: #86b7fe; - box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.15); -} - -.audit-date-group .form-control { - background-color: #0f1a26; - color: #e8edf3; - border-color: #4a5562; + justify-content: flex-start; + gap: 8px; } - -.audit-date-group .form-control::placeholder { - color: #a8b3bf; - opacity: 1; -} - -.audit-date-group .input-group-text { - background-color: #132235; - border-color: #4a5562; - color: #e8edf3; - cursor: pointer; -} - -.logs-filters-bar { - background: rgba(12, 21, 32, 0.85); - border: 1px solid rgba(124, 136, 149, 0.25); - border-radius: 12px; - padding: 12px; + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-button { + float: none !important; + flex: 0 0 auto; + margin: 0 !important; + min-width: auto; + border-radius: 10px; + border: 1px solid #cbd7e8; + background: #f3f7ff; + color: #22374f; + font-size: 0.82rem; + font-weight: 700; + text-shadow: none; + box-shadow: none; + padding: 8px 14px; + line-height: 1.2; + transition: all 0.16s ease; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-button:focus { + outline: none; + box-shadow: 0 0 0 0.2rem rgba(63, 139, 210, 0.2); +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-button:hover { + background: #eaf2fe; + border-color: #b8cbe5; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-nextbutton, +.introjs-tooltip.introjs-tooltip-onboarding .introjs-donebutton { + order: 2; + margin-left: auto !important; + margin-right: 0 !important; + min-width: auto; + background: #2f7ec1; + border-color: #2f7ec1; + color: #fff; + box-shadow: 0 3px 10px rgba(47, 126, 193, 0.2); +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-nextbutton:hover, +.introjs-tooltip.introjs-tooltip-onboarding .introjs-donebutton:hover { + background: #276da8; + border-color: #276da8; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-prevbutton { + order: 1; + margin-right: auto !important; + background: #edf2fa; + border-color: #c8d4e5; + color: #6e7f97; } - -.logs-filter-input { - min-height: 40px; + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-skipbutton { + position: absolute !important; + top: 10px !important; + right: 12px !important; + left: auto !important; + float: none !important; + margin: 0 !important; + display: inline-block !important; + align-items: center !important; + color: #6b7280 !important; + font-weight: 700 !important; + font-size: 0.76rem !important; + letter-spacing: 0.015em !important; + text-transform: none !important; + white-space: nowrap !important; + padding: 4px 9px !important; + border: 1px solid #d5dfed !important; + border-radius: 999px !important; + background: #f3f7ff !important; + line-height: 1.2 !important; + text-decoration: none !important; + box-shadow: none !important; + opacity: 1 !important; + transition: all 0.16s ease !important; + z-index: 5 !important; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-skipbutton:hover { + color: #2f7ec1 !important; + border-color: #b8cae3 !important; + background: #eaf2ff !important; + text-decoration: none !important; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-skipbutton:focus { + outline: none !important; + box-shadow: 0 0 0 0.2rem rgba(63, 139, 210, 0.18) !important; + color: #2f7ec1 !important; +} + +.introjs-tooltip.introjs-tooltip-onboarding .introjs-disabled, +.introjs-tooltip.introjs-tooltip-onboarding .introjs-disabled:hover { + opacity: 0.45; + cursor: not-allowed; +} + +@media (max-width: 576px) { + .introjs-tooltip .introjs-tooltip-header { + padding-right: 64px; + } + + .introjs-tooltip .introjs-skipbutton { + top: 8px !important; + right: 8px !important; + font-size: 0.72rem !important; + padding: 4px 8px !important; + } + + .introjs-tooltip.introjs-tooltip-onboarding { + min-width: 280px; + max-width: 320px; + padding: 14px; + } + + .introjs-tooltip.introjs-tooltip-onboarding .introjs-tooltip-title { + font-size: 0.84rem; + padding-right: 64px; + } + + .introjs-tooltip.introjs-tooltip-onboarding .introjs-button { + font-size: 0.8rem; + padding: 8px 12px; + min-width: auto; + } + + .introjs-tooltip.introjs-tooltip-onboarding .introjs-nextbutton, + .introjs-tooltip.introjs-tooltip-onboarding .introjs-donebutton { + min-width: auto; + } + + .introjs-tooltip.introjs-tooltip-onboarding .introjs-skipbutton { + top: 9px !important; + right: 10px !important; + font-size: 0.72rem !important; + padding: 4px 8px !important; + } } -.logs-filter-input.form-select, -.logs-filter-input.form-control { - background-color: #0f1a26; - color: #e8edf3; - border-color: #4a5562; +/* Onboarding welcome modal (Dashboard) */ +.onboarding-welcome-modal-dialog { + max-width: 520px; } -.logs-filter-input.form-select:focus, -.logs-filter-input.form-control:focus { - border-color: #6ea8fe; - box-shadow: 0 0 0 0.2rem rgba(110, 168, 254, 0.2); +.onboarding-welcome-modal-content { + border: 1px solid #d8e1ed; + border-radius: 16px; + background: #f8faff; + box-shadow: 0 18px 42px rgba(15, 23, 42, 0.18); } -.logs-filter-addon { - background-color: #132235; - border-color: #4a5562; - color: #9fb2c5; +.onboarding-welcome-modal-header, +.onboarding-welcome-modal-footer { + border-color: #dfe6f0; } -.logs-apply-btn { - min-width: 150px; +.onboarding-welcome-modal-title { + color: #1f2937; + font-size: 1rem; + font-weight: 800; } -.logs-clear-btn { - min-width: 90px; +.onboarding-welcome-modal-subtitle { + color: #4b5563; + font-size: 0.92rem; + line-height: 1.45; + font-weight: 600; } diff --git a/app/controllers/app/budgets_controller.rb b/app/controllers/app/budgets_controller.rb index 615977d..f1b4104 100644 --- a/app/controllers/app/budgets_controller.rb +++ b/app/controllers/app/budgets_controller.rb @@ -27,6 +27,7 @@ def create @budget = base_scope.new(budget_params) if @budget.save + mark_onboarding_step("created_budget") redirect_to app_budgets_path, notice: "Orçamento criado com sucesso." else @budget.service_items.build if @budget.service_items.empty? @@ -73,6 +74,7 @@ def send_for_approval def approve already_linked = @budget.order_service.present? @budget.approve_and_create_order_service!(approver_role: :gestor) + mark_onboarding_step("created_first_work_order") notice = already_linked ? "Orçamento já aprovado. OS vinculada mantida como pendente." : "Orçamento aprovado pelo gestor e OS criada como pendente." redirect_to app_budget_path(@budget), notice: notice rescue ActiveRecord::RecordInvalid => e diff --git a/app/controllers/app/dashboard_controller.rb b/app/controllers/app/dashboard_controller.rb index 1d6e136..39ee718 100644 --- a/app/controllers/app/dashboard_controller.rb +++ b/app/controllers/app/dashboard_controller.rb @@ -1,12 +1,4 @@ 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 @@ -155,7 +147,6 @@ def initialize_default_dashboard_variables 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 @show_onboarding_checklist = !current_user.tecnico? @onboarding_checklist_steps = onboarding_checklist_steps end @@ -165,26 +156,18 @@ def onboarding_welcome_eligible? return true if @onboarding_progress.nil? return false if @onboarding_progress.dismissed_at.present? return false if @onboarding_progress.finished_at.present? + return false if @onboarding_progress.last_seen_step.present? + return false if @onboarding_progress.completed_steps_count.positive? !@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 - def onboarding_checklist_steps [ { key: "created_technician", label: "Cadastrar técnico", path: app_technicians_path }, { key: "created_customer", label: "Cadastrar cliente", path: app_clients_path }, - { key: "created_first_work_order", label: "Criar primeira ordem de serviço", path: app_order_services_path }, + { key: "created_budget", label: "Criar primeiro orçamento", path: app_budgets_path }, + { key: "created_first_work_order", label: "Aprovar orçamento para gerar a primeira OS", path: app_budgets_path }, { key: "moved_work_order_status", label: "Atualizar status da ordem de serviço", path: app_order_services_path }, { key: "viewed_reports", label: "Visualizar relatórios", path: app_reports_path } ] diff --git a/app/controllers/app/order_services_controller.rb b/app/controllers/app/order_services_controller.rb index 847dc00..a0af163 100644 --- a/app/controllers/app/order_services_controller.rb +++ b/app/controllers/app/order_services_controller.rb @@ -62,7 +62,6 @@ def create @order_service.created_without_budget = true if @order_service.update(order_service_params_with_auto_schedule_status) - mark_onboarding_step("created_first_work_order") redirect_to app_order_service_url(@order_service), notice: "Ordem de serviço criada com sucesso." else set_other_resources diff --git a/app/javascript/controllers/onboarding_checklist_controller.js b/app/javascript/controllers/onboarding_checklist_controller.js index 052430b..39c0788 100644 --- a/app/javascript/controllers/onboarding_checklist_controller.js +++ b/app/javascript/controllers/onboarding_checklist_controller.js @@ -102,7 +102,6 @@ export default class extends Controller { this.detailsExpanded = false this.summaryTarget.classList.remove("d-none") } else { - this.detailsExpanded = true this.summaryTarget.classList.add("d-none") } diff --git a/app/javascript/controllers/onboarding_tour_controller.js b/app/javascript/controllers/onboarding_tour_controller.js index 5c25904..85a2a30 100644 --- a/app/javascript/controllers/onboarding_tour_controller.js +++ b/app/javascript/controllers/onboarding_tour_controller.js @@ -9,6 +9,9 @@ export default class extends Controller { connect() { this.intro = null + this.persistableStepKeys = [] + this.onWelcomeStarted = this.onWelcomeStarted.bind(this) + window.addEventListener("onboarding-welcome:started", this.onWelcomeStarted) if (!this.autoStartValue) return @@ -18,18 +21,27 @@ export default class extends Controller { } disconnect() { + window.removeEventListener("onboarding-welcome:started", this.onWelcomeStarted) + if (!this.intro) return this.intro.exit() this.intro = null } + onWelcomeStarted() { + this.startTour().catch((error) => { + console.warn("[OnboardingTour] failed to start from welcome", error) + }) + } + async startTour() { if (typeof window.introJs === "undefined") return await this.resumeIfRequested() const progress = await this.fetchProgress() + this.persistableStepKeys = Array.isArray(progress?.step_keys) ? progress.step_keys : [] const builtSteps = this.buildSteps() if (builtSteps.length === 0) return @@ -49,17 +61,24 @@ export default class extends Controller { const stepKey = targetElement?.dataset?.onboardingTourStepKey if (!stepKey) return - this.persistLastSeen(stepKey) + const persistStepKey = targetElement?.dataset?.onboardingTourPersistStepKey || stepKey + if (this.persistableStepKeys.includes(persistStepKey)) { + this.persistLastSeen(persistStepKey) + } + this.enforceSkipButtonLayout() }) + this.intro.onafterchange(() => this.enforceSkipButtonLayout()) this.intro.onexit(() => this.clearAutoStartParam()) this.intro.oncomplete(() => this.clearAutoStartParam()) const resumeIndex = this.findResumeIndex(progress?.last_seen_step, builtSteps) this.intro.start() + this.enforceSkipButtonLayout() if (resumeIndex > 0) { this.intro.goToStep(resumeIndex + 1) + this.enforceSkipButtonLayout() } } @@ -98,6 +117,9 @@ export default class extends Controller { if (!element) return null element.dataset.onboardingTourStepKey = step.key + if (step.persist_step_key) { + element.dataset.onboardingTourPersistStepKey = step.persist_step_key + } return { element, @@ -112,7 +134,11 @@ export default class extends Controller { findResumeIndex(lastSeenStep, steps) { if (!lastSeenStep) return 0 - const idx = steps.findIndex((step) => step.element?.dataset?.onboardingTourStepKey === lastSeenStep) + const idx = steps.findIndex((step) => { + const visibleStepKey = step.element?.dataset?.onboardingTourStepKey + const persistStepKey = step.element?.dataset?.onboardingTourPersistStepKey + return visibleStepKey === lastSeenStep || persistStepKey === lastSeenStep + }) if (idx < 0) return 0 return Math.min(idx + 1, Math.max(steps.length - 1, 0)) @@ -151,4 +177,31 @@ export default class extends Controller { url.searchParams.delete("resume_onboarding") window.history.replaceState({}, "", url.toString()) } + + enforceSkipButtonLayout() { + window.requestAnimationFrame(() => { + const tooltip = document.querySelector(".introjs-tooltip") + const skipButton = document.querySelector(".introjs-skipbutton") + const title = document.querySelector(".introjs-tooltip .introjs-tooltip-title") + + if (!tooltip || !skipButton) return + + tooltip.style.position = "relative" + skipButton.style.position = "absolute" + skipButton.style.top = "10px" + skipButton.style.right = "12px" + skipButton.style.left = "auto" + skipButton.style.width = "auto" + skipButton.style.height = "auto" + skipButton.style.lineHeight = "1.2" + skipButton.style.padding = "4px 9px" + skipButton.style.margin = "0" + skipButton.style.display = "inline-block" + skipButton.style.borderRadius = "999px" + skipButton.style.textDecoration = "none" + skipButton.style.zIndex = "20" + + if (title) title.style.paddingRight = "72px" + }) + } } diff --git a/app/javascript/controllers/onboarding_welcome_controller.js b/app/javascript/controllers/onboarding_welcome_controller.js index 45f4cce..15d9eeb 100644 --- a/app/javascript/controllers/onboarding_welcome_controller.js +++ b/app/javascript/controllers/onboarding_welcome_controller.js @@ -2,10 +2,7 @@ import { Controller } from "@hotwired/stimulus" export default class extends Controller { static targets = ["modal", "startButton", "dismissButton"] - static values = { - autoShow: Boolean, - startPath: String - } + static values = { autoShow: Boolean } connect() { this.modalInstance = null @@ -43,15 +40,8 @@ export default class extends Controller { await this.sendOperation("resume") this.hideModal() - - this.dispatch("started") - - if (this.hasStartPathValue && this.startPathValue) { - const url = new URL(this.startPathValue, window.location.origin) - url.searchParams.set("onboarding_tour", "1") - window.location.href = url.toString() - return - } + // Wait for the modal animation/backdrop teardown, then start the dashboard tour in place. + window.setTimeout(() => this.dispatch("started"), 220) this.setButtonsDisabled(false) } diff --git a/app/models/user_onboarding_progress.rb b/app/models/user_onboarding_progress.rb index 3597cc5..06c19b8 100644 --- a/app/models/user_onboarding_progress.rb +++ b/app/models/user_onboarding_progress.rb @@ -2,6 +2,7 @@ class UserOnboardingProgress < ApplicationRecord STEP_KEYS = %w[ created_technician created_customer + created_budget created_first_work_order moved_work_order_status viewed_reports diff --git a/app/views/app/dashboard/_onboarding_checklist.html.erb b/app/views/app/dashboard/_onboarding_checklist.html.erb index 483d190..75e321a 100644 --- a/app/views/app/dashboard/_onboarding_checklist.html.erb +++ b/app/views/app/dashboard/_onboarding_checklist.html.erb @@ -10,14 +10,14 @@