Răsfoiți Sursa

pick giờ ở pick 10 qua mili

student 5 ore în urmă
părinte
comite
efa6646d3b

+ 97 - 52
website/Areas/LotteryV2/Controllers/HomeController.cs

@@ -141,7 +141,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
 
-                model.termType = termType != null ? termType : Constants.MEGA_LOTO_Pick10;
+                model.termType = termType != null ? termType : Constants.MEGA_LOTO;
                 model.userStatus = userStatus;
                 model.profile = profile;
                 model.listTerm = new List<Term>();
@@ -185,7 +185,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
 
                 if (!string.IsNullOrEmpty(termType))
                 {
-                     HttpContext.Session.SetString("termType", termType);
+                    HttpContext.Session.SetString("termType", termType);
                 }
             }
             catch (Exception ex)
@@ -194,6 +194,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 return RedirectToAction("Login", "Account", new { area = "" });
             }
 
+            model.serverTime = DateTime.Now;
             return View(model);
         }
 
@@ -202,7 +203,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -218,14 +219,14 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
 
                 if (!string.IsNullOrEmpty(termType))
                 {
-                     HttpContext.Session.SetString("termType", termType);
+                    HttpContext.Session.SetString("termType", termType);
                 }
             }
             catch (Exception ex)
             {
                 log.Error(ex);
             }
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         public async Task<IActionResult> FAQ()
@@ -233,7 +234,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -248,7 +249,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             {
                 log.Error(ex);
             }
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         public IActionResult More()
@@ -256,7 +257,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -271,7 +272,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             {
                 log.Error(ex);
             }
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         public IActionResult Profile()
@@ -279,7 +280,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -294,7 +295,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             {
                 log.Error(ex);
             }
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         [HttpPost]
@@ -313,9 +314,11 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 string birthdayFormat = birthday;
                 if (!string.IsNullOrEmpty(birthday) && birthday.Contains("-"))
                 {
-                    try {
+                    try
+                    {
                         birthdayFormat = DateTime.ParseExact(birthday, "yyyy-MM-dd", CultureInfo.InvariantCulture).ToString("dd/MM/yyyy");
-                    } catch { }
+                    }
+                    catch { }
                 }
 
                 UserUpdateProfileRequest request = new UserUpdateProfileRequest
@@ -327,7 +330,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 };
 
                 UserUpdateProfileResponse response = api.UserUpdateProfileApi(configuration, request);
-                
+
                 if (response.status == Code.SUCCESS)
                 {
                     // Update session profile
@@ -354,7 +357,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -369,7 +372,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             {
                 log.Error(ex);
             }
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         public IActionResult HowToPlay()
@@ -377,7 +380,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -392,7 +395,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             {
                 log.Error(ex);
             }
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         public IActionResult Results(string termType, string fromDate, string toDate)
@@ -400,7 +403,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             TermResultHistoryModel model = new TermResultHistoryModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -408,9 +411,9 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
 
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
-                
+
                 model.termType = termType != null ? termType : (HttpContext.Session.GetString("termType") ?? Constants.PIC10_BASIC_CODE);
-                
+
                 // Set default dates if not provided (same as root implementation)
                 string fromFormatted = fromDate != null ? fromDate : DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd");
                 string toFormatted = toDate != null ? toDate : DateTime.Now.ToString("yyyy-MM-dd");
@@ -447,7 +450,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 log.Error(ex);
                 model.listTerm = new List<Term>();
             }
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         public IActionResult TermResultHistory(string termType, string fromDate, string toDate)
@@ -455,7 +458,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             TermResultHistoryModel model = new TermResultHistoryModel();
             try
             {
-               var token = HttpContext.Session.GetComplexData<string>("token");
+                var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token)) return Json(new { status = "error", message = "Session expired" });
 
                 string fromFormatted = fromDate != null ? fromDate : DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd");
@@ -519,7 +522,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                         order = Constants.DECS,
                         fromDate = DateTime.ParseExact(fromFormatted, "yyyy-MM-dd", CultureInfo.InvariantCulture).ToString("dd/MM/yyyy"),
                         toDate = DateTime.ParseExact(toFormatted, "yyyy-MM-dd", CultureInfo.InvariantCulture).ToString("dd/MM/yyyy"),
-                        rowsOnPage = "50", 
+                        rowsOnPage = "50",
                         seqPage = "1",
                         id = Constants.ALL_DATA
                     };
@@ -563,7 +566,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 }
 
                 string msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
-                
+
                 model.termType = termType ?? Constants.PIC10_BASIC_CODE;
                 model.status = status ?? Constants.ALL_DATA; // -1 for all, or 0, 1, 2
                 model.seqPage = seqPage ?? "1";
@@ -596,6 +599,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 log.Error(ex);
                 model.listTicket = new List<Ticket>();
             }
+            model.serverTime = DateTime.Now;
             return View(model);
         }
 
@@ -683,29 +687,28 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
         {
             try
             {
+                log.Info($"[ConfirmTicketData] START - Request: {JsonConvert.SerializeObject(request)}");
                 var token = HttpContext.Session.GetComplexData<string>("token");
                 var msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
-                if (string.IsNullOrEmpty(token)) return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                if (string.IsNullOrEmpty(token))
+                {
+                    log.Info("[ConfirmTicketData] Session expired");
+                    return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                }
 
                 request.token = token;
                 request.msisdn = msisdn;
                 request.language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1";
                 request.requestId = Guid.NewGuid().ToString();
 
-                // DEBUG: Log request data
-                var ticketDebug = request.ticket != null ? string.Join("; ", request.ticket.Select(t => $"code={t.code}, money={t.money}")) : "NULL";
-                log.Info($"[ConfirmTicketData] gameId={request.gameId}, msisdn={request.msisdn}, tickets=[{ticketDebug}]");
-
                 ConfirmTicketDataResponse response = api.ConfirmTicketDataApi(configuration, request);
-                
-                // DEBUG: Log response
-                log.Info($"[ConfirmTicketData] Response: code={response.responseCode}, msg={response.responseMessage}, transId={response.transId}");
-                
+                log.Info($"[ConfirmTicketData] Call ConfirmTicketDataApi Response: {JsonConvert.SerializeObject(response)}");
+
                 return Json(response);
             }
             catch (Exception ex)
             {
-                log.Error(ex);
+                log.Error("[ConfirmTicketData] EXCEPTION: ", ex);
                 return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
             }
         }
