| 1 |
<?php |
| 2 |
/** |
| 3 |
* Plan detail - Products tab. |
| 4 |
* |
| 5 |
* Lists the products attached to this plan group. In free this is read-only: |
| 6 |
* products are connected from their own editor. With Pro active, an "Add |
| 7 |
* Products" bulk picker is available here. |
| 8 |
* |
| 9 |
* @var array $plan Plan (PlanPresenter shape). |
| 10 |
* |
| 11 |
* @package SpringDevs\Subscription\Admin |
| 12 |
*/ |
| 13 |
|
| 14 |
if ( ! defined( 'ABSPATH' ) ) { |
| 15 |
exit; |
| 16 |
} |
| 17 |
|
| 18 |
$pro_active = function_exists( 'subscrpt_pro_activated' ) && subscrpt_pro_activated(); |
| 19 |
// Products can only be attached once the plan group has at least one term. |
| 20 |
$has_terms = ! empty( $plan['terms'] ); |
| 21 |
?> |
| 22 |
<div style="padding-top:8px;"> |
| 23 |
|
| 24 |
<?php if ( empty( $plan['products'] ) ) : ?> |
| 25 |
<div class="wpsubs-empty"> |
| 26 |
<div class="wpsubs-empty__icon">📦</div> |
| 27 |
<h3 class="wpsubs-empty__title"><?php esc_html_e( 'No products connected', 'subscription' ); ?></h3> |
| 28 |
<?php if ( ! $has_terms ) : ?> |
| 29 |
<p class="wpsubs-empty__desc"><?php esc_html_e( 'Add at least one duration on the Durations tab before attaching products.', 'subscription' ); ?></p> |
| 30 |
<?php else : ?> |
| 31 |
<p class="wpsubs-empty__desc"><?php esc_html_e( 'Add products to this plan and set their prices here, or connect a product from its own Subscription tab.', 'subscription' ); ?></p> |
| 32 |
<button type="button" class="wpsubs-btn wpsubs-btn--primary" style="margin-top:20px;" data-wpsubs-modal-open="subscrpt-add-product"> |
| 33 |
<span class="dashicons dashicons-plus-alt2" style="font-size:16px;width:16px;height:16px;line-height:1;"></span> |
| 34 |
<?php esc_html_e( 'Add Products', 'subscription' ); ?> |
| 35 |
</button> |
| 36 |
<?php endif; ?> |
| 37 |
</div> |
| 38 |
<?php else : ?> |
| 39 |
|
| 40 |
<?php |
| 41 |
/** |
| 42 |
* Render the price table for a set of relation rows (Duration / |
| 43 |
* Regular / Offer / Status). Each editable cell has a read view + a |
| 44 |
* hidden input revealed by the card's Edit/Save buttons (JS). |
| 45 |
* |
| 46 |
* When $one_time is provided, a "One-time purchase" row is appended: its |
| 47 |
* price is the product's/variation's native WooCommerce price and the |
| 48 |
* card's single Save persists both the plan relations and the one-time |
| 49 |
* native price. Pro-gated (read-only + Pro badge when Pro is inactive). |
| 50 |
* |
| 51 |
* @param array $rows Price rows (term / regular / offer / …). |
| 52 |
* @param array|null $one_time One-time data: enabled, regular, offer. |
| 53 |
*/ |
| 54 |
$subscrpt_render_rows = function ( $rows, $one_time = null ) { |
| 55 |
?> |
| 56 |
<table class="wpsubs-table"> |
| 57 |
<thead> |
| 58 |
<tr> |
| 59 |
<th><?php esc_html_e( 'Duration', 'subscription' ); ?></th> |
| 60 |
<th> |
| 61 |
<?php esc_html_e( 'Regular Price', 'subscription' ); ?> |
| 62 |
<?php echo wp_kses_post( wpsubs_render_hint( __( 'The recurring price charged each billing cycle.', 'subscription' ) ) ); ?> |
| 63 |
</th> |
| 64 |
<th> |
| 65 |
<?php esc_html_e( 'Offer Price', 'subscription' ); ?> |
| 66 |
<?php echo wp_kses_post( wpsubs_render_hint( __( 'A discounted recurring price shown in place of the regular price. Leave empty for no discount.', 'subscription' ) ) ); ?> |
| 67 |
</th> |
| 68 |
<th><?php esc_html_e( 'Status', 'subscription' ); ?></th> |
| 69 |
</tr> |
| 70 |
</thead> |
| 71 |
<tbody> |
| 72 |
<?php foreach ( $rows as $row ) : ?> |
| 73 |
<tr data-subscrpt-relation="<?php echo esc_attr( $row['relation_id'] ); ?>" data-plan-id="<?php echo esc_attr( isset( $row['plan_id'] ) ? $row['plan_id'] : '' ); ?>"> |
| 74 |
|
| 75 |
<td><?php echo esc_html( $row['term'] ); ?></td> |
| 76 |
<td> |
| 77 |
<span class="subscrpt-pe-view"><?php echo esc_html( $row['regular'] ); ?></span> |
| 78 |
<input type="number" min="0" step="0.01" class="wpsubs-input subscrpt-pe-edit" data-field="regular_price" value="<?php echo esc_attr( $row['regular_raw'] ); ?>" placeholder="0.00" style="display:none;width:120px;max-width:100%;" /> |
| 79 |
</td> |
| 80 |
<td> |
| 81 |
<span class="subscrpt-pe-view"><?php echo ! empty( $row['has_offer'] ) ? esc_html( $row['offer'] ) : '<span style="color:var(--wpsubs-text-subtle);">—</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Static dash markup / escaped price. ?></span> |
| 82 |
<input type="number" min="0" step="0.01" class="wpsubs-input subscrpt-pe-edit" data-field="sale_price" value="<?php echo esc_attr( $row['offer_raw'] ); ?>" placeholder="0.00" style="display:none;width:120px;max-width:100%;" /> |
| 83 |
</td> |
| 84 |
<td> |
| 85 |
<span class="subscrpt-pe-view"> |
| 86 |
<?php if ( ! empty( $row['exclude'] ) ) : ?> |
| 87 |
<span class="wpsubs-badge wpsubs-badge--draft"><?php esc_html_e( 'Disabled', 'subscription' ); ?></span> |
| 88 |
<?php else : ?> |
| 89 |
<span class="wpsubs-badge wpsubs-badge--active"><?php esc_html_e( 'Enabled', 'subscription' ); ?></span> |
| 90 |
<?php endif; ?> |
| 91 |
</span> |
| 92 |
<label class="wpsubs-settings-toggle-label subscrpt-pe-edit" style="display:none;align-items:center;" title="<?php esc_attr_e( 'Enable this plan for the product', 'subscription' ); ?>"> |
| 93 |
<input type="checkbox" class="wpsubs-toggle" data-field="enabled" <?php checked( empty( $row['exclude'] ) ); ?> /> |
| 94 |
<span class="wpsubs-toggle-ui" aria-hidden="true"></span> |
| 95 |
</label> |
| 96 |
</td> |
| 97 |
</tr> |
| 98 |
<?php endforeach; ?> |
| 99 |
|
| 100 |
<?php |
| 101 |
if ( is_array( $one_time ) ) : |
| 102 |
$subscrpt_ot_on = ! empty( $one_time['enabled'] ); |
| 103 |
$subscrpt_ot_reg = (string) $one_time['regular']; |
| 104 |
$subscrpt_ot_off = (string) $one_time['offer']; |
| 105 |
$subscrpt_ot_dash = '<span style="color:var(--wpsubs-text-subtle);">—</span>'; |
| 106 |
$subscrpt_ot_rdsp = '' !== $subscrpt_ot_reg ? esc_html( \SpringDevs\Subscription\Admin\PlanPresenter::money( (float) $subscrpt_ot_reg ) ) : $subscrpt_ot_dash; |
| 107 |
$subscrpt_ot_odsp = '' !== $subscrpt_ot_off ? esc_html( \SpringDevs\Subscription\Admin\PlanPresenter::money( (float) $subscrpt_ot_off ) ) : $subscrpt_ot_dash; |
| 108 |
?> |
| 109 |
<tr data-subscrpt-onetime data-subscrpt-onetime-row style="border-top:2px solid var(--wpsubs-border,#e5e7eb);background:var(--wpsubs-surface-muted,#f6f7f7);"> |
| 110 |
<td> |
| 111 |
<span style="display:inline-flex;align-items:center;gap:6px;"> |
| 112 |
<span class="dashicons dashicons-cart" style="flex:0 0 auto;font-size:15px;width:15px;height:15px;color:var(--wpsubs-text-subtle);"></span> |
| 113 |
<?php esc_html_e( 'One-time purchase', 'subscription' ); ?> |
| 114 |
<?php echo wp_kses_post( wpsubs_render_hint( __( 'A single, non-recurring purchase at the product’s regular WooCommerce price.', 'subscription' ) ) ); ?> |
| 115 |
</span> |
| 116 |
</td> |
| 117 |
<?php |
| 118 |
// Two independent conditions, so two wrappers: the outer is the card's |
| 119 |
// read/edit cycle, the inner is the toggle. One element carrying both |
| 120 |
// would have them fight over `display`. |
| 121 |
$subscrpt_ot_hidden = $subscrpt_ot_on ? '' : ' style="display:none;"'; |
| 122 |
?> |
| 123 |
<td> |
| 124 |
<span class="subscrpt-pe-view"><?php echo wp_kses_post( $subscrpt_ot_rdsp ); ?></span> |
| 125 |
<span class="subscrpt-pe-edit" style="display:none;"> |
| 126 |
<span data-subscrpt-onetime-price<?php echo $subscrpt_ot_hidden; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- fixed literal. ?>> |
| 127 |
<input type="number" min="0" step="0.01" class="wpsubs-input" data-ot-field="price" value="<?php echo esc_attr( $subscrpt_ot_reg ); ?>" placeholder="0.00" style="max-width:110px;" /> |
| 128 |
</span> |
| 129 |
</span> |
| 130 |
</td> |
| 131 |
<td> |
| 132 |
<span class="subscrpt-pe-view"><?php echo wp_kses_post( $subscrpt_ot_odsp ); ?></span> |
| 133 |
<span class="subscrpt-pe-edit" style="display:none;"> |
| 134 |
<span data-subscrpt-onetime-price<?php echo $subscrpt_ot_hidden; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- fixed literal. ?>> |
| 135 |
<input type="number" min="0" step="0.01" class="wpsubs-input" data-ot-field="offer" value="<?php echo esc_attr( $subscrpt_ot_off ); ?>" placeholder="<?php esc_attr_e( 'No offer', 'subscription' ); ?>" style="max-width:110px;" /> |
| 136 |
</span> |
| 137 |
</span> |
| 138 |
</td> |
| 139 |
<td> |
| 140 |
<span class="subscrpt-pe-view"> |
| 141 |
<?php if ( $subscrpt_ot_on ) : ?> |
| 142 |
<span class="wpsubs-badge wpsubs-badge--active"><?php esc_html_e( 'Enabled', 'subscription' ); ?></span> |
| 143 |
<?php else : ?> |
| 144 |
<span class="wpsubs-badge wpsubs-badge--draft"><?php esc_html_e( 'Disabled', 'subscription' ); ?></span> |
| 145 |
<?php endif; ?> |
| 146 |
</span> |
| 147 |
<label class="wpsubs-settings-toggle-label subscrpt-pe-edit" style="display:none;align-items:center;" title="<?php esc_attr_e( 'Offer this product for one-time purchase', 'subscription' ); ?>"> |
| 148 |
<input type="checkbox" class="wpsubs-toggle" data-subscrpt-onetime-enable <?php checked( $subscrpt_ot_on ); ?> /> |
| 149 |
<span class="wpsubs-toggle-ui" aria-hidden="true"></span> |
| 150 |
</label> |
| 151 |
</td> |
| 152 |
</tr> |
| 153 |
<?php endif; ?> |
| 154 |
</tbody> |
| 155 |
</table> |
| 156 |
<?php |
| 157 |
}; |
| 158 |
|
| 159 |
/** |
| 160 |
* Render the price-card header controls: Edit / Cancel / Save. |
| 161 |
* JS toggles the card into edit mode and saves the plan prices via REST. |
| 162 |
*/ |
| 163 |
$subscrpt_price_actions = function () { |
| 164 |
?> |
| 165 |
<button type="button" class="wpsubs-btn wpsubs-btn--outline wpsubs-btn--sm" data-subscrpt-edit-prices> |
| 166 |
<span class="dashicons dashicons-edit" style="font-size:15px;width:15px;height:15px;line-height:1;"></span> |
| 167 |
<?php esc_html_e( 'Edit prices', 'subscription' ); ?> |
| 168 |
</button> |
| 169 |
<button type="button" class="wpsubs-btn wpsubs-btn--outline wpsubs-btn--sm" data-subscrpt-cancel-prices style="display:none;"><?php esc_html_e( 'Cancel', 'subscription' ); ?></button> |
| 170 |
<button type="button" class="wpsubs-btn wpsubs-btn--primary wpsubs-btn--sm" data-subscrpt-save-prices style="display:none;"><?php esc_html_e( 'Save', 'subscription' ); ?></button> |
| 171 |
<?php |
| 172 |
}; |
| 173 |
|
| 174 |
/** |
| 175 |
* Render a simple product's one-time purchase card (its own toggle + Save). |
| 176 |
* One-time is product-specific: the price is the product’s native |
| 177 |
* WooCommerce price (regular = one-time, sale = offer). Pro-gated: disabled |
| 178 |
* with a Pro badge when Pro is inactive. Variable products use the |
| 179 |
* per-variation one-time row inside render_rows(). |
| 180 |
* |
| 181 |
* @param array $product Product entry (PlanPresenter shape). |
| 182 |
*/ |
| 183 |
$subscrpt_render_onetime = function ( $product ) { |
| 184 |
$subscrpt_on = ! empty( $product['one_time_on'] ); |
| 185 |
$subscrpt_show_body = $subscrpt_on; |
| 186 |
?> |
| 187 |
<div style="width:90%;border-top:1px dashed var(--wpsubs-border-strong,#d1d5db);margin:16px auto 0;"></div> |
| 188 |
<div data-subscrpt-onetime data-subscrpt-onetime-card data-product-id="<?php echo esc_attr( $product['id'] ); ?>" style="border:1px solid var(--wpsubs-border,#e5e7eb);border-radius:8px;background:var(--wpsubs-surface,#fff);margin-top:14px;"> |
| 189 |
<div style="display:flex;align-items:center;gap:10px;padding:11px 14px;"> |
| 190 |
<span class="dashicons dashicons-cart" style="flex:0 0 auto;font-size:16px;width:16px;height:16px;color:var(--wpsubs-text-subtle);"></span> |
| 191 |
<strong style="font-size:13px;color:var(--wpsubs-text);"><?php esc_html_e( 'One-time purchase', 'subscription' ); ?></strong> |
| 192 |
<?php echo wp_kses_post( wpsubs_render_hint( __( 'This is the product’s regular WooCommerce price, charged when a customer buys it once instead of subscribing.', 'subscription' ) ) ); ?> |
| 193 |
<span class="wpsubs-toolbar__spacer"></span> |
| 194 |
<?php // The switch saves itself (plans.js): Save lives in the price row below, which hides while it is off. ?> |
| 195 |
<label class="wpsubs-settings-toggle-label" style="display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--wpsubs-text-muted);cursor:pointer;"> |
| 196 |
<input type="checkbox" class="wpsubs-toggle" data-subscrpt-onetime-enable <?php checked( $subscrpt_on ); ?> /> |
| 197 |
<span class="wpsubs-toggle-ui" aria-hidden="true"></span> |
| 198 |
<span><?php esc_html_e( 'Allow one-time purchase', 'subscription' ); ?></span> |
| 199 |
</label> |
| 200 |
</div> |
| 201 |
<div data-subscrpt-onetime-body style="padding:12px 14px;border-top:1px solid var(--wpsubs-border,#e5e7eb);<?php echo $subscrpt_show_body ? '' : 'display:none;'; ?>"> |
| 202 |
<?php // Flex on an inner row: the body's own inline display is what the switch toggles. ?> |
| 203 |
<div style="display:flex;align-items:flex-end;gap:16px;flex-wrap:wrap;"> |
| 204 |
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:16px;max-width:460px;flex:1 1 360px;"> |
| 205 |
<label style="display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--wpsubs-text-muted);"> |
| 206 |
<?php esc_html_e( 'Regular Price', 'subscription' ); ?> |
| 207 |
<input type="number" min="0" step="0.01" class="wpsubs-input" data-ot-field="price" value="<?php echo esc_attr( $product['ot_regular'] ); ?>" placeholder="0.00" style="width:100%;box-sizing:border-box;" /> |
| 208 |
</label> |
| 209 |
<label style="display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--wpsubs-text-muted);"> |
| 210 |
<?php esc_html_e( 'Offer Price', 'subscription' ); ?> |
| 211 |
<input type="number" min="0" step="0.01" class="wpsubs-input" data-ot-field="offer" value="<?php echo esc_attr( $product['ot_offer'] ); ?>" placeholder="<?php esc_attr_e( 'No offer', 'subscription' ); ?>" style="width:100%;box-sizing:border-box;" /> |
| 212 |
</label> |
| 213 |
</div> |
| 214 |
<button type="button" class="wpsubs-btn wpsubs-btn--primary wpsubs-btn--sm" data-subscrpt-onetime-save style="margin-left:auto;"><?php esc_html_e( 'Save', 'subscription' ); ?></button> |
| 215 |
</div> |
| 216 |
</div> |
| 217 |
</div> |
| 218 |
<?php |
| 219 |
}; |
| 220 |
|
| 221 |
/** |
| 222 |
* Render a simple product's "Allow User Cancellation" card. The switch |
| 223 |
* saves itself (plans.js), as the one-time switch does. Variable products |
| 224 |
* set it per variation in the product editor. |
| 225 |
* |
| 226 |
* @param array $product Product entry (PlanPresenter shape). |
| 227 |
*/ |
| 228 |
$subscrpt_render_user_cancel = function ( $product ) { |
| 229 |
?> |
| 230 |
<div data-subscrpt-user-cancel-card data-product-id="<?php echo esc_attr( $product['id'] ); ?>" style="border:1px solid var(--wpsubs-border,#e5e7eb);border-radius:8px;background:var(--wpsubs-surface,#fff);margin-top:14px;"> |
| 231 |
<div style="display:flex;align-items:center;gap:10px;padding:11px 14px;"> |
| 232 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" width="16" height="16" fill="currentColor" aria-hidden="true" focusable="false" style="flex:0 0 auto;color:var(--wpsubs-text-subtle);"><path d="M431.2 476.5L163.5 208.8C141.1 240.2 128 278.6 128 320C128 426 214 512 320 512C361.5 512 399.9 498.9 431.2 476.5zM476.5 431.2C498.9 399.8 512 361.4 512 320C512 214 426 128 320 128C278.5 128 240.1 141.1 208.8 163.5L476.5 431.2zM64 320C64 178.6 178.6 64 320 64C461.4 64 576 178.6 576 320C576 461.4 461.4 576 320 576C178.6 576 64 461.4 64 320z"/></svg> |
| 233 |
<strong style="font-size:13px;color:var(--wpsubs-text);"><?php esc_html_e( 'User cancellation', 'subscription' ); ?></strong> |
| 234 |
<?php echo wp_kses_post( wpsubs_render_hint( __( 'Allow subscribers to cancel their subscription manually from their account dashboard. Applies to subscriptions bought after the change.', 'subscription' ) ) ); ?> |
| 235 |
<span class="wpsubs-toolbar__spacer"></span> |
| 236 |
<label class="wpsubs-settings-toggle-label" style="display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--wpsubs-text-muted);cursor:pointer;"> |
| 237 |
<input type="checkbox" class="wpsubs-toggle" data-subscrpt-user-cancel-enable <?php checked( ! empty( $product['user_cancel'] ) ); ?> /> |
| 238 |
<span class="wpsubs-toggle-ui" aria-hidden="true"></span> |
| 239 |
<span><?php esc_html_e( 'Allow User Cancellation', 'subscription' ); ?></span> |
| 240 |
</label> |
| 241 |
</div> |
| 242 |
</div> |
| 243 |
<?php |
| 244 |
}; |
| 245 |
?> |
| 246 |
|
| 247 |
<div data-subscrpt-browse data-per-page="10"> |
| 248 |
<div class="wpsubs-toolbar" style="margin-bottom:14px;"> |
| 249 |
<div class="wpsubs-search"> |
| 250 |
<div class="wpsubs-input-wrap wpsubs-input-wrap--icon-l"> |
| 251 |
<svg class="wpsubs-input-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-4.35-4.35M17 11A6 6 0 1 1 5 11a6 6 0 0 1 12 0z"/></svg> |
| 252 |
<input type="search" class="wpsubs-input" placeholder="<?php esc_attr_e( 'Search products...', 'subscription' ); ?>" data-subscrpt-browse-search /> |
| 253 |
</div> |
| 254 |
</div> |
| 255 |
|
| 256 |
<?php |
| 257 |
wpsubs_render_per_page_select( |
| 258 |
array( |
| 259 |
'name' => 'subscrpt_products_per_page', |
| 260 |
'attrs' => array( 'data-subscrpt-browse-perpage' => '1' ), |
| 261 |
) |
| 262 |
); |
| 263 |
?> |
| 264 |
|
| 265 |
<div class="wpsubs-toolbar__spacer"></div> |
| 266 |
|
| 267 |
<button type="button" class="wpsubs-btn wpsubs-btn--outline" data-wpsubs-modal-open="subscrpt-bulk-price"> |
| 268 |
<span class="dashicons dashicons-money-alt" style="font-size:16px;width:16px;height:16px;line-height:1;"></span> |
| 269 |
<?php esc_html_e( 'Quick price update', 'subscription' ); ?> |
| 270 |
</button> |
| 271 |
</div> |
| 272 |
|
| 273 |
<div class="wpsubs-accordion" data-multi="1" data-subscrpt-product-list data-subscrpt-sortable="products"> |
| 274 |
<?php $subscrpt_is_first = true; ?> |
| 275 |
<?php foreach ( $plan['products'] as $product ) : ?> |
| 276 |
<?php $subscrpt_panel_id = 'subscrpt-prod-' . (int) $product['id']; ?> |
| 277 |
<div class="wpsubs-accordion__item" data-subscrpt-browse-item data-subscrpt-sort-item="<?php echo esc_attr( $product['id'] ); ?>" data-name="<?php echo esc_attr( strtolower( $product['name'] ) ); ?>" data-pid="<?php echo esc_attr( $product['id'] ); ?>"> |
| 278 |
<div style="display:flex;align-items:stretch;background:var(--wpsubs-surface-muted,#f9fafb);"> |
| 279 |
<span style="display:flex;align-items:center;padding-left:10px;"> |
| 280 |
<button type="button" class="wpsubs-sort-handle" data-subscrpt-sort-handle title="<?php esc_attr_e( 'Drag to reorder', 'subscription' ); ?>" aria-label="<?php esc_attr_e( 'Drag to reorder', 'subscription' ); ?>"> |
| 281 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="16" height="16" fill="currentColor" aria-hidden="true"><circle cx="7" cy="5" r="1.5"/><circle cx="13" cy="5" r="1.5"/><circle cx="7" cy="10" r="1.5"/><circle cx="13" cy="10" r="1.5"/><circle cx="7" cy="15" r="1.5"/><circle cx="13" cy="15" r="1.5"/></svg> |
| 282 |
</button> |
| 283 |
</span> |
| 284 |
<button type="button" class="wpsubs-accordion__header wpsubs-accordion__header--chevron-start" style="flex:1 1 auto;min-width:0;background:transparent;" aria-controls="<?php echo esc_attr( $subscrpt_panel_id ); ?>" aria-expanded="<?php echo $subscrpt_is_first ? 'true' : 'false'; ?>"> |
| 285 |
<span style="display:flex;align-items:center;gap:10px;min-width:0;"> |
| 286 |
<span style="flex:0 0 auto;width:44px;height:44px;border-radius:6px;background:var(--wpsubs-surface,#fff);border:1px solid var(--wpsubs-border,#e5e7eb);overflow:hidden;display:flex;align-items:center;justify-content:center;"> |
| 287 |
<?php if ( ! empty( $product['image'] ) ) : ?> |
| 288 |
<img src="<?php echo esc_url( $product['image'] ); ?>" alt="" style="width:100%;height:100%;object-fit:cover;display:block;" /> |
| 289 |
<?php else : ?> |
| 290 |
<span class="dashicons dashicons-format-image" style="font-size:22px;width:22px;height:22px;color:var(--wpsubs-text-subtle);"></span> |
| 291 |
<?php endif; ?> |
| 292 |
</span> |
| 293 |
<span style="display:flex;flex-direction:column;min-width:0;line-height:1.35;"> |
| 294 |
<span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"><?php echo esc_html( $product['name'] ); ?></span> |
| 295 |
<span style="font-size:12px;font-weight:400;color:var(--wpsubs-text-muted);white-space:nowrap;"> |
| 296 |
<?php |
| 297 |
/* translators: %d: product ID. */ |
| 298 |
$subscrpt_desc = sprintf( __( 'ID: %d', 'subscription' ), (int) $product['id'] ); |
| 299 |
if ( ! empty( $product['is_variable'] ) ) { |
| 300 |
$subscrpt_var_count = count( $product['variations'] ); |
| 301 |
/* translators: %d: number of variations. */ |
| 302 |
$subscrpt_desc .= ' · ' . sprintf( _n( '%d variation', '%d variations', $subscrpt_var_count, 'subscription' ), $subscrpt_var_count ); |
| 303 |
} |
| 304 |
echo wp_kses_post( $subscrpt_desc ); |
| 305 |
?> |
| 306 |
</span> |
| 307 |
</span> |
| 308 |
</span> |
| 309 |
</button> |
| 310 |
<div style="display:flex;align-items:center;gap:8px;padding:0 12px 0 4px;"> |
| 311 |
<?php if ( ! empty( $product['edit_url'] ) ) : ?> |
| 312 |
<a href="<?php echo esc_url( $product['edit_url'] ); ?>" class="wpsubs-btn wpsubs-btn--muted wpsubs-btn--sm" target="_blank" rel="noopener"> |
| 313 |
<span class="dashicons dashicons-external" aria-hidden="true"></span> |
| 314 |
<?php esc_html_e( 'Edit on WooCommerce', 'subscription' ); ?> |
| 315 |
</a> |
| 316 |
<?php endif; ?> |
| 317 |
<?php if ( ! empty( $product['view_url'] ) ) : ?> |
| 318 |
<a href="<?php echo esc_url( $product['view_url'] ); ?>" class="wpsubs-btn wpsubs-btn--muted wpsubs-btn--sm" target="_blank" rel="noopener"> |
| 319 |
<span class="dashicons dashicons-visibility" aria-hidden="true"></span> |
| 320 |
<?php esc_html_e( 'Preview product', 'subscription' ); ?> |
| 321 |
</a> |
| 322 |
<?php endif; ?> |
| 323 |
<?php if ( $pro_active ) : ?> |
| 324 |
<button type="button" class="wpsubs-btn wpsubs-btn--outline wpsubs-btn--sm wpsubs-btn--danger" data-subscrpt-remove-product="<?php echo esc_attr( $product['id'] ); ?>"> |
| 325 |
<?php esc_html_e( 'Remove', 'subscription' ); ?> |
| 326 |
</button> |
| 327 |
<?php endif; ?> |
| 328 |
</div> |
| 329 |
</div> |
| 330 |
|
| 331 |
<div class="wpsubs-accordion__panel" id="<?php echo esc_attr( $subscrpt_panel_id ); ?>" style="padding:14px 16px;background:var(--wpsubs-surface-muted,#f9fafb);" <?php echo $subscrpt_is_first ? '' : 'hidden'; ?>> |
| 332 |
<?php if ( ! empty( $product['is_variable'] ) ) : ?> |
| 333 |
<div style="display:flex;flex-direction:column;gap:14px;"> |
| 334 |
<?php foreach ( $product['variations'] as $variation ) : ?> |
| 335 |
<div data-subscrpt-price-card data-product-id="<?php echo esc_attr( $product['id'] ); ?>" data-variation-id="<?php echo esc_attr( $variation['vid'] ); ?>" style="border:1px solid var(--wpsubs-border,#e5e7eb);border-radius:8px;background:var(--wpsubs-surface,#fff);"> |
| 336 |
<div style="display:flex;align-items:center;gap:10px;padding:11px 14px;border-bottom:1px solid var(--wpsubs-border,#e5e7eb);"> |
| 337 |
<span class="dashicons dashicons-image-filter" style="flex:0 0 auto;font-size:16px;width:16px;height:16px;color:var(--wpsubs-text-subtle);"></span> |
| 338 |
<strong style="font-size:13px;color:var(--wpsubs-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"><?php echo esc_html( $variation['name'] ); ?></strong> |
| 339 |
<span class="wpsubs-toolbar__spacer"></span> |
| 340 |
<?php $subscrpt_price_actions(); ?> |
| 341 |
<?php if ( $pro_active ) : ?> |
| 342 |
<button type="button" class="wpsubs-btn wpsubs-btn--outline wpsubs-btn--sm wpsubs-btn--danger" data-subscrpt-remove-variation data-oid="<?php echo esc_attr( $product['id'] ); ?>" data-vid="<?php echo esc_attr( $variation['vid'] ); ?>"> |
| 343 |
<?php esc_html_e( 'Remove', 'subscription' ); ?> |
| 344 |
</button> |
| 345 |
<?php endif; ?> |
| 346 |
</div> |
| 347 |
<?php |
| 348 |
$subscrpt_render_rows( |
| 349 |
$variation['rows'], |
| 350 |
array( |
| 351 |
'enabled' => ! empty( $variation['one_time_on'] ), |
| 352 |
'regular' => $variation['ot_regular'], |
| 353 |
'offer' => $variation['ot_offer'], |
| 354 |
) |
| 355 |
); |
| 356 |
?> |
| 357 |
</div> |
| 358 |
<?php endforeach; ?> |
| 359 |
</div> |
| 360 |
<?php else : ?> |
| 361 |
<div data-subscrpt-price-card data-product-id="<?php echo esc_attr( $product['id'] ); ?>" style="border:1px solid var(--wpsubs-border,#e5e7eb);border-radius:8px;background:var(--wpsubs-surface,#fff);"> |
| 362 |
<div style="display:flex;align-items:center;gap:8px;padding:11px 14px;border-bottom:1px solid var(--wpsubs-border,#e5e7eb);"> |
| 363 |
<strong style="font-size:13px;color:var(--wpsubs-text);"><?php esc_html_e( 'Pricing', 'subscription' ); ?></strong> |
| 364 |
<span class="wpsubs-toolbar__spacer"></span> |
| 365 |
<?php $subscrpt_price_actions(); ?> |
| 366 |
</div> |
| 367 |
<?php $subscrpt_render_rows( $product['rows'] ); ?> |
| 368 |
</div> |
| 369 |
<?php $subscrpt_render_onetime( $product ); ?> |
| 370 |
<?php $subscrpt_render_user_cancel( $product ); ?> |
| 371 |
<?php endif; ?> |
| 372 |
</div> |
| 373 |
</div> |
| 374 |
<?php $subscrpt_is_first = false; ?> |
| 375 |
<?php endforeach; ?> |
| 376 |
</div> |
| 377 |
|
| 378 |
<p data-subscrpt-browse-empty style="display:none;padding:20px 4px;color:var(--wpsubs-text-subtle);font-size:13px;text-align:center;"> |
| 379 |
<?php esc_html_e( 'No products match your search.', 'subscription' ); ?> |
| 380 |
</p> |
| 381 |
|
| 382 |
<div data-subscrpt-browse-pager style="margin-top:14px;"></div> |
| 383 |
</div> |
| 384 |
|
| 385 |
<?php endif; ?> |
| 386 |
|
| 387 |
</div> |
| 388 |
|
| 389 |
<?php |
| 390 |
require __DIR__ . '/modal-add-product.php'; |
| 391 |
require __DIR__ . '/modal-bulk-price.php'; |
| 392 |
|