public function add_buy_together_menu() {
add_menu_page(
'Buy Together',
'Buy Together',
'manage_woocommerce',
'sk-buy-together',
[$this, 'render_admin_page'],
'dashicons-cart',
56
);
}
public function admin_page_assets($hook) {
if ($hook !== 'toplevel_page_sk-buy-together') return;
wp_enqueue_script('jquery');
wp_enqueue_style('skbt-admin-page', false);
wp_add_inline_style('skbt-admin-page', '
.skbt-wrap{max-width:1100px}
.skbt-card{background:#fff;border:1px solid #e5e5e5;border-radius:14px;padding:14px;margin-top:12px}
.skbt-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:900px){.skbt-grid{grid-template-columns:1fr}}
.skbt-input{width:100%;padding:10px 12px;border:1px solid #ccd0d4;border-radius:10px}
.skbt-results{border:1px solid #ccd0d4;border-radius:12px;overflow:auto;max-height:260px;margin-top:8px}
.skbt-item{padding:10px 12px;border-bottom:1px solid #eee;cursor:pointer}
.skbt-item:hover{background:#f6f7f7}
.skbt-chip{display:inline-flex;gap:8px;align-items:center;border:1px solid #ddd;border-radius:16px;padding:6px 10px;margin:5px;background:#fff}
.skbt-chip button{border:none;background:transparent;color:#b32d2e;font-weight:700;cursor:pointer}
.skbt-btn{padding:10px 12px;border-radius:12px;border:0;cursor:pointer;font-weight:700}
.skbt-btn-primary{background:#111;color:#fff}
.skbt-muted{color:#666;font-size:12px}
.skbt-row{display:flex;gap:10px;align-items:center;justify-content:space-between;flex-wrap:wrap}
');
wp_enqueue_script('skbt-admin-page', false, ['jquery'], '1.0', true);
wp_add_inline_script('skbt-admin-page', '
(function($){
var ajaxurl = "'.esc_js(admin_url('admin-ajax.php')).'";
var nonce = "'.esc_js(wp_create_nonce('skbt_admin')).'";
function searchProducts(q, $box){
if(q.length<2){ $box.empty(); return; }
$.post(ajaxurl,{action:"sk_bt_search_products", q:q, nonce:"'.esc_js(wp_create_nonce('skbt_ajax')).'"},function(res){
$box.empty();
if(!res || !res.success || !res.data || !res.data.length){
$box.html("
No results
");
return;
}
res.data.forEach(function(p){
var txt = p.name+" (ID: "+p.id+")"+(p.sku?(" — SKU: "+p.sku):"");
$box.append($("
",{class:"skbt-item"}).text(txt).data("pid",p.id));
});
});
}
var mainId = 0;
$("#skbt_main_search").on("input", function(){
searchProducts($(this).val().trim(), $("#skbt_main_results"));
});
$("#skbt_add_search").on("input", function(){
searchProducts($(this).val().trim(), $("#skbt_add_results"));
});
$(document).on("click","#skbt_main_results .skbt-item", function(){
mainId = parseInt($(this).data("pid"),10);
$("#skbt_selected_main").text("Selected Main Product ID: "+mainId);
loadLinks();
});
function loadLinks(){
if(!mainId) return;
$("#skbt_linked").html("Loading...
");
$.post(ajaxurl,{action:"skbt_admin_get_links", nonce:nonce, main_id:mainId}, function(res){
if(!res || !res.success){ $("#skbt_linked").html("Failed to load
"); return; }
renderLinked(res.data || []);
});
}
function renderLinked(list){
var $w = $("#skbt_linked").empty();
if(!list.length){ $w.html("No linked products.
"); return; }
list.forEach(function(p){
var txt = p.name+" (ID: "+p.id+")"+(p.sku?(" — SKU: "+p.sku):"");
var $c = $(" ",{class:"skbt-chip","data-id":p.id}).append(
$(" ").text(txt),
$(" ",{type:"button"}).text("×")
);
$w.append($c);
});
}
// Add from search list
$(document).on("click","#skbt_add_results .skbt-item", function(){
if(!mainId){ alert("Select Main Product first"); return; }
var id = parseInt($(this).data("pid"),10);
// add chip locally
var exists = $("#skbt_linked .skbt-chip[data-id=\'"+id+"\']").length>0;
if(exists) return;
$("#skbt_linked").append(
$(" ",{class:"skbt-chip","data-id":id}).append(
$(" ").text($(this).text()),
$(" ",{type:"button"}).text("×")
)
);
});
// Remove chip
$(document).on("click","#skbt_linked .skbt-chip button", function(){
$(this).closest(".skbt-chip").remove();
});
// Save
$("#skbt_save").on("click", function(){
if(!mainId){ alert("Select Main Product first"); return; }
var ids = [];
$("#skbt_linked .skbt-chip").each(function(){ ids.push(parseInt($(this).data("id"),10)); });
$("#skbt_status").text("Saving...");
$.post(ajaxurl,{action:"skbt_admin_save_links", nonce:nonce, main_id:mainId, ids:ids}, function(res){
if(res && res.success){ $("#skbt_status").text("Saved ✅"); }
else { $("#skbt_status").text("Save failed"); }
});
});
})(jQuery);
');
}
public function render_admin_page() {
echo '';
echo '
Buy Together ';
echo '
Manage Buy Together links without opening each product edit screen.
';
echo '
';
echo '
';
echo '
1) Select Main Product ';
echo '
';
echo '
';
echo '
No main product selected
';
echo '
';
echo '
';
echo '
2) Add Together Products ';
echo '
';
echo '
';
echo '
';
echo '
';
echo '
';
echo '
';
echo '
Linked Products ';
echo '
';
echo ' Save ';
echo ' ';
echo '
';
echo '
';
echo '
';
echo '
';
echo '
';
}
public function ajax_admin_get_links() {
if (!current_user_can('manage_woocommerce')) wp_send_json_error();
$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
if (!wp_verify_nonce($nonce, 'skbt_admin')) wp_send_json_error();
$main_id = isset($_POST['main_id']) ? absint($_POST['main_id']) : 0;
if (!$main_id) wp_send_json_success([]);
$ids = get_post_meta($main_id, self::META_KEY, true);
if (!is_array($ids)) $ids = array_filter(array_map('absint', explode(',', (string)$ids)));
$out = [];
foreach ($ids as $id) {
$p = wc_get_product($id);
if (!$p) continue;
$out[] = ['id'=>$p->get_id(), 'name'=>$p->get_name(), 'sku'=>$p->get_sku()];
}
wp_send_json_success($out);
}
public function ajax_admin_save_links() {
if (!current_user_can('manage_woocommerce')) wp_send_json_error();
$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
if (!wp_verify_nonce($nonce, 'skbt_admin')) wp_send_json_error();
$main_id = isset($_POST['main_id']) ? absint($_POST['main_id']) : 0;
$ids = isset($_POST['ids']) ? (array) $_POST['ids'] : [];
$ids = array_values(array_unique(array_filter(array_map('absint', $ids))));
if (!$main_id) wp_send_json_error();
update_post_meta($main_id, self::META_KEY, $ids);
wp_send_json_success(['saved'=>true, 'count'=>count($ids)]);
}
Products Archive - Page 20 of 203 - Sarkkart
“Kroozer Strobe Light Kit” has been added to your basket.
View basket
50 % Off
Adjustable carbon-fiber finish rear wheel mudguard made with a strong aluminium alloy bracket. Compatible with motorcycles, electric bikes, electric scooters, and scooties. Reduces mud and water splash, protects suspension, and adds a sporty premium look. Lightweight, durable, and easy to install.
59 % Off
Adjustable carbon-fiber finish rear wheel mudguard made with a strong aluminium alloy bracket. Compatible with motorcycles, electric bikes, electric scooters, and scooties. Reduces mud and water splash, protects suspension, and adds a sporty premium look. Lightweight, durable, and easy to install.
“Experience the ultimate style and safety with the limited edition Vega-Bolt DX Crown helmet.
9 % Off
10 % Off
14 % Off
The Vega Sonic Full Face Sports Helmet in Black and Grey features a big spoiler and dual visor, providing superior protection and style. ISI & DOT certified, this helmet ensures maximum safety and comfort for every ride.
14 % Off
The Vega Sonic Full Face Sports Helmet in Black and Grey features a big spoiler and dual visor, providing superior protection and style. ISI & DOT certified, this helmet ensures maximum safety and comfort for every ride.
6 % Off
Steelbird SBH-25 SHARP Full Face Helmet
ISI Certified : Ensures high safety standards for reliable protection.
Glossy Black Finish : Sleek and stylish design for a premium look.
Clear Visor : Provides enhanced visibility and eye protection.
Comfortable Fit : Designed for all-day comfort during rides.
Durable Construction : Built to last with high-quality materials.
10 % Off
Step up your safety with the KTM Duke 160 crash guard by Sarkkart. This Gen3-specific guard features a steel build, black slider for crash protection, and seamless bolt-on mounting. Every ride feels protected, whether you tackle city roads or rugged trails.
Our Toughest Crash Guard – 25mm Outer Tube, 3mm Wall for Maximum Impact Resistance
Direct fit for Gen3 Duke 160 (2024+)
Black powder-coated finish and CNC precision
Sliding impact absorbers safeguard engine & tank
All mounting hardware included, easy install
Stylish upgrade enhances aggression & protection
10 % Off
Step up your safety with the KTM Duke 200 crash guard by Sarkkart. This Gen3-specific guard features a steel build, black slider for crash protection, and seamless bolt-on mounting. Every ride feels protected, whether you tackle city roads or rugged trails.
Our Toughest Crash Guard – 25mm Outer Tube, 3mm Wall for Maximum Impact Resistance
Direct fit for Gen3 Duke 200 (2024+)
Black powder-coated finish and CNC precision
Sliding impact absorbers safeguard engine & tank
All mounting hardware included, easy install
Stylish upgrade enhances aggression & protection
10 % Off
Step up your safety with the KTM Duke 250 crash guard by Sarkkart. This Gen3-specific guard features a steel build, black slider for crash protection, and seamless bolt-on mounting. Every ride feels protected, whether you tackle city roads or rugged trails.
Our Toughest Crash Guard – 25mm Outer Tube, 3mm Wall for Maximum Impact Resistance
Direct fit for Gen3 Duke 250 (2024+)
Black powder-coated finish and CNC precision
Sliding impact absorbers safeguard engine & tank
All mounting hardware included, easy install
Stylish upgrade enhances aggression & protection
55 % Off
Premium SUOMY SU-23 Motorcycle Riding Gloves with hard-knuckle protection, non-slip microfiber palm, touchscreen-enabled fingertips, breathable fabric, and anti-fall PVC shell. Designed for daily riding, touring, and outdoor sports with superior comfort, grip, and safety.
Scroll To Top