Results.cshtml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. @model LotteryWebApp.Models.TermResultHistoryModel
  2. @{
  3. ViewData["Title"] = "Millions - Results History";
  4. Layout = "~/Areas/Millions/Views/Shared/_Layout.cshtml";
  5. ViewData["ActiveTab"] = "Results";
  6. // Default to last 3 days if not specified
  7. if (string.IsNullOrEmpty(Model.fromDate)) {
  8. Model.fromDate = DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd");
  9. }
  10. if (string.IsNullOrEmpty(Model.toDate)) {
  11. Model.toDate = DateTime.Now.ToString("yyyy-MM-dd");
  12. }
  13. }
  14. @using LotteryWebApp.Languages;
  15. @using LotteryWebApp.Common;
  16. @section Styles {
  17. <script src="https://cdn.tailwindcss.com"></script>
  18. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  19. <!-- Flatpickr for premium calendar -->
  20. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
  21. <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
  22. <link rel="stylesheet" href="/Millions/css/site.css" />
  23. <link rel="stylesheet" href="/Millions/css/results.css" />
  24. }
  25. <div class="main-container results-container animate__animated animate__fadeIn pb-40 relative mx-auto max-w-[414px] shadow-2xl min-h-screen bg-white">
  26. <!-- Header Group: Sticky at Top -->
  27. <div class="sticky top-0 w-full z-[100] bg-[#F3F4F6] pb-2 shadow-md">
  28. <!-- Header: Matches Figma (Right Image) -->
  29. <div class="results-top-header">
  30. <a href="javascript:history.back()" class="back-btn">
  31. <i class="fas fa-arrow-left"></i>
  32. </a>
  33. <h1 class="font-bricolage">@Lang.results</h1>
  34. </div>
  35. <!-- Selection Bar: Side-by-side dates and search -->
  36. <div class="selection-bar bg-white/50 backdrop-blur-sm px-4 pt-2 pb-2">
  37. <div class="flex gap-3">
  38. <div class="date-pick-input flex-1 cursor-pointer relative bg-white border border-gray-200 rounded-lg p-2 flex items-center gap-2">
  39. <img src="/Millions/img/icon_calendar.svg" class="w-5 h-5" />
  40. <input type="text" id="fromDate" value="@Model.fromDate" class="bg-transparent border-none outline-none font-bold text-[13px] w-full ml-1 cursor-pointer" readonly />
  41. <i class="fas fa-caret-down text-gray-400"></i>
  42. </div>
  43. <div class="date-pick-input flex-1 cursor-pointer relative bg-white border border-gray-200 rounded-lg p-2 flex items-center gap-2">
  44. <img src="/Millions/img/icon_calendar.svg" class="w-5 h-5" />
  45. <input type="text" id="toDate" value="@Model.toDate" class="bg-transparent border-none outline-none font-bold text-[13px] w-full ml-1 cursor-pointer" readonly />
  46. <i class="fas fa-caret-down text-gray-400"></i>
  47. </div>
  48. <button id="btnSearch" class="btn-search-red !w-12 !h-12 flex items-center justify-center bg-[#0062FF] text-white rounded-xl shadow-md" onclick="triggerSearch()">
  49. <i class="fas fa-search"></i>
  50. </button>
  51. </div>
  52. </div>
  53. <!-- Red Separator Line -->
  54. <div class="px-4 mt-1">
  55. <div class="h-[2px] bg-gradient-to-r from-transparent via-[#0062FF] to-transparent rounded-full opacity-40"></div>
  56. </div>
  57. </div>
  58. <!-- Result List Container -->
  59. <div id="results-list-container" class="results-items-list px-4 min-h-[300px]">
  60. <!-- Content will be loaded via JS for all 3 games -->
  61. <div class="flex flex-col items-center justify-center py-20 text-gray-400">
  62. <i class="fas fa-circle-notch fa-spin text-3xl mb-2"></i>
  63. <span>Loading results...</span>
  64. </div>
  65. </div>
  66. <!-- Bottom Promo Bar (Matches Bottom message with yellow text) -->
  67. <div class="fixed bottom-[82px] left-1/2 -translate-x-1/2 w-full min-[600px]:max-w-[414px] bg-[#0062FF] text-white py-2 text-center text-[12px] font-bold tracking-wide z-40 flex flex-col items-center justify-center overflow-hidden h-auto shadow-md">
  68. <div class="flex flex-col items-center w-full animate-slide-up">
  69. <div class="opacity-90">@Lang.have_chance_to_get</div>
  70. <div class="text-[18px] font-black text-[#FBF3A7] mt-0.5">@Lang.millions_jackpot_today_htg</div>
  71. </div>
  72. </div>
  73. <!-- Shared Bottom Navbar -->
  74. <div class="fixed bottom-0 left-0 w-full z-50">
  75. <div class="mx-auto max-w-[414px]">
  76. <partial name="_BottomNavbar" />
  77. </div>
  78. </div>
  79. <!-- Custom Notification Modal -->
  80. <div id="notificationModal" class="fixed inset-0 z-[300] flex items-center justify-center hidden px-6 font-bricolage" style="background: linear-gradient(135deg, rgba(26, 26, 46, 0.9) 0%, rgba(22, 33, 62, 0.9) 100%);">
  81. <div class="w-full max-w-[343px] min-h-[420px] bg-white rounded-[24px] overflow-hidden flex flex-col items-center p-8 animate__animated animate__zoomIn animate__faster shadow-2xl border border-white/50">
  82. <div class="w-full flex justify-center mb-8 mt-4">
  83. <img src="/Millions/img/modal/fail_icon.png" class="w-[160px] h-auto object-contain" alt="Notificaton icon" />
  84. </div>
  85. <div class="px-2 text-center mb-10 flex-1 flex items-center justify-center">
  86. <p id="notificationMessage" class="text-black font-[800] text-[20px] leading-snug"></p>
  87. </div>
  88. <div class="w-full">
  89. <button onclick="closeNotificationModal()" class="w-full bg-[#0062FF] text-white font-[800] text-[18px] py-[12px] rounded-[16px] shadow-lg active:scale-95 transition-all">
  90. @Lang.login
  91. </button>
  92. </div>
  93. </div>
  94. </div>
  95. </div>
  96. @section Scripts {
  97. <script>
  98. const gameConfigs = [
  99. { code: '@Constants.Millions_CODE', name: 'Millions', color: '#0062FF' }
  100. ];
  101. function initBrandedFlatpickr(selector, yearStart, yearEnd) {
  102. const inputEl = document.querySelector(selector);
  103. const wrapper = inputEl.closest('.date-pick-input');
  104. flatpickr(selector, {
  105. dateFormat: "Y-m-d",
  106. altInput: true,
  107. altFormat: "M d, Y",
  108. altInputClass: "bg-transparent border-none outline-none font-bold text-[13px] w-full ml-1 cursor-pointer",
  109. disableMobile: true,
  110. monthSelectorType: "dropdown",
  111. appendTo: wrapper,
  112. onReady: function (selectedDates, dateStr, instance) {
  113. instance.calendarContainer.style.zIndex = "9999";
  114. const yearInput = instance.calendarContainer.querySelector(".numInput.cur-year");
  115. if (yearInput) {
  116. const yearSelect = document.createElement("select");
  117. yearSelect.className = "flatpickr-monthDropdown-months cur-year-select";
  118. yearSelect.style.cssText = "appearance:none; font-weight:800; border:none; background:transparent; color:white; cursor:pointer; margin-left:4px; outline:none; font-family:inherit; font-size:inherit;";
  119. for (let y = yearEnd; y >= yearStart; y--) {
  120. const opt = document.createElement("option");
  121. opt.value = y;
  122. opt.text = y;
  123. opt.style.color = "#333";
  124. if (y === instance.currentYear) opt.selected = true;
  125. yearSelect.appendChild(opt);
  126. }
  127. yearSelect.addEventListener("change", function () {
  128. instance.changeYear(parseInt(this.value));
  129. });
  130. yearInput.style.display = "none";
  131. yearInput.parentNode.appendChild(yearSelect);
  132. }
  133. }
  134. });
  135. }
  136. document.addEventListener('DOMContentLoaded', function() {
  137. initBrandedFlatpickr("#fromDate", 2020, 2030);
  138. initBrandedFlatpickr("#toDate", 2020, 2030);
  139. triggerSearch(); // Initial load for all games
  140. });
  141. var systemUpgrading = false;
  142. function showNotification(message, code) {
  143. $("#notificationMessage").text(message);
  144. const $btn = $("#notificationModal button");
  145. if (code === "-2" || (message && message.includes("System is upgrading"))) {
  146. systemUpgrading = true;
  147. $btn.text("@Lang.login");
  148. } else {
  149. systemUpgrading = false;
  150. $btn.text("OK");
  151. }
  152. $("#notificationModal").removeClass("hidden").addClass("flex");
  153. }
  154. function closeNotificationModal() {
  155. $("#notificationModal").addClass("hidden").removeClass("flex");
  156. if (systemUpgrading) {
  157. window.location.href = subDomain + "/Account/Login";
  158. }
  159. }
  160. async function triggerSearch() {
  161. const fromDate = document.getElementById("fromDate").value;
  162. const toDate = document.getElementById("toDate").value;
  163. const btn = document.getElementById("btnSearch");
  164. const container = document.getElementById("results-list-container");
  165. btn.disabled = true;
  166. btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
  167. container.style.opacity = "0.7";
  168. try {
  169. // Call the new grouped endpoint
  170. const response = await fetch(`${subDomain}/Millions/Home/TermResultHistoryGrouped?fromDate=${fromDate}&toDate=${toDate}`);
  171. if (!response.ok) throw new Error('Network response was not ok');
  172. const html = await response.text();
  173. try {
  174. const json = JSON.parse(html);
  175. if (json.responseCode === "-2" || (json.responseMessage && json.responseMessage.includes("System is upgrading"))) {
  176. showNotification(json.responseMessage || "System is upgrading", "-2");
  177. return;
  178. }
  179. } catch (e) {
  180. // Not JSON, likely HTML partial
  181. }
  182. if (html.trim() === "") {
  183. container.innerHTML = `
  184. <div class="w-full py-20 flex flex-col items-center justify-center text-gray-400 opacity-60">
  185. <i class="fas fa-search text-5xl mb-4"></i>
  186. <p class="font-bold">@Lang.no_results_found</p>
  187. </div>
  188. `;
  189. } else {
  190. container.innerHTML = html;
  191. }
  192. } catch (error) {
  193. console.error("Error loading grouped results:", error);
  194. // Check if the error response is JSON and has code -2
  195. if (error.message && (error.message.includes("System is upgrading") || error.message.includes("-2"))) {
  196. showNotification(error.message, "-2");
  197. } else {
  198. container.innerHTML = `<div class="text-center py-10 text-red-500 font-bold">Error loading results. Please try again.</div>`;
  199. }
  200. }
  201. container.style.opacity = "1";
  202. btn.disabled = false;
  203. btn.innerHTML = '<i class="fas fa-search"></i>';
  204. }
  205. </script>
  206. }