Elementor #3545
// === V.S.O.P. Wall Shortcode === //
function vsop_wall_shortcode($atts){
$atts = shortcode_atts([
‘per_page’ => 8,
‘columns’ => 3,
‘progress_color’ => ‘#000000’,
‘card_bg’ => ‘#ffffff’,
], $atts, ‘vsop_wall’);
ob_start(); ?>
<div class=”vsop-elementor- container”>
<div class=”vsop-search-container” style=”text-align:center; margin-bottom:30px;”>
<input type=”text” id=”vsop-search-input” placeholder=”Search member by name…” style=”padding:10px;width: 250px;border-radius:5px; border:1px solid #ccc;”>
<button id=”vsop-search-btn” style=”background:#000;color:# fff;padding:10px 15px;border:none;border- radius:5px;”>Search</button>
<button id=”vsop-random-btn” style=”margin-left:10px; background:#555;color:#fff; padding:10px 15px;border-radius:5px;”>
Random</button>
Random</button> </div>
<div id=”vsop-grid” class=”vsop-grid” style=”display:grid;grid- template-columns:repeat(<?php echo esc_attr($atts[‘columns’]); ?>,1fr);gap:20px;”></div>
<div style=”text-align:center; margin-top:20px;”>
<button id=”vsop-load-more” style=”background:#000;color:# fff;padding:10px 25px;border:none;border- radius:5px;display:none;”>Load More</button>
</div>
</div>
<script>
jQuery(document).ready( function($){
let page=1,loading=false, lastSearch=”,randomMode= false;
function loadMembers(reset=false){
if(loading) return; loading=true;
if(reset){ $(‘#vsop-grid’).html(”); page=1; }
$(‘#vsop-load-more’).hide();
$.ajax({
url: ‘<?php echo admin_url(‘admin-ajax.php’); ?>’,
type: ‘GET’,
data: { action:’vsop_load_members’, page:page, search:lastSearch, random:randomMode?1:0 },
success: function(res){
if(reset){ $(‘#vsop-grid’).html(res); } else { $(‘#vsop-grid’).append(res); }
if($.trim(res).length>0){ $(‘#vsop-load-more’).show(); page++; }
else{ $(‘#vsop-load-more’).hide(); }
animateProgressBars();
loading=false;
}
});
}
$(‘#vsop-search-btn’).on(‘ click’, function(){ lastSearch=$(‘#vsop-search- input’).val(); randomMode=false; loadMembers(true); });
$(‘#vsop-random-btn’).on(‘ click’, function(){ lastSearch=”; randomMode=true; loadMembers(true); });
$(‘#vsop-load-more’).on(‘ click’, function(){ loadMembers(); });
$(window).on(‘scroll’, function(){ if($(window).scrollTop() + $(window).height() >= $(document).height() – 200) loadMembers(); });
function animateProgressBars(){
$(‘.vsop-progress-fill’).each( function(){
var bar=$(this),percent=bar.data(‘ percent’);
if(bar.visible(true) && !bar.hasClass(‘animated’)){
bar.addClass(‘animated’); bar.animate({width:percent+’%’ },1200);
}
});
}
$.fn.visible=function(partial) { var $t=$(this),$w=$(window), viewTop=$w.scrollTop(), viewBottom=viewTop+$w.height() ,_top=$t.offset().top,_bottom= _top+$t.height(),compareTop= partial===true?_bottom:_top, compareBottom=partial===true?_ top:_bottom; return ((compareBottom<=viewBottom)&& (compareTop>=viewTop)); }
});
</script>
<style>
.vsop-grid .vsop-card{opacity:0; transform:translateY(20px); transition:all 0.6s ease;background:<?php echo esc_attr($atts[‘card_bg’]); ?>;border-radius:10px;padding: 15px;text-align:center;box- shadow:0 2px 5px rgba(0,0,0,0.1);}
.vsop-grid .vsop-card.animated{opacity:1; transform:translateY(0);}
.vsop-progress-fill{ background:<?php echo esc_attr($atts[‘progress_ color’]); ?>;height:10px;width:0;border- radius:5px;}
</style>
<?php
return ob_get_clean();
}
add_shortcode(‘vsop_wall’,’ vsop_wall_shortcode’);
// === AJAX loader backend (reuse from previous code) === //
add_action(‘wp_ajax_vsop_load_ members’,’vsop_load_members’);
add_action(‘wp_ajax_nopriv_ vsop_load_members’,’vsop_load_ members’);
function vsop_load_members(){
$paged=isset($_GET[‘page’])? intval($_GET[‘page’]):1;
$search=isset($_GET[‘search’]) ?sanitize_text_field($_GET[‘ search’]):”;
$random=isset($_GET[‘random’]) ?intval($_GET[‘random’]):0;
$per_page=8; $offset=($paged-1)*$per_page;
$args=[‘role’=>’subscriber’,’ meta_key’=>’vsop_approved’,’ meta_value’=>’1′,’number’=>$ per_page,’offset’=>$offset];
if($search!==”){$args[‘ search’]=’*’.$search.’*’;$ args[‘search_columns’]=[‘ display_name’];}
if($random){$args[‘orderby’]=’ rand’;$args[‘number’]=1;}
$users=get_users($args);
foreach($users as $user){
$profile_image=get_user_meta($ user->ID,’profile_image’,true) ;
$bio=get_user_meta($user->ID,’ description’,true);
$goal=floatval(get_user_meta($ user->ID,’vsop_goal_amount’, true));
$raised=floatval(get_user_ meta($user->ID,’vsop_amount_ raised’,true));
$percent=($goal>0)?min(100,($ raised/$goal)*100):0;
$donate_link=site_url(‘/ support/?user_id=’.$user->ID);
echo ‘<div class=”vsop-card”>’;
echo ‘<img src=”‘.esc_url($profile_image) .'” alt=”‘.esc_attr($user-> display_name).'” style=”width:100px;height: 100px;border-radius:50%; object-fit:cover;”>’;
echo ‘<h3>’.esc_html($user-> display_name).'</h3>’;
echo ‘<p>’.esc_html($bio).'</p>’;
echo ‘<div class=”vsop-progress-bar” style=”background:#eee;border- radius:10px;overflow:hidden; margin:10px 0;”>’;
echo ‘<div class=”vsop-progress-fill” data-percent=”‘.$percent.'”></ div></div>’;
echo ‘<small><strong>$’.number_ format($raised,2).'</strong> raised of $’.number_format($goal,2).'</ small><br><br>’;
echo ‘<a href=”‘.esc_url($donate_link). ‘” class=”button” style=”background:#000;color:# fff;padding:10px 20px;border-radius:5px;text- decoration:none;”>Support</a>’ ;
echo ‘</div>’;
}
wp_die();
}