Countdown timer for Flatsome Product
Show countdown for products that have a discount start and end date
One of the annoying shortcomings of the FlatSome template is not showing the countdown until the end of the product discount
which can be considered as a big shortcoming for Flatsome thems
You can use the following code to fix this problem
add_action('woocommerce_single_product_summary', 'custom_sale_end_timer', 25);
function custom_sale_end_timer() {
global $product;
$sale_dates = array();
$countdown_display = false;
// Pre-fetch sale dates for variations if it's a variable product
if ($product->is_type('variable')) {
$variation_ids = $product->get_visible_children(); // Get visible variation IDs
foreach ($variation_ids as $variation_id) {
$variation = wc_get_product($variation_id);
if ($variation->is_on_sale()) {
$date_on_sale_from = $variation->get_date_on_sale_from();
$date_on_sale_to = $variation->get_date_on_sale_to();
if (!empty($date_on_sale_from) || !empty($date_on_sale_to)) {
$sale_dates[$variation_id] = array(
'from' => $date_on_sale_from ? $date_on_sale_from->getTimestamp() : '',
'to' => $date_on_sale_to ? $date_on_sale_to->getTimestamp() : '',
);
// If there's at least one variation with a sale end date, enable countdown display
$countdown_display = true;
}
}
}
// Pass the sale dates to the frontend JavaScript
wc_enqueue_js("
var variationSaleDates = " . json_encode($sale_dates) . ";
var countdownInterval;
jQuery(document).ready(function($) {
function updateCountdown(saleEndDate) {
var now = new Date().getTime();
var timeLeft = (saleEndDate - now) / 1000;
var days = Math.floor(timeLeft / 86400);
var hours = Math.floor((timeLeft % 86400) / 3600);
var minutes = Math.floor((timeLeft % 3600) / 60);
var seconds = Math.floor(timeLeft % 60);
if (timeLeft > 0) {
$('.custom-sale-countdown .days .value').text(days.toString().padStart(2, '0'));
$('.custom-sale-countdown .hours .value').text(hours.toString().padStart(2, '0'));
$('.custom-sale-countdown .mins .value').text(minutes.toString().padStart(2, '0'));
$('.custom-sale-countdown .secs .value').text(seconds.toString().padStart(2, '0'));
} else {
$('.custom-sale-countdown .countdown').text('Sale Ended');
clearInterval(countdownInterval);
}
}
function clearPreviousCountdown() {
if (countdownInterval) {
clearInterval(countdownInterval);
}
}
$('form.variations_form').on('found_variation', function(event, variation) {
var variationId = variation.variation_id;
if (variationSaleDates[variationId] && variationSaleDates[variationId].to) {
var saleEndDate = new Date(variationSaleDates[variationId].to * 1000);
clearPreviousCountdown();
updateCountdown(saleEndDate);
countdownInterval = setInterval(function() {
updateCountdown(saleEndDate);
}, 1000);
}
});
// if no variation selected, use the first available variation end date if it exists
var firstVariationId = Object.keys(variationSaleDates)[0];
if (firstVariationId && variationSaleDates[firstVariationId].to) {
var saleEndDate = new Date(variationSaleDates[firstVariationId].to * 1000);
clearPreviousCountdown();
updateCountdown(saleEndDate);
countdownInterval = setInterval(function() {
updateCountdown(saleEndDate);
}, 1000);
}
});
");
// Display countdown HTML structure, always visible
echo '<div class="custom-sale-countdown" style="display: block;">
<h3>Sale ends in</h3>
<div class="countdown">
<span class="days">
<span class="value">00</span>
<span class="countdown-label">Days</span>
</span>
:
<span class="hours">
<span class="value">00</span>
<span class="countdown-label">Hours</span>
</span>
:
<span class="mins">
<span class="value">00</span>
<span class="countdown-label">Min</span>
</span>
:
<span class="secs">
<span class="value">00</span>
<span class="countdown-label">Sec</span>
</span>
</div>
</div>';
} elseif ($product->is_on_sale() && $product->get_date_on_sale_to()) {
// For simple products, display countdown always
$sale_end_date = $product->get_date_on_sale_to()->getTimestamp();
wc_enqueue_js("
jQuery(document).ready(function($) {
var saleEndDate = new Date($sale_end_date * 1000);
function updateCountdown() {
var now = new Date().getTime();
var timeLeft = (saleEndDate - now) / 1000;
var days = Math.floor(timeLeft / 86400);
var hours = Math.floor((timeLeft % 86400) / 3600);
var minutes = Math.floor((timeLeft % 3600) / 60);
var seconds = Math.floor(timeLeft % 60);
if (timeLeft > 0) {
$('.custom-sale-countdown .days .value').text(days.toString().padStart(2, '0'));
$('.custom-sale-countdown .hours .value').text(hours.toString().padStart(2, '0'));
$('.custom-sale-countdown .mins .value').text(minutes.toString().padStart(2, '0'));
$('.custom-sale-countdown .secs .value').text(seconds.toString().padStart(2, '0'));
} else {
$('.custom-sale-countdown .countdown').text('Sale Ended');
clearInterval(countdownInterval);
}
}
// Immediately update countdown once
updateCountdown();
var countdownInterval = setInterval(updateCountdown, 1000);
});
");
// Display countdown HTML structure
echo '<div class="custom-sale-countdown">
<h3>Sale ends in</h3>
<div class="countdown">
<span class="days">
<span class="value">00</span>
<span class="countdown-label">Days</span>
</span>
:
<span class="hours">
<span class="value">00</span>
<span class="countdown-label">Hours</span>
</span>
:
<span class="mins">
<span class="value">00</span>
<span class="countdown-label">Min</span>
</span>
:
<span class="secs">
<span class="value">00</span>
<span class="countdown-label">Sec</span>
</span>
</div>
</div>';
}
}
Add the following codes to the customization section and custom css
.custom-sale-countdown {
text-align: left;
margin-bottom: 20px;
font-weight: bold;
color: #333;
}
.custom-sale-countdown h3 {
font-size: 18px;
margin-bottom: 10px;
}
.custom-sale-countdown .countdown {
display: flex;
justify-content: flex-start;
gap: 10px;
font-size: 32px;
letter-spacing: 2px;
}.custom-sale-countdown .countdown span {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 5px 10px;
background-color: #f8f9fa;
border-radius: 5px;
color: #000;
font-size: 24px;
border: none; /* Remove the border */
}
.custom-sale-countdown .countdown span .countdown-label {
font-size: 12px; /* Smaller label size */
font-weight: normal;
text-transform: uppercase;
color: #666;
margin-top: -15px;
}