diff --git a/assets/css/onboarding/onboarding.css b/assets/css/onboarding/onboarding.css index b477624eb..acb997ece 100644 --- a/assets/css/onboarding/onboarding.css +++ b/assets/css/onboarding/onboarding.css @@ -1,3 +1,46 @@ +/* Full-screen takeover mode */ +.prpl-onboarding-fullscreen { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #f9fafb; + z-index: 999999; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + box-sizing: border-box; +} + +/* Hide WordPress admin elements when in fullscreen onboarding */ +body.prpl-onboarding-active #adminmenumain, +body.prpl-onboarding-active #wpadminbar, +body.prpl-onboarding-active #wpfooter, +body.prpl-onboarding-active #wpcontent { + display: none !important; +} + +body.prpl-onboarding-active { + margin: 0 !important; + padding: 0 !important; + overflow: hidden; +} + +/* When in fullscreen mode, the popover becomes the centered card */ + +/* Override the popover attribute's default hidden state */ +.prpl-onboarding-fullscreen .prpl-popover-onboarding.prpl-popover-visible { + display: block; + position: relative; + inset: auto; + margin: 0; + max-height: 90vh; + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); + border: none; +} + .prpl-popover-onboarding { --prpl-color-text: #4b5563; diff --git a/assets/js/onboarding/onboarding.js b/assets/js/onboarding/onboarding.js index 0d93ac074..c32232d30 100644 --- a/assets/js/onboarding/onboarding.js +++ b/assets/js/onboarding/onboarding.js @@ -23,6 +23,9 @@ class ProgressPlannerOnboardWizard { // Store previously focused element for accessibility this.previouslyFocusedElement = null; + // Fullscreen mode flag + this.isFullscreenMode = config.fullscreenMode || false; + // Restore saved progress if available this.restoreSavedProgress(); @@ -31,6 +34,9 @@ class ProgressPlannerOnboardWizard { // Set DOM related properties FIRST. this.popover = document.getElementById( this.config.popoverId ); + this.fullscreenWrapper = document.getElementById( + 'prpl-onboarding-fullscreen' + ); this.contentWrapper = this.popover.querySelector( '.tour-content-wrapper' ); @@ -43,6 +49,11 @@ class ProgressPlannerOnboardWizard { // Setup event listeners after DOM is ready this.setupEventListeners(); + + // Auto-start onboarding if on the dedicated onboarding page + if ( this.config.isOnboardingPage ) { + this.startOnboarding(); + } } /** @@ -225,10 +236,12 @@ class ProgressPlannerOnboardWizard { this.closeTour(); // Redirect to the Progress Planner dashboard + // Wait for save to complete before redirecting to prevent re-triggering if ( this.config.lastStepRedirectUrl && this.config.lastStepRedirectUrl.length > 0 ) { + await this.saveProgressToServer(); window.location.href = this.config.lastStepRedirectUrl; } } @@ -248,9 +261,15 @@ class ProgressPlannerOnboardWizard { * Close the tour */ closeTour() { - if ( this.popover ) { + // If fullscreen mode, hide the wrapper and remove body class + if ( this.isFullscreenMode && this.fullscreenWrapper ) { + this.fullscreenWrapper.style.display = 'none'; + document.body.classList.remove( 'prpl-onboarding-active' ); + this.popover.classList.remove( 'prpl-popover-visible' ); + } else if ( this.popover ) { this.popover.hidePopover(); } + this.saveProgressToServer(); // Cleanup active step @@ -258,6 +277,12 @@ class ProgressPlannerOnboardWizard { this.state.cleanup(); } + // If on the onboarding page and not finishing, redirect back + if ( this.config.isOnboardingPage && this.config.cancelUrl && ! this.state.data.finished ) { + window.location.href = this.config.cancelUrl; + return; + } + // Reset cleanup this.state.cleanup = null; @@ -280,7 +305,16 @@ class ProgressPlannerOnboardWizard { this.previouslyFocusedElement = this.popover.ownerDocument.activeElement; - this.popover.showPopover(); + // If fullscreen mode, show the wrapper and add body class + // Don't use popover API in fullscreen mode - it moves to top layer and breaks positioning + if ( this.isFullscreenMode && this.fullscreenWrapper ) { + this.fullscreenWrapper.style.display = 'flex'; + document.body.classList.add( 'prpl-onboarding-active' ); + this.popover.classList.add( 'prpl-popover-visible' ); + } else { + this.popover.showPopover(); + } + this.updateStepNavigation(); this.renderStep(); diff --git a/classes/class-onboard-wizard.php b/classes/class-onboard-wizard.php index 61735969a..4c39efb0c 100644 --- a/classes/class-onboard-wizard.php +++ b/classes/class-onboard-wizard.php @@ -12,6 +12,13 @@ */ class Onboard_Wizard { + /** + * The onboarding page slug. + * + * @var string + */ + const PAGE_SLUG = 'progress-planner-onboarding'; + /** * Steps and their order. * @@ -69,6 +76,9 @@ public function maybe_register_popover_hooks() { return; } + // Register onboarding admin page (always, so it's accessible). + \add_action( 'admin_menu', [ $this, 'add_onboarding_page' ] ); + // Add popover on front end. \add_action( 'wp_footer', [ $this, 'add_popover' ] ); \add_action( 'wp_footer', [ $this, 'add_popover_step_templates' ] ); @@ -276,6 +286,13 @@ public function add_popover_scripts() { // Get saved progress from user meta. $saved_progress = $this->get_saved_progress(); + // Check if we're on the onboarding page. + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $is_onboarding_page = \is_admin() && isset( $_GET['page'] ) && self::PAGE_SLUG === $_GET['page']; + + // Check if onboarding was already completed. + $onboarding_completed = \get_option( 'prpl_onboarding_completed', false ); + // Enqueue main onboarding.js (depends on all step components). \progress_planner()->get_admin__enqueue()->enqueue_script( 'onboarding/onboarding', @@ -292,6 +309,9 @@ public function add_popover_scripts() { 'timezone_offset' => (float) ( \wp_timezone()->getOffset( new \DateTime( 'midnight' ) ) / 3600 ), 'savedProgress' => $saved_progress, 'lastStepRedirectUrl' => \esc_url_raw( admin_url( 'admin.php?page=progress-planner' ) ), + 'cancelUrl' => $is_onboarding_page ? \esc_url_raw( \wp_get_referer() ? \wp_get_referer() : admin_url( 'admin.php?page=progress-planner' ) ) : '', + 'isOnboardingPage' => $is_onboarding_page, + 'onboardingCompleted' => (bool) $onboarding_completed, 'fullscreenMode' => true, // Enable fullscreen takeover mode. 'hasLicense' => false !== \progress_planner()->get_license_key(), 'l10n' => [ @@ -319,7 +339,7 @@ protected function get_saved_progress() { return null; } - $onboarding_progress = \get_option( 'prpl_onboard_progress', true ); + $onboarding_progress = \get_option( 'prpl_onboard_progress', false ); if ( ! $onboarding_progress ) { return null; } @@ -332,6 +352,50 @@ protected function get_saved_progress() { return $decoded; } + /** + * Add the onboarding admin page. + * + * @return void + */ + public function add_onboarding_page() { + // Use 'options.php' as parent to create a hidden page (common WordPress pattern). + \add_submenu_page( + 'options.php', + \esc_html__( 'Setup Wizard', 'progress-planner' ), + \esc_html__( 'Setup Wizard', 'progress-planner' ), + 'manage_options', + self::PAGE_SLUG, + [ $this, 'render_onboarding_page' ] + ); + } + + /** + * Render the onboarding admin page. + * + * @return void + */ + public function render_onboarding_page() { + \progress_planner()->the_view( 'onboarding-page.php' ); + } + + /** + * Get the onboarding page URL. + * + * @return string + */ + public static function get_onboarding_page_url() { + return \admin_url( 'options.php?page=' . self::PAGE_SLUG ); + } + + /** + * Add admin toolbar item. + * + * @return void + */ + public function add_admin_toolbar_items() { + \add_action( 'admin_bar_menu', [ $this, 'add_admin_toolbar_items_callback' ], 100 ); + } + /** * Verify AJAX security (capability and nonce). * @@ -505,6 +569,7 @@ public function trigger_onboarding() { */ public function add_popover() { ?> +
the_file( 'assets/images/onboarding/thumbs_up_ravi_rtl.svg' ); ?> - + diff --git a/views/onboarding-page.php b/views/onboarding-page.php new file mode 100644 index 000000000..d8ae8216c --- /dev/null +++ b/views/onboarding-page.php @@ -0,0 +1,18 @@ + +