@@ -715,19 +718,25 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
         {
             try
             {
+                log.Info($"[ConfirmOTP] START - Request: {JsonConvert.SerializeObject(request)}");
                 var token = HttpContext.Session.GetComplexData<string>("token");
                 var msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
-                if (string.IsNullOrEmpty(token)) return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                if (string.IsNullOrEmpty(token))
+                {
+                    log.Info("[ConfirmOTP] Session expired");
+                    return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                }
 
                 request.token = token;
                 request.msisdn = msisdn;
 
                 ConfirmOTPResponse response = api.ConfirmOTPApi(configuration, request);
+                log.Info($"[ConfirmOTP] Call ConfirmOTPApi Response: {JsonConvert.SerializeObject(response)}");
                 return Json(response);
             }
             catch (Exception ex)
             {
-                log.Error(ex);
+                log.Error("[ConfirmOTP] EXCEPTION: ", ex);
                 return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
             }
         }
@@ -737,9 +746,14 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
         {
             try
             {
+                log.Info("[SendOTP] START");
                 var token = HttpContext.Session.GetComplexData<string>("token");
                 var msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
-                if (string.IsNullOrEmpty(token)) return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                if (string.IsNullOrEmpty(token))
+                {
+                    log.Info("[SendOTP] Session expired");
+                    return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                }
 
                 SendOTPRequest request = new SendOTPRequest
                 {
@@ -748,13 +762,15 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                     language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1",
                     channel = configuration.GetSection("channel").Value
                 };
+                log.Info($"[SendOTP] Call SendOTPApi Request: {JsonConvert.SerializeObject(request)}");
 
                 SendOTPResponse response = api.SendOTPApi(configuration, request);
+                log.Info($"[SendOTP] Call SendOTPApi Response: {JsonConvert.SerializeObject(response)}");
                 return Json(response);
             }
             catch (Exception ex)
             {
-                log.Error(ex);
+                log.Error("[SendOTP] EXCEPTION: ", ex);
                 return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
             }
         }
@@ -764,9 +780,14 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
         {
             try
             {
+                log.Info($"[ConfirmBuyingTicketV2] START - Request: {JsonConvert.SerializeObject(request)}");
                 var token = HttpContext.Session.GetComplexData<string>("token");
                 var msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
-                if (string.IsNullOrEmpty(token)) return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                if (string.IsNullOrEmpty(token))
+                {
+                    log.Info("[ConfirmBuyingTicketV2] Session expired");
+                    return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+                }
 
                 // Step 1: Verify OTP first
                 ConfirmOTPRequest otpRequest = new ConfirmOTPRequest
@@ -777,10 +798,14 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                     language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1",
                     channel = configuration.GetSection("channel").Value
                 };
+                log.Info($"[ConfirmBuyingTicketV2] Call ConfirmOTPApi Request: {JsonConvert.SerializeObject(otpRequest)}");
+
                 ConfirmOTPResponse otpResponse = api.ConfirmOTPApi(configuration, otpRequest);
+                log.Info($"[ConfirmBuyingTicketV2] Call ConfirmOTPApi Response: {JsonConvert.SerializeObject(otpResponse)}");
 
                 if (otpResponse.responseCode != Code.SUCCESS)
                 {
+                    log.Info($"[ConfirmBuyingTicketV2] OTP Verification Failed: {otpResponse.responseMessage}");
                     return Json(new { responseCode = otpResponse.responseCode, responseMessage = otpResponse.responseMessage });
                 }
 
@@ -791,16 +816,23 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 request.language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1";
                 request.channel = configuration.GetSection("channel").Value;
 
+                log.Info($"[ConfirmBuyingTicketV2] Call ConfirmBuyingTicketApi Request: {JsonConvert.SerializeObject(request)}");
+
                 ConfirmBuyingTicketResponse response = api.ConfirmBuyingTicketApi(configuration, request);
+                log.Info($"[ConfirmBuyingTicketV2] Call ConfirmBuyingTicketApi Response: {JsonConvert.SerializeObject(response)}");
+
                 if (response.responseCode == Code.SUCCESS)
                 {
+                    log.Info($"[ConfirmBuyingTicketV2] Payment Success. Updating user status for {msisdn}");
                     UpdateUserStatus(msisdn, token);
                 }
+
+                log.Info($"[ConfirmBuyingTicketV2] END - Result: {JsonConvert.SerializeObject(response)}");
                 return Json(response);
             }
             catch (Exception ex)
             {
-                log.Error(ex);
+                log.Error("[ConfirmBuyingTicketV2] EXCEPTION: ", ex);
                 return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
             }
         }
@@ -825,8 +857,9 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 {
                     UpdateUserStatus(msisdn, token);
                 }
