| @@ -1,11 +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 |
| 6 | 17 | * |
| 7 | - * @var array $settings_fields Grouped and sorted settings fields. | |
| 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). | |
| 8 | 21 | */ |
| 9 | 22 | |
| 10 | 23 | // Exit if accessed directly. |
| 11 | 24 | if ( ! defined( 'ABSPATH' ) ) { |
| @@ -11,47 +24,118 @@ | ||
| 11 | 24 | if ( ! defined( 'ABSPATH' ) ) { |
| 12 | 25 | exit; |
| 13 | 26 | } |
| 14 | 27 | |
| 28 | +use SpringDevs\Subscription\Admin\SettingsHelper; | |
| 29 | + | |
| 15 | 30 | wp_enqueue_style( 'wp-subscription-admin-settings', SUBSCRPT_ASSETS . '/css/admin-settings.css', [], SUBSCRPT_VERSION ); |
| 16 | 31 | wp_enqueue_script( 'wp-subscription-admin-settings', SUBSCRPT_ASSETS . '/js/admin-settings.js', [ 'jquery' ], SUBSCRPT_VERSION, true ); |
| 32 | + | |
| 33 | +$subscrpt_settings_base = admin_url( 'admin.php?page=wp-subscription-settings' ); | |
| 17 | 34 | ?> |
| 18 | -<div class="wp-subscription-admin-content list-page subscrpt-subs-list"> | |
| 35 | +<div class="wp-subscription-admin-content list-page"> | |
| 19 | 36 | |
| 20 | - <!-- Page header --> | |
| 21 | - <div style="margin-bottom:20px;"> | |
| 22 | - <h1 style="font-size:1.375rem;font-weight:700;color:var(--wpsubs-text);margin:0 0 6px;line-height:1.2;"><?php esc_html_e( 'Settings', 'subscription' ); ?></h1> | |
| 23 | - <p style="font-size:13px;color:var(--wpsubs-text-muted);margin:0 0 12px;line-height:1.5;"><?php esc_html_e( 'Configure subscription plugin behavior and features.', 'subscription' ); ?></p> | |
| 24 | - <div style="border-top:1px dashed #d0d3d7;"></div> | |
| 25 | - </div> | |
| 26 | - | |
| 27 | - <form method="post" action="options.php"> | |
| 37 | + <form method="post" action="options.php" class="subscrpt-settings" data-subscrpt-settings> | |
| 28 | 38 | <?php settings_fields( 'wp_subscription_settings' ); ?> |
| 29 | 39 | <?php do_settings_sections( 'wp_subscription_settings' ); ?> |
| 30 | 40 | |
| 31 | - <?php foreach ( $settings_fields as $group_id => $group ) : ?> | |
| 32 | - <?php | |
| 33 | - $fields = array_values( $group['fields'] ?? array() ); | |
| 34 | - $field_count = count( $fields ); | |
| 35 | - ?> | |
| 36 | - <div class="wpsubs-table-card" style="margin-bottom:16px;padding:20px 24px;"> | |
| 37 | - <?php foreach ( $fields as $idx => $field ) : ?> | |
| 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 | + ?> | |
| 55 | + | |
| 56 | + <div class="subscrpt-settings__layout"> | |
| 57 | + | |
| 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> | |
| 38 | 69 | <?php |
| 39 | - $field_type = $field['type'] ?? 'input'; | |
| 40 | - $field_data = $field['field_data'] ?? array(); | |
| 41 | - SpringDevs\Subscription\Admin\SettingsHelper::render_settings_field( $field_type, $field_data ); | |
| 42 | - ?> | |
| 43 | - <?php if ( 'heading' !== $field_type && $idx + 1 < $field_count ) : ?> | |
| 44 | - <div style="border-top:1px solid #f1f5f9;margin:16px 0;"></div> | |
| 45 | - <?php endif; ?> | |
| 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> | |
| 46 | 85 | <?php endforeach; ?> |
| 86 | + </nav> | |
| 87 | + </aside> | |
| 88 | + | |
| 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 | + | |
| 47 | 136 | </div> |
| 48 | - <?php endforeach; ?> | |
| 49 | 137 | |
| 50 | - <div style="margin-top:8px;"> | |
| 51 | - <button type="submit" class="wpsubs-btn wpsubs-btn--primary"> | |
| 52 | - <?php esc_html_e( 'Save changes', 'subscription' ); ?> | |
| 53 | - </button> | |
| 54 | 138 | </div> |
| 55 | 139 | </form> |
| 56 | 140 | |
| 57 | 141 | </div> |