Chào mọi người, hôm nay mình sẽ hướng dẫn mọi người code chức năng vòng quay may mắn trong wordpress nhé!
Mọi người biết đấy, ai mà chả không thích một cái vòng quay vui nhộn và đối khi mêng mang ít nhề hy vọng may mắn nhương giống mình đang ở sòi Vegas đó phải không nào? Cùng bắt tay vào làm và để tôi chỉ cho bạn cách tạo một vòng quay vừa chân thực, vừa xịn con nhà bà xò nhé.

1. Vì sao bạn cần một “vòng quay may mắn”?
Hãy tưởng tượng thế này: bạn có một cửa hàng online, khách ghé qua, xem sản phẩm, nhưng… họ không mua gì! Sao thế nhỉ? Câu trả lời đơn giản là: bạn cần gì đó thú vị hơn để giữ chân họ. Đây chính là lúc “vòng quay may mắn” xuất hiện. Không chỉ giúp tăng sự hào hứng, mà còn kích thích khách hàng chi tiêu.
Bạn không cần phải là một lập trình viên siêu cấp hay nhà phát minh tài ba để làm được điều này. Với chút mã code và một tinh thần “quay tới bến”, bạn sẽ mang đến cho khách hàng những giây phút vừa cười, vừa thót tim, vừa… hết tiền (vì mua sắm).
2. Ý tưởng tổng quan về vòng quay may mắn
Bạn đã từng thấy những vòng quay may mắn trong các cửa hàng trực tuyến? Khi khách hàng nhấn nút, bánh xe xoay xoay như chong chóng, ánh sáng lấp lánh (nếu bạn có thể tưởng tượng), và cuối cùng dừng lại ở một phần thưởng — hoặc một lời chúc ngọt ngào kiểu “May mắn lần sau!”. Đây chính là thứ bạn sẽ tạo ra:
- Giao diện: Một bánh xe đầy màu sắc với các phần quà được chia đều.
- Hành động: Khách hàng nhấn nút quay → vòng quay chuyển động.
- Kết quả: Một sản phẩm (hoặc “May mắn lần sau”) hiện lên.
- Xử lý phía sau: Nếu khách hàng trúng, hệ thống sẽ tự động tạo đơn hàng WooCommerce cho họ.
3. Lập trình nhưng phải “chất chơi người dơi”
Lập trình không chỉ là gõ vài dòng code rồi xong chuyện. Nó là nghệ thuật, là sự hòa quyện giữa logic và… chút điên rồ. Với vòng quay này, bạn không chỉ học cách viết code mà còn học cách biến nó thành niềm vui cho chính bạn. Hãy chuẩn bị:
- Máy tính (chắc chắn rồi, không lẽ bạn định code trên giấy?).
- Website WordPress với WooCommerce (nếu không có WooCommerce thì như pizza mà thiếu phô mai!).
- Cốc cà phê hoặc trà sữa để chống buồn ngủ (cẩn thận đừng đổ lên bàn phím nhé).
- Tâm trạng vui vẻ, bởi chúng ta sắp tạo nên thứ gì đó khiến khách hàng cười lăn.
4. Cách hoạt động của vòng quay (nhìn thì đơn giản, nhưng kỳ diệu)
Bạn nghĩ vòng quay đơn giản chỉ là quay và dừng lại? Ồ không, bên dưới đó là cả một cơ chế phức tạp như cỗ máy trong phim Inception. Dưới đây là các bước cơ bản:
- Hiển thị vòng quay: Một hình tròn xoay vòng với các phần thưởng.
- Người dùng nhấn nút “Quay”: Bắt đầu hành trình.
- Vòng quay quay quay quay: Kết hợp một chút xác suất, bạn sẽ biết khách hàng trúng gì (hoặc “may mắn lần sau”).
- Thông báo kết quả: Khách hàng sẽ nhận được quà, hoặc… một lời chúc.
Mục tiêu cuối cùng: Mang đến trải nghiệm thú vị, nhưng vẫn khiến khách hàng tiếp tục quay để “thử vận may”.
4. Code thôi nào! (Dành cho những tâm hồn yêu thích thử thách)
Giờ là phần thú vị nhất. Chúng ta sẽ tự tạo vòng quay bằng cách sử dụng shortcode trong WordPress. Mà quên, điều kiện dùng là phải có sử dụng plugin WooCommerce nhé.
Các bạn có thể tìm hiểu WooCommerce tại wiki nhé: xem thêm
4.1. Tạo Shortcode để hiển thị vòng quay
Trong file functions.php của theme (hoặc viết trong plugin của bạn), thêm đoạn code sau:
[an]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | function lucky_wheel_shortcode() { // Lấy danh sách ID sản phẩm (ID của sản phẩm trên WooCommerce) $product_ids = array(5699, 5704, 5581, 5579, 5465, 5341, 5116); $product_data = []; // Lấy thông tin sản phẩm từ WooCommerce foreach ($product_ids as $product_id) { $product = wc_get_product($product_id); // Lấy thông tin sản phẩm qua ID if ($product) { $product_data[] = [ 'id' => $product->get_id(), 'name' => mb_strimwidth($product->get_name(), 0, 10, "..."), // Giới hạn tên sản phẩm 10 ký tự 'full_name' => $product->get_name(), 'price' => wc_price($product->get_regular_price()), 'sale_price' => wc_price($product->get_sale_price()), 'image' => wp_get_attachment_url($product->get_image_id()), 'url' => $product->get_permalink() ]; } } // Thêm phần "May mắn lần sau" vào danh sách sản phẩm $product_data[] = [ 'id' => null, 'name' => 'May mắn lần sau', 'full_name' => 'May mắn lần sau', 'price' => '', 'sale_price' => '', 'image' => '', 'url' => '' ]; // Chuyển đổi dữ liệu sản phẩm thành JSON để sử dụng trong JavaScript $product_data_json = json_encode($product_data); // Tạo nonce bảo mật cho AJAX $ajax_nonce = wp_create_nonce("create_wheel_order_nonce"); // HTML hiển thị vòng quay $html = ' <div id="wheel-container" style="text-align:center;"> <canvas id="wheel-canvas" width="700" height="700" style="border-radius: 50%;"></canvas> <button id="spin-button" style="margin-top:20px;">Nhấn để quay!</button> </div> <script> const productData = ' . $product_data_json . '; const probabilities = [10, 15, 15, 10, 10, 10, 10, 20]; // Xác suất cho từng ô const ajaxNonce = "' . $ajax_nonce . '"; document.addEventListener("DOMContentLoaded", function() { let canvas = document.getElementById("wheel-canvas"); let ctx = canvas.getContext("2d"); let startAngle = 0; let arc = Math.PI / (productData.length / 2); let spinAngleStart = 0; let spinTime = 0; let spinTimeTotal = 0; function drawWheel() { let outsideRadius = 300; let insideRadius = 75; let textRadius = 250; ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < productData.length; i++) { let angle = startAngle + i * arc; ctx.fillStyle = i % 2 === 0 ? "#FFA07A" : "#FFD700"; // Xen kẽ màu sắc cho các phần ctx.beginPath(); ctx.arc(canvas.width / 2, canvas.height / 2, outsideRadius, angle, angle + arc, false); ctx.arc(canvas.width / 2, canvas.height / 2, insideRadius, angle + arc, angle, true); ctx.stroke(); ctx.fill(); ctx.save(); ctx.translate( canvas.width / 2 + Math.cos(angle + arc / 2) * textRadius, canvas.height / 2 + Math.sin(angle + arc / 2) * textRadius ); ctx.rotate(angle + arc / 2 + Math.PI / 2); ctx.fillText(productData[i].name, -ctx.measureText(productData[i].name).width / 2, 0); ctx.restore(); } } function rotateWheel() { spinAngleStart = Math.random() * 10 + 10; // Tạo góc quay ngẫu nhiên spinTime = 0; spinTimeTotal = Math.random() * 3 + 4 * 1000; // Thời gian quay ngẫu nhiên rotate(); } function rotate() { spinTime += 30; if (spinTime >= spinTimeTotal) { stopRotateWheel(); return; } let spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal); startAngle += (spinAngle * Math.PI / 180); drawWheel(); setTimeout(rotate, 30); // Lặp lại cho đến khi hết thời gian quay } function stopRotateWheel() { let index = Math.floor(Math.random() * productData.length); // Tìm kết quả ngẫu nhiên let result = productData[index]; alert("Bạn trúng: " + result.full_name); } function easeOut(t, b, c, d) { t /= d; t--; return c * (t * t * t + 1) + b; // Hiệu ứng quay chậm dần } document.getElementById("spin-button").addEventListener("click", rotateWheel); drawWheel(); }); </script> '; return $html; } add_shortcode('lucky_wheel', 'lucky_wheel_shortcode'); |
[/an]
Giải Thích Từng Dòng Code
Phần tạo danh sách sản phẩm:
- $product_ids: Là danh sách các sản phẩm mà bạn muốn cho vào vòng quay.
- wc_get_product($product_id): Lấy thông tin chi tiết sản phẩm qua ID.
- mb_strimwidth(): Giới hạn độ dài tên sản phẩm để không làm hỏng giao diện vòng quay.
🧑💻 Ví dụ hài hước: Nếu tên sản phẩm dài lê thê kiểu “Siêu phẩm độc nhất vô nhị giảm giá sốc 50% toàn quốc”, bạn cần cắt ngắn xuống thành “Siêu phẩm…” để đỡ nhức mắt.
Thêm “May mắn lần sau”:
Đây là phần “dở khóc dở cười” khi khách hàng quay trúng nhưng không nhận được gì. Một chút thách thức để họ quay tiếp lần sau.
Phần vẽ vòng quay:
- Sử dụng <canvas> để tạo bánh xe. Các ô được tô màu xen kẽ vàng và cam nhìn “ngon mắt”.
- Các phần tên sản phẩm được đặt ở vị trí tương ứng.
🧑🎨 Ví dụ minh họa: Bạn đang tạo ra một chiếc bánh pizza khổng lồ với từng phần là một món quà. Đừng để tên sản phẩm “dài dòng văn tự” chiếm hết phần bánh nhé!
Phần xoay vòng:
- spinAngleStart: Góc bắt đầu quay.
- spinTimeTotal: Tổng thời gian quay.
- easeOut(): Tạo hiệu ứng quay chậm dần khi gần dừng.
🌀 Ví dụ hài hước: Bạn đang mô phỏng chiếc chong chóng của trẻ con, lúc đầu quay vèo vèo, nhưng khi gió ngừng thổi, nó từ từ đứng im.
Kết quả:
Khi vòng quay dừng lại:
- Hàm stopRotateWheel() chọn ra một mục ngẫu nhiên từ danh sách sản phẩm.
- Nếu bạn trúng phần thưởng, một thông báo vui vẻ sẽ xuất hiện như: “Chúc mừng bạn đã trúng một chai nước hoa thơm đến mức chim sẻ cũng ngất!”. Nếu không may, thì “Rất tiếc, may mắn lần sau nhé!”.
Ví dụ hài hước trong thực tế:
- Khách hàng quay trúng một sản phẩm có giá trị lớn, họ có thể cười hả hê và vội vàng thêm hàng vào giỏ.
- Nhưng khi họ quay vào “May mắn lần sau”, họ thường sẽ nghĩ: “Chắc chắn lần này mình xui, quay lại lần nữa chắc chắn sẽ ăn đậm!” (Thế là bạn kéo họ vào vòng quay mua sắm không hồi kết).
Lưu ý: Hãy thay $product_ids = array(5699, 5704, 5581, 5579, 5465, 5341, 5116); thành những ID sản phẩm tương ứng của bạn. Bằng cách vào trang sản phẩm coppy từng ID những sản phẩm quà tặng theo thứ tự từ 1 đến 7 nhé, số 8 sẽ không cần điền mặc định nó sẽ hiểu là may mắn lần sau.

4.2. Phần AJAX: Tự động hóa kết quả
Sau khi khách hàng trúng thưởng, chúng ta cần xử lý phía server để tạo đơn hàng WooCommerce (nếu họ trúng sản phẩm). Dưới đây là cách làm.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | function create_wheel_order() { check_ajax_referer('create_wheel_order_nonce', 'security'); // Bảo vệ yêu cầu AJAX với nonce if (!isset($_POST['product_id'])) { wp_send_json_error('Thiếu ID sản phẩm!'); } $product_id = intval($_POST['product_id']); $user_id = get_current_user_id(); if (!$user_id) { wp_send_json_error('Bạn cần đăng nhập để nhận thưởng!'); } // Kiểm tra sản phẩm có tồn tại không $product = wc_get_product($product_id); if (!$product) { wp_send_json_error('Sản phẩm không tồn tại!'); } try { // Tạo đơn hàng WooCommerce $order = wc_create_order(); $order->add_product($product, 1); // Thêm sản phẩm vào đơn hàng với số lượng 1 $order->set_customer_id($user_id); // Miễn phí đơn hàng foreach ($order->get_items() as $item_id => $item) { $item->set_total(0); } $order->calculate_totals(); // Đánh dấu đơn hàng là đã hoàn thành $order->update_status('completed'); $order->payment_complete(); wp_send_json_success('Đơn hàng của bạn đã được tạo thành công!'); } catch (Exception $e) { wp_send_json_error('Lỗi khi tạo đơn hàng: ' . $e->getMessage()); } } add_action('wp_ajax_create_wheel_order', 'create_wheel_order'); add_action('wp_ajax_nopriv_create_wheel_order', 'create_wheel_order'); |
Giải thích:
Kiểm tra bảo mật với nonce:
- Dòng check_ajax_referer() đảm bảo rằng yêu cầu AJAX được gửi từ website của bạn chứ không phải từ kẻ xấu muốn lợi dụng.
- Kiểm tra thông tin sản phẩm và người dùng:
- $product_id: Lấy ID sản phẩm từ yêu cầu AJAX.
- $user_id: Kiểm tra người dùng hiện tại có đăng nhập không.
🧑💻 Ví dụ hài hước: Nếu khách hàng chưa đăng nhập mà quay, bạn có thể hiện thông báo kiểu: “Để nhận quà, bạn cần đăng nhập. Đừng ngại, chúng tôi không ăn cắp thông tin của bạn đâu mà sợ!”.
Tạo đơn hàng WooCommerce:
- Dòng wc_create_order() tạo một đơn hàng mới.
- add_product($product, 1): Thêm sản phẩm trúng thưởng vào đơn hàng.
🛒 Ví dụ thực tế: Nếu khách hàng trúng một sản phẩm trị giá 0 đồng (do bạn tạo đơn hàng miễn phí), họ sẽ nhận quà mà không cần trả gì cả. Bạn chỉ cần “chốt hạ” bằng cách cho họ mã giảm giá “miễn phí”.
Đánh dấu đơn hàng hoàn thành:
- update_status(‘completed’): Đơn hàng được chuyển sang trạng thái đã hoàn thành.
4.3. Tích hợp giao diện quản trị để xóa lịch sử quay
Khi bạn muốn bắt đầu lại từ đầu (ví dụ, cho khách hàng quay tiếp vào sự kiện mới), bạn cần một công cụ xóa dữ liệu quay. Hãy tạo một mục trong Admin để thực hiện việc này.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | function add_reset_spin_data_button() { add_menu_page( 'Reset Spin Data', 'Reset Spin Data', 'manage_options', 'reset_spin_data', 'reset_spin_data_callback' ); } add_action('admin_menu', 'add_reset_spin_data_button'); function reset_spin_data_callback() { if (isset($_POST['reset_spin_data'])) { $users = get_users(); foreach ($users as $user) { delete_user_meta($user->ID, 'has_spun_wheel'); // Xóa trạng thái quay } echo '<div class="updated"><p>Dữ liệu đã được xóa thành công!</p></div>'; } echo ' <div class="wrap"> <h1>Reset Dữ Liệu Vòng Quay</h1> <form method="post"> <input type="hidden" name="reset_spin_data" value="1"> <p><input type="submit" class="button button-primary" value="Xóa toàn bộ dữ liệu"></p> </form> </div>'; } |
Giải thích:
Thêm menu Admin:
- add_menu_page() thêm một mục vào menu Admin, nơi bạn có thể nhấn nút để reset dữ liệu.
- Xóa lịch sử quay:
- delete_user_meta($user->ID, ‘has_spun_wheel’): Xóa dữ liệu trạng thái “đã quay” của từng người dùng.
Giao diện thân thiện:
- Một form đơn giản trong WordPress Admin cho phép bạn reset dữ liệu chỉ với một cú nhấp chuột.
🎯 Ví dụ thực tế: Bạn có thể đặt thông báo kiểu: “Dữ liệu đã được reset, giờ đây khách hàng có thể quay vòng lại như chưa từng có gì xảy ra”.
5. Tổng kết
Với hướng dẫn này, bạn đã có:
- Một vòng quay đẹp đẽ, thú vị, và hoàn toàn tùy chỉnh.
- Cách xử lý dữ liệu sản phẩm và tạo đơn hàng tự động khi khách hàng trúng thưởng.
- Một giao diện Admin để xóa lịch sử quay khi cần.
6. Một số mẹo hài hước khi triển khai vòng quay
- Thông điệp sáng tạo:
- Khi khách hàng trúng quà: “Wow! Bạn đã trúng một món quà giá trị! Ai bảo thần may mắn không thích bạn nào?”
- Khi trúng “May mắn lần sau”: “Đừng buồn, thần may mắn cũng cần nghỉ ngơi. Thử lại nhé!”
- Gợi ý khuyến mãi:
- Sau khi quay, thêm nút kiểu: “Tăng thêm cơ hội trúng thưởng bằng cách mua hàng ngay!”
- Tạo trải nghiệm:
- Tùy chỉnh màu sắc, thêm âm thanh “ding ding ding” khi bánh xe quay, tạo cảm giác như đang tham gia một gameshow!
Chúc bạn thành công với vòng quay may mắn và mang đến niềm vui bất tận cho khách hàng! 🎉 Dưới đây là code hoàn chỉnh 100%, các bạn chỉ cần bỏ vào funtion là được nhé, các bạn có thể tự chỉnh sửa lại cho phù hợp với nhu cầu của mình nhé.
[an]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | // Shortcode để hiển thị HTML của vòng quay muathemewpgiare.com function lucky_wheel_shortcode() { // Tự định nghĩa ID sản phẩm (thay thế các ID dưới đây bằng ID của sản phẩm bạn muốn) $product_ids = array(5699, 5704, 5581, 5579, 5465, 5341, 5116); // Điền ID của sản phẩm mà bạn muốn $product_data = []; foreach ($product_ids as $product_id) { $product = wc_get_product($product_id); if ($product) { $product_data[] = [ 'id' => $product->get_id(), 'name' => mb_strimwidth($product->get_name(), 0, 10, "..."), // Giới hạn tên sản phẩm 10 ký tự 'full_name' => $product->get_name(), 'price' => wc_price($product->get_regular_price()), 'sale_price' => wc_price($product->get_sale_price()), 'image' => wp_get_attachment_url($product->get_image_id()), 'url' => $product->get_permalink() ]; } } // Thêm phần "May mắn lần sau" vào danh sách sản phẩm muathemewpgiare.com $product_data[] = [ 'id' => null, 'name' => 'May mắn lần sau', 'full_name' => 'May mắn lần sau', 'price' => '', 'sale_price' => '', 'image' => '', 'url' => '' ]; // Chuyển đổi dữ liệu sản phẩm thành JSON để sử dụng trong JavaScript $product_data_json = json_encode($product_data); // Tạo nonce để bảo mật AJAX $ajax_nonce = wp_create_nonce("create_wheel_order_nonce"); // Kiểm tra xem người dùng đã đăng nhập chưa $user_id = get_current_user_id(); $is_logged_in = is_user_logged_in(); $is_admin = current_user_can('administrator'); $has_spun = get_user_meta($user_id, 'has_spun_wheel', true); // HTML để tạo vòng quay $html = ' <div id="wheel-container" style="text-align: center; margin-top: 50px; position: relative;"> <canvas id="wheel-canvas" width="700" height="700" style="border-radius: 50%; box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);"></canvas> <button id="spin-button" class="' . (!$is_logged_in ? 'nut-dang-nhap-sweet' : '') . '" style="margin-top: 20px; padding: 15px 30px; font-size: 20px; cursor: pointer; background-color: #4CAF50; color: white; border: none; border-radius: 5px; box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);"' . (!$is_admin && $has_spun && $is_logged_in ? ' disabled' : '') . '>Quay</button> <div id="tooltip" style="display: none; position: absolute; background: rgba(255, 255, 255, 0.9); border: 1px solid #ccc; padding: 15px; z-index: 1000; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); font-size: 14px;"></div> </div> '; // JavaScript cho chức năng vòng quay may mắn và SweetAlert2 $html .= ' <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script> document.addEventListener("DOMContentLoaded", function() { const productData = ' . $product_data_json . '; const probabilities = [10, 15, 15, 10, 10, 10, 10, 20]; // Xác suất (%) cho từng sản phẩm (bao gồm "May mắn lần sau") const ajaxNonce = "' . $ajax_nonce . '"; const isLoggedIn = ' . ($is_logged_in ? 'true' : 'false') . '; let canvas = document.getElementById("wheel-canvas"); let ctx = canvas.getContext("2d"); let startAngle = 0; let arc = Math.PI / (productData.length / 2); let spinTimeout = null; let spinAngleStart = 10; let spinTime = 0; let spinTimeTotal = 0; let canvasCenterX = canvas.width / 2; let canvasCenterY = canvas.height / 2; function drawRouletteWheel() { let outsideRadius = 300; let textRadius = 250; let insideRadius = 75; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = "#FFF"; ctx.lineWidth = 2; ctx.font = "bold 16px Arial"; for (let i = 0; i < productData.length; i++) { let angle = startAngle + i * arc; ctx.fillStyle = i % 2 === 0 ? "#FFABAB" : "#FFDD94"; ctx.beginPath(); ctx.arc(canvasCenterX, canvasCenterY, outsideRadius, angle, angle + arc, false); ctx.arc(canvasCenterX, canvasCenterY, insideRadius, angle + arc, angle, true); ctx.stroke(); ctx.fill(); ctx.save(); ctx.fillStyle = "#333"; ctx.translate(canvasCenterX + Math.cos(angle + arc / 2) * textRadius, canvasCenterY + Math.sin(angle + arc / 2) * textRadius); ctx.rotate(angle + arc / 2 + Math.PI / 2); ctx.fillText(productData[i].name, -ctx.measureText(productData[i].name).width / 2, 0); ctx.restore(); } } function rotateWheel() { if (!isLoggedIn) { Swal.fire({ title: "Thông báo", text: "Bạn cần phải đăng nhập để quay vòng may mắn!", icon: "info", confirmButtonText: "OK" }); return; } spinAngleStart = Math.random() * 10 + 10; spinTime = 0; spinTimeTotal = Math.random() * 3 + 4 * 1000; rotate(); } function rotate() { spinTime += 30; if (spinTime >= spinTimeTotal) { stopRotateWheel(); return; } let spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal); startAngle += (spinAngle * Math.PI / 180); drawRouletteWheel(); spinTimeout = setTimeout(rotate, 30); } function stopRotateWheel() { let weightedIndex = getWeightedRandomIndex(probabilities); let winningProduct = productData[weightedIndex]; if (winningProduct.id === null) { Swal.fire({ title: "Rất tiếc!", text: "Bạn đã gặp phải may mắn lần sau. Hãy thử lại!", icon: "warning", confirmButtonText: "OK" }); } else { Swal.fire({ title: "Chúc mừng!", text: "Bạn đã trúng: " + winningProduct.full_name, icon: "success", confirmButtonText: "OK" }).then(() => { createOrder(winningProduct.id); }); } // Ghi nhận người dùng đã quay if (isLoggedIn) { jQuery.ajax({ url: "' . admin_url('admin-ajax.php') . '", type: "POST", data: { action: "set_user_spun", user_id: ' . $user_id . ', }, success: function(response) { if (!response.success) { console.error("Có lỗi xảy ra khi lưu trạng thái đã quay:", response.data); } }, error: function(error) { console.error("Có lỗi xảy ra khi lưu trạng thái đã quay:", error); } }); } } function easeOut(t, b, c, d) { t /= d; t--; return c * (t * t * t + 1) + b; } function getWeightedRandomIndex(weights) { let totalWeight = weights.reduce((acc, weight) => acc + weight, 0); let randomNum = Math.random() * totalWeight; for (let i = 0; i < weights.length; i++) { if (randomNum < weights[i]) { return i; } randomNum -= weights[i]; } return weights.length - 1; } function createOrder(productId) { jQuery.ajax({ url: "' . admin_url('admin-ajax.php') . '", type: "POST", data: { action: "create_wheel_order", product_id: productId, security: ajaxNonce }, success: function(response) { if(response.success) { console.log("Đơn hàng đã được tạo thành công."); } else { console.error("Có lỗi xảy ra khi tạo đơn hàng:", response.data); } }, error: function(error) { console.error("Có lỗi xảy ra khi tạo đơn hàng:", error); } }); } let tooltip = document.getElementById("tooltip"); canvas.addEventListener("mousemove", function(event) { let rect = canvas.getBoundingClientRect(); let x = event.clientX - rect.left - canvasCenterX; let y = event.clientY - rect.top - canvasCenterY; let angle = Math.atan2(y, x); if (angle < 0) { angle += 2 * Math.PI; } let index = Math.floor(angle / arc); if (index >= 0 && index < productData.length) { let product = productData[index]; if (product.id !== null) { tooltip.innerHTML = ` <img src="${product.image}" width="60" height="60" style="border-radius: 5px;"><br> <strong>${product.full_name}</strong><br> Giá: ${product.price}<br> Giá khuyến mãi: ${product.sale_price ? product.sale_price : "Không có"} `; tooltip.style.display = "block"; tooltip.style.left = event.clientX + 10 + "px"; tooltip.style.top = event.clientY + 10 + "px"; } else { tooltip.style.display = "none"; } } else { tooltip.style.display = "none"; } }); canvas.addEventListener("mouseleave", function() { tooltip.style.display = "none"; }); document.getElementById("spin-button").addEventListener("click", rotateWheel); drawRouletteWheel(); }); </script> '; return $html; } add_shortcode('lucky_wheel', 'lucky_wheel_shortcode'); // Hàm xử lý tạo đơn hàng muathemewpgiare.com function create_wheel_order_muathemewpgiare() { check_ajax_referer('create_wheel_order_nonce', 'security'); // Kiểm tra nonce bảo mật if (!isset($_POST['product_id'])) { wp_send_json_error('Thiếu sản phẩm.'); } $product_id = intval($_POST['product_id']); $user_id = get_current_user_id(); if (!$user_id) { wp_send_json_error('Người dùng không đăng nhập.'); } // Kiểm tra sản phẩm có tồn tại không $product = wc_get_product($product_id); if (!$product) { wp_send_json_error('Sản phẩm không hợp lệ.'); } try { // Tạo đơn hàng WooCommerce $order = wc_create_order(); $order->add_product($product, 1); // Thêm sản phẩm vào đơn hàng với giá trị 1 $order->set_customer_id($user_id); // Đặt giá trị đơn hàng là 0 đồng foreach ($order->get_items() as $item_id => $item) { $item->set_total(0); } $order->calculate_totals(); // Đặt trạng thái đơn hàng là hoàn thành và đã thanh toán $order->update_status('completed'); // Đặt trạng thái đơn hàng là hoàn thành $order->payment_complete(); // Đánh dấu đơn hàng là đã thanh toán wp_send_json_success('Đơn hàng đã được tạo.'); } catch (Exception $e) { wp_send_json_error('Lỗi khi tạo đơn hàng: ' . $e->getMessage()); } } add_action('wp_ajax_create_wheel_order', 'create_wheel_order_muathemewpgiare'); add_action('wp_ajax_nopriv_create_wheel_order', 'create_wheel_order_muathemewpgiare'); // Đánh dấu người dùng đã quay vòng function set_user_spun() { $user_id = intval($_POST['user_id']); update_user_meta($user_id, 'has_spun_wheel', true); wp_send_json_success('Trạng thái quay đã được ghi nhận.'); } add_action('wp_ajax_set_user_spun', 'set_user_spun'); // Thêm nút trong Admin để xóa trạng thái quay function add_reset_spin_data_button() { add_menu_page( 'Reset Spin Data', // Page title 'Vòng quay may mắn ', // Menu title 'manage_options', // Capability 'reset_spin_data_muathemewpgiare', // Menu slug 'reset_spin_data_callback_muathemewpgiare' // Callback function ); } add_action('admin_menu', 'add_reset_spin_data_button'); function reset_spin_data_callback() { if (isset($_POST['reset_spin_data'])) { // Xóa tất cả dữ liệu quay của người dùng $users = get_users(); foreach ($users as $user) { delete_user_meta($user->ID, 'has_spun_wheel'); } echo '<div class="updated"><p>Dữ liệu quay đã được xóa thành công!</p></div>'; } echo ' <div class="wrap"> <h1>Reset Spin Data</h1> <form method="post"> <input type="hidden" name="reset_spin_data" value="1"> <p><input type="submit" class="button button-primary" value="Xóa toàn bộ dữ liệu quay"></p> </form> </div>'; } |