-                return Json(new { 
-                    responseCode = response.responseCode, 
+                return Json(new
+                {
+                    responseCode = response.responseCode,
                     responseMessage = response.responseMessage,
                     transId = response.transId,
                     orderId = response.orderId,
@@ -857,7 +890,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 model.userStatus = userStatus;
                 model.profile = profile;
-                
+
                 // Get active term
                 ResultOfTermRequest request = new ResultOfTermRequest
                 {
@@ -888,7 +921,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                         token = token,
                         type = Constants.TERM_HAS_RESULT_TYPE,
                         order = Constants.DECS,
-                        fromDate = DateTime.Now.AddDays(-10).ToString("dd/MM/yyyy"), 
+                        fromDate = DateTime.Now.AddDays(-10).ToString("dd/MM/yyyy"),
                         toDate = DateTime.Now.ToString("dd/MM/yyyy"),
                         rowsOnPage = "5",
                         seqPage = "1",
@@ -908,7 +941,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                     }
                 }
 
-                return View(model);
+                model.serverTime = DateTime.Now; return View(model);
             }
             catch (Exception ex)
             {
@@ -926,14 +959,15 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             model.profile = HttpContext.Session.GetComplexData<Profile>("profile");
             model.userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
-            return View(model);
+            model.serverTime = DateTime.Now; return View(model);
         }
 
         [HttpPost]
-        public IActionResult ConfirmTransfer(string otp, string phone, string amount)
+        public IActionResult ConfirmTransfer(string otp, string phone, string amount, string channelPayment)
         {
             try
             {
+                log.Info($"[ConfirmTransfer] START - otp: {otp}, phone: {phone}, amount: {amount}, channelPayment: {channelPayment}");
                 var token = HttpContext.Session.GetComplexData<string>("token");
                 var msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
                 if (string.IsNullOrEmpty(token)) return Json(new { status = Code.SESSION_EXPIRED, message = "Session expired" });
@@ -947,7 +981,9 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                     language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1",
                     channel = configuration.GetSection("channel").Value
                 };
+                log.Info($"[ConfirmTransfer] Call ConfirmOTPApi Request: {JsonConvert.SerializeObject(otpRequest)}");
                 ConfirmOTPResponse otpResponse = api.ConfirmOTPApi(configuration, otpRequest);
+                log.Info($"[ConfirmTransfer] Call ConfirmOTPApi Response: {JsonConvert.SerializeObject(otpResponse)}");
 
                 if (otpResponse.responseCode != Code.SUCCESS)
                 {
@@ -962,20 +998,23 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
                     money = amount,
                     otp = otp,
                     token = token,
-                    channelPayment = Constants.BASIC_WALLET_TRANSFER,
+                    channelPayment = channelPayment ?? Constants.BASIC_WALLET_TRANSFER,
                     language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1",
                     channel = configuration.GetSection("channel").Value
                 };
 
+                log.Info($"[ConfirmTransfer] Call TransferMoneyApi Request: {JsonConvert.SerializeObject(xferRequest)}");
                 TransferMoneyResponse xferResponse = api.TransferMoneyApi(configuration, xferRequest);
+                log.Info($"[ConfirmTransfer] Call TransferMoneyApi Response: {JsonConvert.SerializeObject(xferResponse)}");
 
                 if (xferResponse.responseCode == Code.SUCCESS)
                 {
                     UpdateUserStatus(msisdn, token);
                 }
 
-                return Json(new { 
-                    status = xferResponse.responseCode, 
+                return Json(new
+                {
+                    status = xferResponse.responseCode,
                     message = xferResponse.responseMessage,
                     paymentCode = xferResponse.paymentCode,
                     responseCode = xferResponse.responseCode,
@@ -993,16 +1032,22 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
         {
             try
             {
+                log.Info($"[UpdateUserStatus] START - msisdn: {msisdn}");
                 UserStatusRequest userStatusRequest = new UserStatusRequest { users = msisdn, token = token };
+                log.Info($"[UpdateUserStatus] Call GetUserStatusApi Request: {JsonConvert.SerializeObject(userStatusRequest)}");
+
                 UserStatus userStatusGet = api.GetUserStatusApi(configuration, userStatusRequest);
+                log.Info($"[UpdateUserStatus] Call GetUserStatusApi Response: {JsonConvert.SerializeObject(userStatusGet)}");
+
                 if (userStatusGet != null)
                 {
                     HttpContext.Session.SetComplexData("userStatus", userStatusGet);
                 }
+                log.Info("[UpdateUserStatus] END");
             }
             catch (Exception ex)
             {
-                log.Error("UpdateUserStatus Error: " + ex.Message);
+                log.Error("[UpdateUserStatus] EXCEPTION: ", ex);
             }
         }
 

+ 97 - 95
website/Areas/LotteryV2/Views/Home/GameHome.cshtml

@@ -9,10 +9,12 @@
 
 
 @functions {
-    public string FormatMoney(string amount) {
+    public string FormatMoney(string amount)
+    {
         if (string.IsNullOrEmpty(amount)) return "0";
         var clean = new string(amount.Where(c => char.IsDigit(c)).ToArray());
-        if (long.TryParse(clean, out long val)) {
+        if (long.TryParse(clean, out long val))
+        {
             return val.ToString("#,##0", new System.Globalization.CultureInfo("vi-VN")).Replace(",", ".");
         }
         return amount;
@@ -43,20 +45,20 @@
 
         <!-- Row 2: Pill Actions Full Width Split -->
         <div class="grid grid-cols-2 gap-3 mt-4">
-             <a onclick="checkTerm('@Constants.PIC10_BASIC_CODE')" class="btn-pulse border border-white/50 rounded-xl py-2 px-3 flex items-center justify-center gap-1 text-xr font-extrabold bg-white/10 hover:bg-white/20 transition-all text-white no-underline">
-                 <span class="text-yellow-300 text-xl">⚡</span> @Lang.quick_pick
-             </a>
-             <a href="/LotteryV2/Home/Results" class="btn-pulse border border-white/50 rounded-xl py-2 px-3 flex items-center justify-center gap-1 text-xr font-extrabold bg-white/10 hover:bg-white/20 transition-all text-white no-underline">
+            <a onclick="checkTerm('@Constants.PIC10_BASIC_CODE')" class="btn-pulse border border-white/50 rounded-xl py-2 px-3 flex items-center justify-center gap-1 text-xr font-extrabold bg-white/10 hover:bg-white/20 transition-all text-white no-underline">
+                <span class="text-yellow-300 text-xl">⚡</span> @Lang.quick_pick
+            </a>
+            <a href="/LotteryV2/Home/Results" class="btn-pulse border border-white/50 rounded-xl py-2 px-3 flex items-center justify-center gap-1 text-xr font-extrabold bg-white/10 hover:bg-white/20 transition-all text-white no-underline">
                 <span class="text-yellow-300 text-xl">🎫</span> @Lang.results
-             </a>
+            </a>
         </div>
 
         <!-- Row 3: Withdraw Button Full Width -->
         <div class="w-full mt-3">
-             <button onclick="location.href='@Url.Action("TransferWinMoney", "Home")'" class="btn-pulse w-full text-black font-black py-3 rounded-2xl text-[18px] flex items-center justify-center gap-2 shadow-lg transition-all" style="background: linear-gradient(118deg, #19EF4B 0%, #C0FF4B 100%);">
-                 <span>@Lang.tranfer_win_money</span>
-                 <img src="/LotteryV2/img/gold_wallet.png" alt="Wallet" class="w-6 h-6 object-contain">
-             </button>
+            <button onclick="location.href='@Url.Action("TransferWinMoney", "Home")'" class="btn-pulse w-full text-black font-black py-3 rounded-2xl text-[18px] flex items-center justify-center gap-2 shadow-lg transition-all" style="background: linear-gradient(118deg, #19EF4B 0%, #C0FF4B 100%);">
+                <span>@Lang.tranfer_win_money</span>
+                <img src="/LotteryV2/img/gold_wallet.png" alt="Wallet" class="w-6 h-6 object-contain">
+            </button>
         </div>
     </div>
 
@@ -64,37 +66,37 @@
     <div class="relative w-full overflow-hidden" style="background-image: url('/LotteryV2/img/wavy_border.svg'); background-size: 102% 100%; background-position: center; background-repeat: no-repeat; height: 114px;">
         <!-- Top border red line -->
         <div class="absolute top-0 left-0 w-full h-[1.5px] bg-[#EE0033]"></div>
-        
+
         <div class="flex items-center justify-between px-4 pt-7 relative z-10">
-             <!-- Left: Draw Date -->
-             <div class="flex items-center gap-1 flex-1 min-w-0">
-                 <div class="w-8 h-8 flex-shrink-0">
-                     <img src="/LotteryV2/img/calendar_icon_3d.png" alt="Calendar" class="w-full h-full object-contain" onerror="this.src='/LotteryV2/img/icon_calendar.svg'">
-                 </div>
-                 <div class="flex flex-col min-w-0">
-                     <span class="text-[11px] text-[#A1A1A1] font-bold leading-none mb-1">Next Pick 10 draw</span>
-                     <span class="text-[12px] font-[900] text-black tracking-tight leading-none" id="draw-date">Friday, Mar 20, 2026</span>
-                 </div>
-             </div>
-
-             <!-- Middle: Dashed Divider -->
-             <div class="h-10 w-px border-l border-dashed border-gray-300 mx-2"></div>
-             
-             <!-- Right: Timer -->
-             <div class="flex gap-4 shrink-0">
-                 <div class="flex flex-col items-center min-w-[42px]">
-                     <span class="text-[10px] text-[#A1A1A1] font-bold uppercase tracking-tighter mb-1">@Lang.hours</span>
-                     <span class="text-[28px] font-black text-black leading-none font-bricolage" id="countdown-hours">00</span>
-                 </div>
-                 <div class="flex flex-col items-center min-w-[42px]">
+            <!-- Left: Draw Date -->
+            <div class="flex items-center gap-1 flex-1 min-w-0">
+                <div class="w-8 h-8 flex-shrink-0">
+                    <img src="/LotteryV2/img/calendar_icon_3d.png" alt="Calendar" class="w-full h-full object-contain" onerror="this.src='/LotteryV2/img/icon_calendar.svg'">
+                </div>
+                <div class="flex flex-col min-w-0">
+                    <span class="text-[11px] text-[#A1A1A1] font-bold leading-none mb-1">Next Pick 10 draw</span>
+                    <span class="text-[12px] font-[900] text-black tracking-tight leading-none" id="draw-date">Friday, Mar 20, 2026</span>
+                </div>
+            </div>
+
+            <!-- Middle: Dashed Divider -->
+            <div class="h-10 w-px border-l border-dashed border-gray-300 mx-2"></div>
+
+            <!-- Right: Timer -->
+            <div class="flex gap-4 shrink-0">
+                <div class="flex flex-col items-center min-w-[42px]">
+                    <span class="text-[10px] text-[#A1A1A1] font-bold uppercase tracking-tighter mb-1">@Lang.hours</span>
+                    <span class="text-[28px] font-black text-black leading-none font-bricolage" id="countdown-hours">00</span>
+                </div>
+                <div class="flex flex-col items-center min-w-[42px]">
                     <span class="text-[10px] text-[#A1A1A1] font-bold uppercase tracking-tighter mb-1">@Lang.Minutes</span>
-                     <span class="text-[28px] font-black text-black leading-none font-bricolage" id="countdown-minutes">00</span>
-                 </div>
-                 <div class="flex flex-col items-center min-w-[42px]">
+                    <span class="text-[28px] font-black text-black leading-none font-bricolage" id="countdown-minutes">00</span>
+                </div>
+                <div class="flex flex-col items-center min-w-[42px]">
                     <span class="text-[10px] text-[#A1A1A1] font-bold uppercase tracking-tighter mb-1">@Lang.Secs</span>
-                     <span class="text-[28px] font-black text-black leading-none font-bricolage" id="countdown-seconds">00</span>
-                 </div>
-             </div>
+                    <span class="text-[28px] font-black text-black leading-none font-bricolage" id="countdown-seconds">00</span>
+                </div>
+            </div>
         </div>
     </div>
 
@@ -103,12 +105,12 @@
 
     <!-- Card list items with accurate illustrations -->
     <div class="px-3 flex flex-col gap-2 pb-40 relative z-10 mt-[14px]">
-        
+
         <!-- Game item 1: Basic Pick 10 -->
         <div class="relative w-full h-[120px] rounded-2xl overflow-hidden shadow-xl font-bricolage transition-all duration-300 active:scale-[0.98] cursor-pointer card-red" onclick="checkTerm('@Constants.PIC10_BASIC_CODE')">
             <!-- 1. Premium Gradient Border -->
             <div class="absolute inset-0 rounded-2xl border-[1.5px] border-white/40 pointer-events-none z-20"></div>
-            
+
             <!-- 2. Decorative Highlights -->
             <img src="/LotteryV2/img/decorations/ellipse_1183.png" class="absolute -left-[80px] -top-[130px] w-[220px] h-[220px] pointer-events-none z-10 mix-blend-screen scale-y-[-1]" alt="highlight">
             <img src="/LotteryV2/img/decorations/ellipse_1181.png" class="absolute -right-[60px] -top-[20px] w-[200px] h-[200px] pointer-events-none z-10 mix-blend-screen" alt="highlight">
@@ -120,7 +122,7 @@
                     <div class="flex flex-col items-center leading-[0.85] relative z-10 font-UTM_Futura_Extra">
                         <span class="text-white font-[900] text-[16px] drop-shadow-md">@Lang.Basic</span>
                         <span class="font-[900] text-[30px] drop-shadow-lg leading-[0.9]" style="background: linear-gradient(180deg, #FFFFFF 20%, #FFF307 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">@Lang.Pick</span>
-                        
+
                         <!-- Floating Bubbles (Matching Image) -->
                         <div class="absolute top-[-4px] right-[-4px] w-2.5 h-2.5 bg-white rounded-full shadow-sm"></div>
                         <div class="absolute top-[18px] right-[-6px] w-2 h-2 bg-yellow-400 rounded-full shadow-sm"></div>
@@ -159,7 +161,7 @@
         <div class="relative w-full h-[120px] rounded-2xl overflow-hidden shadow-xl font-bricolage transition-all duration-300 active:scale-[0.98] cursor-pointer card-shadow text-white border border-white/10" style="background-color: rgb(38 163 30);" onclick="checkTerm('@Constants.PIC10_BIGSMALL_CODE')">
             <!-- 1. Premium Gradient Border -->
             <div class="absolute inset-0 rounded-2xl border-[1.5px] border-white/40 pointer-events-none z-20"></div>
-            
+
             <!-- 2. Decorative Highlights -->
             <img src="/LotteryV2/img/decorations/ellipse_1183.png" class="absolute -left-[80px] -top-[130px] w-[220px] h-[220px] pointer-events-none z-10 mix-blend-screen scale-y-[-1]" alt="highlight">
             <img src="/LotteryV2/img/decorations/ellipse_1181.png" class="absolute -right-[60px] -top-[20px] w-[200px] h-[200px] pointer-events-none z-10 mix-blend-screen" alt="highlight">
@@ -171,12 +173,12 @@
                     <div class="flex flex-col items-center leading-[0.85] relative z-10 font-UTM_Futura_Extra">
                         <span class="text-white font-[900] text-[16px] drop-shadow-md">@Lang.Small</span>
                         <span class="font-[900] text-[30px] drop-shadow-lg leading-[0.9]" style="background: linear-gradient(180deg, #FFFFFF 20%, #89FF77 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">@Lang.Big</span>
-                        
+
                         <!-- Decorative dots (Bubbles) -->
-                         <div class="absolute -top-1 -right-1 w-2.5 h-2.5 bg-white/40 rounded-full blur-[1px]"></div>
-                         <div class="absolute top-1/2 -right-5 w-2 h-2 bg-white rounded-full shadow-sm opacity-90"></div>
-                         <div class="absolute -bottom-2 left-6 w-1.5 h-1.5 bg-yellow-200 rounded-full opacity-80"></div>
-                         <div class="absolute top-2 -left-2 w-1.5 h-1.5 bg-white/60 rounded-full"></div>
+                        <div class="absolute -top-1 -right-1 w-2.5 h-2.5 bg-white/40 rounded-full blur-[1px]"></div>
+                        <div class="absolute top-1/2 -right-5 w-2 h-2 bg-white rounded-full shadow-sm opacity-90"></div>
+                        <div class="absolute -bottom-2 left-6 w-1.5 h-1.5 bg-yellow-200 rounded-full opacity-80"></div>
+                        <div class="absolute top-2 -left-2 w-1.5 h-1.5 bg-white/60 rounded-full"></div>
                     </div>
 
                     <!-- Single Ball 88 -->
@@ -210,7 +212,7 @@
         <div class="relative w-full h-[120px] rounded-2xl overflow-hidden shadow-xl font-bricolage transition-all duration-300 active:scale-[0.98] cursor-pointer card-shadow text-white border border-white/10" style="background-color: rgb(213 45 233);" onclick="checkTerm('@Constants.PIC10_ODDEVEN_CODE')">
             <!-- 1. Premium Gradient Border -->
             <div class="absolute inset-0 rounded-2xl border-[1.5px] border-white/40 pointer-events-none z-20"></div>
-            
+
             <!-- 2. Decorative Highlights -->
             <img src="/LotteryV2/img/decorations/ellipse_1183.png" class="absolute -left-[80px] -top-[130px] w-[220px] h-[220px] pointer-events-none z-10 mix-blend-screen scale-y-[-1]" alt="highlight">
             <img src="/LotteryV2/img/decorations/ellipse_1181.png" class="absolute -right-[60px] -top-[20px] w-[200px] h-[200px] pointer-events-none z-10 mix-blend-screen" alt="highlight">
@@ -222,23 +224,23 @@
                     <div class="flex flex-col items-center leading-[0.85] relative z-10 font-UTM_Futura_Extra">
                         <span class="text-white font-[900] text-[16px] drop-shadow-md">@Lang.Odd</span>
                         <span class="font-[900] text-[30px] drop-shadow-lg leading-[0.9]" style="background: linear-gradient(180deg, #FFFFFF 20%, #F29CFF 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">@Lang.Even</span>
-                        
+
                         <!-- Decorative dots (Bubbles) -->
-                         <div class="absolute -top-2 -right-2 w-3 h-3 bg-white/30 rounded-full blur-[1px]"></div>
-                         <div class="absolute top-1/2 -right-5 w-2 h-2 bg-yellow-300 rounded-full shadow-sm"></div>
-                         <div class="absolute -top-1 -left-1 w-1.5 h-1.5 bg-white/50 rounded-full"></div>
-                         <div class="absolute -bottom-2 right-2 w-1.5 h-1.5 bg-white rounded-full opacity-80"></div>
+                        <div class="absolute -top-2 -right-2 w-3 h-3 bg-white/30 rounded-full blur-[1px]"></div>
+                        <div class="absolute top-1/2 -right-5 w-2 h-2 bg-yellow-300 rounded-full shadow-sm"></div>
+                        <div class="absolute -top-1 -left-1 w-1.5 h-1.5 bg-white/50 rounded-full"></div>
+                        <div class="absolute -bottom-2 right-2 w-1.5 h-1.5 bg-white rounded-full opacity-80"></div>
                     </div>
 
                     <!-- Balls Overlapping -->
                     <div class="relative w-[60px] h-[60px] flex-shrink-0 -ml-6 -mt-2 aspect-square z-20">
                         <!-- Ball 3 (Yellow) -->
                         <div class="absolute left-0 top-0 w-8 h-8 rounded-full shadow-lg z-0">
-                             <img src="/LotteryV2/img/ball_3.png" alt="3" class="w-full h-full object-contain">
+                            <img src="/LotteryV2/img/ball_3.png" alt="3" class="w-full h-full object-contain">
                         </div>
                         <!-- Ball 20 (Pink/Magenta) -->
                         <div class="absolute left-4 top-3 w-9 h-9 rounded-full shadow-xl z-10">
-                             <img src="/LotteryV2/img/ball_20.png" alt="20" class="w-full h-full object-contain border-2 border-white/20 rounded-full">
+                            <img src="/LotteryV2/img/ball_20.png" alt="20" class="w-full h-full object-contain border-2 border-white/20 rounded-full">
                         </div>
                         <!-- Small highlight dot near ball -->
                         <div class="absolute -top-1 right-2 w-1.5 h-1.5 bg-white rounded-full shadow-sm opacity-90"></div>
@@ -267,14 +269,14 @@
 
     <!-- Banner Info Section centered red text bar -->
     <div class="fixed bottom-[82px] left-1/2 -translate-x-1/2 w-full min-[600px]:max-w-[414px] bg-[#EE0033] text-white py-2 text-center text-[13px] font-bold tracking-wide z-40 flex flex-col items-center justify-center overflow-hidden h-auto shadow-md">
-         <div class="flex flex-col items-center w-full animate-slide-up">
-             <!-- Row 1 -->
-             <div class="opacity-90">@Lang.have_chance_to_get</div>
-             <!-- Row 2 -->
-             <div class="text-[20px] font-black text-[#FBF3A7] mt-0.5">
-                  @Lang.jackpot_today_htg
-             </div>
-         </div>
+        <div class="flex flex-col items-center w-full animate-slide-up">
+            <!-- Row 1 -->
+            <div class="opacity-90">@Lang.have_chance_to_get</div>
+            <!-- Row 2 -->
+            <div class="text-[20px] font-black text-[#FBF3A7] mt-0.5">
+                @Lang.jackpot_today_htg
+            </div>
+        </div>
     </div>
 
     <!-- Custom Notification Modal (Branded design from Profile) -->
@@ -296,7 +298,7 @@
             <div class="w-full">
                 <button onclick="closeNotificationModal()" class="w-full bg-[#EE0033] text-white font-[800] text-[20px] py-[12px] rounded-[14px] shadow-lg active:scale-95 transition-all">
                     @Lang.try_again
-                </button> 
+                </button>
             </div>
         </div>
     </div>
@@ -336,7 +338,7 @@
 
             // Get anti-forgery token from the page
             var token = $('input[name="__RequestVerificationToken"]').val();
-            
+
             // Show loading or disable buttons if needed
             $.ajax({
                 url: subDomain + '/LotteryV2/Home/TermResult',
@@ -378,43 +380,43 @@
         }
 
         function startCountdown() {
-            const targetHour = 20; // 20:00 (8h tối)
-            const now = new Date();
-            let target = new Date();
-            target.setHours(targetHour, 0, 0, 0);
-
-            if (now >= target) {
-                target.setDate(target.getDate() + 1);
-            }
+            const targetHour = 20; // 20:00 (8 PM) Haiti time
+            const timeZone = 'America/Port-au-Prince';
+            const timers = document.querySelectorAll('.countdown-timer');
 
-            // Định dạng ngày hiển thị (VD: Friday, Mar 20, 2026)
-            const options = { weekday: 'long', month: 'short', day: 'numeric', year: 'numeric' };
-            const dateText = target.toLocaleDateString('en-US', options);
-            document.getElementById('draw-date').innerText = dateText;
+            // Server time string has no offset => must be interpreted in Haiti timezone
+            const serverTimeStr = '@Model.serverTime.ToString("yyyy-MM-ddTHH:mm:ss")';
+            const startBrowser = moment();
+            const baseServer = moment.tz(serverTimeStr, 'YYYY-MM-DDTHH:mm:ss', timeZone);
 
             function updateTime() {
-                const current = new Date();
-                const diff = target - current;
-
-                if (diff <= 0) {
-                    target.setDate(target.getDate() + 1);
-                    const updatedDateText = target.toLocaleDateString('en-US', options);
-                    document.getElementById('draw-date').innerText = updatedDateText;
-                    updateTime();
-                    return;
-                }
+                const elapsedMs = moment().diff(startBrowser);
+                const now = baseServer.clone().add(elapsedMs, 'milliseconds'); // Haiti time
+
+                let target = now.clone().hour(targetHour).minute(0).second(0).millisecond(0);
+                if (now.isSameOrAfter(target)) target.add(1, 'day');
+
+                // Draw date display (e.g. Friday, Mar 20, 2026) in Haiti time
+                const dateText = target.clone().locale('en').format('dddd, MMM D, YYYY');
+                const drawDateEl = document.getElementById('draw-date');
+                if (drawDateEl) drawDateEl.innerText = dateText;
+
+                const dur = moment.duration(target.diff(now));
+                const hours = Math.max(0, Math.floor(dur.asHours()));
+                const minutes = Math.max(0, dur.minutes());
+                const seconds = Math.max(0, dur.seconds());
 
-                const hours = Math.floor((diff / (1000 * 60 * 60)));
-                const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
-                const seconds = Math.floor((diff % (1000 * 60)) / 1000);
+                const hhEl = document.getElementById('countdown-hours');
+                const mmEl = document.getElementById('countdown-minutes');
+                const ssEl = document.getElementById('countdown-seconds');
 
-                document.getElementById('countdown-hours').innerText = hours.toString().padStart(2, '0');
-                document.getElementById('countdown-minutes').innerText = minutes.toString().padStart(2, '0');
-                document.getElementById('countdown-seconds').innerText = seconds.toString().padStart(2, '0');
+                if (hhEl) hhEl.innerText = hours.toString().padStart(2, '0');
+                if (mmEl) mmEl.innerText = minutes.toString().padStart(2, '0');
+                if (ssEl) ssEl.innerText = seconds.toString().padStart(2, '0');
 
                 // Update all card timers
                 const timeStr = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
-                document.querySelectorAll('.countdown-timer').forEach(t => t.innerText = timeStr);
+                timers.forEach(t => t.innerText = timeStr);
             }
 
             updateTime();

+ 38 - 33
website/Areas/LotteryV2/Views/Home/Index.cshtml

@@ -20,7 +20,7 @@
         <div class="w-56 z-10 filter drop-shadow-md">
             <img src="/LotteryV2/img/logo.png" alt="Logo" class="w-full h-auto object-contain">
         </div>
-        
+
         <!-- Banner Illustration sits absolute layered or under -->
         <div class="w-full -mt-12">
             <img src="/LotteryV2/img/top_banner.png" alt="Top Banner" class="w-full h-auto object-cover">
@@ -31,10 +31,10 @@
     <div class="px-3 -mt-24 relative z-30">
         <div class="flex flex-col gap-3">
             <!-- Game Card 1: Basic Pick 10 -->
-            <div class="relative w-full h-[120px] rounded-2xl overflow-hidden shadow-2xl transform active:scale-[0.98] transition-all duration-300 cursor-pointer animate__animated animate__slideInUp card-red" onclick="changeGame('@Constants.MEGA_LOTO_Pick10', 'LotteryV2')">
+            <div class="relative w-full h-[120px] rounded-2xl overflow-hidden shadow-2xl transform active:scale-[0.98] transition-all duration-300 cursor-pointer animate__animated animate__slideInUp card-red" onclick="changeGame()">
                 <!-- 1. Premium Gradient Border -->
                 <div class="absolute inset-0 rounded-2xl border-[1.5px] border-white/40 pointer-events-none z-20"></div>
-                
+
                 <!-- 2. Decorative Highlights -->
                 <img src="/LotteryV2/img/decorations/ellipse_1183.png" class="absolute -left-[80px] -top-[130px] w-[220px] h-[220px] pointer-events-none z-10 mix-blend-screen opacity-90 scale-y-[-1]" alt="highlight">
                 <img src="/LotteryV2/img/decorations/ellipse_1181.png" class="absolute -right-[60px] -top-[20px] w-[200px] h-[200px] pointer-events-none z-10 mix-blend-screen opacity-90" alt="highlight">
@@ -43,7 +43,7 @@
                     <!-- Left: Basic Pick + Ball (4 columns) -->
                     <div class="col-span-4 flex items-center gap-1 pl-1">
                         <div class="flex flex-col leading-none">
-                            <span class="text-white font-black italic text-[14px]">@Lang.Basic</span>
+                            <!-- <span class="text-white font-black italic text-[14px]">@Lang.Basic</span> -->
                             <span class="text-yellow-400 font-black italic text-[22px] -mt-1 shadow-sm">@Lang.Pick</span>
                         </div>
                         <div class="w-8 h-8 bg-gradient-to-br from-yellow-300 to-yellow-500 rounded-full border-[2px] border-white flex items-center justify-center shadow-xl transform rotate-12 flex-shrink-0">
@@ -64,25 +64,25 @@
                     <!-- Right: Action Section (4 columns) -->
                     <div class="col-span-4 flex flex-col items-center justify-end h-full pb-4 relative cursor-pointer group">
                         <img src="/LotteryV2/img/gold.png" alt="Chest" class="absolute bottom-[40px] w-16 h-18 object-contain filter drop-shadow-lg z-10 group-active:scale-95 transition-transform">
-                        <button class="bg-gradient-to-b from-yellow-300 to-white text-black font-black px-2 w-full max-w-[110px] py-1.5 rounded-[12px] text-[13px] shadow-xl border border-white/50 group-hover:brightness-110 group-active:scale-95 transition-all relative z-0" id="MEGA_LOTO_ID" value="@Constants.MEGA_LOTO_Pick10">@Lang.rule_play_now</button>
+                        <button class="bg-gradient-to-b from-yellow-300 to-white text-black font-black px-2 w-full max-w-[110px] py-1.5 rounded-[12px] text-[13px] shadow-xl border border-white/50 group-hover:brightness-110 group-active:scale-95 transition-all relative z-0" id="MEGA_LOTO_ID" value="@Constants.MEGA_LOTO">@Lang.rule_play_now</button>
                     </div>
                 </div>
             </div>
 
             <!-- Card 2 and 3 commented out by user previously -->
             <!-- Game Card 2: Millionair - Blurred/Faded State -->
-            <div class="card-blue relative w-full h-[120px] rounded-2xl overflow-hidden shadow-md animate__animated animate__slideInUp animate__delay-1s cursor-pointer" onclick="changeGame('@Constants.MEGA_LOTO_Millions', 'Millions')">
+            <div class="card-blue relative w-full h-[120px] rounded-2xl overflow-hidden shadow-md opacity-25 grayscale blur-[1px] pointer-events-none animate__animated animate__slideInUp animate__delay-1s">
                 <!-- 1. Premium Gradient Border -->
                 <div class="absolute inset-0 rounded-2xl border-[1.5px] border-white/20 pointer-events-none z-20"></div>
-                
+
                 <!-- 2. Decorative Highlights -->
                 <div class="absolute -left-[70px] -top-[108px] w-[193px] h-[193px] bg-gradient-to-br from-white/30 to-transparent rounded-full blur-3xl pointer-events-none"></div>
 
                 <div class="absolute inset-0 grid grid-cols-12 items-center px-3 z-20 gap-0 text-white">
                     <!-- Left: Millionair text content (4 columns) -->
                     <div class="col-span-4 flex items-center h-full relative pl-1">
-                         <img src="/LotteryV2/img/m1.png" alt="Icon" class="absolute -left-2 bottom-0 h-[90px] object-contain z-0 opacity-80">
-                         <div class="relative z-10 text-[14px] font-black italic tracking-wider text-white drop-shadow-lg leading-tight pl-2">@Lang.millionair</div>
+                        <img src="/LotteryV2/img/m1.png" alt="Icon" class="absolute -left-2 bottom-0 h-[90px] object-contain z-0 opacity-80">
+                        <div class="relative z-10 text-[14px] font-black italic tracking-wider text-white drop-shadow-lg leading-tight pl-2">@Lang.millionair</div>
                     </div>
 
                     <!-- Center: Jackpot info (4 columns) -->
@@ -98,20 +98,20 @@
                     <!-- Right: Action Section (4 columns) -->
                     <div class="col-span-4 flex flex-col items-center justify-end h-full pb-4 relative px-1">
                         <img src="/LotteryV2/img/money_bag_large.png" alt="Money Bag" class="absolute bottom-[40px] w-16 h-18 object-contain filter drop-shadow-lg z-10">
-                        <button class="bg-gradient-to-b from-yellow-300 to-white text-black font-black px-2 w-full max-w-[110px] py-1.5 rounded-[12px] text-[13px] shadow-xl border border-white/50 group-hover:brightness-110 group-active:scale-95 transition-all relative z-0" id="MEGA_LOTO_ID" value="@Constants.MEGA_LOTO_Millions">@Lang.rule_play_now</button>
+                        <button class="bg-gradient-to-b from-yellow-300 to-white text-black font-black px-2 w-full max-w-[110px] py-1.5 rounded-[12px] text-[13px] shadow-xl border border-white/50 group-hover:brightness-110 group-active:scale-95 transition-all relative z-0">@Lang.rule_play_now</button>
                     </div>
                 </div>
             </div>
 
             <!-- Game Card 3: Mega Bet - Blurred/Faded State -->
             <div class="card-orange relative w-full h-[120px] rounded-2xl overflow-hidden shadow-md opacity-25 grayscale blur-[1px] pointer-events-none animate__animated animate__slideInUp animate__delay-2s">
-                 <!-- 1. Premium Gradient Border -->
-                 <div class="absolute inset-0 rounded-2xl border-[1.5px] border-white/20 pointer-events-none z-20"></div>
+                <!-- 1. Premium Gradient Border -->
+                <div class="absolute inset-0 rounded-2xl border-[1.5px] border-white/20 pointer-events-none z-20"></div>
 
-                 <!-- 2. Decorative Highlights -->
-                 <div class="absolute -left-[70px] -top-[108px] w-[193px] h-[193px] bg-gradient-to-br from-white/30 to-transparent rounded-full blur-3xl pointer-events-none"></div>
+                <!-- 2. Decorative Highlights -->
+                <div class="absolute -left-[70px] -top-[108px] w-[193px] h-[193px] bg-gradient-to-br from-white/30 to-transparent rounded-full blur-3xl pointer-events-none"></div>
 
-                 <div class="absolute inset-0 grid grid-cols-12 items-center px-3 z-20 gap-0 text-white">
+                <div class="absolute inset-0 grid grid-cols-12 items-center px-3 z-20 gap-0 text-white">
                     <!-- Left: Mega Bet text content (4 columns) -->
                     <div class="col-span-4 flex flex-col items-start justify-center pl-2">
                         <div class="relative">
@@ -146,32 +146,37 @@
 
 </div>
 <script>
-    function changeGame(termType, area) {
-        location.href = subDomain + '/' + area + '/Home/GameHome?termType=' + termType;
+    function changeGame() {
+        var termType = $("#MEGA_LOTO_ID").val();
+        location.href = subDomain + '@Url.Action("GameHome", "Home", new { area = "LotteryV2" })?termType=' + termType;
     }
 
     function startCountdown() {
-        const targetHour = 20; // 20:00 (8 PM)
+        const targetHour = 20; // 20:00 (8 PM) Haiti time
+        const timeZone = 'America/Port-au-Prince';
         const timers = document.querySelectorAll('.countdown-timer');
-        
+
+        // Server time string has no offset => must be interpreted in Haiti timezone
+        const serverTimeStr = '@Model.serverTime.ToString("yyyy-MM-ddTHH:mm:ss")';
+        const startBrowser = moment();
+        const baseServer = moment.tz(serverTimeStr, 'YYYY-MM-DDTHH:mm:ss', timeZone);
+
         function update() {
-            const now = new Date();
-            let target = new Date();
-            target.setHours(targetHour, 0, 0, 0);
-            
-            if (now >= target) {
-                target.setDate(target.getDate() + 1);
-            }
-            
-            const diff = target - now;
-            const h = Math.floor(diff / (1000 * 60 * 60));
-            const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
-            const s = Math.floor((diff % (1000 * 60)) / 1000);
-            
+            const elapsedMs = moment().diff(startBrowser);
+            const now = baseServer.clone().add(elapsedMs, 'milliseconds'); // Haiti time
+
+            let target = now.clone().hour(targetHour).minute(0).second(0).millisecond(0);
+            if (now.isSameOrAfter(target)) target.add(1, 'day');
+
+            const dur = moment.duration(target.diff(now));
+            const h = Math.max(0, Math.floor(dur.asHours()));
+            const m = Math.max(0, dur.minutes());
+            const s = Math.max(0, dur.seconds());
+
             const timeStr = `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
             timers.forEach(t => t.innerText = timeStr);
         }
-        
+
         update();
         setInterval(update, 1000);
     }

+ 15 - 6
website/Areas/LotteryV2/Views/Shared/_Layout.cshtml

@@ -5,10 +5,10 @@
     <meta charset="utf-8" />
     <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
     <title>@ViewData["Title"] - LotteryV2</title>
-    
+
     <!-- Original website bootstrap if needed, or link separate -->
     <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css" />
-    
+
     <!-- Isolated CSS just for LotteryV2 -->
     <link rel="stylesheet" href="/LotteryV2/css/site.css" />
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
@@ -16,10 +16,15 @@
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
     <link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;700;800&display=swap" rel="stylesheet">
     <style>
-        .font-bricolage { font-family: 'Bricolage Grotesque', sans-serif; }
-        .font-UTM_Futura_Extra { font-family: 'UTM Futura Extra', sans-serif; }
+        .font-bricolage {
+            font-family: 'Bricolage Grotesque', sans-serif;
+        }
+
+        .font-UTM_Futura_Extra {
+            font-family: 'UTM Futura Extra', sans-serif;
+        }
     </style>
-    
+
     @RenderSection("Styles", required: false)
 </head>
 <body class="lottery-v2-bg">
@@ -37,7 +42,11 @@
     <!-- Original jquery or similar -->
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/bootstrap/js/bootstrap.bundle.min.js"></script>
-    
+
+    <!-- Moment (timezone-safe countdown) -->
+    <script src="/js/vendors/moment-with-locales.min.js"></script>
+    <script src="/js/vendors/moment-timezone-with-data.min.js"></script>
+
     <!-- Isolated JS just for LotteryV2 -->
     <script src="/LotteryV2/js/site.js"></script>