_TermUserTicketHistory.cshtml 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. @model LotteryWebApp.Models.UserTicketHistoryModel
  2. @using LotteryWebApp.Languages
  3. @using LotteryWebApp.Common
  4. @functions {
  5. public string FormatMoney(string amount) {
  6. if (string.IsNullOrEmpty(amount)) return "0";
  7. var clean = new string(amount.Where(c => char.IsDigit(c)).ToArray());
  8. if (long.TryParse(clean, out long val)) {
  9. return val.ToString("#,##0", new System.Globalization.CultureInfo("vi-VN")).Replace(",", ".");
  10. }
  11. return amount;
  12. }
  13. }
  14. @if (Model != null && Model.listTicket != null && Model.listTicket.Count > 0)
  15. {
  16. foreach (var item in Model.listTicket)
  17. {
  18. <div class="ticket-card animate__animated animate__fadeInUp">
  19. <div class="ticket-card-top">
  20. <div class="ticket-header">
  21. <span class="ticket-id">#@item.seq</span>
  22. </div>
  23. <div class="ticket-numbers flex flex-wrap gap-2">
  24. @if (!string.IsNullOrEmpty(item.code))
  25. {
  26. var delimiters = new[] { ';', ',' };
  27. var balls = item.code.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
  28. // Millions result = 5 main numbers + 1 Mega Ball (the last one):
  29. // - the 5 main numbers match in any order
  30. // - the Mega Ball must match by position (the last ticket number)
  31. var resultBalls = !string.IsNullOrEmpty(item.termResult)
  32. ? item.termResult.Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
  33. : new string[0];
  34. var mainWinning = new HashSet<string>();
  35. string mbWinning = null;
  36. if (resultBalls.Length > 0)
  37. {
  38. for (int i = 0; i < resultBalls.Length - 1; i++) mainWinning.Add(resultBalls[i].Trim());
  39. mbWinning = resultBalls[resultBalls.Length - 1].Trim();
  40. }
  41. var mbIndex = balls.Length - 1;
  42. for (int bi = 0; bi < balls.Length; bi++)
  43. {
  44. var ballValue = balls[bi].Trim();
  45. if (!string.IsNullOrEmpty(ballValue))
  46. {
  47. string ballClass;
  48. if (item.status == Constants.NOT_DRAW_CODE) {
  49. ballClass = "ball-waiting";
  50. } else if (bi == mbIndex) {
  51. // Mega Ball: position-based comparison
  52. ballClass = ballValue == mbWinning ? "ball-win" : "ball-lose";
  53. } else if (mainWinning.Contains(ballValue)) {
  54. ballClass = "ball-win";
  55. } else {
  56. ballClass = "ball-lose";
  57. }
  58. var isMbBall = bi == mbIndex;
  59. <div class="ticket-ball @ballClass @(isMbBall ? "ticket-ball-mb" : "")">
  60. <span class="ticket-ball-value">@ballValue</span>
  61. @if (isMbBall)
  62. {
  63. <span class="ticket-mb-label">MB</span>
  64. }
  65. </div>
  66. }
  67. }
  68. }
  69. </div>
  70. </div>
  71. <div class="ticket-perforation"></div>
  72. <div class="ticket-card-bottom">
  73. <div class="ticket-info-grid">
  74. <div class="info-row">
  75. <span class="info-label">@Lang.millions_date_and_time</span>
  76. <span class="info-value">@item.createDate</span>
  77. </div>
  78. <div class="info-row">
  79. <span class="info-label">@Lang.millions_amount_won</span>
  80. <span class="info-value win-amount">@FormatMoney(item.moneyWin) HTG</span>
  81. </div>
  82. <div class="info-row">
  83. <span class="info-label">@Lang.millions_amount_played</span>
  84. <span class="info-value">@FormatMoney(item.money) HTG</span>
  85. </div>
  86. </div>
  87. <!-- Ticket Action: Detail Button -->
  88. <div class="mt-3 pt-3 border-t border-gray-100 flex justify-between items-center">
  89. <div class="flex items-center gap-1.5 text-gray-400">
  90. <i class="fa-solid fa-circle-info text-[12px]"></i>
  91. <span class="text-[10px] font-bold uppercase tracking-tight">@Lang.millions_tap_to_see_detail</span>
  92. </div>
  93. <button onclick="showTicketDetail('@item.billCode', '@item.money', '@item.moneyWin', '@item.createDate', '@item.channel', '@item.channelPayment', '@item.code', '@item.gameId', '@item.termRandomDate', '@item.id')"
  94. class="bg-[#00A3FF] text-white px-5 py-1.5 rounded-lg font-black text-[12px] shadow-[0_4px_10px_rgba(0,163,255,0.3)] active:scale-95 transition-all border-[1.5px] border-white uppercase tracking-wide">
  95. @Lang.millions_detail
  96. </button>
  97. </div>
  98. </div>
  99. </div>
  100. }
  101. @if (Model.totalPage != null && int.Parse(Model.totalPage) > 1)
  102. {
  103. var seq = int.Parse(Model.seqPage);
  104. var total = int.Parse(Model.totalPage);
  105. <div class="flex justify-center items-center gap-4 py-8 pb-32">
  106. <button onclick="changePage(currentSeqPage - 1)"
  107. class="p-2 px-6 bg-white rounded-xl shadow-sm font-bold text-gray-500 active:scale-95 transition-transform disabled:opacity-30 disabled:pointer-events-none"
  108. id="prevPage" @(seq <= 1 ? "disabled" : "")>
  109. <i class="fas fa-chevron-left mr-1"></i> Prev
  110. </button>
  111. <div class="flex flex-col items-center">
  112. <span class="text-[10px] text-gray-400 font-bold uppercase tracking-widest">Page</span>
  113. <span class="font-black text-[#0062FF] text-lg" id="pageDisplay">@Model.seqPage / @Model.totalPage</span>
  114. </div>
  115. <button onclick="changePage(currentSeqPage + 1)"
  116. class="p-2 px-6 bg-white rounded-xl shadow-sm font-bold text-gray-500 active:scale-95 transition-transform disabled:opacity-30 disabled:pointer-events-none"
  117. id="nextPage" @(seq >= total ? "disabled" : "")>
  118. Next <i class="fas fa-chevron-right ml-1"></i>
  119. </button>
  120. </div>
  121. <script>
  122. totalPages = parseInt('@Model.totalPage');
  123. </script>
  124. }
  125. else
  126. {
  127. <div class="w-full pb-32"></div>
  128. }
  129. }
  130. else
  131. {
  132. <div class="w-full py-24 flex flex-col items-center justify-center text-gray-400 opacity-60">
  133. <i class="fas fa-receipt text-5xl mb-4"></i>
  134. <p class="font-bold">@Lang.no_results_found</p>
  135. </div>
  136. }