| @@ -1,9 +1,24 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | 3 | * Subscription settings admin view. |
| 4 | 4 | * |
| 5 | + * One form, every panel rendered, one panel visible. The form posts to | |
| 6 | + * `options.php`, which saves whatever it is given — so a panel that is not | |
| 7 | + * rendered is a panel whose settings do not save. Hiding is therefore CSS, not | |
| 8 | + * a conditional, and every one of the fields below submits on every save | |
| 9 | + * whichever section happens to be open. | |
| 10 | + * | |
| 11 | + * One level of navigation: the rail picks a section and the section's panel | |
| 12 | + * stacks whatever groups belong to it. A section holding a single group drops | |
| 13 | + * that group's heading, because the rail item beside it already says the same | |
| 14 | + * word. | |
| 15 | + * | |
| 5 | 16 | * @package SpringDevs\Subscription\Admin |
| 17 | + * | |
| 18 | + * @var array $settings_fields Grouped and sorted settings fields. | |
| 19 | + * @var string $active_cat Section currently open. | |
| 20 | + * @var array $category_groups Section key => ordered group keys (empty ones dropped). | |
| 6 | 21 | */ |
| 7 | 22 | |
| 8 | 23 | // Exit if accessed directly. |
| 9 | 24 | if ( ! defined( 'ABSPATH' ) ) { |
| @@ -9,127 +24,118 @@ | ||
| 9 | 24 | if ( ! defined( 'ABSPATH' ) ) { |
| 10 | 25 | exit; |
| 11 | 26 | } |
| 12 | 27 | |
| 13 | -// Add Tailwind CSS for styling. | |
| 14 | -subscrpt_include_tailwind_css(); | |
| 28 | +use SpringDevs\Subscription\Admin\SettingsHelper; | |
| 15 | 29 | |
| 16 | -// Add admin settings styles. | |
| 17 | 30 | wp_enqueue_style( 'wp-subscription-admin-settings', SUBSCRPT_ASSETS . '/css/admin-settings.css', [], SUBSCRPT_VERSION ); |
| 18 | - | |
| 19 | -// Add admin settings scripts. | |
| 20 | 31 | wp_enqueue_script( 'wp-subscription-admin-settings', SUBSCRPT_ASSETS . '/js/admin-settings.js', [ 'jquery' ], SUBSCRPT_VERSION, true ); |
| 21 | 32 | |
| 33 | +$subscrpt_settings_base = admin_url( 'admin.php?page=wp-subscription-settings' ); | |
| 22 | 34 | ?> |
| 23 | -<div class="wp-subscription-admin-content" style="max-width:1240px;margin:32px auto 0 auto"> | |
| 24 | - <div class="wp-subscription-admin-box wpsubs-tw-root"> | |
| 25 | - <h1 class="wp-heading-inline"><?php esc_html_e( 'Subscription Settings', 'subscription' ); ?></h1> | |
| 26 | - <hr class="wp-header-end"><br/> | |
| 35 | +<div class="wp-subscription-admin-content list-page"> | |
| 27 | 36 | |
| 28 | - <form method="post" action="options.php" class="border border-gray-200 rounded-lg p-5"> | |
| 29 | - <!-- Settings nonce and other requirements --> | |
| 30 | - <?php settings_fields( 'wp_subscription_settings' ); ?> | |
| 31 | - <?php do_settings_sections( 'wp_subscription_settings' ); ?> | |
| 37 | + <form method="post" action="options.php" class="subscrpt-settings" data-subscrpt-settings> | |
| 38 | + <?php settings_fields( 'wp_subscription_settings' ); ?> | |
| 39 | + <?php do_settings_sections( 'wp_subscription_settings' ); ?> | |
| 32 | 40 | |
| 33 | - <!-- Settings Fields --> | |
| 34 | - <?php | |
| 35 | - foreach ( $settings_fields as $group_id => $group ) { | |
| 36 | - foreach ( ( $group['fields'] ?? [] ) as $field ) { | |
| 37 | - $field_type = $field['type'] ?? 'input'; | |
| 38 | - $field_data = $field['field_data'] ?? []; | |
| 41 | + <?php | |
| 42 | + // Shared page header (title + description + dashed rule) with the Save | |
| 43 | + // button pinned to the right of the title row. | |
| 44 | + wpsubs_render_page_header( | |
| 45 | + array( | |
| 46 | + 'title' => __( 'Settings', 'subscription' ), | |
| 47 | + 'description' => __( 'Configure how subscriptions renew, charge and behave for your customers.', 'subscription' ), | |
| 48 | + 'actions' => sprintf( | |
| 49 | + '<button type="submit" class="wpsubs-btn wpsubs-btn--primary subscrpt-settings__save">%s</button>', | |
| 50 | + esc_html__( 'Save changes', 'subscription' ) | |
| 51 | + ), | |
| 52 | + ) | |
| 53 | + ); | |
| 54 | + ?> | |
| 39 | 55 | |
| 40 | - SpringDevs\Subscription\Admin\SettingsHelper::render_settings_field( $field_type, $field_data ); | |
| 56 | + <div class="subscrpt-settings__layout"> | |
| 41 | 57 | |
| 42 | - echo wp_kses_post( '<div class="my-5 border-t border-gray-100"></div>' ); | |
| 43 | - } | |
| 44 | - } | |
| 45 | - ?> | |
| 58 | + <aside class="subscrpt-settings__sidebar"> | |
| 59 | + <nav class="wpsubs-vnav" aria-label="<?php esc_attr_e( 'Settings sections', 'subscription' ); ?>"> | |
| 60 | + <?php $subscrpt_all_active = 'all' === $active_cat; ?> | |
| 61 | + <a | |
| 62 | + class="wpsubs-vnav__item<?php echo $subscrpt_all_active ? ' is-active' : ''; ?>" | |
| 63 | + href="<?php echo esc_url( add_query_arg( 'cat', 'all', $subscrpt_settings_base ) ); ?>" | |
| 64 | + data-subscrpt-cat="all" | |
| 65 | + aria-current="<?php echo $subscrpt_all_active ? 'page' : 'false'; ?>" | |
| 66 | + > | |
| 67 | + <span class="wpsubs-vnav__label"><?php esc_html_e( 'All Settings', 'subscription' ); ?></span> | |
| 68 | + </a> | |
| 69 | + <?php | |
| 70 | + $subscrpt_cat_labels = SettingsHelper::categories(); | |
| 71 | + foreach ( $category_groups as $subscrpt_cat_id => $subscrpt_cat_group_ids ) : | |
| 72 | + $subscrpt_cat_active = $subscrpt_cat_id === $active_cat; | |
| 73 | + ?> | |
| 74 | + <a | |
| 75 | + class="wpsubs-vnav__item<?php echo $subscrpt_cat_active ? ' is-active' : ''; ?>" | |
| 76 | + href="<?php echo esc_url( add_query_arg( 'cat', $subscrpt_cat_id, $subscrpt_settings_base ) ); ?>" | |
| 77 | + data-subscrpt-cat="<?php echo esc_attr( $subscrpt_cat_id ); ?>" | |
| 78 | + aria-current="<?php echo $subscrpt_cat_active ? 'page' : 'false'; ?>" | |
| 79 | + > | |
| 80 | + <span class="wpsubs-vnav__label"><?php echo esc_html( $subscrpt_cat_labels[ $subscrpt_cat_id ] ?? $subscrpt_cat_id ); ?></span> | |
| 81 | + <?php if ( SettingsHelper::category_is_pro_locked( $subscrpt_cat_group_ids, $settings_fields ) ) : ?> | |
| 82 | + <?php echo wp_kses_post( SettingsHelper::pro_badge_html() ); ?> | |
| 83 | + <?php endif; ?> | |
| 84 | + </a> | |
| 85 | + <?php endforeach; ?> | |
| 86 | + </nav> | |
| 87 | + </aside> | |
| 46 | 88 | |
| 47 | - <!-- Submit Button --> | |
| 48 | - <div> | |
| 49 | - <input | |
| 50 | - type="submit" | |
| 51 | - value="<?php esc_attr_e( 'Save changes', 'subscription' ); ?>" | |
| 52 | - class="button button-primary px-3! py-1! rounded-md!" | |
| 53 | - /> | |
| 89 | + <div class="subscrpt-settings__content"> | |
| 90 | + | |
| 91 | + <div class="subscrpt-settings__panels"> | |
| 92 | + <?php | |
| 93 | + // One card per settings group, so groups stay visually separate | |
| 94 | + // instead of running together in a single section card. The rail | |
| 95 | + // shows a group's whole section; "All Settings" shows every card. | |
| 96 | + foreach ( $category_groups as $subscrpt_cat_id => $subscrpt_cat_group_ids ) : | |
| 97 | + $subscrpt_cat_open = 'all' === $active_cat || $subscrpt_cat_id === $active_cat; | |
| 98 | + foreach ( $subscrpt_cat_group_ids as $subscrpt_group_id ) : | |
| 99 | + $subscrpt_group = $settings_fields[ $subscrpt_group_id ] ?? array(); | |
| 100 | + $subscrpt_fields = array_values( $subscrpt_group['fields'] ?? array() ); | |
| 101 | + $subscrpt_count = count( $subscrpt_fields ); | |
| 102 | + if ( 0 === $subscrpt_count ) { | |
| 103 | + continue; | |
| 104 | + } | |
| 105 | + $subscrpt_label = SettingsHelper::group_label( $subscrpt_group_id, $subscrpt_group ); | |
| 106 | + ?> | |
| 107 | + <section | |
| 108 | + class="subscrpt-settings__panel wpsubs-table-card" | |
| 109 | + id="subscrpt-panel-<?php echo esc_attr( $subscrpt_group_id ); ?>" | |
| 110 | + role="region" | |
| 111 | + aria-label="<?php echo esc_attr( $subscrpt_label ); ?>" | |
| 112 | + data-subscrpt-panel="<?php echo esc_attr( $subscrpt_group_id ); ?>" | |
| 113 | + data-subscrpt-cat="<?php echo esc_attr( $subscrpt_cat_id ); ?>" | |
| 114 | + <?php echo $subscrpt_cat_open ? '' : 'hidden'; ?> | |
| 115 | + > | |
| 116 | + <?php foreach ( $subscrpt_fields as $subscrpt_idx => $subscrpt_field ) : ?> | |
| 117 | + <?php | |
| 118 | + $subscrpt_type = $subscrpt_field['type'] ?? 'input'; | |
| 119 | + SettingsHelper::render_settings_field( $subscrpt_type, $subscrpt_field['field_data'] ?? array() ); | |
| 120 | + | |
| 121 | + // No rule before a heading — the heading is itself the break. | |
| 122 | + $subscrpt_next = $subscrpt_fields[ $subscrpt_idx + 1 ] ?? null; | |
| 123 | + $subscrpt_rule = 'heading' !== $subscrpt_type | |
| 124 | + && $subscrpt_idx + 1 < $subscrpt_count | |
| 125 | + && 'heading' !== ( $subscrpt_next['type'] ?? '' ); | |
| 126 | + ?> | |
| 127 | + <?php if ( $subscrpt_rule ) : ?> | |
| 128 | + <div class="subscrpt-settings__rule"></div> | |
| 129 | + <?php endif; ?> | |
| 130 | + <?php endforeach; ?> | |
| 131 | + </section> | |
| 132 | + <?php endforeach; ?> | |
| 133 | + <?php endforeach; ?> | |
| 134 | + </div> | |
| 135 | + | |
| 54 | 136 | </div> |
| 55 | - </form> | |
| 56 | - </div> | |
| 57 | -</div> | |
| 58 | 137 | |
| 59 | -<?php return; ?> | |
| 138 | + </div> | |
| 139 | + </form> | |
| 60 | 140 | |
| 61 | -<?php | |
| 62 | -/** | |
| 63 | - * TODO: Refactor this section later | |
| 64 | - * | |
| 65 | - * phpcs:disable | |
| 66 | - */ | |
| 67 | -?> | |
| 68 | -<!-- Pro Gimmicks --> | |
| 69 | -<?php if ( ! class_exists( 'Sdevs_Wc_Subscription_Pro' ) ) : ?> | |
| 70 | - <!-- PRO Features (subtle, grayed out) --> | |
| 71 | - <tr class="wp-subscription-pro-setting-row" style="opacity:0.55;pointer-events:none;"> | |
| 72 | - <th scope="row"> | |
| 73 | - <label><?php esc_html_e( 'Variable Product Options', 'subscription' ); ?></label> | |
| 74 | - </th> | |
| 75 | - <td> | |
| 76 | - <input type="text" disabled placeholder="Available in PRO" style="width:220px;" /> | |
| 77 | - <p class="description">Set flexible options for variable subscription products <span style="color:#2196f3;font-weight:600;">PRO</span></p> | |
| 78 | - </td> | |
| 79 | - </tr> | |
| 80 | - <tr class="wp-subscription-pro-setting-row" style="opacity:0.55;pointer-events:none;"> | |
| 81 | - <th scope="row"> | |
| 82 | - <label><?php esc_html_e( 'Delivery Schedule', 'subscription' ); ?></label> | |
| 83 | - </th> | |
| 84 | - <td> | |
| 85 | - <select disabled><option><?php esc_html_e( 'Available in PRO', 'subscription' ); ?></option></select> | |
| 86 | - <p class="description">Custom delivery intervals for subscriptions <span style="color:#2196f3;font-weight:600;">PRO</span></p> | |
| 87 | - </td> | |
| 88 | - </tr> | |
| 89 | - <tr class="wp-subscription-pro-setting-row" style="opacity:0.55;pointer-events:none;"> | |
| 90 | - <th scope="row"> | |
| 91 | - <label><?php esc_html_e( 'Subscription History', 'subscription' ); ?></label> | |
| 92 | - </th> | |
| 93 | - <td> | |
| 94 | - <input type="text" disabled placeholder="Available in PRO" style="width:220px;" /> | |
| 95 | - <p class="description">View detailed subscription change history <span style="color:#2196f3;font-weight:600;">PRO</span></p> | |
| 96 | - </td> | |
| 97 | - </tr> | |
| 98 | - <tr class="wp-subscription-pro-setting-row" style="opacity:0.55;pointer-events:none;"> | |
| 99 | - <th scope="row"> | |
| 100 | - <label><?php esc_html_e( 'More Subscription Durations', 'subscription' ); ?></label> | |
| 101 | - </th> | |
| 102 | - <td> | |
| 103 | - <input type="text" disabled placeholder="Available in PRO" style="width:220px;" /> | |
| 104 | - <p class="description">Offer more flexible/custom subscription periods <span style="color:#2196f3;font-weight:600;">PRO</span></p> | |
| 105 | - </td> | |
| 106 | - </tr> | |
| 107 | - <tr class="wp-subscription-pro-setting-row" style="opacity:0.55;pointer-events:none;"> | |
| 108 | - <th scope="row"> | |
| 109 | - <label><?php esc_html_e( 'Sign Up Fee', 'subscription' ); ?></label> | |
| 110 | - </th> | |
| 111 | - <td> | |
| 112 | - <input type="number" disabled placeholder="Available in PRO" style="width:120px;" /> | |
| 113 | - <p class="description">Charge a one-time sign up fee <span style="color:#2196f3;font-weight:600;">PRO</span></p> | |
| 114 | - </td> | |
| 115 | - </tr> | |
| 116 | - <tr class="wp-subscription-pro-setting-row" style="opacity:0.55;pointer-events:none;"> | |
| 117 | - <th scope="row"> | |
| 118 | - <label><?php esc_html_e( 'Early Renewal', 'subscription' ); ?></label> | |
| 119 | - </th> | |
| 120 | - <td> | |
| 121 | - <input class="wp-subscription-toggle" type="checkbox" disabled /> | |
| 122 | - <span class="wp-subscription-toggle-ui" aria-hidden="true"></span> | |
| 123 | - <p class="description">Allow early renewal for subscriptions <span style="color:#2196f3;font-weight:600;">PRO</span></p> | |
| 124 | - </td> | |
| 125 | - </tr> | |
| 126 | - <tr class="wp-subscription-pro-setting-row" style="opacity:0.55;pointer-events:none;"> | |
| 127 | - <th scope="row"> | |
| 128 | - <label><?php esc_html_e( 'Renewal Price', 'subscription' ); ?></label> | |
| 129 | - </th> | |
| 130 | - <td> | |
| 131 | - <input type="number" disabled placeholder="Available in PRO" style="width:120px;" /> | |
| 132 | - <p class="description">Set a different price for renewals <span style="color:#2196f3;font-weight:600;">PRO</span></p> | |
| 133 | - </td> | |
| 134 | - </tr> | |
| 135 | -<?php endif; ?> | |
| 141 | +</div> | |