‘Featured Dance Chart’,
‘subtitle’ => ‘Add your own links in settings later’,
‘url’ => ‘https://open.spotify.com/’,
‘service’ => ‘Spotify’,
],
[
‘title’ => ‘YouTube Dance Picks’,
‘subtitle’ => ‘Perfect for socials & practice’,
‘url’ => ‘https://www.youtube.com/’,
‘service’ => ‘YouTube’,
],
];
add_option(‘w2d_featured_charts’, $default);
}
$this->register_cpt_and_tax();
flush_rewrite_rules();
}
public function register_cpt_and_tax() {
// Custom Post Type: Playlists
register_post_type(self::CPT, [
‘labels’ => [
‘name’ => ‘Playlists’,
‘singular_name’ => ‘Playlist’,
],
‘public’ => true,
‘has_archive’ => false,
‘show_in_rest’ => true,
‘menu_icon’ => ‘dashicons-playlist-audio’,
‘supports’ => [‘title’, ‘editor’, ‘author’],
‘rewrite’ => [‘slug’ => ‘playlists’],
]);
// Taxonomy: Dance Style
register_taxonomy(‘w2d_dance_style’, [self::CPT], [
‘labels’ => [‘name’ => ‘Dance Styles’],
‘public’ => true,
‘show_in_rest’ => true,
‘hierarchical’ => false,
‘rewrite’ => [‘slug’ => ‘dance-style’],
]);
// Taxonomy: Service
register_taxonomy(‘w2d_playlist_service’, [self::CPT], [
‘labels’ => [‘name’ => ‘Services’],
‘public’ => true,
‘show_in_rest’ => true,
‘hierarchical’ => false,
‘rewrite’ => [‘slug’ => ‘playlist-service’],
]);
}
public function enqueue_assets() {
// Only load when shortcode exists on the page
if (!is_singular() && !is_page()) return;
global $post;
if (!$post || stripos($post->post_content ?? ”, ‘[w2d_dance_charts’) === false) return;
wp_register_style(‘w2d-dance-css’, false, [], ‘1.0.0’);
wp_enqueue_style(‘w2d-dance-css’);
$css = ”
.w2d-dance-wrap{max-width:1100px;margin:0 auto;padding:18px}
.w2d-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px}
.w2d-card{
grid-column:span 12;
background:rgba(20,20,24,.72);
border:1px solid rgba(255,255,255,.08);
border-radius:18px;
box-shadow:0 12px 30px rgba(0,0,0,.35);
padding:16px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
@media(min-width:820px){
.w2d-card.half{grid-column:span 6}
.w2d-card.third{grid-column:span 4}
}
.w2d-h1{font-size:28px;line-height:1.2;margin:0 0 6px 0}
.w2d-sub{opacity:.85;margin:0 0 10px 0}
.w2d-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.w2d-pill{display:inline-flex;gap:8px;align-items:center;border:1px solid rgba(255,255,255,.10);padding:8px 12px;border-radius:999px;background:rgba(255,255,255,.04)}
.w2d-btn{
border:none;cursor:pointer;border-radius:999px;
padding:10px 14px;
background:rgba(70,130,255,.95);
color:#fff;font-weight:600;
box-shadow:0 10px 20px rgba(0,0,0,.25);
}
.w2d-btn.secondary{background:rgba(255,255,255,.10);color:#fff;border:1px solid rgba(255,255,255,.10)}
.w2d-btn:disabled{opacity:.55;cursor:not-allowed}
.w2d-input,.w2d-select,.w2d-textarea{
width:100%;
background:rgba(255,255,255,.06);
border:1px solid rgba(255,255,255,.10);
border-radius:14px;
padding:12px 12px;
color:#fff;
outline:none;
}
.w2d-textarea{min-height:96px;resize:vertical}
.w2d-label{display:block;margin:10px 0 6px 0;opacity:.9;font-weight:600}
.w2d-muted{opacity:.75;font-size:13px}
.w2d-embed iframe{width:100%;min-height:152px;border:0;border-radius:14px;overflow:hidden}
.w2d-topbar{display:flex;gap:10px;flex-wrap:wrap;justify-content:space-between;align-items:center}
.w2d-search{flex:1;min-width:220px}
.w2d-like{display:inline-flex;gap:8px;align-items:center}
.w2d-like-count{opacity:.85}
.w2d-hr{height:1px;background:rgba(255,255,255,.08);margin:12px 0}
.w2d-note{padding:10px 12px;border-radius:14px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08)}
“;
wp_add_inline_style(‘w2d-dance-css’, $css);
wp_register_script(‘w2d-dance-js’, false, [‘jquery’], ‘1.0.0’, true);
wp_enqueue_script(‘w2d-dance-js’);
$data = [
‘ajaxurl’ => admin_url(‘admin-ajax.php’),
‘nonce’ => wp_create_nonce(self::NONCE_ACTION),
‘loggedIn’ => is_user_logged_in(),
];
wp_add_inline_script(‘w2d-dance-js’, ‘window.W2D_DANCE=’ . wp_json_encode($data) . ‘;’);
$js = <<‘+msg+’
‘);
}
// Client-side filter
$(document).on(‘input’, ‘#w2dPlaylistSearch’, function(){
var q = ($(this).val() || ”).toLowerCase().trim();
$(‘.w2d-playlist-card’).each(function(){
var t = ($(this).data(‘search’) || ”).toLowerCase();
$(this).toggle(!q || t.indexOf(q) !== -1);
});
});
// Submit playlist
$(document).on(‘submit’, ‘#w2dPlaylistForm’, function(e){
e.preventDefault();
var $form = $(this);
var $msg = $(‘#w2dFormMsg’);
var payload = $form.serializeArray();
payload.push({name:’action’, value:’w2d_submit_playlist’});
payload.push({name:’nonce’, value: (window.W2D_DANCE ? W2D_DANCE.nonce : ”) });
$form.find(‘button[type=”submit”]’).prop(‘disabled’, true);
$.post((window.W2D_DANCE ? W2D_DANCE.ajaxurl : ”), payload)
.done(function(res){
if(res && res.success){
showMsg($msg, res.data.message, true);
$form[0].reset();
}else{
showMsg($msg, (res && res.data && res.data.message) ? res.data.message : ‘Something went wrong.’, false);
}
})
.fail(function(){
showMsg($msg, ‘Request failed. Please try again.’, false);
})
.always(function(){
$form.find(‘button[type=”submit”]’).prop(‘disabled’, false);
});
});
// Like playlist
$(document).on(‘click’, ‘.w2dLikeBtn’, function(){
var $btn = $(this);
var postId = $btn.data(‘id’);
if(!postId) return;
$btn.prop(‘disabled’, true);
$.post((window.W2D_DANCE ? W2D_DANCE.ajaxurl : ”), {
action: ‘w2d_like_playlist’,
nonce: (window.W2D_DANCE ? W2D_DANCE.nonce : ”),
post_id: postId
}).done(function(res){
if(res && res.success){
$btn.closest(‘.w2d-like’).find(‘.w2d-like-count’).text(res.data.likes);
}
}).always(function(){
$btn.prop(‘disabled’, false);
});
});
})(jQuery);
JS;
wp_add_inline_script(‘w2d-dance-js’, $js);
}
private function get_featured_charts() {
$charts = get_option(‘w2d_featured_charts’, []);
return is_array($charts) ? $charts : [];
}
private function get_like_count($post_id) {
return (int) get_post_meta($post_id, ‘_w2d_likes’, true);
}
private function render_embed($url) {
$url = esc_url($url);
if (!$url) return ”;
// Try WordPress oEmbed first
$embed = wp_oembed_get($url);
if ($embed) {
return ‘‘;
}
// Fallback: link only
return ‘‘;
}
public function shortcode() {
ob_start();
$charts = $this->get_featured_charts();
?>
Dance
Explore featured dance charts, then share the playlists that get your community moving.
🎧 Charts
🕺 Community Playlists
❤️ Like & discover
Featured charts
Starter set shown below. Later we can add an admin UI and/or automatic chart imports.
No featured charts yet.
self::CPT,
‘post_status’ => ‘publish’,
‘posts_per_page’ => 12,
‘orderby’ => ‘date’,
‘order’ => ‘DESC’,
]);
if (!$q->have_posts()):
?>
No playlists yet — be the first to share one.
have_posts()): $q->the_post();
$pid = get_the_ID();
$url = get_post_meta($pid, ‘_w2d_url’, true);
$bpm = get_post_meta($pid, ‘_w2d_bpm’, true);
$likes = $this->get_like_count($pid);
$services = wp_get_post_terms($pid, ‘w2d_playlist_service’, [‘fields’ => ‘names’]);
$styles = wp_get_post_terms($pid, ‘w2d_dance_style’, [‘fields’ => ‘names’]);
$search_blob = strtolower(get_the_title() . ‘ ‘ . implode(‘ ‘, (array)$services) . ‘ ‘ . implode(‘ ‘, (array)$styles));
?>
by ·
Service:
Style:
BPM:
render_embed($url); ?>
