Implementacija funkcionalnosti brezplačnega dnevnega vrtenja
Deploy to Test Server / deploy (push) Failing after 9s Details

This commit is contained in:
Mark Poljanšek 2025-06-22 21:58:51 +02:00
parent 175f79e303
commit d77be150d9
7 changed files with 366 additions and 149 deletions

View File

@ -193,6 +193,29 @@ if (
} }
} }
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_wheel_settings') {
if (check_admin_referer('wheel_edit_settings_nonce')) {
global $wpdb;
$wheels_table = $wpdb->prefix . 'wof_wheels';
$wheel_id = isset($_POST['wheel_id']) ? intval($_POST['wheel_id']) : 0;
$has_daily_spin = isset($_POST['has_daily_spin']) ? 1 : 0;
if ($wheel_id > 0) {
$wpdb->update(
$wheels_table,
['has_daily_spin' => $has_daily_spin],
['id' => $wheel_id],
['%d'],
['%d']
);
echo '<div class="notice notice-success is-dismissible"><p>' . __('Wheel settings updated!', 'wheel-of-fortune') . '</p></div>';
// Osvežimo podatke o kolesu po shranjevanju
$wheel = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wheels_table WHERE id = %d", $wheel_id), ARRAY_A);
}
}
}
global $wpdb; global $wpdb;
$wheels_table = $wpdb->prefix . 'wof_wheels'; $wheels_table = $wpdb->prefix . 'wof_wheels';
$prizes_table = $wpdb->prefix . 'wheel_prizes'; $prizes_table = $wpdb->prefix . 'wheel_prizes';
@ -231,6 +254,28 @@ if (class_exists('WooCommerce')) {
<hr class="wp-header-end"> <hr class="wp-header-end">
<div class="wheel-card">
<h2><?php _e('Wheel Settings', 'wheel-of-fortune'); ?></h2>
<form method="post" action="">
<?php wp_nonce_field('wheel_edit_settings_nonce'); ?>
<input type="hidden" name="action" value="update_wheel_settings">
<input type="hidden" name="wheel_id" value="<?php echo esc_attr($wheel_id); ?>">
<table class="form-table">
<tr>
<th scope="row"><?php _e('Daily Free Spin', 'wheel-of-fortune'); ?></th>
<td>
<label for="has_daily_spin">
<input name="has_daily_spin" type="checkbox" id="has_daily_spin" value="1" <?php checked(isset($wheel['has_daily_spin']) && $wheel['has_daily_spin'], 1); ?>>
<?php _e('Enable 1 free daily spin for all logged-in users on this wheel.', 'wheel-of-fortune'); ?>
</label>
<p class="description"><?php _e('If checked, users can spin this wheel once per day for free, regardless of their purchased spins.', 'wheel-of-fortune'); ?></p>
</td>
</tr>
</table>
<p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e('Save Wheel Settings', 'wheel-of-fortune'); ?>"></p>
</form>
</div>
<div class="wheel-card"> <div class="wheel-card">
<h2><?php echo esc_html__('Prizes for this Wheel', 'wheel-of-fortune'); ?></h2> <h2><?php echo esc_html__('Prizes for this Wheel', 'wheel-of-fortune'); ?></h2>
@ -354,7 +399,8 @@ if (class_exists('WooCommerce')) {
<table class="wheel-form-table"> <table class="wheel-form-table">
<tr><th scope="row"><label for="edit-prize-name"><?php _e('Prize Name', 'wheel-of-fortune'); ?></label></th><td><input type="text" id="edit-prize-name" name="prize_name" class="regular-text" required></td></tr> <tr><th scope="row"><label for="edit-prize-name"><?php _e('Prize Name', 'wheel-of-fortune'); ?></label></th><td><input type="text" id="edit-prize-name" name="prize_name" class="regular-text" required></td></tr>
<tr><th scope="row"><label for="edit-prize-description"><?php _e('Description', 'wheel-of-fortune'); ?></label></th><td><textarea id="edit-prize-description" name="prize_description" rows="3" class="large-text"></textarea></td></tr> <tr><th scope="row"><label for="edit-prize-description"><?php _e('Description', 'wheel-of-fortune'); ?></label></th><td><textarea id="edit-prize-description" name="prize_description" rows="3" class="large-text"></textarea></td></tr>
<tr><th scope="row"><label for="edit-prize-probability"><?php _e('Probability', 'wheel-of-fortune'); ?></label></th><td><input type="number" id="edit-prize-probability" name="prize_probability" step="any" min="0" max="1" required><p class="description"><?php _e('Enter a value between 0 and 1. Use 0 for prizes that cannot be won.', 'wheel-of-fortune'); ?></p></td></tr> <tr><th scope="row"><label for="edit-prize-probability"><?php _e('Probability (Paid Spin)', 'wheel-of-fortune'); ?></label></th><td><input type="number" id="edit-prize-probability" name="prize_probability" step="any" min="0" max="1" required><p class="description"><?php _e('Enter a value between 0 and 1. Use 0 for prizes that cannot be won.', 'wheel-of-fortune'); ?></p></td></tr>
<tr><th scope="row"><label for="edit-prize-daily-spin-probability"><?php _e('Probability (Daily Spin)', 'wheel-of-fortune'); ?></label></th><td><input type="number" id="edit-prize-daily-spin-probability" name="prize_daily_spin_probability" step="any" min="0" max="1"><p class="description"><?php _e('Chance for a FREE daily spin. Leave empty to use the same probability as the paid spin.', 'wheel-of-fortune'); ?></p></td></tr>
<tr><th scope="row"><?php _e('Status', 'wheel-of-fortune'); ?></th><td><label for="edit-prize-is-active"><input type="checkbox" id="edit-prize-is-active" name="prize_is_active" value="1"><?php _e('Prize is active', 'wheel-of-fortune'); ?></label></td></tr> <tr><th scope="row"><?php _e('Status', 'wheel-of-fortune'); ?></th><td><label for="edit-prize-is-active"><input type="checkbox" id="edit-prize-is-active" name="prize_is_active" value="1"><?php _e('Prize is active', 'wheel-of-fortune'); ?></label></td></tr>
<tr><th scope="row"><label for="edit-prize-redemption-code"><?php _e('Redemption Code', 'wheel-of-fortune'); ?></label></th><td><input type="text" id="edit-prize-redemption-code" name="prize_redemption_code" class="regular-text"><p class="description"><?php _e('Optional code for the user to redeem the prize.', 'wheel-of-fortune'); ?></p></td></tr> <tr><th scope="row"><label for="edit-prize-redemption-code"><?php _e('Redemption Code', 'wheel-of-fortune'); ?></label></th><td><input type="text" id="edit-prize-redemption-code" name="prize_redemption_code" class="regular-text"><p class="description"><?php _e('Optional code for the user to redeem the prize.', 'wheel-of-fortune'); ?></p></td></tr>
<tr><th scope="row"><label for="edit-prize-is-discount"><?php _e('Is Discount?', 'wheel-of-fortune'); ?></label></th><td><input type="checkbox" id="edit-prize-is-discount" name="prize_is_discount" value="1"><p class="description"><?php _e('Check if the prize is a discount.', 'wheel-of-fortune'); ?></p></td></tr> <tr><th scope="row"><label for="edit-prize-is-discount"><?php _e('Is Discount?', 'wheel-of-fortune'); ?></label></th><td><input type="checkbox" id="edit-prize-is-discount" name="prize_is_discount" value="1"><p class="description"><?php _e('Check if the prize is a discount.', 'wheel-of-fortune'); ?></p></td></tr>

View File

@ -65,6 +65,7 @@ jQuery(document).ready(function($) {
$('#edit-prize-name').val(prize.name); $('#edit-prize-name').val(prize.name);
$('#edit-prize-description').val(prize.description); $('#edit-prize-description').val(prize.description);
$('#edit-prize-probability').val(prize.probability); $('#edit-prize-probability').val(prize.probability);
$('#edit-prize-daily-spin-probability').val(prize.daily_spin_probability);
$('#edit-prize-is-active').prop('checked', parseInt(prize.is_active, 10)); $('#edit-prize-is-active').prop('checked', parseInt(prize.is_active, 10));
$('#edit-prize-redemption-code').val(prize.redemption_code); $('#edit-prize-redemption-code').val(prize.redemption_code);
$('#edit-prize-is-discount').prop('checked', parseInt(prize.is_discount, 10)); $('#edit-prize-is-discount').prop('checked', parseInt(prize.is_discount, 10));
@ -94,6 +95,7 @@ jQuery(document).ready(function($) {
name: $('#edit-prize-name').val(), name: $('#edit-prize-name').val(),
description: $('#edit-prize-description').val(), description: $('#edit-prize-description').val(),
probability: $('#edit-prize-probability').val(), probability: $('#edit-prize-probability').val(),
daily_spin_probability: $('#edit-prize-daily-spin-probability').val(),
is_active: $('#edit-prize-is-active').is(':checked') ? 1 : 0, is_active: $('#edit-prize-is-active').is(':checked') ? 1 : 0,
redemption_code: $('#edit-prize-redemption-code').val(), redemption_code: $('#edit-prize-redemption-code').val(),
is_discount: $('#edit-prize-is-discount').is(':checked') ? 1 : 0, is_discount: $('#edit-prize-is-discount').is(':checked') ? 1 : 0,

View File

@ -13,12 +13,19 @@ if (!defined('ABSPATH')) exit;
<td><textarea id="prize_description" name="prize_description" rows="3" class="large-text"></textarea></td> <td><textarea id="prize_description" name="prize_description" rows="3" class="large-text"></textarea></td>
</tr> </tr>
<tr> <tr>
<th scope="row"><label for="prize_probability"><?php _e('Probability', 'wheel-of-fortune'); ?></label></th> <th scope="row"><label for="prize_probability"><?php _e('Probability (Paid Spin)', 'wheel-of-fortune'); ?></label></th>
<td> <td>
<input type="number" id="prize_probability" name="prize_probability" step="any" min="0" max="1" required> <input type="number" id="prize_probability" name="prize_probability" step="any" min="0" max="1" required>
<p class="description"><?php _e('Enter a value between 0 and 1 (e.g., 0.1 for 10% chance). Use 0 for prizes that cannot be won.', 'wheel-of-fortune'); ?></p> <p class="description"><?php _e('Enter a value between 0 and 1 (e.g., 0.1 for 10% chance). Use 0 for prizes that cannot be won.', 'wheel-of-fortune'); ?></p>
</td> </td>
</tr> </tr>
<tr>
<th scope="row"><label for="prize_daily_spin_probability"><?php _e('Probability (Daily Spin)', 'wheel-of-fortune'); ?></label></th>
<td>
<input type="number" id="prize_daily_spin_probability" name="prize_daily_spin_probability" step="any" min="0" max="1">
<p class="description"><?php _e('Chance for a FREE daily spin. Leave empty to use the same probability as the paid spin.', 'wheel-of-fortune'); ?></p>
</td>
</tr>
<tr> <tr>
<th scope="row"><?php _e('Status', 'wheel-of-fortune'); ?></th> <th scope="row"><?php _e('Status', 'wheel-of-fortune'); ?></th>
<td> <td>

View File

@ -20,6 +20,7 @@ jQuery(document).ready(function($) {
var isSpinning = false; var isSpinning = false;
var accumulatedRotation = 0; var accumulatedRotation = 0;
var wheelSpins = wof_data.spins_left; var wheelSpins = wof_data.spins_left;
var dailySpinAvailable = wof_data.daily_spin_available;
var l10n = wof_data.l10n; var l10n = wof_data.l10n;
// Nastavitve animacije // Nastavitve animacije
@ -58,11 +59,7 @@ jQuery(document).ready(function($) {
showPrizePopup(prize); showPrizePopup(prize);
isSpinning = false; isSpinning = false;
if (wheelSpins > 0) { updateButtonState();
spinButton.prop('disabled', false).text(l10n.spin_button);
} else {
spinButton.prop('disabled', true).text(l10n.no_spins_left);
}
} }
// Prikaz nagrade // Prikaz nagrade
@ -81,9 +78,31 @@ jQuery(document).ready(function($) {
} }
} }
// Posodobitev stanja gumba
function updateButtonState() {
if (isSpinning) return;
if (dailySpinAvailable) {
spinButton.prop('disabled', false).text(l10n.free_daily_spin || 'FREE DAILY SPIN');
} else if (wheelSpins > 0) {
spinButton.prop('disabled', false).text(l10n.spin_button);
} else {
spinButton.prop('disabled', true).text(l10n.no_spins_left);
}
}
// Klik na gumb za vrtenje // Klik na gumb za vrtenje
spinButton.on('click', function() { spinButton.on('click', function() {
if (isSpinning || wheelSpins <= 0) return; if (isSpinning) return;
var spinType = 'paid'; // Privzeto je plačan
// Preveri, ali najprej porabimo dnevnega
if (dailySpinAvailable) {
spinType = 'daily';
} else if (wheelSpins <= 0) {
return; // Ničesar za porabiti
}
isSpinning = true; isSpinning = true;
spinButton.prop('disabled', true).text(l10n.spinning); spinButton.prop('disabled', true).text(l10n.spinning);
@ -97,10 +116,16 @@ jQuery(document).ready(function($) {
}, },
data: { data: {
wheel_id: wof_data.wheel_id, wheel_id: wof_data.wheel_id,
spin_type: spinType
}, },
success: function(response) { success: function(response) {
if (response.success) { if (response.success) {
window.wof_spin_result = response.data; window.wof_spin_result = response.data;
// Posodobimo stanje
if (spinType === 'daily') {
dailySpinAvailable = false;
}
wheelSpins = response.data.remaining_spins; wheelSpins = response.data.remaining_spins;
updateSpinsCounter(); updateSpinsCounter();
@ -131,17 +156,13 @@ jQuery(document).ready(function($) {
function handleError(message) { function handleError(message) {
resultDiv.html('<p>' + message + '</p>').addClass('error').fadeIn(300); resultDiv.html('<p>' + message + '</p>').addClass('error').fadeIn(300);
isSpinning = false; isSpinning = false;
if(wheelSpins > 0){ updateButtonState();
spinButton.prop('disabled', false).text(l10n.spin_button);
}
} }
// Inicializacija // Inicializacija
function init() { function init() {
updateSpinsCounter(); updateSpinsCounter();
if (wheelSpins <= 0) { updateButtonState();
spinButton.prop('disabled', true).text(l10n.no_spins_left);
}
} }
init(); init();

View File

@ -1,5 +1,9 @@
"./README.md" : "./README.md" :
""" """
# Wheel of Fortune Plugin
Test posodobitve za preverjanje Gitea workflow.
# Wheel of Fortune - WordPress Plugin # Wheel of Fortune - WordPress Plugin
Vtičnik "Kolo Sreče" (Wheel of Fortune) omogoča uporabnikom vrtenje kolesa za nagrade. Povezan je z WooCommerce za dodeljevanje spinov ob nakupu izdelkov. Vtičnik "Kolo Sreče" (Wheel of Fortune) omogoča uporabnikom vrtenje kolesa za nagrade. Povezan je z WooCommerce za dodeljevanje spinov ob nakupu izdelkov.
@ -1351,6 +1355,8 @@ if (class_exists('WooCommerce')) {
<div class="notice notice-warning"><p><?php printf(__('Notice: The total probability is %s, which is less than 1 (100%%).', 'wheel-of-fortune'), '<strong>' . esc_html($total_probability) . '</strong>'); ?></p></div> <div class="notice notice-warning"><p><?php printf(__('Notice: The total probability is %s, which is less than 1 (100%%).', 'wheel-of-fortune'), '<strong>' . esc_html($total_probability) . '</strong>'); ?></p></div>
<?php endif; ?> <?php endif; ?>
<p><button class="button button-primary add-new-prize"><?php _e('Add New Prize', 'wheel-of-fortune'); ?></button></p>
<table class="wheel-prizes-table widefat fixed striped"> <table class="wheel-prizes-table widefat fixed striped">
<thead> <thead>
<tr> <tr>
@ -1364,7 +1370,7 @@ if (class_exists('WooCommerce')) {
</thead> </thead>
<tbody> <tbody>
<?php if (empty($prizes)): ?> <?php if (empty($prizes)): ?>
<tr><td colspan="6"><?php _e('No prizes found. Add your first prize below.', 'wheel-of-fortune'); ?></td></tr> <tr><td colspan="6"><?php _e('No prizes found. Add your first prize using the button above.', 'wheel-of-fortune'); ?></td></tr>
<?php else: ?> <?php else: ?>
<?php foreach ($prizes as $prize): ?> <?php foreach ($prizes as $prize): ?>
<tr> <tr>
@ -1451,7 +1457,7 @@ if (class_exists('WooCommerce')) {
</div> </div>
<!-- Edit Prize Modal (ostaja večinoma nespremenjen, wheel_id se doda dinamično z JS) --> <!-- Edit Prize Modal (ostaja večinoma nespremenjen, wheel_id se doda dinamično z JS) -->
<div id="edit-prize-modal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);"> <div id="edit-prize-modal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);" data-wheel-id="<?php echo esc_attr($wheel_id); ?>">
<div style="background-color: #fefefe; margin: 5% auto; padding: 20px; border: 1px solid #888; width: 60%; max-width: 700px;"> <div style="background-color: #fefefe; margin: 5% auto; padding: 20px; border: 1px solid #888; width: 60%; max-width: 700px;">
<span class="close" style="color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer;">×</span> <span class="close" style="color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer;">×</span>
<h2><?php echo esc_html__('Edit Prize', 'wheel-of-fortune'); ?></h2> <h2><?php echo esc_html__('Edit Prize', 'wheel-of-fortune'); ?></h2>
@ -1562,6 +1568,23 @@ jQuery(document).ready(function($) {
} }
}); });
// --- Add New Prize ---
$('.add-new-prize').on('click', function(e) {
e.preventDefault();
// Clear form for new prize
$('#edit-prize-form')[0].reset();
$('#edit-prize-id').val(''); // Clear prize ID for new prize
// Get wheel_id from the modal's data attribute
var wheelId = $('#edit-prize-modal').data('wheel-id');
$('#edit-wheel-id').val(wheelId);
console.log('Opening modal for new prize with wheel_id:', wheelId);
modal.show();
});
// --- Edit Prize --- // --- Edit Prize ---
$('.edit-prize').on('click', function(e) { $('.edit-prize').on('click', function(e) {
e.preventDefault(); e.preventDefault();
@ -1570,7 +1593,7 @@ jQuery(document).ready(function($) {
// AJAX call to get prize details // AJAX call to get prize details
$.post(ajaxurl, { $.post(ajaxurl, {
action: 'wheel_get_prize_details', action: 'wheel_get_prize_details',
nonce: wheel_admin_nonce.nonce, _ajax_nonce: wheel_admin_nonce._ajax_nonce,
prize_id: prizeId prize_id: prizeId
}, function(response) { }, function(response) {
if (response.success) { if (response.success) {
@ -1592,6 +1615,8 @@ jQuery(document).ready(function($) {
} else { } else {
alert(response.data.message || 'An error occurred.'); alert(response.data.message || 'An error occurred.');
} }
}).fail(function() {
alert('An error occurred while loading prize details.');
}); });
}); });
@ -1602,7 +1627,7 @@ jQuery(document).ready(function($) {
// Pripravimo podatke iz forme // Pripravimo podatke iz forme
const formData = { const formData = {
action: 'wheel_save_prize', action: 'wheel_save_prize',
nonce: wheel_admin_nonce.nonce, _ajax_nonce: wheel_admin_nonce._ajax_nonce,
wheel_id: $('#edit-wheel-id').val(), // **KLJUČNO: pošljemo wheel_id** wheel_id: $('#edit-wheel-id').val(), // **KLJUČNO: pošljemo wheel_id**
prize_id: $('#edit-prize-id').val(), prize_id: $('#edit-prize-id').val(),
name: $('#edit-prize-name').val(), name: $('#edit-prize-name').val(),
@ -1616,6 +1641,10 @@ jQuery(document).ready(function($) {
email_template: $('#edit-prize-email-template').val(), email_template: $('#edit-prize-email-template').val(),
}; };
// Debug: preveri wheel_id
console.log('Wheel ID from form:', formData.wheel_id);
console.log('Form data:', formData);
// Validate form fields // Validate form fields
if (!formData.name) { if (!formData.name) {
alert('Prize name is required.'); alert('Prize name is required.');
@ -1625,9 +1654,14 @@ jQuery(document).ready(function($) {
alert('Probability must be a number between 0 and 1.'); alert('Probability must be a number between 0 and 1.');
return; return;
} }
if (!formData.wheel_id || formData.wheel_id == 0) {
alert('Wheel ID is missing. Please refresh the page and try again.');
return;
}
// AJAX call to save the prize // AJAX call to save the prize
$.post(ajaxurl, formData, function(response) { $.post(ajaxurl, formData, function(response) {
console.log('Server response:', response);
if (response.success) { if (response.success) {
alert(response.data.message); alert(response.data.message);
modal.hide(); modal.hide();
@ -1635,7 +1669,8 @@ jQuery(document).ready(function($) {
} else { } else {
alert(response.data.message || 'An error occurred while saving.'); alert(response.data.message || 'An error occurred while saving.');
} }
}).fail(function() { }).fail(function(xhr, status, error) {
console.error('AJAX error:', {xhr: xhr, status: status, error: error});
alert('A critical error occurred. Please try again.'); alert('A critical error occurred. Please try again.');
}); });
}); });
@ -1649,7 +1684,7 @@ jQuery(document).ready(function($) {
$.post(ajaxurl, { $.post(ajaxurl, {
action: 'wheel_delete_prize', action: 'wheel_delete_prize',
nonce: wheel_admin_nonce.nonce, _ajax_nonce: wheel_admin_nonce._ajax_nonce,
prize_id: prizeId prize_id: prizeId
}, function(response) { }, function(response) {
if (response.success) { if (response.success) {
@ -1684,7 +1719,7 @@ jQuery(document).ready(function($) {
// Collect all settings from the form to test unsaved values // Collect all settings from the form to test unsaved values
const data = { const data = {
action: 'wheel_test_email', action: 'wheel_test_email',
nonce: wheel_admin_nonce, _ajax_nonce: wheel_admin_nonce._ajax_nonce,
recipient_email: recipientEmail, recipient_email: recipientEmail,
smtp_enabled: $('#wheel_smtp_enabled').is(':checked') ? '1' : '0', smtp_enabled: $('#wheel_smtp_enabled').is(':checked') ? '1' : '0',
smtp_host: $('#wheel_smtp_host').val(), smtp_host: $('#wheel_smtp_host').val(),
@ -1722,6 +1757,70 @@ jQuery(document).ready(function($) {
}); });
}); });
} }
// Dodajanje/brisanje produkta za spine
$('#add-product-button').on('click', function() {
const button = $(this);
const productId = $('#new-product-id').val();
const spins = $('#new-product-spins').val();
const wheelId = button.data('wheel-id');
if (!productId || !spins) {
alert('Prosim vnesite ID produkta in število spinov.');
return;
}
$.ajax({
url: ajaxurl,
method: 'POST',
data: {
action: 'ajax_update_wheel_product_spins',
_ajax_nonce: wheel_admin_nonce._ajax_nonce,
wheel_id: wheelId,
product_id: productId,
spins: spins
},
success: function(response) {
if(response.success) {
location.reload();
} else {
alert('Napaka: ' + response.data.message);
}
},
error: function() {
alert('Prišlo je do kritične napake.');
}
});
});
$('.delete-product-button').on('click', function() {
if(!confirm('Ste prepričani?')) return;
const button = $(this);
const productId = button.data('product-id');
const wheelId = button.data('wheel-id');
$.ajax({
url: ajaxurl,
method: 'POST',
data: {
action: 'ajax_delete_wheel_product',
_ajax_nonce: wheel_admin_nonce._ajax_nonce,
wheel_id: wheelId,
product_id: productId
},
success: function(response) {
if(response.success) {
location.reload();
} else {
alert('Napaka: ' + response.data.message);
}
},
error: function() {
alert('Prišlo je do kritične napake.');
}
});
});
});""" });"""
@ -3587,12 +3686,12 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
margin: 0 auto; margin: 0 auto;
width: 100%; width: 100%;
max-width: 700px; max-width: 700px;
filter: drop-shadow(0 0 25px rgba(0, 200, 255, 0.5)); filter: drop-shadow(0 0 15px rgba(0, 200, 255, 0.3));
padding-top: 80px; padding-top: 80px;
transition: transform 0.05s ease-out; transition: transform 0.05s ease-out;
} }
/* Outer ring lighting effect */ /* Outer ring lighting effect - POENOSTAVLJENO */
.wheel-wrapper::before { .wheel-wrapper::before {
content: ''; content: '';
position: absolute; position: absolute;
@ -3601,9 +3700,10 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
width: 110%; width: 110%;
height: 110%; height: 110%;
border-radius: 50%; border-radius: 50%;
/* Manj kompleksen gradient */
background: radial-gradient( background: radial-gradient(
circle at center, circle at center,
rgba(0, 200, 255, 0.2) 0%, rgba(0, 150, 200, 0.1) 0%,
rgba(0, 0, 0, 0) 70% rgba(0, 0, 0, 0) 70%
); );
z-index: -1; z-index: -1;
@ -3618,28 +3718,27 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
transition: none; /* POMEMBNO: ne uporabljamo CSS tranzicije, saj jo upravlja JS */ transition: none; /* POMEMBNO: ne uporabljamo CSS tranzicije, saj jo upravlja JS */
display: block; display: block;
will-change: transform; will-change: transform;
/* Enostavnejši shadow, ki ga podpirajo vse naprave */
filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.25)); filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.25));
border: 4px solid #222; border: 4px solid #222;
box-shadow: 0 0 10px 2px #00dfe9, 0 2px 8px rgba(0,0,0,0.3); box-shadow: 0 0 10px 2px rgba(0, 223, 233, 0.5), 0 2px 8px rgba(0,0,0,0.3);
border-radius: 50%; border-radius: 50%;
background: #111; background: #111;
} }
/* Wheel frame */ /* Wheel frame - BREZ SVG FILTRA */
.wheel-frame { .wheel-frame {
fill: #0a4d6e; fill: #0a4d6e;
stroke: #0a7bb5; stroke: #0a7bb5;
stroke-width: 8; stroke-width: 8;
filter: url(#bevel);
} }
/* LED lighting on wheel frame */ /* LED lighting on wheel frame - BREZ SVG FILTRA */
.wheel-light-track { .wheel-light-track {
fill: none; fill: none;
stroke: #00c8ff; stroke: #00c8ff;
stroke-width: 6; stroke-width: 6;
stroke-dasharray: 3, 8; stroke-dasharray: 3, 8;
filter: url(#glow);
animation: lightTrackAnimation 5s linear infinite; animation: lightTrackAnimation 5s linear infinite;
} }
@ -3662,48 +3761,33 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
} }
} }
/* Wheel segments */ /* Wheel segment - BREZ SVG FILTRA */
.wheel-segment { .wheel-segment {
transform-origin: center; stroke: #fff;
transition: all 0.3s ease; stroke-width: 1px;
filter: url(#innerShadow); transition: all 0.2s;
} }
/* Segment colors */ /* Simple gradients for cross-browser compatibility */
.wheel-segment-yellow { .wheel-segment-yellow { fill: #ffdd00; }
/* fill: url(#gradientYellow); */ .wheel-segment-green { fill: #88ff00; }
} .wheel-segment-red { fill: #ff5500; }
.wheel-segment-pink { fill: #ff44aa; }
.wheel-segment-blue { fill: #00ccff; }
.wheel-segment-green { /* Divider between segments */
/* fill: url(#gradientGreen); */
}
.wheel-segment-red {
/* fill: url(#gradientRed); */
}
.wheel-segment-pink {
/* fill: url(#gradientPink); */
}
.wheel-segment-blue {
/* fill: url(#gradientBlue); */
}
/* Segment dividers */
.wheel-divider { .wheel-divider {
fill: #303030; stroke: rgba(255, 255, 255, 0.5);
stroke: #505050; stroke-width: 2px;
stroke-width: 1;
filter: url(#bevel);
} }
/* Pegs at the end of dividers */ /* Pegs on the wheel */
.wheel-peg { .wheel-peg {
fill: #e0e0e0; fill: #e0e0e0;
stroke: #c0c0c0; stroke: #666;
stroke-width: 1; stroke-width: 1px;
filter: url(#pegGlow); /* Enostavnejši shadow namesto glow filtra */
filter: drop-shadow(0 1px 2px rgba(0,0,0,0.5));
} }
@keyframes pegPulse { @keyframes pegPulse {
@ -3733,7 +3817,7 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
} }
} }
/* Text on wheel */ /* Text on wheel - BREZ SVG FILTRA */
.wheel-text { .wheel-text {
font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif; font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif;
font-size: 24px; font-size: 24px;
@ -3745,67 +3829,39 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
letter-spacing: 1px; letter-spacing: 1px;
pointer-events: none; pointer-events: none;
text-anchor: middle; text-anchor: middle;
filter: url(#textShadow); /* Enostavnejša senca, ki deluje povsod */
text-shadow: 1px 1px 3px rgba(0,0,0,0.7);
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: 70px; max-width: 70px;
} }
/* Center hub */ /* Center hub - BREZ SVG FILTRA */
.wheel-hub-outer { .wheel-hub-outer {
fill: #0a4d6e; fill: #0a4d6e;
stroke: #0a7bb5; stroke: #0a7bb5;
stroke-width: 4; stroke-width: 4;
filter: url(#bevel);
} }
.wheel-hub-inner { .wheel-hub-inner {
fill: url(#hubGradient); fill: #999;
filter: url(#innerGlow);
} }
.wheel-hub-button { .wheel-hub-button {
fill: url(#buttonGradient); fill: #330066;
filter: url(#buttonGlow);
} }
/* Hub text - BREZ SVG FILTRA */
.wheel-hub-text { .wheel-hub-text {
font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif; font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif;
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
fill: #ff00aa; fill: #ff00aa;
text-anchor: middle; text-anchor: middle;
filter: url(#neonGlow); /* Enostavnejša senca namesto glow filtra */
animation: neonPulse 2s infinite alternate; text-shadow: 0 0 10px #ff00aa;
} }
@keyframes neonPulse { /* Pointer - BREZ SVG FILTRA */
from {
filter: url(#neonGlow);
text-shadow: 0 0 10px #ff00aa, 0 0 20px #ff00aa;
}
to {
filter: url(#neonGlowBright);
text-shadow: 0 0 15px #ff00aa, 0 0 25px #ff00aa, 0 0 30px #ff00aa;
}
}
/* Fast neon pulse for spinning */
@keyframes fastNeonPulse {
0% {
filter: url(#neonGlow);
text-shadow: 0 0 10px #ff00aa, 0 0 20px #ff00aa;
}
50% {
filter: url(#neonGlowBright);
text-shadow: 0 0 20px #ff00aa, 0 0 30px #ff00aa, 0 0 40px #ff00aa;
}
100% {
filter: url(#neonGlow);
text-shadow: 0 0 10px #ff00aa, 0 0 20px #ff00aa;
}
}
/* Pointer */
.wheel-pointer { .wheel-pointer {
position: absolute; position: absolute;
top: 60px; top: 60px;
@ -3820,7 +3876,7 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
margin-bottom: 20px; margin-bottom: 20px;
} }
/* Pointer active state */ /* Pointer active state - BREZ SVG FILTRA */
.wheel-pointer.active { .wheel-pointer.active {
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.8)); filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.8));
animation: pointerPulse 1s infinite alternate; animation: pointerPulse 1s infinite alternate;
@ -3833,10 +3889,10 @@ $wheels = $wpdb->get_results("SELECT * FROM $wheels_table ORDER BY id ASC", ARRA
@keyframes pointerPulse { @keyframes pointerPulse {
from { from {
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.8)); opacity: 0.8;
} }
to { to {
filter: drop-shadow(0 0 15px #ff00aa) drop-shadow(0 0 25px rgba(255, 255, 255, 0.9)); opacity: 1;
} }
} }
@ -4232,21 +4288,21 @@ jQuery(document).ready(function($) {
} }
// Elementi // Elementi
const wheelContainer = $('.wheel-container'); var wheelContainer = $('.wheel-container');
const wheelElement = wheelContainer.find('.wheel'); var wheelElement = wheelContainer.find('.wheel');
const spinButton = wheelContainer.find('.wheel-button'); var spinButton = wheelContainer.find('.wheel-button');
const resultDiv = wheelContainer.find('.wheel-result'); var resultDiv = wheelContainer.find('.wheel-result');
const spinsCounter = wheelContainer.find('.wheel-spins-counter span'); var spinsCounter = wheelContainer.find('.wheel-spins-counter span');
// Stanje // Stanje
let isSpinning = false; var isSpinning = false;
let accumulatedRotation = 0; var accumulatedRotation = 0;
let wheelSpins = wof_data.spins_left; var wheelSpins = wof_data.spins_left;
const l10n = wof_data.l10n; var l10n = wof_data.l10n;
// Nastavitve animacije // Nastavitve animacije
const spinDuration = 8000; var spinDuration = 8000;
const baseRotations = 5; var baseRotations = 5;
// Funkcija za animacijo // Funkcija za animacijo
function easeOutCubic(t) { function easeOutCubic(t) {
@ -4254,27 +4310,29 @@ jQuery(document).ready(function($) {
} }
function animateWheel(startTime, startRotation, totalRotation) { function animateWheel(startTime, startRotation, totalRotation) {
const currentTime = Date.now(); var currentTime = Date.now();
const elapsedTime = currentTime - startTime; var elapsedTime = currentTime - startTime;
if (elapsedTime >= spinDuration) { if (elapsedTime >= spinDuration) {
wheelElement.css('transform', `rotate(${startRotation + totalRotation}deg)`); wheelElement.css('transform', 'rotate(' + (startRotation + totalRotation) + 'deg)');
accumulatedRotation = (startRotation + totalRotation); accumulatedRotation = (startRotation + totalRotation);
finishSpin(); finishSpin();
return; return;
} }
const timeProgress = elapsedTime / spinDuration; var timeProgress = elapsedTime / spinDuration;
const rotationProgress = easeOutCubic(timeProgress); var rotationProgress = easeOutCubic(timeProgress);
const currentRotation = startRotation + (totalRotation * rotationProgress); var currentRotation = startRotation + (totalRotation * rotationProgress);
wheelElement.css('transform', `rotate(${currentRotation}deg)`); wheelElement.css('transform', 'rotate(' + currentRotation + 'deg)');
requestAnimationFrame(() => animateWheel(startTime, startRotation, totalRotation)); requestAnimationFrame(function() {
animateWheel(startTime, startRotation, totalRotation);
});
} }
// Obdelava po koncu vrtenja // Obdelava po koncu vrtenja
function finishSpin() { function finishSpin() {
const prize = window.wof_spin_result.prize; var prize = window.wof_spin_result.prize;
showPrizePopup(prize); showPrizePopup(prize);
isSpinning = false; isSpinning = false;
@ -4287,9 +4345,9 @@ jQuery(document).ready(function($) {
// Prikaz nagrade // Prikaz nagrade
function showPrizePopup(prize) { function showPrizePopup(prize) {
let html = `<h3>${l10n.congratulations}</h3><p>${l10n.you_won} <strong>${prize.name}</strong></p>`; var html = '<h3>' + l10n.congratulations + '</h3><p>' + l10n.you_won + ' <strong>' + prize.name + '</strong></p>';
if (window.wof_spin_result.discount_code) { if (window.wof_spin_result.discount_code) {
html += `<p>${l10n.discount_code_sent}</p>`; html += '<p>' + l10n.discount_code_sent + '</p>';
} }
resultDiv.html(html).addClass('win').fadeIn(300); resultDiv.html(html).addClass('win').fadeIn(300);
} }
@ -4323,25 +4381,33 @@ jQuery(document).ready(function($) {
window.wof_spin_result = response.data; window.wof_spin_result = response.data;
wheelSpins = response.data.remaining_spins; wheelSpins = response.data.remaining_spins;
updateSpinsCounter(); updateSpinsCounter();
var targetAngle = response.data.degree;
var fullSpinsRotation = baseRotations * 360;
var currentAngle = accumulatedRotation % 360;
const finalAngle = response.data.degree; var rotationToTarget = targetAngle - currentAngle;
const totalRotation = (360 * baseRotations) + finalAngle; if (rotationToTarget < 0) {
rotationToTarget += 360;
}
animateWheel(Date.now(), accumulatedRotation, totalRotation); var totalRotationAmount = fullSpinsRotation + rotationToTarget;
animateWheel(Date.now(), accumulatedRotation, totalRotationAmount);
} else { } else {
handleError(response.data.message || l10n.error); handleError(response.data.message || l10n.error);
} }
}, },
error: function(xhr) { error: function(xhr) {
const errorMsg = xhr.responseJSON ? (xhr.responseJSON.message || l10n.error) : l10n.error; var errorMsg = xhr.responseJSON ? (xhr.responseJSON.message || l10n.error) : l10n.error;
handleError(errorMsg); handleError(errorMsg);
} }
}); });
}); });
function handleError(message) { function handleError(message) {
resultDiv.html(`<p>${message}</p>`).addClass('error').fadeIn(300); resultDiv.html('<p>' + message + '</p>').addClass('error').fadeIn(300);
isSpinning = false; isSpinning = false;
if(wheelSpins > 0){ if(wheelSpins > 0){
spinButton.prop('disabled', false).text(l10n.spin_button); spinButton.prop('disabled', false).text(l10n.spin_button);
@ -6091,7 +6157,7 @@ class WheelOfFortune {
wp_enqueue_style('wheel-of-fortune-admin-css', WHEEL_OF_FORTUNE_PLUGIN_URL . 'assets/css/admin.css', [], WHEEL_OF_FORTUNE_VERSION); wp_enqueue_style('wheel-of-fortune-admin-css', WHEEL_OF_FORTUNE_PLUGIN_URL . 'assets/css/admin.css', [], WHEEL_OF_FORTUNE_VERSION);
wp_enqueue_script('wheel-of-fortune-admin-js', WHEEL_OF_FORTUNE_PLUGIN_URL . 'admin/js/admin.js', ['jquery'], WHEEL_OF_FORTUNE_VERSION, true); wp_enqueue_script('wheel-of-fortune-admin-js', WHEEL_OF_FORTUNE_PLUGIN_URL . 'admin/js/admin.js', ['jquery'], WHEEL_OF_FORTUNE_VERSION, true);
wp_localize_script('wheel-of-fortune-admin-js', 'wheel_admin_nonce', array('nonce' => wp_create_nonce('wheel_admin_nonce'))); wp_localize_script('wheel-of-fortune-admin-js', 'wheel_admin_nonce', array('_ajax_nonce' => wp_create_nonce('wheel_admin_nonce')));
wp_localize_script('wheel-of-fortune-admin-js', 'wheel_admin_i18n', [ wp_localize_script('wheel-of-fortune-admin-js', 'wheel_admin_i18n', [
'select_user' => __('Select a user', 'wheel-of-fortune'), 'select_user' => __('Select a user', 'wheel-of-fortune'),
'select_user_and_spins' => __('Please select a user and enter the number of spins.', 'wheel-of-fortune'), 'select_user_and_spins' => __('Please select a user and enter the number of spins.', 'wheel-of-fortune'),
@ -6187,7 +6253,7 @@ class WheelOfFortune {
if ($rotate > 90 && $rotate < 270) { if ($rotate > 90 && $rotate < 270) {
$rotate += 180; $rotate += 180;
} }
$text_paths .= "<text class='wheel-text' x='{$text_x}' y='{$text_y}' transform='rotate({$rotate},{$text_x},{$text_y})'>{$prize['name']}</text>"; $text_paths .= "<text class='wheel-text' dominant-baseline='middle' x='{$text_x}' y='{$text_y}' transform='rotate({$rotate},{$text_x},{$text_y})'>{$prize['name']}</text>";
} }
$defs .= '</defs>'; $defs .= '</defs>';
@ -6209,7 +6275,7 @@ class WheelOfFortune {
} }
public function ajax_get_prize_details() { public function ajax_get_prize_details() {
check_ajax_referer('wheel_admin_nonce', 'nonce'); check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
if (!current_user_can('manage_options')) { if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]); wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
@ -6231,7 +6297,7 @@ class WheelOfFortune {
} }
public function ajax_save_prize() { public function ajax_save_prize() {
check_ajax_referer('wheel_admin_nonce', 'nonce'); check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
if (!current_user_can('manage_options')) { if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]); wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);
@ -6295,7 +6361,7 @@ class WheelOfFortune {
} }
public function ajax_delete_prize() { public function ajax_delete_prize() {
check_ajax_referer('wheel_admin_nonce', 'nonce'); check_ajax_referer('wheel_admin_nonce', '_ajax_nonce');
if (!current_user_can('manage_options')) { if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]); wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'wheel-of-fortune')]);

0
export_code.sh Normal file → Executable file
View File

View File

@ -296,6 +296,7 @@ class WheelOfFortune {
id mediumint(9) NOT NULL AUTO_INCREMENT, id mediumint(9) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL, name varchar(255) NOT NULL,
slug varchar(100) NOT NULL, slug varchar(100) NOT NULL,
has_daily_spin tinyint(1) NOT NULL DEFAULT 0,
created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
PRIMARY KEY (id), PRIMARY KEY (id),
UNIQUE KEY slug (slug) UNIQUE KEY slug (slug)
@ -319,6 +320,7 @@ class WheelOfFortune {
name varchar(255) NOT NULL, name varchar(255) NOT NULL,
description text DEFAULT '', description text DEFAULT '',
probability float NOT NULL, probability float NOT NULL,
daily_spin_probability float DEFAULT NULL,
is_active tinyint(1) NOT NULL DEFAULT 1, is_active tinyint(1) NOT NULL DEFAULT 1,
image_url varchar(255) DEFAULT '', image_url varchar(255) DEFAULT '',
email_subject varchar(255) DEFAULT '', email_subject varchar(255) DEFAULT '',
@ -576,29 +578,65 @@ class WheelOfFortune {
} }
$wheel_id = $request->get_param('wheel_id'); $wheel_id = $request->get_param('wheel_id');
$spin_type = $request->get_param('spin_type') === 'daily' ? 'daily' : 'paid'; // NOVO
if (empty($wheel_id)) { if (empty($wheel_id)) {
return new WP_Error('no_wheel_id', __('Wheel ID is missing.', 'wheel-of-fortune'), ['status' => 400]); return new WP_Error('no_wheel_id', __('Wheel ID is missing.', 'wheel-of-fortune'), ['status' => 400]);
} }
global $wpdb; global $wpdb;
$spins_table = $wpdb->prefix . 'wheel_spins'; $wheels_table = $wpdb->prefix . 'wof_wheels';
$user_spins = $wpdb->get_row($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id)); $wheel_data = $wpdb->get_row($wpdb->prepare("SELECT has_daily_spin FROM $wheels_table WHERE id = %d", $wheel_id), ARRAY_A);
$spins = $user_spins ? intval($user_spins->spins_available) : 0;
$spins_left = 0;
if ($spins <= 0) { $is_eligible_for_daily = false;
return new WP_Error('no_spins', __('You have no spins left.', 'wheel-of-fortune'), ['status' => 403]);
// Preverjanje za DNEVNI SPIN
if ($spin_type === 'daily') {
if (!empty($wheel_data) && $wheel_data['has_daily_spin']) {
$last_spin_meta_key = '_wof_last_daily_spin_' . $wheel_id;
$last_spin_timestamp = get_user_meta($user_id, $last_spin_meta_key, true);
if (empty($last_spin_timestamp) || strtotime('today') > $last_spin_timestamp) {
$is_eligible_for_daily = true;
}
}
if (!$is_eligible_for_daily) {
return new WP_Error('daily_spin_used', __('You have already used your free daily spin today.', 'wheel-of-fortune'), ['status' => 403]);
}
}
// Preverjanje za PLAČAN SPIN
else {
$spins_table = $wpdb->prefix . 'wheel_spins';
$user_spins = $wpdb->get_row($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id));
$spins_left = $user_spins ? intval($user_spins->spins_available) : 0;
if ($spins_left <= 0) {
return new WP_Error('no_spins', __('You have no spins left.', 'wheel-of-fortune'), ['status' => 403]);
}
} }
$prizes = $this->get_wheel_prizes($wheel_id); // Nadaljuj z logiko vrtenja
$prizes = $this->get_wheel_prizes($wheel_id, $is_eligible_for_daily);
if (empty($prizes)) { if (empty($prizes)) {
return new WP_Error('no_prizes', __('No prizes available.', 'wheel-of-fortune'), ['status' => 500]); return new WP_Error('no_prizes', __('No prizes available.', 'wheel-of-fortune'), ['status' => 500]);
} }
// Uporabi delujočo logiko za izbiro nagrade
$prize = $this->select_random_prize($prizes); $prize = $this->select_random_prize($prizes);
$new_spins = $spins - 1;
$wpdb->update($spins_table, ['spins_available' => $new_spins, 'last_spin_date' => current_time('mysql')], ['user_id' => $user_id, 'wheel_id' => $wheel_id]); // Zmanjšaj spine ali zabeleži dnevni spin
if ($spin_type === 'daily') {
$last_spin_meta_key = '_wof_last_daily_spin_' . $wheel_id;
update_user_meta($user_id, $last_spin_meta_key, time());
// Pridobimo trenutno število spinov za response
$spins_table = $wpdb->prefix . 'wheel_spins';
$user_spins_obj = $wpdb->get_row($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id));
$new_spins = $user_spins_obj ? intval($user_spins_obj->spins_available) : 0;
} else {
$new_spins = $spins_left - 1;
$spins_table = $wpdb->prefix . 'wheel_spins';
$wpdb->update($spins_table, ['spins_available' => $new_spins, 'last_spin_date' => current_time('mysql')], ['user_id' => $user_id, 'wheel_id' => $wheel_id]);
}
$log_table = $wpdb->prefix . 'wheel_log'; $log_table = $wpdb->prefix . 'wheel_log';
$wpdb->insert($log_table, ['user_id' => $user_id, 'wheel_id' => $wheel_id, 'prize_id' => $prize['id'], 'spin_date' => current_time('mysql'), 'redeemed' => 0]); $wpdb->insert($log_table, ['user_id' => $user_id, 'wheel_id' => $wheel_id, 'prize_id' => $prize['id'], 'spin_date' => current_time('mysql'), 'redeemed' => 0]);
@ -625,15 +663,33 @@ class WheelOfFortune {
$this->send_prize_email($user_id, $prize); $this->send_prize_email($user_id, $prize);
} }
$response_data = [ 'prize' => $prize, 'degree' => $degree, 'remaining_spins' => $new_spins, 'discount_code' => $redemption_code ]; $response_data = [
'prize' => $prize,
'degree' => $degree,
'remaining_spins' => $new_spins,
'discount_code' => $redemption_code,
'spin_type' => $spin_type
];
return new WP_REST_Response(['success' => true, 'data' => $response_data], 200); return new WP_REST_Response(['success' => true, 'data' => $response_data], 200);
} }
public function get_wheel_prizes($wheel_id = 1) { public function get_wheel_prizes($wheel_id = 1, $is_daily_spin = false) {
global $wpdb; global $wpdb;
$table_name = $wpdb->prefix . 'wheel_prizes'; $table_name = $wpdb->prefix . 'wheel_prizes';
return $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE wheel_id = %d AND is_active = 1 ORDER BY id ASC", $wheel_id), ARRAY_A); $prizes = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE wheel_id = %d AND is_active = 1 ORDER BY id ASC", $wheel_id), ARRAY_A);
if ($is_daily_spin) {
foreach ($prizes as &$prize) {
// Če je daily_spin_probability nastavljena, jo uporabi. Sicer uporabi standardno.
if (isset($prize['daily_spin_probability']) && $prize['daily_spin_probability'] !== null) {
$prize['probability'] = $prize['daily_spin_probability'];
}
}
unset($prize); // Prekini referenco
}
return $prizes;
} }
private function select_random_prize($prizes) { private function select_random_prize($prizes) {
@ -739,11 +795,23 @@ class WheelOfFortune {
$spins_left = $wpdb->get_var($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id)); $spins_left = $wpdb->get_var($wpdb->prepare("SELECT spins_available FROM $spins_table WHERE user_id = %d AND wheel_id = %d", $user_id, $wheel_id));
$spins_left = ($spins_left === null) ? 0 : (int)$spins_left; $spins_left = ($spins_left === null) ? 0 : (int)$spins_left;
// Preveri, ali je dnevni spin na voljo
$daily_spin_available = false;
if (isset($wheel['has_daily_spin']) && $wheel['has_daily_spin']) {
$last_spin_meta_key = '_wof_last_daily_spin_' . $wheel_id;
$last_spin_timestamp = get_user_meta($user_id, $last_spin_meta_key, true);
if (empty($last_spin_timestamp) || strtotime('today') > $last_spin_timestamp) {
$daily_spin_available = true;
}
}
// Definiramo polje za prevode, da bo dostopno v PHP in JS // Definiramo polje za prevode, da bo dostopno v PHP in JS
$l10n = [ $l10n = [
'spin_button' => __('SPIN', 'wheel-of-fortune'), 'spin_button' => __('SPIN', 'wheel-of-fortune'),
'spinning' => __('Spinning...', 'wheel-of-fortune'), 'spinning' => __('Spinning...', 'wheel-of-fortune'),
'no_spins_left' => __('No More Spins', 'wheel-of-fortune'), 'no_spins_left' => __('No More Spins', 'wheel-of-fortune'),
'free_daily_spin' => __('FREE DAILY SPIN', 'wheel-of-fortune'),
'congratulations' => __('Congratulations!', 'wheel-of-fortune'), 'congratulations' => __('Congratulations!', 'wheel-of-fortune'),
'you_won' => __('You won:', 'wheel-of-fortune'), 'you_won' => __('You won:', 'wheel-of-fortune'),
'close' => __('Close', 'wheel-of-fortune'), 'close' => __('Close', 'wheel-of-fortune'),
@ -757,6 +825,7 @@ class WheelOfFortune {
'nonce' => wp_create_nonce('wp_rest'), 'nonce' => wp_create_nonce('wp_rest'),
'wheel_id' => $wheel_id, 'wheel_id' => $wheel_id,
'spins_left' => $spins_left, 'spins_left' => $spins_left,
'daily_spin_available' => $daily_spin_available,
'prizes' => $prizes, 'prizes' => $prizes,
'l10n' => $l10n // Uporabimo definirano polje 'l10n' => $l10n // Uporabimo definirano polje
)); ));
@ -930,6 +999,7 @@ class WheelOfFortune {
$name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : ''; $name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : '';
$description = isset($_POST['description']) ? sanitize_textarea_field($_POST['description']) : ''; $description = isset($_POST['description']) ? sanitize_textarea_field($_POST['description']) : '';
$probability = isset($_POST['probability']) ? floatval($_POST['probability']) : 0; $probability = isset($_POST['probability']) ? floatval($_POST['probability']) : 0;
$daily_spin_probability = isset($_POST['daily_spin_probability']) && $_POST['daily_spin_probability'] !== '' ? floatval($_POST['daily_spin_probability']) : null;
$is_active = isset($_POST['is_active']) ? intval($_POST['is_active']) : 0; $is_active = isset($_POST['is_active']) ? intval($_POST['is_active']) : 0;
$redemption_code = isset($_POST['redemption_code']) ? sanitize_text_field($_POST['redemption_code']) : ''; $redemption_code = isset($_POST['redemption_code']) ? sanitize_text_field($_POST['redemption_code']) : '';
$is_discount = isset($_POST['is_discount']) ? intval($_POST['is_discount']) : 0; $is_discount = isset($_POST['is_discount']) ? intval($_POST['is_discount']) : 0;
@ -949,6 +1019,10 @@ class WheelOfFortune {
wp_send_json_error(['message' => __('Probability must be between 0 and 1.', 'wheel-of-fortune')]); wp_send_json_error(['message' => __('Probability must be between 0 and 1.', 'wheel-of-fortune')]);
} }
if ($daily_spin_probability !== null && ($daily_spin_probability < 0 || $daily_spin_probability > 1)) {
wp_send_json_error(['message' => __('Daily spin probability must be between 0 and 1.', 'wheel-of-fortune')]);
}
global $wpdb; global $wpdb;
$table_name = $wpdb->prefix . 'wheel_prizes'; $table_name = $wpdb->prefix . 'wheel_prizes';
@ -957,6 +1031,7 @@ class WheelOfFortune {
'name' => $name, 'name' => $name,
'description' => $description, 'description' => $description,
'probability' => $probability, 'probability' => $probability,
'daily_spin_probability' => $daily_spin_probability,
'is_active' => $is_active, 'is_active' => $is_active,
'redemption_code' => $redemption_code, 'redemption_code' => $redemption_code,
'is_discount' => $is_discount, 'is_discount' => $is_discount,
@ -965,7 +1040,7 @@ class WheelOfFortune {
'discount_value' => $discount_value, 'discount_value' => $discount_value,
]; ];
$format = ['%d', '%s', '%s', '%f', '%d', '%s', '%d', '%s', '%s', '%f']; $format = ['%d', '%s', '%s', '%f', '%f', '%d', '%s', '%d', '%s', '%s', '%f'];
if ($prize_id > 0) { if ($prize_id > 0) {
$result = $wpdb->update($table_name, $data, ['id' => $prize_id], $format, ['%d']); $result = $wpdb->update($table_name, $data, ['id' => $prize_id], $format, ['%d']);