student il y a 1 mois
Parent
commit
dd3d264afc
65 fichiers modifiés avec 4462 ajouts et 134 suppressions
  1. 31 0
      FIGMA_MCP_INTEGRATION.md
  2. 478 1
      website/Areas/LotteryV2/Controllers/HomeController.cs
  3. 1244 0
      website/Areas/LotteryV2/Views/Home/BuyTicket.cshtml
  4. 5 2
      website/Areas/LotteryV2/Views/Home/FAQ.cshtml
  5. 101 19
      website/Areas/LotteryV2/Views/Home/GameHome.cshtml
  6. 141 0
      website/Areas/LotteryV2/Views/Home/History.cshtml
  7. 5 25
      website/Areas/LotteryV2/Views/Home/Index.cshtml
  8. 2 1
      website/Areas/LotteryV2/Views/Home/More.cshtml
  9. 168 17
      website/Areas/LotteryV2/Views/Home/Profile.cshtml
  10. 177 0
      website/Areas/LotteryV2/Views/Home/Results.cshtml
  11. 39 35
      website/Areas/LotteryV2/Views/Home/Rule.cshtml
  12. 350 0
      website/Areas/LotteryV2/Views/Home/TransferWinMoney.cshtml
  13. 48 0
      website/Areas/LotteryV2/Views/Home/_TermResultHistoryV2.cshtml
  14. 87 0
      website/Areas/LotteryV2/Views/Home/_TermUserTicketHistory.cshtml
  15. 1 1
      website/Areas/LotteryV2/Views/Shared/_BottomNavbar.cshtml
  16. 32 0
      website/Areas/LotteryV2/Views/Shared/_Layout.cshtml
  17. 7 1
      website/Common/Constants.cs
  18. 537 6
      website/Languages/Lang.Designer.cs
  19. 185 11
      website/Languages/Lang.fr.resx
  20. 185 11
      website/Languages/Lang.resx
  21. 1 2
      website/LotteryWebApp.csproj
  22. 10 1
      website/Models/HomeViewModel.cs
  23. 55 0
      website/wwwroot/LotteryV2/css/buy-ticket.css
  24. 185 0
      website/wwwroot/LotteryV2/css/history.css
  25. 221 0
      website/wwwroot/LotteryV2/css/results.css
  26. 42 1
      website/wwwroot/LotteryV2/css/site.css
  27. 2 0
      website/wwwroot/LotteryV2/img/Rectangle 132.svg
  28. BIN
      website/wwwroot/LotteryV2/img/bigsmall/ball_1_big.png
  29. BIN
      website/wwwroot/LotteryV2/img/bigsmall/ball_42_dark.png
  30. BIN
      website/wwwroot/LotteryV2/img/bigsmall/ball_54_dark.png
  31. BIN
      website/wwwroot/LotteryV2/img/bigsmall/ball_5_blue.png
  32. BIN
      website/wwwroot/LotteryV2/img/bigsmall/ball_88_big.png
  33. BIN
      website/wwwroot/LotteryV2/img/bigsmall/ball_8_pink.png
  34. BIN
      website/wwwroot/LotteryV2/img/bigsmall/bg_curve.png
  35. BIN
      website/wwwroot/LotteryV2/img/bigsmall/card_big_full.png
  36. BIN
      website/wwwroot/LotteryV2/img/bigsmall/card_small_full.png
  37. BIN
      website/wwwroot/LotteryV2/img/bigsmall/light_effect_1.png
  38. BIN
      website/wwwroot/LotteryV2/img/bigsmall/light_effect_2.png
  39. BIN
      website/wwwroot/LotteryV2/img/bigsmall/select_btn.png
  40. BIN
      website/wwwroot/LotteryV2/img/bigsmall/selected_btn.png
  41. BIN
      website/wwwroot/LotteryV2/img/modal/fail_icon.png
  42. BIN
      website/wwwroot/LotteryV2/img/modal/otp_coins.png
  43. BIN
      website/wwwroot/LotteryV2/img/modal/otp_glitter.png
  44. 48 0
      website/wwwroot/LotteryV2/img/modal/otp_light_1.svg
  45. 48 0
      website/wwwroot/LotteryV2/img/modal/otp_light_2.svg
  46. BIN
      website/wwwroot/LotteryV2/img/modal/otp_shield.png
  47. 9 0
      website/wwwroot/LotteryV2/img/modal/otp_sparkle_1.svg
  48. 9 0
      website/wwwroot/LotteryV2/img/modal/otp_sparkle_2.svg
  49. 9 0
      website/wwwroot/LotteryV2/img/modal/otp_sparkle_3.svg
  50. BIN
      website/wwwroot/LotteryV2/img/modal/otp_success.png
  51. BIN
      website/wwwroot/LotteryV2/img/modal/success_footer.png
  52. BIN
      website/wwwroot/LotteryV2/img/modal/success_header.png
  53. BIN
      website/wwwroot/LotteryV2/img/oddeven/ball_1.png
  54. BIN
      website/wwwroot/LotteryV2/img/oddeven/ball_19.png
  55. BIN
      website/wwwroot/LotteryV2/img/oddeven/ball_3.png
  56. BIN
      website/wwwroot/LotteryV2/img/oddeven/ball_66.png
  57. BIN
      website/wwwroot/LotteryV2/img/oddeven/ball_68.png
  58. BIN
      website/wwwroot/LotteryV2/img/oddeven/ball_88.png
  59. BIN
      website/wwwroot/LotteryV2/img/transfer_account_card.png
  60. BIN
      website/wwwroot/LotteryV2/img/transfer_arrow_left.png
  61. BIN
      website/wwwroot/LotteryV2/img/transfer_basic_icon.png
  62. BIN
      website/wwwroot/LotteryV2/img/transfer_gold_coin.png
  63. BIN
      website/wwwroot/LotteryV2/img/transfer_gold_stack.png
  64. BIN
      website/wwwroot/LotteryV2/img/transfer_other_card.png
  65. BIN
      website/wwwroot/LotteryV2/img/transfer_wallet_icon.png

+ 31 - 0
FIGMA_MCP_INTEGRATION.md

@@ -0,0 +1,31 @@
+# Figma MCP Integration with Antigravity IDE
+
+Figma MCP (Model Context Protocol) is **already configured** in your Antigravity IDE global settings.
+
+## 🛠 Configuration Details
+- **Location**: `C:\Users\ADMIN\.gemini\antigravity\mcp_config.json`
+- **MCP Server**: `figma-developer-mcp`
+- **Authentication**: A Figma API Key is already configured in the environment.
+
+---
+
+## ⚠️ Issue & Fix Applied
+The server was failing to load initially due to **Node.js v17.9.1** (which has issues with some modern package dependencies like `hono`).
+- **Fix**: I have switched the active Node version to **v18.20.8** using `nvm use 18.20.8`.
+
+---
+
+## 🚀 How to Use
+
+Now that it's active, you can instruct me to interact with your Figma design!
+
+To read a design or generate code, simply chat with me providing:
+1.  **Figma File URL**: `https://www.figma.com/design/...`
+2.  **Node/Layer Name** or **ID** (Optional, if you want a specific component)
+
+### Example prompts:
+> "Hãy đọc thiết kế từ Figma URL [URL] và sinh code HTML/Tailwind cho màn hình Login"
+> "Liệt kê các thành phần (components) trong file Figma [URL]"
+
+---
+**Status**: Ready to use. No further installation required. If the IDE doesn't pick it up immediately, a quick restart of the IDE will complete the process.

+ 478 - 1
website/Areas/LotteryV2/Controllers/HomeController.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Linq;
 using System.Globalization;
 using System.Globalization;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
@@ -18,6 +19,7 @@ using LotteryWebApp.Controllers;
 namespace LotteryWebApp.Areas.LotteryV2.Controllers
 namespace LotteryWebApp.Areas.LotteryV2.Controllers
 {
 {
     [Area("LotteryV2")]
     [Area("LotteryV2")]
+    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
     public class HomeController : BaseController
     public class HomeController : BaseController
     {
     {
         private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
         private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
@@ -200,7 +202,7 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             try
             {
             {
-                var token = HttpContext.Session.GetString("token");
+               var token = HttpContext.Session.GetComplexData<string>("token");
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
                 {
                 {
                     return RedirectToAction("Login", "Account", new { area = "" });
                     return RedirectToAction("Login", "Account", new { area = "" });
@@ -231,6 +233,12 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             try
             {
             {
+               var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 model.userStatus = userStatus;
                 model.userStatus = userStatus;
@@ -248,6 +256,12 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             try
             {
             {
+               var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 model.userStatus = userStatus;
                 model.userStatus = userStatus;
@@ -265,6 +279,12 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             try
             {
             {
+               var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 model.userStatus = userStatus;
                 model.userStatus = userStatus;
@@ -277,11 +297,69 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             return View(model);
             return View(model);
         }
         }
 
 
+        [HttpPost]
+        public IActionResult UserUpdateProfile(string fullName, string birthday)
+        {
+            try
+            {
+                string msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
+                string token = HttpContext.Session.GetComplexData<string>("token");
+
+                if (string.IsNullOrEmpty(msisdn) || string.IsNullOrEmpty(token))
+                {
+                    return Json(new { status = Code.ERROR, message = "Session expired" });
+                }
+
+                string birthdayFormat = birthday;
+                if (!string.IsNullOrEmpty(birthday) && birthday.Contains("-"))
+                {
+                    try {
+                        birthdayFormat = DateTime.ParseExact(birthday, "yyyy-MM-dd", CultureInfo.InvariantCulture).ToString("dd/MM/yyyy");
+                    } catch { }
+                }
+
+                UserUpdateProfileRequest request = new UserUpdateProfileRequest
+                {
+                    users = msisdn,
+                    token = token,
+                    fullName = fullName,
+                    birthday = birthdayFormat
+                };
+
+                UserUpdateProfileResponse response = api.UserUpdateProfileApi(configuration, request);
+                
+                if (response.status == Code.SUCCESS)
+                {
+                    // Update session profile
+                    Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
+                    if (profile != null)
+                    {
+                        profile.fullName = fullName;
+                        profile.birthday = birthdayFormat;
+                        HttpContext.Session.SetComplexData("profile", profile);
+                    }
+                }
+
+                return Json(response);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                return Json(new { status = Code.ERROR, message = ex.Message });
+            }
+        }
+
         public IActionResult Rule()
         public IActionResult Rule()
         {
         {
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             try
             {
             {
+               var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 model.userStatus = userStatus;
                 model.userStatus = userStatus;
@@ -299,6 +377,12 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();
             try
             try
             {
             {
+               var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
                 model.userStatus = userStatus;
                 model.userStatus = userStatus;
@@ -311,6 +395,399 @@ namespace LotteryWebApp.Areas.LotteryV2.Controllers
             return View(model);
             return View(model);
         }
         }
 
 
+        public IActionResult Results(string termType, string fromDate, string toDate)
+        {
+            TermResultHistoryModel model = new TermResultHistoryModel();
+            try
+            {
+               var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
+                Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
+                UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
+                
+                model.termType = termType != null ? termType : (HttpContext.Session.GetString("termType") ?? Constants.MEGA_LOTO);
+                
+                // Set default dates if not provided (same as root implementation)
+                string fromFormatted = fromDate != null ? fromDate : DateTime.Now.AddDays(-7).ToString("yyyy-MM-dd");
+                string toFormatted = toDate != null ? toDate : DateTime.Now.ToString("yyyy-MM-dd");
+
+                model.fromDate = fromFormatted;
+                model.toDate = toFormatted;
+
+                // Load initial results
+                ResultOfTermRequest resultOfTermRequest = new ResultOfTermRequest
+                {
+                    gameId = model.termType,
+                    token = token,
+                    type = Constants.TERM_HAS_RESULT_TYPE,
+                    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 = Constants.ROW_ON_PAGE,
+                    seqPage = "1",
+                    id = Constants.ALL_DATA
+                };
+
+                ResultOfTermResponse result = api.GetResultOfTermApi(configuration, resultOfTermRequest);
+                if (result.responseCode == Code.SUCCESS)
+                {
+                    model.listTerm = result.listTerm ?? new List<Term>();
+                }
+                else {
+                    model.listTerm = new List<Term>();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                model.listTerm = new List<Term>();
+            }
+            return View(model);
+        }
+
+        public IActionResult TermResultHistory(string termType, string fromDate, string toDate)
+        {
+            TermResultHistoryModel model = new TermResultHistoryModel();
+            try
+            {
+               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(-7).ToString("yyyy-MM-dd");
+                string toFormatted = toDate != null ? toDate : DateTime.Now.ToString("yyyy-MM-dd");
+
+                model.termType = termType;
+                model.fromDate = fromFormatted;
+                model.toDate = toFormatted;
+
+                ResultOfTermRequest request = new ResultOfTermRequest
+                {
+                    gameId = termType,
+                    token = token,
+                    type = Constants.TERM_HAS_RESULT_TYPE,
+                    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 = Constants.ROW_ON_PAGE,
+                    seqPage = "1",
+                    id = Constants.ALL_DATA
+                };
+
+                ResultOfTermResponse result = api.GetResultOfTermApi(configuration, request);
+                if (result.responseCode == Code.SUCCESS)
+                {
+                    model.listTerm = result.listTerm ?? new List<Term>();
+                }
+                else {
+                    model.listTerm = new List<Term>();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                model.listTerm = new List<Term>();
+            }
+            return PartialView("_TermResultHistoryV2", model);
+        }
+
+        public IActionResult History(string termType, string status, string seqPage)
+        {
+            UserTicketHistoryModel model = new UserTicketHistoryModel();
+            try
+            {
+                var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
+                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";
+
+                UserTicketRequest request = new UserTicketRequest
+                {
+                    gameId = model.termType,
+                    msisdn = msisdn,
+                    token = token,
+                    type = model.status,
+                    order = Constants.DECS,
+                    rowsOnPage = Constants.ROW_ON_PAGE,
+                    seqPage = model.seqPage
+                };
+
+                UserTicketResponse result = api.GetUserTicketApi(configuration, request);
+                if (result.responseCode == Code.SUCCESS)
+                {
+                    model.listTicket = result.listTicket ?? new List<Ticket>();
+                    model.totalPage = result.totalPage;
+                }
+                else
+                {
+                    model.listTicket = new List<Ticket>();
+                    model.totalPage = "0";
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                model.listTicket = new List<Ticket>();
+            }
+            return View(model);
+        }
+
+        public IActionResult TermUserTicketHistory(string termType, string status, string seqPage)
+        {
+            UserTicketHistoryModel model = new UserTicketHistoryModel();
+            try
+            {
+                var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token)) return Json(new { status = "error", message = "Session expired" });
+
+                string msisdn = HttpContext.Session.GetComplexData<string>("msisdn");
+
+                model.termType = termType;
+                model.status = status;
+                model.seqPage = seqPage ?? "1";
+
+                UserTicketRequest request = new UserTicketRequest
+                {
+                    gameId = termType,
+                    msisdn = msisdn,
+                    token = token,
+                    type = status,
+                    order = Constants.DECS,
+                    rowsOnPage = Constants.ROW_ON_PAGE,
+                    seqPage = model.seqPage
+                };
+
+                UserTicketResponse result = api.GetUserTicketApi(configuration, request);
+                if (result.responseCode == Code.SUCCESS)
+                {
+                    model.listTicket = result.listTicket ?? new List<Ticket>();
+                    model.totalPage = result.totalPage;
+                }
+                else
+                {
+                    model.listTicket = new List<Ticket>();
+                    model.totalPage = "0";
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                model.listTicket = new List<Ticket>();
+            }
+            return PartialView("_TermUserTicketHistory", model);
+        }
+
+        [HttpPost]
+        [ValidateAntiForgeryToken]
+        public IActionResult TermResult(string termType)
+        {
+            try
+            {
+                var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token)) return Json(new { responseCode = Code.SESSION_EXPIRED, responseMessage = "Session expired" });
+
+                string lang = CultureInfo.CurrentCulture.Name;
+                string langValue = (lang.StartsWith("en") || lang.StartsWith("fr")) ? "0" : "1";
+
+                ResultOfTermRequest request = new ResultOfTermRequest
+                {
+                    gameId = termType,
+                    language = langValue,
+                    token = token,
+                    type = Constants.TERM_HAS_NOT_RESULT_TYPE,
+                    order = Constants.DECS,
+                    rowsOnPage = "5",
+                    seqPage = "1",
+                    id = Constants.ALL_DATA
+                };
+
+                ResultOfTermResponse result = api.GetResultOfTermApi(configuration, request);
+                return Json(result);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
+            }
+        }
+
+        [HttpPost]
+        public IActionResult ConfirmTicketData([FromBody] ConfirmTicketDataRequest request)
+        {
+            try
+            {
+                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" });
+
+                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}");
+                
+                return Json(response);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
+            }
+        }
+
+        [HttpPost]
+        public IActionResult ConfirmOTP([FromBody] ConfirmOTPRequest request)
+        {
+            try
+            {
+                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" });
+
+                request.token = token;
+                request.msisdn = msisdn;
+
+                ConfirmOTPResponse response = api.ConfirmOTPApi(configuration, request);
+                return Json(response);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
+            }
+        }
+
+        [HttpPost]
+        public IActionResult SendOTP()
+        {
+            try
+            {
+                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" });
+
+                SendOTPRequest request = new SendOTPRequest
+                {
+                    msisdn = msisdn,
+                    token = token,
+                    language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1",
+                    channel = configuration.GetSection("channel").Value
+                };
+
+                SendOTPResponse response = api.SendOTPApi(configuration, request);
+                return Json(response);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
+            }
+        }
+
+        [HttpPost]
+        public IActionResult ConfirmBuyingTicket([FromBody] ConfirmBuyingTicketRequest request)
+        {
+            try
+            {
+                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" });
+
+                request.token = token;
+                request.msisdn = msisdn;
+                request.requestId = Guid.NewGuid().ToString();
+                request.language = CultureInfo.CurrentCulture.Name.StartsWith("en") ? "0" : "1";
+                request.channel = configuration.GetSection("channel").Value;
+
+                ConfirmBuyingTicketResponse response = api.ConfirmBuyingTicketApi(configuration, request);
+                return Json(response);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                return Json(new { responseCode = Code.ERROR, responseMessage = ex.Message });
+            }
+        }
+
+        public IActionResult BuyTicket(string termType)
+        {
+            try
+            {
+                var token = HttpContext.Session.GetComplexData<string>("token");
+                if (string.IsNullOrEmpty(token) && !User.Identity.IsAuthenticated)
+                {
+                    return RedirectToAction("Login", "Account", new { area = "" });
+                }
+
+                HomeIndex_ViewModel model = new HomeIndex_ViewModel();
+                model.termType = termType ?? Constants.PIC10_BASIC_CODE;
+
+                Profile profile = HttpContext.Session.GetComplexData<Profile>("profile");
+                UserStatus userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
+                model.userStatus = userStatus;
+                model.profile = profile;
+                
+                // Get active term
+                ResultOfTermRequest request = new ResultOfTermRequest
+                {
+                    gameId = model.termType,
+                    token = token,
+                    type = Constants.TERM_HAS_NOT_RESULT_TYPE,
+                    order = Constants.DECS,
+                    rowsOnPage = "1",
+                    seqPage = "1",
+                    id = Constants.ALL_DATA
+                };
+
+                ResultOfTermResponse result = api.GetResultOfTermApi(configuration, request);
+                if (result.responseCode == Code.SUCCESS && result.listTerm != null && result.listTerm.Count > 0)
+                {
+                    model.listTerm = result.listTerm;
+                }
+                else
+                {
+                    model.listTerm = new List<Term>();
+                }
+
+                return View(model);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                return RedirectToAction("GameHome", new { termType = termType });
+            }
+        }
+
+        public IActionResult TransferWinMoney()
+        {
+            if (!CheckAuthToken())
+            {
+                return RedirectToAction("Login", "Account", new { area = "" });
+            }
+            HomeIndex_ViewModel model = new HomeIndex_ViewModel();
+            model.profile = HttpContext.Session.GetComplexData<Profile>("profile");
+            model.userStatus = HttpContext.Session.GetComplexData<UserStatus>("userStatus");
+            return View(model);
+        }
+
         public IActionResult Logout()
         public IActionResult Logout()
         {
         {
             ClearCache();
             ClearCache();

+ 1244 - 0
website/Areas/LotteryV2/Views/Home/BuyTicket.cshtml

@@ -0,0 +1,1244 @@
+@model LotteryWebApp.Models.HomeIndex_ViewModel
+@{
+    ViewData["Title"] = "LotteryV2 - Buy Ticket";
+    Layout = "~/Areas/LotteryV2/Views/Shared/_Layout.cshtml";
+    var currentTerm = Model.listTerm?.FirstOrDefault();
+}
+@using LotteryWebApp.Languages;
+@using LotteryWebApp.Common;
+
+<link rel="stylesheet" href="/LotteryV2/css/buy-ticket.css" />
+
+<link rel="stylesheet" href="/LotteryV2/css/buy-ticket.css" />
+
+@if (Model.termType == Constants.PIC10_BIGSMALL_CODE || Model.termType == Constants.PIC10_ODDEVEN_CODE)
+{
+    var isBigSmall = Model.termType == Constants.PIC10_BIGSMALL_CODE;
+    var themeColor = isBigSmall ? "#0A9800" : "#AA3DC8";
+    var gameTitle = isBigSmall ? Lang.v2_big_small : Lang.v2_odd_even;
+    var prizeAmount = isBigSmall ? "100" : "200";
+    
+    <!-- ==================== CARD SELECTION GAME UI (BIG/SMALL or ODD/EVEN) ==================== -->
+    <div class="main-container animate__animated animate__fadeIn bg-[#F5F5F5] h-screen flex flex-col font-bricolage overflow-hidden max-w-[414px] mx-auto relative">
+        <!-- Header -->
+        <div class="w-full py-3 px-4 text-white flex items-center justify-between sticky top-0 z-[60]" style="background: @themeColor;">
+            <button onclick="location.href='@Url.Action("GameHome", "Home")'" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-all">
+                <i class="fa-solid fa-arrow-left text-[20px]"></i>
+            </button>
+            <span class="font-[800] text-[18px] absolute left-1/2 -translate-x-1/2 whitespace-nowrap">
+                @gameTitle
+            </span>
+            <div class="w-8"></div>
+        </div>
+
+        <!-- Sticky Term Info sub-header -->
+        <div class="p-4 py-2.5 bg-white flex items-center justify-between shadow-sm sticky top-[52px] z-50">
+            <div class="flex items-center gap-2 border border-[#E5E7EB] rounded-lg px-3 py-1.5 bg-gray-50">
+                <i class="fa-regular fa-calendar text-[[@themeColor]] text-sm" style="color: @themeColor"></i>
+                <span class="text-[12px] font-bold text-gray-700">@DateTime.Now.ToString("dddd, MMM dd, yyyy", System.Globalization.CultureInfo.InvariantCulture)</span>
+            </div>
+            <div class="flex items-center gap-1 ml-4 flex-1 justify-end">
+                <span class="text-[12px] font-bold text-gray-400">@Lang.v2_round</span>
+                <span class="text-[18px] font-black text-brown-main">#@(currentTerm?.id ?? "123")</span>
+            </div>
+        </div>
+
+        <!-- Scrollable Content Area -->
+        <div class="flex-1 overflow-y-auto bg-white pb-40" id="bsContent">
+            <!-- Results for the last 5 days -->
+            <div class="px-5 pt-4 pb-2">
+                <h3 class="text-[17px] font-bold text-black text-center mb-3">Results for the last 5 days</h3>
+                <div id="last5Results" class="flex justify-between gap-1.5 px-1">
+                    @* Mock data for results *@
+                    @for(int r=0; r<5; r++) {
+                        var resTitle = isBigSmall ? (r % 2 == 0 ? "Big" : "Small") : (r % 2 == 0 ? "Odd" : "Even");
+                        var resColor = isBigSmall ? (resTitle == "Big" ? "#A2FF00" : "#FF4157") : (resTitle == "Odd" ? "#FFC700" : "#B33BD0");
+                        <div class="flex flex-col items-center justify-center min-h-[56px] flex-1 rounded-lg py-1.5 border border-gray-200" style="background: linear-gradient(136deg, #FFFAE6 0%, #FFE588 100%);">
+                            <span class="text-[10px] font-bold text-black whitespace-nowrap opacity-70">Mar @(16+r)</span>
+                            <span class="text-[18px] font-black leading-tight" style="-webkit-text-stroke: 0.5px #000; color: @resColor;">@resTitle</span>
+                        </div>
+                    }
+                </div>
+            </div>
+
+            <!-- Selection Cards -->
+            <!-- Selection Cards -->
+            <div class="px-5 pt-4 flex gap-3 h-[245px]">
+                <!-- Card 1 (Big or Odd) -->
+                <div id="cardBig" onclick="selectBigSmall('big')" class="bigsmall-card flex-1 rounded-2xl relative cursor-pointer transition-all duration-300 active:scale-[0.97] border-2 border-transparent overflow-hidden flex flex-col" style="background: linear-gradient(180deg, #FFF7DB 0%, #FFEEB3 100%);">
+                    <img src="/LotteryV2/img/bigsmall/light_effect_1.png" class="absolute top-0 left-0 w-full opacity-60 pointer-events-none" alt="" />
+                    <img src="/LotteryV2/img/bigsmall/light_effect_2.png" class="absolute bottom-12 left-0 w-full opacity-60 pointer-events-none" alt="" />
+                    <div class="flex flex-col items-center pt-4 pb-3 px-3 relative z-10 h-full justify-between">
+                        <div class="flex flex-col items-center w-full">
+                            <div class="h-[34px] flex items-center justify-center">
+                                <div class="text-[30px] font-[800] leading-none" style="-webkit-text-stroke: 1px #000; text-shadow: 1px 2px 2px rgba(0,0,0,0.15); color: @(isBigSmall ? "#A2FF00" : "#FFC700");">@(isBigSmall ? "Big" : "Odd")</div>
+                            </div>
+                            <div class="text-[11px] font-medium text-gray-500 mt-1 h-[28px] text-center leading-tight">
+                                @(isBigSmall ? "13 number from" : "Odd numbers") <br/> <b>@(isBigSmall ? "41-80" : "1, 3, 5, 7, 9")</b>
+                            </div>
+                        </div>
+                        <div class="flex items-center justify-center -space-x-2 my-2">
+                            @if (isBigSmall) {
+                                <img src="/LotteryV2/img/bigsmall/ball_42_dark.png" class="w-12 h-12 relative z-[1]" alt="42" />
+                                <img src="/LotteryV2/img/bigsmall/ball_88_big.png" class="w-16 h-16 relative z-[2]" alt="88" />
+                                <img src="/LotteryV2/img/bigsmall/ball_54_dark.png" class="w-12 h-12 relative z-[1]" alt="54" />
+                            } else {
+                                <img src="/LotteryV2/img/oddeven/ball_3.png" class="w-12 h-12 relative z-[1]" alt="3" />
+                                <img src="/LotteryV2/img/oddeven/ball_1.png" class="w-16 h-16 relative z-[2]" alt="1" />
+                                <img src="/LotteryV2/img/oddeven/ball_19.png" class="w-12 h-12 relative z-[1]" alt="19" />
+                            }
+                        </div>
+                        <button class="bigsmall-btn w-full py-2.5 rounded-xl font-black text-[15px] transition-all shadow-md" style="background: @themeColor; color: white;">@Lang.v2_select</button>
+                    </div>
+                </div>
+
+                <!-- Card 2 (Small or Even) -->
+                <div id="cardSmall" onclick="selectBigSmall('small')" class="bigsmall-card flex-1 rounded-2xl relative cursor-pointer transition-all duration-300 active:scale-[0.97] border-2 border-transparent overflow-hidden flex flex-col" style="background: linear-gradient(180deg, #FFF7DB 0%, #FFEEB3 100%);">
+                    <img src="/LotteryV2/img/bigsmall/light_effect_1.png" class="absolute top-0 left-0 w-full opacity-60 pointer-events-none" alt="" />
+                    <img src="/LotteryV2/img/bigsmall/light_effect_2.png" class="absolute bottom-12 left-0 w-full opacity-60 pointer-events-none" alt="" />
+                    <div class="flex flex-col items-center pt-4 pb-3 px-3 relative z-10 h-full justify-between">
+                        <div class="flex flex-col items-center w-full">
+                            <div class="h-[34px] flex items-center justify-center">
+                                <div class="text-[22px] font-[800] leading-none italic" style="-webkit-text-stroke: 1px #000; text-shadow: 1px 2px 2px rgba(0,0,0,0.15); color: @(isBigSmall ? "#FF4157" : "#B33BD0");">@(isBigSmall ? "Small" : "Even")</div>
+                            </div>
+                            <div class="text-[11px] font-medium text-gray-500 mt-1 h-[28px] text-center leading-tight">
+                                @(isBigSmall ? "13 number from" : "Even numbers") <br/> <b>@(isBigSmall ? "01-40" : "0, 2, 4, 6, 8")</b>
+                            </div>
+                        </div>
+                        <div class="flex items-center justify-center -space-x-2 my-2">
+                            @if (isBigSmall) {
+                                <img src="/LotteryV2/img/bigsmall/ball_5_blue.png" class="w-12 h-12 relative z-[1]" alt="5" />
+                                <img src="/LotteryV2/img/bigsmall/ball_1_big.png" class="w-16 h-16 relative z-[2]" alt="1" />
+                                <img src="/LotteryV2/img/bigsmall/ball_8_pink.png" class="w-12 h-12 relative z-[1]" alt="8" />
+                            } else {
+                                <img src="/LotteryV2/img/oddeven/ball_66.png" class="w-12 h-12 relative z-[1]" alt="66" />
+                                <img src="/LotteryV2/img/oddeven/ball_68.png" class="w-16 h-16 relative z-[2]" alt="68" />
+                                <img src="/LotteryV2/img/oddeven/ball_88.png" class="w-12 h-12 relative z-[1]" alt="88" />
+                            }
+                        </div>
+                        <button class="bigsmall-btn w-full py-2.5 rounded-xl font-black text-[15px] transition-all shadow-md"
+								style="background: @themeColor; color: white;">@Lang.v2_select</button>
+                    </div>
+                </div>
+            </div>
+
+            <!-- You Choose + Prize Section -->
+            <div class="px-5 pt-6 flex flex-col items-center gap-4">
+                <div class="flex flex-col items-center">
+                    <span class="text-[12px] font-medium text-gray-500">@Lang.v2_you_choose</span>
+                    <span id="choiceDisplay" class="text-[32px] font-[800] leading-tight" style="-webkit-text-stroke: 1px #000;">—</span>
+                </div>
+                <div class="flex flex-col items-center">
+                    <span class="text-[12px] font-medium text-gray-500">@Lang.v2_prize_if_win</span>
+                    <div class="flex items-baseline gap-1">
+                        <span class="text-[28px] font-black text-black">@prizeAmount</span>
+                        <span class="text-[14px] font-black text-[#E56B23]">HTG</span>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- Bottom Action Bar -->
+        <div class="p-4 bg-white border-t border-gray-200 z-[70] shadow-[0px_-4px_10px_rgba(0,0,0,0.03)] absolute bottom-0 w-full left-0">
+            <div class="flex items-center justify-between">
+                <div class="flex flex-col">
+                    <span class="text-[12px] text-gray-500 font-bold uppercase">@Lang.v2_estimated_ticket_price</span>
+                    <div class="flex items-baseline gap-1">
+                        <span id="bsTotalPrice" class="text-[28px] font-black text-black">50</span>
+                        <span class="text-[13px] font-black" style="color: @themeColor">HTG</span>
+                    </div>
+                </div>
+                <button id="bsPaymentBtn" onclick="bsShowPayment()" class="text-white text-[20px] font-black px-10 py-3.5 rounded-xl shadow-lg active:scale-95 transition-all" style="background: @themeColor;">
+                    @Lang.v2_payment
+                </button>
+            </div>
+        </div>
+    </div>
+}
+else
+{
+<!-- ==================== CLASSIC PICK 10 / ODD-EVEN GAME UI ==================== -->
+<div class="main-container animate__animated animate__fadeIn bg-[#F5F5F5] h-screen flex flex-col font-bricolage overflow-hidden max-w-[414px] mx-auto relative">
+    <!-- Header -->
+    <div class="w-full bg-[#EE0033] py-3 px-4 text-white flex items-center justify-between sticky top-0 z-[60]">
+        <button onclick="location.href='@Url.Action("GameHome", "Home")'" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-all">
+            <i class="fa-solid fa-arrow-left text-[20px]"></i>
+        </button>
+        <span class="font-[800] text-[18px] absolute left-1/2 -translate-x-1/2 whitespace-nowrap">
+            @if (Model.termType == Constants.PIC10_BASIC_CODE) { @Lang.v2_buy_classic_pick_10 }
+            else { @Lang.v2_odd_even }
+        </span>
+        <div class="w-8"></div>
+    </div>
+
+    <!-- Sticky Term Info sub-header -->
+    <div class="p-4 py-2.5 bg-white flex items-center justify-between shadow-sm sticky top-[52px] z-50">
+        <div class="flex items-center gap-2 border border-[#E5E7EB] rounded-lg px-3 py-1.5 bg-gray-50">
+            <i class="fa-regular fa-calendar text-[#EE0033] text-sm"></i>
+            <span class="text-[12px] font-bold text-gray-700">@DateTime.Now.ToString("dddd, MMM dd, yyyy", System.Globalization.CultureInfo.InvariantCulture)</span>
+        </div>
+        <div class="flex items-center gap-1 ml-4 flex-1 justify-end">
+            <span class="text-[12px] font-bold text-gray-400">@Lang.v2_round</span>
+            <span class="text-[18px] font-black text-brown-main">#@(currentTerm?.id ?? "12459")</span>
+        </div>
+    </div>
+
+    <!-- Ticket Scrollable List Area -->
+    <div id="ticketContainer" class="p-4 flex flex-col gap-6 flex-1 overflow-y-auto bg-[#F5F5F5]">
+        @for (int i = 1; i <= 2; i++)
+        {
+            <div class="ticket-card relative group active:bg-gray-50 transition-colors cursor-pointer animate__animated animate__fadeIn">
+                <button onclick="removeEntry(this)" class="absolute -right-2 top-2 w-7 h-7 bg-[#999] text-white rounded-full flex items-center justify-center text-[11px] shadow-sm z-[10] hover:bg-red-500 transition-all border-2 border-white">
+                    <i class="fa-solid fa-xmark"></i>
+                </button>
+                <div class="absolute left-2 top-4 w-9 h-9 rounded-full bg-[#EE0033] border-[3px] border-white flex items-center justify-center text-white font-black text-sm shadow-md ticket-index">@i</div>
+                <div class="flex flex-col gap-1 pl-8">
+                    <span class="text-[16px] font-extrabold text-[#333]">@Lang.v2_select_10_lucky_numbers</span>
+                    <div class="flex items-start gap-4">
+                        <div class="grid grid-cols-5 gap-y-1 gap-x-2 flex-1">
+                            @for (int j = 0; j < (Model.termType == Constants.PIC10_BASIC_CODE ? 10 : 15); j++)
+                            {
+                                <div class="ball-circle ball-empty"></div>
+                            }
+                        </div>
+                        <div class="w-20 action-area flex flex-col gap-2">
+                             <button onclick="randomizeTicket(this)" class="rand-btn bg-green-main text-white flex items-center justify-center gap-2 w-20 py-2 rounded-xl font-extrabold text-[11px] shadow-sm active:scale-95 transition-all">
+                                <i class="fa-solid fa-arrows-rotate text-[10px]"></i> @Lang.Random
+                             </button>
+                             <div class="edit-delete-group hidden flex flex-col gap-2">
+                                 <button onclick="editFullTicket(this)" class="bg-[#2B83F2] text-white flex items-center justify-center gap-2 w-20 py-1.5 rounded-lg font-bold text-[12px] shadow-sm active:scale-95 transition-all">
+                                    <i class="fa-solid fa-pen text-[10px]"></i> @Lang.v2_edit
+                                 </button>
+                                 <button onclick="clearTicket(this)" class="bg-[#EE0033] text-white flex items-center justify-center gap-2 w-20 py-1.5 rounded-lg font-bold text-[12px] shadow-sm active:scale-95 transition-all">
+                                    <i class="fa-solid fa-trash-can text-[10px]"></i> @Lang.v2_delete
+                                 </button>
+                             </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        }
+
+        <div class="w-full pt-2" id="addButtonWrapper">
+            <button onclick="addNewTicket()" class="w-fit min-w-[220px] mx-auto bg-green-main text-white font-black text-md py-2.5 px-6 rounded-xl shadow-md border-b-[4px] border-[#129A30] active:translate-y-[1px] active:border-b-[1px] transition-all flex items-center justify-center gap-2">
+                @Lang.v2_add_more_ticket
+            </button>
+        </div>
+        <div class="h-4"></div>
+    </div>
+
+    <!-- Bottom Action Bar -->
+    <div class="p-4 bg-white border-t border-gray-200 z-[70] shadow-[0px_-4px_10px_rgba(0,0,0,0.03)]">
+        <div class="flex items-center justify-between">
+            <div class="flex flex-col">
+                <span class="text-[12px] text-gray-500 font-bold uppercase">@Lang.v2_estimated_ticket_price</span>
+                <div class="flex items-baseline gap-1">
+                    <span id="totalPrice" class="text-[28px] font-black text-black">0</span>
+                    <span class="text-[13px] font-black text-[#EE0033]">HTG</span>
+                </div>
+            </div>
+            <button onclick="preparePayment()" class="bg-[#EE0033] text-white text-[20px] font-black px-10 py-3.5 rounded-xl shadow-[0px_6px_15px_rgba(238,0,51,0.25)] active:scale-95 transition-all">
+                @Lang.v2_payment
+            </button>
+        </div>
+    </div>
+</div>
+}
+
+<!-- Order Summary Screen (from Figma) -->
+<div id="orderSummaryModal" class="hidden fixed inset-0 z-[150] bg-black/60 flex items-center justify-center p-0 font-bricolage backdrop-blur-[2px]">
+    <div class="w-full max-w-[414px] h-full bg-white flex flex-col animate__animated animate__fadeInRight animate__faster border-x shadow-2xl relative">
+        <!-- Header đồng bộ tuyệt đối -->
+        <div class="w-full bg-[#EE0033] py-3 px-4 text-white flex items-center justify-between sticky top-0 z-[60]">
+            <button onclick="hideOrderSummary()" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-all">
+                <i class="fa-solid fa-arrow-left text-[20px]"></i>
+            </button>
+            <span class="font-[800] text-[18px] absolute left-1/2 -translate-x-1/2 whitespace-nowrap">
+                @if (Model.termType == Constants.PIC10_BASIC_CODE) { @Lang.v2_buy_classic_pick_10 }
+                else if (Model.termType == Constants.PIC10_BIGSMALL_CODE) { @Lang.v2_big_small }
+                else { @Lang.v2_odd_even }
+            </span>
+            <div class="w-8"></div>
+        </div>
+
+        <!-- Content Area -->
+        <div class="flex-1 overflow-y-auto p-5 space-y-5 bg-gray-50 pb-72">
+            <!-- Phần Round Info từ Model -->
+            <div class="flex items-center justify-end gap-1 mb-2 px-1">
+                <span class="text-[12px] font-bold text-gray-400">@Lang.v2_round</span>
+                <span class="text-[16px] font-black text-brown-main">#@(currentTerm?.id ?? "12459")</span>
+            </div>
+
+            <div class="flex justify-between items-center px-1">
+                 <span class="text-[14px] font-bold text-gray-800">Selected Tickets</span>
+                 <span class="text-[14px] font-bold text-gray-800">@Lang.price</span>
+            </div>
+
+            <!-- Ticket List List -->
+            <div id="summaryTicketList" class="flex flex-col gap-4">
+                 <!-- Populated dynamically via JS -->
+            </div>
+
+            <!-- Dates Section -->
+            <div class="grid grid-cols-2 gap-4 mt-8 pt-6 border-t border-dashed border-gray-300">
+                 <div class="space-y-1">
+                     <span class="text-[11px] font-black text-[#EE0033] block text-center uppercase tracking-tight">@Lang.date_purchase</span>
+                     <div class="bg-white border border-gray-100 rounded-xl py-2.5 px-2 text-center font-black text-[11px] text-gray-700 shadow-sm">
+                         @DateTime.Now.ToString("dddd MMM dd, yyyy", System.Globalization.CultureInfo.InvariantCulture)
+                     </div>
+                 </div>
+                 <div class="space-y-1">
+                     <span class="text-[11px] font-black text-[#EE0033] block text-center uppercase tracking-tight">@Lang.draw_date</span>
+                     <div class="bg-white border border-gray-100 rounded-xl py-2.5 px-2 text-center font-black text-[11px] text-gray-700 shadow-sm" id="summaryResultDate">
+                         @{
+                             DateTime drawDate;
+                             bool isValidDate = DateTime.TryParse(currentTerm?.date_start, out drawDate);
+                             if (isValidDate) {
+                                @drawDate.ToString("dddd MMM dd, yyyy", System.Globalization.CultureInfo.InvariantCulture)
+                             } else {
+                                @:N/A
+                             }
+                         }
+                     </div>
+                 </div>
+            </div>
+
+            <!-- Totals Section -->
+            <div class="mt-10 px-2 space-y-2">
+                 <div class="flex justify-between items-center">
+                     <span class="text-[14px] font-bold text-gray-400">@Lang.total_ticket</span>
+                     <span id="summaryTotalCount" class="text-[16px] font-black text-black">0</span>
+                 </div>
+                 <div class="flex justify-between items-center">
+                     <span class="text-[14px] font-bold text-gray-400">@Lang.total_money</span>
+                     <div class="flex items-baseline gap-1">
+                         <span id="summaryTotalAmount" class="text-[32px] font-black text-black">0</span>
+                         <span class="text-[16px] font-black text-[#EE0033]">HTG</span>
+                     </div>
+                 </div>
+            </div>
+            
+            <!-- Scalloped edge visual separator filler -->
+            <div class="w-full h-8 flex overflow-hidden opacity-5 mt-4">
+                 @for(int i=0; i<30; i++) {
+                     <div class="w-4 h-4 rounded-full bg-black -mt-2 shrink-0"></div>
+                 }
+            </div>
+        </div>
+
+        <div class="p-4 bg-white border-t border-gray-100 grid grid-cols-2 gap-4 pb-8 shadow-[0px_-4px_20px_rgba(0,0,0,0.05)] absolute bottom-0 w-full left-0 z-[70]">
+            <button onclick="hideOrderSummary()" class="bg-[#FFB000] text-white py-2.5 rounded-2xl font-black text-[18px] shadow-lg shadow-orange-200 active:scale-95 transition-all uppercase tracking-wide">
+                @Lang.reorder
+            </button>
+            <button id="finalPaymentBtn" onclick="confirmCheckout(this)" class="bg-[#EE0033] text-white py-2.5 rounded-2xl font-black text-[18px] shadow-lg shadow-red-200 active:scale-95 transition-all uppercase tracking-wide">
+                @Lang.v2_payment
+            </button>
+        </div>
+    </div>
+</div>
+
+    <!-- OTP Verification Modal (V2 Design Overhaul - Matching Figma) -->
+    <div id="otpModal" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-[200] hidden items-center justify-center p-4">
+        
+        <!-- Outer container to hold the modal + external overflowing elements (like stars/glitter) -->
+        <div class="relative w-full max-w-[360px] mt-6 animate__animated animate__zoomIn animate__faster">
+            
+            <!-- Glitter effect (external to the white box) -->
+            <div class="absolute -top-[100px] -left-[10px] w-[380px] h-[160px] mix-blend-screen pointer-events-none z-0 overflow-visible opacity-90" style="background: url('/LotteryV2/img/modal/otp_glitter.png') no-repeat center center; background-size: contain;"></div>
+
+            <!-- The White Box -->
+            <div class="bg-white rounded-[32px] w-full relative z-10 shadow-[0px_0px_30px_rgba(255,255,255,0.15)] pb-5 border border-yellow-500/20">
+                
+                <!-- Floating Coins from Figma -->
+                <div class="absolute -top-[40px] -right-[10px] z-[80] w-[120px] pointer-events-none drop-shadow-2xl">
+                    <img src="/LotteryV2/img/modal/otp_coins.png" class="w-full object-contain" />
+                </div>
+
+                <!-- Red Header Section -->
+                <div class="relative w-full pt-4 pb-4 bg-[#EE0033] rounded-t-[32px] flex flex-col items-center justify-center z-20" style="border-bottom-left-radius: 50% 20px; border-bottom-right-radius: 50% 20px;">
+                    <h2 class="text-white text-[17px] sm:text-[20px] font-[900] uppercase tracking-wide relative z-10 font-bricolage drop-shadow-md text-center px-4 leading-tight w-[80%] mr-auto">@Lang.v2_confirm_purchase</h2>
+                </div>
+                
+                <!-- Modal Body Content -->
+                <div class="relative px-6 pt-3 flex flex-col items-center gap-3 z-10">
+                    
+                    <!-- Shield Icon: mix-blend-mode multiply to remove the white square background -->
+                    <div class="relative w-full flex justify-center mb-0 mt-1">
+                        <img src="/LotteryV2/img/modal/otp_shield.png" alt="Success" class="w-[90px] object-contain" style="mix-blend-mode: multiply;">
+                    </div>
+        
+                    <!-- Info Rows (Aligned exactly like screenshot) -->
+                    <div class="w-full flex flex-col gap-2 items-center mt-0">
+                        <!-- Ticket Info -->
+                        <div class="grid grid-cols-[90px_auto] items-center gap-3 w-full justify-center">
+                            <span class="text-[15px] font-bold text-[#555] text-right font-bricolage">@Lang.v2_ticket</span>
+                            <div id="otpTicketTypeContainer" class="flex justify-start">
+                                <img id="otpTicketTypeImg" src="/LotteryV2/img/even_text.png" class="h-6 object-contain drop-shadow-sm" />
+                            </div>
+                        </div>
+
+                        <!-- Amount Info -->
+                        <div class="grid grid-cols-[90px_auto] items-center gap-3 w-full justify-center">
+                            <span class="text-[15px] font-bold text-[#555] text-right font-bricolage">@Lang.v2_amount</span>
+                            <div class="flex items-baseline gap-1.5 justify-start">
+                                <span id="otpTotalAmount" class="text-[22px] font-[900] text-black leading-none tracking-tight">1.000</span>
+                                <span class="text-[15px] font-[900] text-[#F37021] font-bricolage">HTG</span>
+                            </div>
+                        </div>
+                    </div>
+        
+                    <p class="text-[14px] font-bold text-[#555] text-center px-4 leading-snug mt-0 font-bricolage">@Lang.v2_otp_instruction</p>
+        
+                    <!-- 6-Slots OTP Grid (Large Gray Blocks) -->
+                    <div class="flex items-center justify-center gap-2 w-full mt-1 px-2" id="otpInputs">
+                        @for (int i = 1; i <= 6; i++)
+                        {
+                            <input type="tel" maxlength="1" id="otp@(i)" 
+                                   oninput="moveToNext(this, '@(i < 6 ? "otp" + (i + 1) : "")')" 
+                                   class="w-[42px] h-[48px] bg-[#757575] rounded-[10px] text-white text-[26px] font-bold text-center appearance-none focus:bg-[#555] focus:scale-[1.03] focus:ring-2 focus:ring-[#EE0033]/50 transition-all outline-none shadow-inner otp-slot"
+                                   placeholder="-">
+                        }
+                    </div>
+        
+                    <!-- Timer & Resend -->
+                    <div class="flex flex-col items-center gap-1 mt-0">
+                        <span id="otpTimer" class="text-[15px] font-black text-[#EE0033] font-bricolage">60s</span>
+                        <button id="resendOtpBtn" onclick="sendOtpRequest()" disabled class="text-[14px] font-black text-[#0A9800] underline decoration-solid underline-offset-[3px] transition-all hover:text-[#087a00] disabled:opacity-40 disabled:no-underline font-bricolage">@Lang.v2_request_new_otp</button>
+                    </div>
+        
+                    <!-- Action Buttons: Cancel / Confirm -->
+                    <div class="grid grid-cols-2 gap-3 w-full mt-2">
+                        <button onclick="hideOtpModal()" class="bg-[#FF0000] text-white py-[12px] rounded-[16px] font-[900] text-[17px] shadow-[0_8px_15px_rgba(255,0,0,0.2)] active:scale-95 transition-all tracking-wide">@Lang.v2_cancel</button>
+                        <button onclick="finalizePurchase(this)" class="bg-[#0A9800] text-white py-[12px] rounded-[16px] font-[900] text-[17px] shadow-[0_8px_15px_rgba(10,152,0,0.2)] active:scale-95 transition-all tracking-wide">@Lang.v2_confirm</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+@section Scripts {
+    <script>
+
+        const maxBalls = @(Model.termType == Constants.PIC10_BASIC_CODE ? 10 : (Model.termType == Constants.PIC10_BIGSMALL_CODE ? 13 : 15));
+
+        function reindexTickets() {
+            $(".ticket-card").each(function(index) {
+                $(this).find(".ticket-index").text(index + 1);
+            });
+        }
+
+        function removeEntry(btn) {
+            var card = $(btn).closest('.ticket-card');
+            card.addClass('animate__animated animate__fadeOutRight animate__faster');
+            setTimeout(function() {
+                card.remove();
+                reindexTickets();
+                updateTotalPrice();
+            }, 300);
+        }
+
+        function randomizeTicket(btn) {
+            var icon = $(btn).find('i');
+            icon.addClass('fa-spin');
+            
+            var card = $(btn).closest('.ticket-card');
+            var balls = card.find('.ball-circle');
+            
+            // Generate unique random numbers 1-80
+            var numbers = [];
+            while(numbers.length < maxBalls){
+                var r = Math.floor(Math.random() * 80) + 1;
+                if(numbers.indexOf(r) === -1) numbers.push(r);
+            }
+            numbers.sort((a, b) => a - b);
+            
+            // Update balls with staggered animation
+            balls.each(function(index) {
+                var ball = $(this);
+                setTimeout(function() {
+                    var formattedNum = numbers[index].toString().padStart(2, '0');
+                    ball.removeClass('ball-empty').addClass('ball-filled').text(formattedNum);
+                    ball.addClass('animate__animated animate__flipInY');
+                    
+                    if(index === maxBalls - 1) {
+                        setTimeout(() => {
+                            icon.removeClass('fa-spin');
+                            // Replace button with Edit/Delete group
+                            $(btn).hide();
+                            card.find('.edit-delete-group').removeClass('hidden').addClass('animate__animated animate__fadeInRight animate__faster');
+                            updateTotalPrice();
+                        }, 300);
+                    }
+                }, index * 40);
+            });
+        }
+
+        function clearTicket(btn) {
+            var card = $(btn).closest('.ticket-card');
+            var balls = card.find('.ball-circle');
+            
+            balls.removeClass('ball-filled animate__animated animate__flipInY shadow-inner').addClass('ball-empty').text('');
+            
+            // Hide Edit/Delete group and show Rand button
+            card.find('.edit-delete-group').addClass('hidden');
+            card.find('.rand-btn').show().addClass('animate__animated animate__fadeInLeft animate__faster');
+            
+            updateTotalPrice();
+        }
+
+        // Open Number Picker Modal
+        var activeBall = null;
+        var activeTicketCard = null;
+        var selectedNumbers = [];
+
+        function editFullTicket(btn) {
+            activeTicketCard = $(btn).closest('.ticket-card');
+            activeBall = null;
+            selectedNumbers = [];
+            activeTicketCard.find('.ball-filled').each(function() {
+                var num = $(this).text().trim();
+                if(num) selectedNumbers.push(num);
+            });
+            openNumberPicker(true);
+        }
+
+        function openNumberPicker(isMulti) {
+            var modal = $("#numberPickerModal");
+            var grid = $("#numberGrid");
+            var title = $("#modalTitle");
+            var countArea = $(".selection-count-area");
+            var confirmBtn = $("#confirmBtn");
+            
+            grid.empty();
+            if (isMulti) {
+                title.text("Edit Ticket");
+                countArea.removeClass('hidden');
+                confirmBtn.removeClass('hidden').text("@Lang.confirm");
+                updateSelectionCount();
+            } else {
+                title.text("Pick Number");
+                countArea.addClass('hidden');
+                confirmBtn.removeClass('hidden').text("@Lang.confirm");
+                selectedNumbers = [activeBall.text().trim()];
+                updateSelectionCount(); 
+            }
+
+            for (var i = 1; i <= 80; i++) {
+                var formatted = i.toString().padStart(2, '0');
+                var isSelected = selectedNumbers.includes(formatted);
+                
+                var btnClass = isSelected 
+                    ? 'bg-[#EE0033] text-white shadow-md scale-105' 
+                    : 'bg-white text-gray-700 hover:bg-gray-100 border border-gray-100';
+                
+                var btn = $(`<button class="num-btn h-10 rounded-lg font-black text-sm transition-all focus:outline-none ${btnClass}">${formatted}</button>`);
+                
+                btn.click(function(e) {
+                    e.preventDefault();
+                    var picked = $(this).text().trim();
+                    if (isMulti) {
+                        if (selectedNumbers.includes(picked)) {
+                            selectedNumbers = selectedNumbers.filter(n => n !== picked);
+                            $(this).removeClass('bg-[#EE0033] text-white shadow-md scale-105').addClass('bg-white text-gray-700 border border-gray-100');
+                        } else if (selectedNumbers.length < maxBalls) {
+                            selectedNumbers.push(picked);
+                            $(this).addClass('bg-[#EE0033] text-white shadow-md scale-105').removeClass('bg-white text-gray-700 border border-gray-100');
+                        }
+                    } else {
+                        grid.find('.num-btn').removeClass('bg-[#EE0033] text-white shadow-md scale-105').addClass('bg-white text-gray-700 border border-gray-100');
+                        selectedNumbers = [picked];
+                        $(this).addClass('bg-[#EE0033] text-white shadow-md scale-105').removeClass('bg-white text-gray-700 border border-gray-100');
+                    }
+                    updateSelectionCount();
+                });
+                
+                grid.append(btn);
+            }
+
+            modal.removeClass('hidden').addClass('flex');
+            modal.find('.modal-content').removeClass('animate__zoomOut').addClass('animate__zoomIn');
+        }
+
+        function updateSelectionCount() {
+            var count = selectedNumbers.length;
+            $("#selectionCount").text(count);
+            $("#maxSelectionCount").text(maxBalls);
+            var isValid = activeTicketCard ? (count === maxBalls) : (count === 1);
+            if (isValid) {
+                $("#confirmBtn").prop('disabled', false).removeClass('opacity-50 cursor-not-allowed').addClass('cursor-pointer');
+            } else {
+                $("#confirmBtn").prop('disabled', true).addClass('opacity-50 cursor-not-allowed').removeClass('cursor-pointer');
+            }
+        }
+
+        // All immediate jQuery event bindings must wait for DOM + jQuery to be ready
+        document.addEventListener("DOMContentLoaded", function() {
+            // Click on a filled ball to edit single number
+            $(document).on('click', '.ball-filled', function() {
+                activeBall = $(this);
+                activeTicketCard = null;
+                openNumberPicker(false);
+            });
+
+            // Confirm button handler
+            $(document).off('click', '#confirmBtn').on('click', '#confirmBtn', function(e) {
+                e.preventDefault();
+                if (selectedNumbers.length === 0) return;
+
+                if (activeTicketCard && activeTicketCard.length > 0) {
+                    // Multi mode: Update the entire ticket card
+                    selectedNumbers.sort((a, b) => parseInt(a) - parseInt(b));
+                    
+                    var balls = activeTicketCard.find('.ball-circle, .ball-empty, .ball-filled');
+                    
+                    balls.each(function(index) {
+                        if (index < selectedNumbers.length) {
+                            $(this).removeClass('ball-empty').addClass('ball-filled').text(selectedNumbers[index]);
+                            $(this).addClass('animate__animated animate__pulse');
+                            setTimeout(() => $(this).removeClass('animate__animated animate__pulse'), 500);
+                        }
+                    });
+
+                    activeTicketCard.find('.rand-btn').hide();
+                    activeTicketCard.find('.edit-delete-group').removeClass('hidden').show();
+                    
+                    updateTotalPrice();
+                } else if (activeBall && activeBall.length > 0) {
+                    // Single mode: Update only the active ball
+                    activeBall.text(selectedNumbers[0]).removeClass('ball-empty').addClass('ball-filled');
+                    activeBall.addClass('animate__animated animate__pulse');
+                    setTimeout(() => activeBall.removeClass('animate__animated animate__pulse'), 500);
+                }
+
+                closeNumberPicker();
+            });
+        });
+
+        function closeNumberPicker() {
+            var modal = $("#numberPickerModal");
+            modal.find('.modal-content').removeClass('animate__zoomIn').addClass('animate__zoomOut');
+            setTimeout(() => {
+                modal.removeClass('flex').addClass('hidden');
+                // Reset state
+                activeBall = null;
+                activeTicketCard = null;
+            }, 200);
+        }
+
+        function updateTotalPrice() {
+            var filledTickets = 0;
+            $(".ticket-card").each(function() {
+                if ($(this).find(".ball-filled").length === maxBalls) {
+                    filledTickets++;
+                }
+            });
+            const pricePerTicket = @(Model.termType == Constants.PIC10_BASIC_CODE ? "10" : "50");
+            $("#totalPrice").text(filledTickets * pricePerTicket);
+        }
+
+        function addNewTicket() {
+            var container = $("#ticketContainer");
+            var wrapper = $("#addButtonWrapper");
+            var currentIndex = $(".ticket-card").length + 1;
+            
+            var ballsHtml = '';
+            for (var i = 0; i < maxBalls; i++) {
+                ballsHtml += '<div class="ball-circle ball-empty"></div>';
+            }
+
+            var ticketHtml = `
+                <div class="ticket-card relative group active:bg-gray-50 transition-colors cursor-pointer animate__animated animate__fadeInUp animate__faster">
+                    <button onclick="removeEntry(this)" class="absolute -right-2 top-1 w-7 h-7 bg-[#999] text-white rounded-full flex items-center justify-center text-[11px] shadow-sm z-[10] hover:bg-red-500 transition-all border-2 border-white">
+                        <i class="fa-solid fa-xmark"></i>
+                    </button>
+                    <div class="absolute left-2 top-4 w-9 h-9 rounded-full bg-[#EE0033] border-[3px] border-white flex items-center justify-center text-white font-black text-sm shadow-md ticket-index">${currentIndex}</div>
+                    <div class="flex flex-col gap-1 pl-8">
+                        <span class="text-[16px] font-extrabold text-[#333]">@Lang.v2_select_10_lucky_numbers</span>
+                        <div class="flex items-start gap-4">
+                            <div class="grid grid-cols-5 gap-y-1 gap-x-2 flex-1">
+                                ${ballsHtml}
+                            </div>
+                            <div class="w-20 action-area flex flex-col gap-2">
+                                 <button onclick="randomizeTicket(this)" class="rand-btn bg-green-main text-white flex items-center justify-center gap-2 w-20 py-2 rounded-xl font-extrabold text-[11px] shadow-sm active:scale-95 transition-all">
+                                     <i class="fa-solid fa-arrows-rotate text-[10px]"></i> @Lang.Random
+                                 </button>
+                                 <div class="edit-delete-group hidden flex flex-col gap-2">
+                                     <button onclick="editFullTicket(this)" class="bg-[#2B83F2] text-white flex items-center justify-center gap-2 w-20 py-1.5 rounded-lg font-bold text-[12px] shadow-sm active:scale-95 transition-all">
+                                         <i class="fa-solid fa-pen text-[10px]"></i> @Lang.v2_edit
+                                     </button>
+                                     <button onclick="clearTicket(this)" class="bg-[#EE0033] text-white flex items-center justify-center gap-2 w-20 py-1.5 rounded-lg font-bold text-[12px] shadow-sm active:scale-95 transition-all">
+                                         <i class="fa-solid fa-trash-can text-[10px]"></i> @Lang.v2_delete
+                                     </button>
+                                 </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            `;
+            
+            $(ticketHtml).insertBefore(wrapper);
+            container.animate({ scrollTop: container.prop("scrollHeight") }, 300);
+        }
+
+        // --- Order Summary Modal Logic ---
+        // --- Payment Preparation & Order Summary Logic ---
+        function preparePayment(event) {
+            const isBSMode = @(Model.termType == Constants.PIC10_BIGSMALL_CODE || Model.termType == Constants.PIC10_ODDEVEN_CODE ? "true" : "false");
+            const tickets = [];
+
+            if (isBSMode) {
+                if (!bsChoice) {
+                    showNotification("Please select a choice first.", "warning");
+                    return;
+                }
+                
+                let bsCode = "";
+                if ('@Model.termType' === '@Constants.PIC10_BIGSMALL_CODE') {
+                    bsCode = (bsChoice === 'big') ? "B" : "S";
+                } else {
+                    bsCode = (bsChoice === 'big') ? "O" : "E"; // Odd = O, Even = E
+                }
+
+                tickets.push({
+                    code: bsCode,
+                    money: "50"
+                });
+            } else {
+                $(".ticket-card").each(function() {
+                    const balls = $(this).find(".ball-filled");
+                    if (balls.length === maxBalls) {
+                        const selectedNumbers = [];
+                        balls.each(function() { selectedNumbers.push($(this).text().trim()); });
+                        const itemPrice = "@(Model.termType == Constants.PIC10_BASIC_CODE ? "10" : "50")";
+                        tickets.push({
+                            code: selectedNumbers.join(','),
+                            money: itemPrice
+                        });
+                    }
+                });
+
+                if (tickets.length === 0) {
+                    showNotification("@Lang.v2_ticket_not_valid", "warning");
+                    return;
+                }
+            }
+
+            const requestData = {
+                gameId: "@Model.termType",
+                ticket: tickets
+            };
+
+            const btn = event ? event.currentTarget : null;
+            const originalText = btn ? btn.innerHTML : "@Lang.v2_payment";
+            if (btn) {
+                btn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Loading...';
+                btn.disabled = true;
+            }
+
+            // Gọi ConfirmTicketData API (giống nhau cho tất cả loại game)
+            // Pick 10: code = "21,26,40,47,48,52,67,69,71,74"
+            // Big/Small: code = "B" hoặc "S"
+            // Odd/Even: code = "O" hoặc "E"
+            console.log("[DEBUG] ConfirmTicketData request:", JSON.stringify(requestData));
+            $.ajax({
+                url: subDomain + '@Url.Action("ConfirmTicketData", "Home")',
+                type: 'POST',
+                contentType: 'application/json',
+                data: JSON.stringify(requestData),
+                success: function(data) {
+                    console.log("[DEBUG] ConfirmTicketData response:", JSON.stringify(data));
+                    if (btn) {
+                        btn.innerHTML = originalText;
+                        btn.disabled = false;
+                    }
+                    if (data.responseCode === "0") {
+                        showOrderSummary(data, tickets);
+                    } else {
+                        showNotification(data.responseMessage || "Confirmation failed", "warning");
+                    }
+                },
+                error: function(err) {
+                    console.error("[DEBUG] ConfirmTicketData AJAX Error:", err);
+                    if (btn) {
+                        btn.innerHTML = originalText;
+                        btn.disabled = false;
+                    }
+                    console.error("AJAX Error:", err);
+                    showNotification("Network error occurred.", "warning");
+                }
+            });
+        }
+
+        let currentTransId = null;
+
+        function showOrderSummary(apiData, localTickets) {
+            currentTransId = apiData.transId;
+            const summaryModal = $("#orderSummaryModal");
+            const summaryList = $("#summaryTicketList");
+            summaryList.empty();
+
+            const displayTickets = (apiData && apiData.ticket) ? apiData.ticket : (localTickets || []);
+            if (!displayTickets || !Array.isArray(displayTickets)) {
+                console.warn("No tickets found to display in summary.");
+                return;
+            }
+
+            displayTickets.forEach((t, index) => {
+                const numbers = t.code.split(',');
+                let contentHtml = '';
+                
+                if (numbers.length > 1) {
+                    let numbersBalls = '';
+                    numbers.forEach(n => {
+                        numbersBalls += `<div class="w-7 h-7 rounded-full flex items-center justify-center text-white text-[11px] font-black shadow-lg" style="background: radial-gradient(circle at 30% 30%, #444, #000);">${n.trim()}</div>`;
+                    });
+                    contentHtml = `<div class="grid grid-cols-5 gap-y-2 relative z-10 px-2 justify-items-center">${numbersBalls}</div>`;
+                } else {
+                    const isBS = @(Model.termType == Constants.PIC10_BIGSMALL_CODE ? "true" : "false");
+                    const isFirstChoice = (numbers[0] === 'B' || numbers[0] === 'O');
+                    const label = isFirstChoice ? (isBS ? "Big" : "Odd") : (isBS ? "Small" : "Even");
+                    const color = isFirstChoice ? (isBS ? "#A2FF00" : "#FFC700") : (isBS ? "#FF4157" : "#B33BD0");
+                    contentHtml = `<div class="w-full flex justify-center"><span class="text-[28px] font-black italic uppercase" style="-webkit-text-stroke: 1px #000; color: ${color};">${label}</span></div>`;
+                }
+
+                const itemHtml = `
+                    <div class="flex items-center gap-3">
+                        <div class="flex-1 rounded-2xl p-3 relative overflow-hidden flex flex-col gap-2 min-h-[80px] justify-center" 
+                             style="background: linear-gradient(90deg, #EE0033 0%, rgba(238, 0, 51, 0.4) 70%, rgba(238, 0, 51, 0.05) 100%); border: 1px solid rgba(238, 0, 51, 0.1);">
+                            ${contentHtml}
+                        </div>
+                        <div class="w-24 shrink-0 bg-white border border-gray-200 rounded-2xl p-2.5 flex items-center justify-between shadow-sm">
+                            <div class="flex items-baseline gap-0.5">
+                                <span class="text-[16px] font-black text-black">${t.money}</span>
+                                <span class="text-[10px] font-black text-[#EE0033]">HTG</span>
+                            </div>
+                        </div>
+                    </div>
+                `;
+                summaryList.append(itemHtml);
+            });
+
+            $("#summaryTotalCount").text(displayTickets.length);
+            const totalMoney = apiData.totalMoneyPayment || apiData.totalMoney || "0";
+            $("#summaryTotalAmount").text(parseFloat(totalMoney).toLocaleString('en-US'));
+
+            summaryModal.removeClass("hidden").addClass("flex");
+        }
+
+        function hideOrderSummary() {
+            $("#orderSummaryModal").removeClass("flex").addClass("hidden");
+        }
+
+        function confirmCheckout(btn) {
+            const originalText = $(btn).html();
+            $(btn).prop('disabled', true).html('<i class="fa-solid fa-spinner fa-spin mr-2"></i>Processing...');
+
+            // Trigger SendOTP API
+            $.ajax({
+                url: subDomain + '@Url.Action("SendOTP", "Home")',
+                type: 'POST',
+                success: function(data) {
+                    $(btn).prop('disabled', false).html(originalText);
+                    
+                    if (data.responseCode === "0") {
+                        showOtpModal();
+                    } else {
+                        showNotification(data.responseMessage || "Failed to send OTP", "warning");
+                    }
+                },
+                error: function() {
+                    $(btn).prop('disabled', false).html(originalText);
+                    showNotification("Network error occurred.", "warning");
+                }
+            });
+        }
+
+        let otpInterval;
+        function showOtpModal() {
+            hideOrderSummary();
+            $("#otpModal").removeClass("hidden").addClass("flex");
+            $("#otpInputs input").val("");
+            $("#otp1").focus();
+            
+            // Map game type to readable name & image
+            let gameTypeStr = "@Model.termType";
+            let displayName = "Classic Pick 10";
+            let imgSrc = "";
+            
+            if (gameTypeStr === "@Constants.PIC10_BIGSMALL_CODE") {
+                displayName = "Big / Small";
+                // Detect if current selection is Big or Small from summary
+                let firstTicket = $("#summaryTicketList .flex.items-center span.font-black").first().text().trim();
+                if (firstTicket.toLowerCase().includes("big")) imgSrc = "/LotteryV2/img/big_text.png";
+                else if (firstTicket.toLowerCase().includes("small")) imgSrc = "/LotteryV2/img/small_text.png";
+            } else if (gameTypeStr === "@Constants.PIC10_ODDEVEN_CODE") {
+                displayName = "Odd / Even";
+                let firstTicket = $("#summaryTicketList .flex.items-center span.font-black").first().text().trim();
+                if (firstTicket.toLowerCase().includes("odd")) imgSrc = "/LotteryV2/img/odd_text.png";
+                else if (firstTicket.toLowerCase().includes("even")) imgSrc = "/LotteryV2/img/even_text.png";
+            }
+            
+            $("#otpTicketTypeContainer").find("span").remove();
+            if (imgSrc) {
+                $("#otpTicketTypeImg").attr("src", imgSrc).show();
+            } else {
+                $("#otpTicketTypeImg").hide();
+                if ($("#otpTicketTypeContainer").find("span").length === 0) {
+                    $("#otpTicketTypeContainer").append(`<span class='text-[17px] font-[900] text-purple-700 italic'>${displayName}</span>`);
+                }
+            }
+            
+            $("#otpTotalAmount").text($("#summaryTotalAmount").text());
+            startOtpTimer(60);
+        }
+
+        // Add backspace support for OTP inputs
+        $("#otpInputs input").on("keydown", function(e) {
+            if (e.key === "Backspace" && this.value.length === 0) {
+                $(this).prev('input').focus();
+            }
+        });
+
+        function hideOtpModal() {
+            $("#otpModal").removeClass("flex").addClass("hidden");
+            clearInterval(otpInterval);
+        }
+
+        function startOtpTimer(seconds) {
+            let timeLeft = seconds;
+            $("#resendOtpBtn").prop("disabled", true);
+            clearInterval(otpInterval);
+            
+            otpInterval = setInterval(() => {
+                timeLeft--;
+                $("#otpTimer").text(timeLeft + "s");
+                if (timeLeft <= 0) {
+                    clearInterval(otpInterval);
+                    $("#resendOtpBtn").prop("disabled", false);
+                    $("#otpTimer").text("");
+                }
+            }, 1000);
+        }
+
+        function moveToNext(el, nextId) {
+            if (el.value.length >= 1) {
+                if (nextId) document.getElementById(nextId).focus();
+            }
+        }
+
+        function sendOtpRequest() {
+            // Re-trigger SendOTP
+            $.ajax({
+                url: subDomain + '@Url.Action("SendOTP", "Home")',
+                type: 'POST',
+                success: function(data) {
+                    if (data.responseCode === "0") {
+                        startOtpTimer(60);
+                        showNotification("OTP has been resent.", "success");
+                    } else {
+                        showNotification(data.responseMessage || "Failed to resend OTP", "warning");
+                    }
+                }
+            });
+        }
+
+        function showReceiptSuccess(transId, amount, phone) {
+            // Setup data dynamically
+            $("#receiptAmount").text(amount + " HTG");
+            if(phone) $("#receiptPhone").text(phone);
+            
+            let gameTypeStr = "@Model.termType";
+            let displayName = "@Lang.v2_classic_pick_10";
+            if (gameTypeStr === "@Constants.PIC10_BIGSMALL_CODE") displayName = "@Lang.v2_big_small";
+            else if (gameTypeStr === "@Constants.PIC10_ODDEVEN_CODE") displayName = "@Lang.v2_odd_even";
+            
+            $("#receiptGameType").text("@Lang.buy " + displayName);
+            $("#receiptTicketCode").text("#" + transId);
+            
+            let choiceText = "-";
+            if (gameTypeStr === "@Constants.PIC10_BIGSMALL_CODE" || gameTypeStr === "@Constants.PIC10_ODDEVEN_CODE") {
+                choiceText = $("#summaryTicketList .flex.items-center span.font-black").first().text().trim();
+            } else {
+                choiceText = "PICK 10";
+            }
+            $("#receiptChoice").text(choiceText);
+            
+            // Format current date "dd/MM/yyyy - HH:mm:ss"
+            let now = new Date();
+            let ds = now.getDate().toString().padStart(2, '0') + '/' + (now.getMonth() + 1).toString().padStart(2, '0') + '/' + now.getFullYear() + ' - ' + now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0') + ':' + now.getSeconds().toString().padStart(2, '0');
+            $("#receiptTime").text(ds);
+
+            hideOtpModal();
+            $("#receiptSuccessModal").removeClass("hidden").addClass("flex");
+        }
+
+        function finalizePurchase(btn) {
+            let otpCode = "";
+            $("#otpInputs input").each(function() {
+                otpCode += $(this).val();
+            });
+            
+            if (otpCode.length < 6) {
+                showNotification("Please enter full 6-digit OTP", "warning");
+                return;
+            }
+
+            const originalText = $(btn).html();
+            $(btn).prop('disabled', true).html('<i class="fa-solid fa-spinner fa-spin mr-2"></i> ...');
+
+            const finalData = {
+                transIdByTicket: currentTransId,
+                paymentCode: otpCode
+            };
+
+            // STEP 1: Confirm OTP API
+            $.ajax({
+                url: subDomain + '@Url.Action("ConfirmOTP", "Home")',
+                type: 'POST',
+                contentType: 'application/json',
+                data: JSON.stringify({ otp: otpCode }),
+                success: function(otpResp) {
+                    // Check if OTP validation succeeds
+                    if (otpResp.responseCode === "0" || otpResp.responseCode === 200 || otpResp.responseCode === "0000") {
+                        
+                        // STEP 2: Confirm Buying Ticket API
+                        $.ajax({
+                            url: subDomain + '@Url.Action("ConfirmBuyingTicket", "Home")',
+                            type: 'POST',
+                            contentType: 'application/json',
+                            data: JSON.stringify(finalData),
+                            success: function(buyResp) {
+                                $(btn).prop('disabled', false).html(originalText);
+                                
+                                if (buyResp.responseCode === "0" || buyResp.responseCode === "0000") {
+                                    // Open Figma styled success modal!
+                                    showReceiptSuccess(buyResp.transId || currentTransId, $("#summaryTotalAmount").text(), "@(Model.userStatus?.msisdn ?? "-")");
+                                } else {
+                                    showNotification(buyResp.responseMessage || "Payment failed", "warning");
+                                }
+                            },
+                            error: function() {
+                                $(btn).prop('disabled', false).html(originalText);
+                                showNotification("Network error occurred during payment completion.", "warning");
+                            }
+                        });
+
+                    } else {
+                        $(btn).prop('disabled', false).html(originalText);
+                        showNotification(otpResp.responseMessage || "Invalid OTP code", "warning");
+                    }
+                },
+                error: function() {
+                    $(btn).prop('disabled', false).html(originalText);
+                    showNotification("Network error while validating OTP.", "warning");
+                }
+            });
+        }
+
+        function showNotification(message, type = 'success') {
+            const msgEl = $("#notificationMessage");
+            const iconEl = $("#notificationModal img");
+            
+            msgEl.text(message);
+            
+            // Toggle icon based on type (warning or success)
+            const warningIcon = '/LotteryV2/img/modal/warning_icon.png';
+            const successIcon = '/LotteryV2/img/modal/success_icon.png';
+            const fallbackWarning = 'https://cdn-icons-png.flaticon.com/512/564/564619.png';
+            const fallbackSuccess = 'https://cdn-icons-png.flaticon.com/512/190/190411.png';
+
+            if (type === 'warning' || type === 'error') {
+                iconEl.attr('src', warningIcon);
+                iconEl.attr('onerror', `this.src='${fallbackWarning}'`);
+            } else {
+                iconEl.attr('src', successIcon);
+                iconEl.attr('onerror', `this.src='${fallbackSuccess}'`);
+            }
+
+            $("#notificationModal").removeClass("hidden").addClass("flex");
+        }
+
+        function closeNotificationModal() {
+            $("#notificationModal").addClass("hidden").removeClass("flex");
+        }
+
+        // ==================== CARD SELECTION GAME LOGIC (BIG/SMALL / ODD/EVEN) ====================
+        var bsChoice = null; // 'big' or 'small' (reused as 'odd' or 'even')
+        const isBigSmall = @(Model.termType == Constants.PIC10_BIGSMALL_CODE ? "true" : "false");
+        const themeColor = isBigSmall ? "#0A9800" : "#AA3DC8";
+        const labelBig = isBigSmall ? "Big" : "Odd";
+        const labelSmall = isBigSmall ? "Small" : "Even";
+        const colorBig = isBigSmall ? "#A2FF00" : "#FFC700";
+        const colorSmall = isBigSmall ? "#FF4157" : "#B33BD0";
+
+        // Loclized text from resources
+        const langSelect = "@Lang.v2_select";
+        const langSelected = "@Lang.v2_selected";
+
+        function selectBigSmall(choice) {
+            bsChoice = choice;
+            var cardBig = document.getElementById('cardBig');
+            var cardSmall = document.getElementById('cardSmall');
+            var choiceDisplay = document.getElementById('choiceDisplay');
+
+            if (!cardBig || !cardSmall) return;
+
+            if (choice === 'big') {
+                // Highlight Big/Odd card with theme glow
+                cardBig.style.border = '2px solid ' + themeColor;
+                cardBig.style.boxShadow = '0px 0px 12px 0px ' + (isBigSmall ? 'rgba(162, 255, 0, 1)' : 'rgba(179, 59, 208, 0.6)');
+                cardBig.querySelector('.bigsmall-btn').textContent = langSelected;
+                cardBig.querySelector('.bigsmall-btn').style.background = '#333';
+
+                // Reset Small/Even card
+                cardSmall.style.border = '2px solid transparent';
+                cardSmall.style.boxShadow = 'none';
+                cardSmall.querySelector('.bigsmall-btn').textContent = langSelect;
+                cardSmall.querySelector('.bigsmall-btn').style.background = themeColor;
+
+                // Update display
+                if (choiceDisplay) {
+                    choiceDisplay.textContent = labelBig;
+                    choiceDisplay.style.color = colorBig;
+                    choiceDisplay.style.webkitTextStroke = '1px #000';
+                }
+            } else {
+                // Highlight Small/Even card with theme glow
+                cardSmall.style.border = '2px solid ' + themeColor;
+                cardSmall.style.boxShadow = '0px 0px 12px 0px ' + (isBigSmall ? 'rgba(162, 255, 0, 1)' : 'rgba(179, 59, 208, 0.6)');
+                cardSmall.querySelector('.bigsmall-btn').textContent = langSelected;
+                cardSmall.querySelector('.bigsmall-btn').style.background = '#333';
+
+                // Reset Big/Odd card
+                cardBig.style.border = '2px solid transparent';
+                cardBig.style.boxShadow = 'none';
+                cardBig.querySelector('.bigsmall-btn').textContent = langSelect;
+                cardBig.querySelector('.bigsmall-btn').style.background = themeColor;
+
+                // Update display
+                if (choiceDisplay) {
+                    choiceDisplay.textContent = labelSmall;
+                    choiceDisplay.style.color = colorSmall;
+                    choiceDisplay.style.webkitTextStroke = '1px #000';
+                }
+            }
+        }
+
+        function bsShowPayment(e) {
+            preparePayment(e);
+        }
+    </script>
+
+    <!-- Number Picker Modal (Premium Design) -->
+    <div id="numberPickerModal" class="fixed inset-0 bg-black/60 z-[200] hidden items-center justify-center p-4 backdrop-blur-sm transition-all">
+        <div class="modal-content bg-white w-full max-w-[360px] rounded-3xl overflow-hidden shadow-2xl animate__animated animate__zoomIn animate__faster">
+            <div class="p-5 bg-[#EE0033] text-white flex justify-between items-center">
+                <div class="flex items-center gap-3">
+                    <div class="w-8 h-8 rounded-lg bg-white/20 flex items-center justify-center">
+                        <i class="fa-solid fa-hashtag text-sm"></i>
+                    </div>
+                    <h3 class="font-black text-lg uppercase tracking-tight" id="modalTitle">Pick Number</h3>
+                </div>
+                <button onclick="closeNumberPicker()" class="w-8 h-8 flex items-center justify-center rounded-full hover:bg-white/20 transition-all">
+                    <i class="fa-solid fa-xmark text-xl"></i>
+                </button>
+            </div>
+            <div class="p-3 bg-gray-50 flex items-center justify-center border-b selection-count-area hidden">
+                <span class="text-[12px] font-bold text-gray-500 uppercase">Selected: <span id="selectionCount" class="text-[#EE0033]">0</span>/<span id="maxSelectionCount">10</span></span>
+            </div>
+            <div class="p-4 grid grid-cols-6 gap-2 max-h-[450px] overflow-y-auto bg-gray-50" id="numberGrid">
+                 <!-- 1-80 populated via JS -->
+            </div>
+            <div class="p-4 bg-white border-t flex flex-col gap-2">
+                 <button id="confirmBtn" class="hidden w-full py-3 bg-[#EE0033] text-white rounded-xl font-black text-md active:bg-[#CC002D] transition-all uppercase tracking-wide shadow-lg">
+                     @Lang.confirm
+                 </button>
+                 <button onclick="closeNumberPicker()" class="w-full py-3 bg-gray-100 text-gray-700 rounded-xl font-black text-[14px] active:bg-gray-200 transition-all uppercase tracking-wide">
+                     @Lang.v2_back
+                 </button>
+            </div>
+        </div>
+    </div>
+    <div id="notificationModal" class="fixed inset-0 z-[300] bg-black/60 flex items-center justify-center hidden px-4 font-bricolage backdrop-blur-sm">
+        <div class="w-full max-w-[360px] bg-white rounded-[32px] overflow-hidden flex flex-col items-center px-6 pt-5 pb-6 animate__animated animate__zoomIn animate__faster shadow-2xl relative border border-white/50">
+            <!-- Alert Icon -->
+            <div class="w-full flex justify-center mb-3 mt-1">
+                <img src="/LotteryV2/img/modal/success_icon.png" class="w-[100px] h-auto object-contain" alt="Notificaton icon" onerror="this.src='https://cdn-icons-png.flaticon.com/512/190/190411.png'" />
+            </div>
+
+            <!-- Message Area -->
+            <div class="px-2 text-center mb-5">
+                <p id="notificationMessage" class="text-black font-[800] text-[17px] leading-snug">
+                    <!-- Message content -->
+                </p>
+            </div>
+
+            <!-- Action Button -->
+            <div class="w-full">
+                <button onclick="closeNotificationModal()" class="w-full bg-[#EE0033] text-white font-[900] text-[18px] py-[13px] rounded-[18px] shadow-[0_8px_20px_rgba(238,0,51,0.25)] active:scale-95 transition-all uppercase tracking-wide">
+                    OK
+                </button> 
+            </div>
+        </div>
+    </div>
+
+    <!-- Beautiful Success Receipt Modal (Matches Figma 161:3722) -->
+    <div id="receiptSuccessModal" class="fixed inset-0 z-[300] bg-black/80 hidden items-center justify-center px-4 font-bricolage backdrop-blur-md">
+        <div class="w-full max-w-[360px] bg-[#F9F9F9] rounded-[32px] overflow-hidden flex flex-col items-center px-6 pt-4 pb-5 shadow-2xl relative animate__animated animate__zoomIn animate__faster border border-white/50">
+            <!-- Confetti/Celebration background effect (Subtle) -->
+            <div class="absolute top-0 inset-x-0 h-[150px] pointer-events-none opacity-40 mix-blend-multiply" style="background: url('/LotteryV2/img/modal/otp_glitter.png') no-repeat top center; background-size: cover;"></div>
+            
+            <h2 class="text-[#534A4A] font-[800] text-[19px] tracking-tight relative z-10 w-full text-center mt-1">@Lang.v2_payment_successfully</h2>
+            
+            <!-- Ticket / Success Graphic -->
+            <div class="relative w-full flex justify-center mt-2 mb-0 z-10">
+                <div class="relative w-[100px] flex items-center justify-center">
+                    <div class="absolute inset-0 bg-green-400 blur-2xl opacity-20 rounded-full scale-125"></div>
+                    <img src="/LotteryV2/img/modal/otp_shield.png" alt="Success" class="w-full drop-shadow-xl z-20" style="mix-blend-mode: multiply;" />
+                </div>
+            </div>
+
+            <h3 class="text-[#0A9800] font-[900] text-[20px] uppercase tracking-wide relative z-10">@Lang.success</h3>
+
+            <div class="w-full h-px border-t-[2px] border-dashed border-gray-300 my-3 relative z-10"></div>
+            
+            <div class="w-full flex justify-between items-center mb-2 relative z-10 px-1">
+                <span class="text-[#534A4A] font-bold text-[14px]">@Lang.number</span>
+                <span class="font-black text-[14px] text-gray-800" id="receiptPhone">-</span>
+            </div>
+            
+            <div class="w-full flex justify-between items-center mb-2 relative z-10 px-1">
+                <span class="text-[#534A4A] font-bold text-[14px]">@Lang.v2_your_choice</span>
+                <span class="text-[#EE0033] font-[900] text-[15px] uppercase" id="receiptChoice">-</span>
+            </div>
+            
+            <div class="w-full flex justify-between items-center mb-2 relative z-10 px-1">
+                <span class="text-[#534A4A] font-bold text-[14px]">@Lang.ticket_code</span>
+                <span class="font-black text-[13px] text-gray-800" id="receiptTicketCode">#</span>
+            </div>
+            
+            <div class="w-full flex justify-between items-center mb-1 relative z-10 px-1">
+                <span class="text-[#534A4A] font-bold text-[14px]">@Lang.payment</span>
+                <span class="text-[#EE0033] font-[900] text-[15px]" id="receiptAmount">0 HTG</span>
+            </div>
+
+            <div class="w-full h-px border-t-[2px] border-dashed border-gray-300 my-3 relative z-10"></div>
+            
+            <div class="w-full flex justify-between items-center mb-2 relative z-10 px-1">
+                <span class="text-[#534A4A] font-bold text-[14px]">@Lang.time</span>
+                <span class="font-bold text-[13px] text-gray-600" id="receiptTime">00:00:00</span>
+            </div>
+            
+            <div class="w-full flex justify-start items-center relative z-10 px-1 mt-1">
+                <span class="text-[#534A4A] font-bold text-[13px] italic text-gray-500" id="receiptGameType">@Lang.v2_buy_ticket_label</span>
+            </div>
+            
+            <div class="text-[#534A4A] font-[900] text-[18px] relative z-10 text-center mt-3">@Lang.thank_you <span class="text-[#EE0033]">♥️</span></div>
+            
+            <!-- Action Button -->
+            <button onclick="location.href='@Url.Action("GameHome", "Home", new { termType = Model.termType })'" class="w-full bg-[#EE0033] text-white font-[900] text-[18px] py-[13px] rounded-[18px] shadow-[0_8px_20px_rgba(238,0,51,0.25)] active:scale-95 transition-all mt-4 relative z-10 uppercase tracking-wide">
+                @Lang.back_to_homepage
+            </button> 
+        </div>
+    </div>
+}

+ 5 - 2
website/Areas/LotteryV2/Views/Home/FAQ.cshtml

@@ -10,8 +10,8 @@
 
 
 <div class="main-container animate__animated animate__fadeIn bg-[#F5F5F5] min-h-screen relative flex flex-col pb-24 shadow-xl overflow-x-hidden">
 <div class="main-container animate__animated animate__fadeIn bg-[#F5F5F5] min-h-screen relative flex flex-col pb-24 shadow-xl overflow-x-hidden">
 
 
-    <!-- Header Block (Red) -->
-    <div class="w-full bg-[#EE0033] h-[52px] flex items-center justify-between px-4 sticky top-0 z-50 shadow-sm">
+    <!-- Header Block (Red) - Fixed -->
+    <div class="fixed top-0 left-1/2 -translate-x-1/2 w-full max-w-[414px] bg-[#EE0033] h-[52px] flex items-center justify-between px-4 z-[100] shadow-sm">
         <!-- Back Button -->
         <!-- Back Button -->
         <button onclick="window.history.back()" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-colors z-10 text-white cursor-pointer">
         <button onclick="window.history.back()" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-colors z-10 text-white cursor-pointer">
             <i class="fa-solid fa-arrow-left text-[20px]"></i>
             <i class="fa-solid fa-arrow-left text-[20px]"></i>
@@ -22,6 +22,9 @@
         </div>
         </div>
     </div>
     </div>
 
 
+    <!-- Header Spacer (~52px) -->
+    <div class="h-[52px]"></div>
+
 
 
 
 
     <!-- Banner Graphic directly integrated with Grey background -->
     <!-- Banner Graphic directly integrated with Grey background -->

+ 101 - 19
website/Areas/LotteryV2/Views/Home/GameHome.cshtml

@@ -4,12 +4,9 @@
     Layout = "~/Areas/LotteryV2/Views/Shared/_Layout.cshtml";
     Layout = "~/Areas/LotteryV2/Views/Shared/_Layout.cshtml";
 }
 }
 @using LotteryWebApp.Languages;
 @using LotteryWebApp.Languages;
+@using LotteryWebApp.Controllers;
+@using LotteryWebApp.Common;
 
 
-@section Styles {
-    <script src="https://cdn.tailwindcss.com"></script>
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
-    <link rel="stylesheet" href="/LotteryV2/css/site.css" />
-}
 
 
 <div class="main-container animate__animated animate__fadeIn bg-[#F5F5F5] min-h-screen">
 <div class="main-container animate__animated animate__fadeIn bg-[#F5F5F5] min-h-screen">
     <!-- Top Account Profile Bar / Backgound Red header -->
     <!-- Top Account Profile Bar / Backgound Red header -->
@@ -30,9 +27,9 @@
 
 
         <!-- Row 2: Pill Actions Full Width Split -->
         <!-- Row 2: Pill Actions Full Width Split -->
         <div class="grid grid-cols-2 gap-3 mt-4">
         <div class="grid grid-cols-2 gap-3 mt-4">
-             <button class="btn-pulse border border-white/50 rounded-xl py-2 px-3 flex items-center justify-center gap-1 text-xs font-extrabold bg-white/10 hover:bg-white/20 transition-all">
+             <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-xs 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
                  <span class="text-yellow-300 text-xl">⚡</span> @Lang.quick_pick
-             </button>
+             </a>
              <button class="btn-pulse border border-white/50 rounded-xl py-2 px-3 flex items-center justify-center gap-1 text-xs font-extrabold bg-white/10 hover:bg-white/20 transition-all">
              <button class="btn-pulse border border-white/50 rounded-xl py-2 px-3 flex items-center justify-center gap-1 text-xs font-extrabold bg-white/10 hover:bg-white/20 transition-all">
                  <span>🎫</span> @Lang.my_ticket
                  <span>🎫</span> @Lang.my_ticket
              </button>
              </button>
@@ -40,7 +37,7 @@
 
 
         <!-- Row 3: Withdraw Button Full Width -->
         <!-- Row 3: Withdraw Button Full Width -->
         <div class="w-full mt-3">
         <div class="w-full mt-3">
-             <button 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%);">
+             <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>
                  <span>@Lang.tranfer_win_money</span>
                  <img src="/LotteryV2/img/gold_wallet.png" alt="Wallet" class="w-6 h-6 object-contain">
                  <img src="/LotteryV2/img/gold_wallet.png" alt="Wallet" class="w-6 h-6 object-contain">
              </button>
              </button>
@@ -72,11 +69,14 @@
         </div>
         </div>
     </div>
     </div>
 
 
+    <!-- Anti-forgery token for AJAX -->
+    @Html.AntiForgeryToken()
+
     <!-- Card list items with accurate illustrations -->
     <!-- Card list items with accurate illustrations -->
     <div class="px-3 flex flex-col gap-3 pb-40 relative z-10 mt-[5px]">
     <div class="px-3 flex flex-col gap-3 pb-40 relative z-10 mt-[5px]">
         
         
         <!-- Game item 1: Basic Pick 10 -->
         <!-- Game item 1: Basic Pick 10 -->
-        <div class="w-full bg-[#E11D48] p-3.5 rounded-2xl relative overflow-hidden card-shadow text-white border border-white/10 filter brightness-105">
+        <div class="w-full bg-[#E11D48] p-3.5 rounded-2xl relative overflow-hidden card-shadow text-white border border-white/10 filter brightness-105 cursor-pointer transform active:scale-[0.98] transition-all" onclick="checkTerm('@Constants.PIC10_BASIC_CODE')">
             <div class="absolute -left-6 -top-6 w-16 h-16 bg-white/10 rounded-full blur-xl"></div>
             <div class="absolute -left-6 -top-6 w-16 h-16 bg-white/10 rounded-full blur-xl"></div>
             <div class="grid grid-cols-10 items-center">
             <div class="grid grid-cols-10 items-center">
                 <div class="col-span-3 flex flex-col items-start">
                 <div class="col-span-3 flex flex-col items-start">
@@ -89,17 +89,17 @@
                 <div class="col-span-4 flex flex-col items-center text-center">
                 <div class="col-span-4 flex flex-col items-center text-center">
                     <div class="text-[12px] uppercase font-bold text-white/80">@Lang.jackpot_prize</div>
                     <div class="text-[12px] uppercase font-bold text-white/80">@Lang.jackpot_prize</div>
                     <div class="text-xl font-extrabold text-[#FBF3A7] tracking-wider">100.000 <span class="text-[10px] font-bold">HTG</span></div>
                     <div class="text-xl font-extrabold text-[#FBF3A7] tracking-wider">100.000 <span class="text-[10px] font-bold">HTG</span></div>
-                    <div class="text-[8px] mt-1 flex gap-1 items-center">@Lang.next_round <span class="font-bold text-yellow-300">05:00</span></div>
+                    <div class="text-[10px] mt-1 flex gap-1 items-center">@Lang.next_round <span class="font-bold text-yellow-300">05:00</span></div>
                 </div>
                 </div>
                 <div class="col-span-3 flex flex-col justify-end items-center h-full relative">
                 <div class="col-span-3 flex flex-col justify-end items-center h-full relative">
                     <img src="/LotteryV2/img/gold_chest.png" alt="Chest" class="w-14 h-14 object-contain filter drop-shadow-md">
                     <img src="/LotteryV2/img/gold_chest.png" alt="Chest" class="w-14 h-14 object-contain filter drop-shadow-md">
-                    <button class="bg-gradient-to-b from-yellow-300 to-yellow-400 text-red-700 font-extrabold px-3 py-1 rounded-xl text-[12px] shadow-sm transform active:scale-95 transition-all mt-1">@Lang.play</button>
+                    <button class="bg-gradient-to-b from-yellow-300 to-yellow-400 text-red-700 font-extrabold px-3 py-1 rounded-xl text-[12px] shadow-sm mt-1">@Lang.play</button>
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
 
 
         <!-- Game item 2: Big/Small -->
         <!-- Game item 2: Big/Small -->
-        <div class="w-full p-3.5 rounded-2xl relative overflow-hidden card-shadow text-white border border-white/10" style="background-color: rgb(38 163 30);">
+        <div class="w-full p-3.5 rounded-2xl relative overflow-hidden card-shadow text-white border border-white/10 cursor-pointer transform active:scale-[0.98] transition-all" style="background-color: rgb(38 163 30);" onclick="checkTerm('@Constants.PIC10_BIGSMALL_CODE')">
             <div class="absolute -left-6 -top-6 w-16 h-16 bg-white/10 rounded-full blur-xl"></div>
             <div class="absolute -left-6 -top-6 w-16 h-16 bg-white/10 rounded-full blur-xl"></div>
             <div class="grid grid-cols-10 items-center">
             <div class="grid grid-cols-10 items-center">
                 <div class="col-span-3 flex flex-col items-start">
                 <div class="col-span-3 flex flex-col items-start">
@@ -111,17 +111,17 @@
                 <div class="col-span-4 flex flex-col items-center text-center">
                 <div class="col-span-4 flex flex-col items-center text-center">
                     <div class="text-[12px] uppercase font-bold text-white/80">@Lang.jackpot_prize</div>
                     <div class="text-[12px] uppercase font-bold text-white/80">@Lang.jackpot_prize</div>
                     <div class="text-xl font-extrabold text-[#FBF3A7] tracking-wider">100 <span class="text-[10px] font-bold">HTG</span></div>
                     <div class="text-xl font-extrabold text-[#FBF3A7] tracking-wider">100 <span class="text-[10px] font-bold">HTG</span></div>
-                    <div class="text-[8px] mt-1 flex gap-1 items-center">@Lang.next_round <span class="font-bold text-yellow-300">05:00</span></div>
+                    <div class="text-[10px] mt-1 flex gap-1 items-center">@Lang.next_round <span class="font-bold text-yellow-300">05:00</span></div>
                 </div>
                 </div>
                 <div class="col-span-3 flex flex-col justify-end items-center h-full relative">
                 <div class="col-span-3 flex flex-col justify-end items-center h-full relative">
                     <img src="/LotteryV2/img/gold_bag.png" alt="Bag" class="w-14 h-14 object-contain filter drop-shadow-md">
                     <img src="/LotteryV2/img/gold_bag.png" alt="Bag" class="w-14 h-14 object-contain filter drop-shadow-md">
-                    <button class="bg-gradient-to-b from-yellow-300 to-yellow-400 text-emerald-800 font-extrabold px-3 py-1 rounded-xl text-[12px] shadow-sm transform active:scale-95 transition-all mt-1">@Lang.play</button>
+                    <button class="bg-gradient-to-b from-yellow-300 to-yellow-400 text-emerald-800 font-extrabold px-3 py-1 rounded-xl text-[12px] shadow-sm mt-1">@Lang.play</button>
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
 
 
         <!-- Game item 3: @Lang.odd_even -->
         <!-- Game item 3: @Lang.odd_even -->
-        <div class="w-full p-3.5 rounded-2xl relative overflow-hidden card-shadow text-white border border-white/10" style="background-color: rgb(213 45 233);">
+        <div class="w-full p-3.5 rounded-2xl relative overflow-hidden card-shadow text-white border border-white/10 cursor-pointer transform active:scale-[0.98] transition-all" style="background-color: rgb(213 45 233);" onclick="checkTerm('@Constants.PIC10_ODDEVEN_CODE')">
             <div class="absolute -left-6 -top-6 w-16 h-16 bg-white/10 rounded-full blur-xl"></div>
             <div class="absolute -left-6 -top-6 w-16 h-16 bg-white/10 rounded-full blur-xl"></div>
             <div class="grid grid-cols-10 items-center">
             <div class="grid grid-cols-10 items-center">
                 <div class="col-span-3 flex flex-col items-start">
                 <div class="col-span-3 flex flex-col items-start">
@@ -134,11 +134,11 @@
                 <div class="col-span-4 flex flex-col items-center text-center">
                 <div class="col-span-4 flex flex-col items-center text-center">
                     <div class="text-[12px] uppercase font-bold text-white/80">@Lang.jackpot_prize</div>
                     <div class="text-[12px] uppercase font-bold text-white/80">@Lang.jackpot_prize</div>
                     <div class="text-xl font-extrabold text-[#FBF3A7] tracking-wider">200 <span class="text-[10px] font-bold">HTG</span></div>
                     <div class="text-xl font-extrabold text-[#FBF3A7] tracking-wider">200 <span class="text-[10px] font-bold">HTG</span></div>
-                    <div class="text-[8px] mt-1 flex gap-1 items-center">@Lang.next_round <span class="font-bold text-yellow-300">05:00</span></div>
+                    <div class="text-[10px] mt-1 flex gap-1 items-center">@Lang.next_round <span class="font-bold text-yellow-300">05:00</span></div>
                 </div>
                 </div>
                 <div class="col-span-3 flex flex-col justify-end items-center h-full relative">
                 <div class="col-span-3 flex flex-col justify-end items-center h-full relative">
                     <img src="/LotteryV2/img/gold_wallet.png" alt="Wallet" class="w-14 h-14 object-contain filter drop-shadow-md">
                     <img src="/LotteryV2/img/gold_wallet.png" alt="Wallet" class="w-14 h-14 object-contain filter drop-shadow-md">
-                    <button class="bg-gradient-to-b from-yellow-300 to-yellow-400 text-blue-800 font-extrabold px-3 py-1 rounded-xl text-[12px] shadow-sm transform active:scale-95 transition-all mt-1">@Lang.play</button>
+                    <button class="bg-gradient-to-b from-yellow-300 to-yellow-400 text-blue-800 font-extrabold px-3 py-1 rounded-xl text-[12px] shadow-sm mt-1">@Lang.play</button>
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
@@ -152,24 +152,106 @@
              <div class="opacity-90">@Lang.have_chance_to_get</div>
              <div class="opacity-90">@Lang.have_chance_to_get</div>
              <!-- Row 2 -->
              <!-- Row 2 -->
              <div class="text-[18px] font-black text-[#FBF3A7] mt-0.5">
              <div class="text-[18px] font-black text-[#FBF3A7] mt-0.5">
-                  100.000 HTG today !
+                  @Lang.jackpot_today_htg
              </div>
              </div>
          </div>
          </div>
     </div>
     </div>
 
 
+    <!-- Custom Notification Modal (Branded design from Profile) -->
+    <div id="notificationModal" class="fixed inset-0 z-[100] 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%);">
+        <div class="w-full max-w-[343px] min-h-[480px] bg-white rounded-[24px] overflow-hidden flex flex-col items-center p-8 animate__animated animate__zoomIn animate__faster shadow-2xl">
+            <!-- Alert Icon -->
+            <div class="w-full flex justify-center mb-8 mt-6">
+                <img src="/LotteryV2/img/modal/fail_icon.png" class="w-[180px] h-auto object-contain" alt="Notificaton icon" />
+            </div>
+
+            <!-- Message Area -->
+            <div class="px-2 text-center mb-10 flex-1 flex items-center justify-center">
+                <p id="notificationMessage" class="text-black font-[800] text-[22px] leading-snug">
+                    <!-- Message content -->
+                </p>
+            </div>
+
+            <!-- Action Button -->
+            <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> 
+            </div>
+        </div>
+    </div>
+
     <!-- Bottom Navbar shared component -->
     <!-- Bottom Navbar shared component -->
     <partial name="_BottomNavbar" />
     <partial name="_BottomNavbar" />
 </div>
 </div>
 
 
 @section Scripts {
 @section Scripts {
     <script>
     <script>
+        function showNotification(message) {
+            $("#notificationMessage").text(message);
+            $("#notificationModal").removeClass("hidden").addClass("flex");
+        }
+
+        function closeNotificationModal() {
+            $("#notificationModal").addClass("hidden").removeClass("flex");
+        }
+
+        let isCheckingTerm = false;
+
+        function checkTerm(termType) {
+            if (isCheckingTerm) return;
+            isCheckingTerm = true;
+
+            // 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',
+                type: 'POST',
+                data: {
+                    __RequestVerificationToken: token,
+                    termType: termType
+                },
+                success: function (res) {
+                    if (res.responseCode === "0") {
+                        if (res.listTerm && res.listTerm.length > 0) {
+                            var status = res.listTerm[0].status;
+                            if (status === "0" || status === "1") {
+                                location.href = subDomain + '/LotteryV2/Home/BuyTicket?termType=' + termType;
+                                return;
+                            } else if (status === "2") {
+                                showNotification("@Lang.v2_game_locked");
+                            } else if (status === "3") {
+                                showNotification("@Lang.v2_updating_results");
+                            } else {
+                                showNotification("@Lang.v2_game_locked");
+                            }
+                        } else {
+                            showNotification("@Lang.no_results_found");
+                        }
+                    } else if (res.responseCode === "401") {
+                        window.location.href = subDomain + "/Account/Login";
+                        return;
+                    } else {
+                        showNotification(res.responseMessage || "@Lang.error_happened");
+                    }
+                    isCheckingTerm = false;
+                },
+                error: function (err) {
+                    console.error("AJAX Error:", err);
+                    showNotification("@Lang.error_happened");
+                    isCheckingTerm = false;
+                }
+            });
+        }
+
         function startCountdown() {
         function startCountdown() {
             const targetHour = 20; // 20:00 (8h tối)
             const targetHour = 20; // 20:00 (8h tối)
             const now = new Date();
             const now = new Date();
             let target = new Date();
             let target = new Date();
             target.setHours(targetHour, 0, 0, 0);
             target.setHours(targetHour, 0, 0, 0);
 
 
-            // Nếu giờ hiện tại đã qua 20h tối, mốc đếm ngược sẽ nhảy sang 20h tối ngày mai
             if (now >= target) {
             if (now >= target) {
                 target.setDate(target.getDate() + 1);
                 target.setDate(target.getDate() + 1);
             }
             }

+ 141 - 0
website/Areas/LotteryV2/Views/Home/History.cshtml

@@ -0,0 +1,141 @@
+@model LotteryWebApp.Models.UserTicketHistoryModel
+@using LotteryWebApp.Languages
+@using LotteryWebApp.Common
+@{
+    ViewData["Title"] = "LotteryV2 - History";
+    Layout = "~/Areas/LotteryV2/Views/Shared/_Layout.cshtml";
+    ViewData["ActiveTab"] = "History";
+}
+
+@section Styles {
+    <script src="https://cdn.tailwindcss.com"></script>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
+    <link rel="stylesheet" href="/LotteryV2/css/site.css" />
+    <link rel="stylesheet" href="/LotteryV2/css/results.css" />
+    <link rel="stylesheet" href="/LotteryV2/css/history.css" />
+}
+
+<div class="main-container results-container animate__animated animate__fadeIn pb-40 relative">
+    <!-- Header Group: Fixed at Top -->
+    <div class="fixed top-0 left-1/2 -translate-x-1/2 w-full max-w-[414px] z-[100] bg-[#F3F4F6] pb-2 shadow-md">
+        <!-- Header -->
+        <div class="results-top-header">
+            <a href="/LotteryV2/Home/GameHome" class="back-btn">
+                <i class="fas fa-arrow-left"></i>
+            </a>
+            <h1 class="font-bricolage">@Lang.history</h1>
+        </div>
+
+        <!-- Game Tabs -->
+        <div class="history-game-tabs !mt-0 pt-3 scale-95 origin-top">
+            <div class="game-tab @(Model.termType == Constants.PIC10_BASIC_CODE ? "active" : "")" 
+                 onclick="changeGame('@Constants.PIC10_BASIC_CODE', this)">@Lang.v2_classic_pick_10</div>
+            <div class="game-tab @(Model.termType == Constants.PIC10_BIGSMALL_CODE ? "active" : "")" 
+                 onclick="changeGame('@Constants.PIC10_BIGSMALL_CODE', this)">@Lang.v2_big_small</div>
+            <div class="game-tab @(Model.termType == Constants.PIC10_ODDEVEN_CODE ? "active" : "")" 
+                 onclick="changeGame('@Constants.PIC10_ODDEVEN_CODE', this)">@Lang.v2_odd_even</div>
+        </div>
+
+        <!-- Status Filters -->
+        <div class="status-filters !mt-1">
+            <div class="status-filter @(Model.status == Constants.ALL_DATA ? "active" : "")" 
+                 onclick="changeStatus('@Constants.ALL_DATA', this)">@Lang.v2_all</div>
+            <div class="status-filter @(Model.status == Constants.NOT_DRAW_CODE ? "active" : "")" 
+                 onclick="changeStatus('@Constants.NOT_DRAW_CODE', this)">@Lang.v2_waiting</div>
+            <div class="status-filter @(Model.status == Constants.WIN_CODE ? "active" : "")" 
+                 onclick="changeStatus('@Constants.WIN_CODE', this)">@Lang.v2_win</div>
+            <div class="status-filter @(Model.status == Constants.DRAWN_CODE ? "active" : "")" 
+                 onclick="changeStatus('@Constants.DRAWN_CODE', this)">@Lang.v2_not_win</div>
+        </div>
+    </div>
+
+    <!-- Spacer to push content down below fixed header (~160px) -->
+    <div class="h-[160px]"></div>
+
+    <!-- Ticket List Container -->
+    <div id="history-list-container" class="history-items-list px-4 mt-2">
+        <partial name="_TermUserTicketHistory" model="Model" />
+    </div>
+
+    <!-- Pagination (Optional but good to have if supported) -->
+    @if (Model.totalPage != null && int.Parse(Model.totalPage) > 1) {
+        <div class="flex justify-center gap-4 pb-40">
+             <button onclick="changePage(currentSeqPage - 1)" class="p-2 px-4 bg-white rounded-lg shadow-sm font-bold text-gray-500 disabled:opacity-30" id="prevPage">Prev</button>
+             <span class="p-2 font-bold text-[#EE0033]" id="pageDisplay">@Model.seqPage / @Model.totalPage</span>
+             <button onclick="changePage(currentSeqPage + 1)" class="p-2 px-4 bg-white rounded-lg shadow-sm font-bold text-gray-500 disabled:opacity-30" id="nextPage">Next</button>
+        </div>
+    }
+
+    <!-- Shared Bottom Navbar -->
+    <partial name="_BottomNavbar" />
+</div>
+
+@section Scripts {
+    <script>
+
+        let currentTermType = '@Model.termType';
+        let currentStatus = '@Model.status';
+        let currentSeqPage = parseInt('@Model.seqPage');
+        let totalPages = parseInt('@Model.totalPage' || '1');
+
+        function changeGame(type, el) {
+            if (currentTermType === type) return;
+            currentTermType = type;
+            currentSeqPage = 1;
+            
+            document.querySelectorAll('.game-tab').forEach(t => t.classList.remove('active'));
+            el.classList.add('active');
+            
+            loadHistory();
+        }
+
+        function changeStatus(status, el) {
+            if (currentStatus === status) return;
+            currentStatus = status;
+            currentSeqPage = 1;
+
+            document.querySelectorAll('.status-filter').forEach(t => t.classList.remove('active'));
+            el.classList.add('active');
+
+            loadHistory();
+        }
+
+        function changePage(page) {
+            if (page < 1 || page > totalPages) return;
+            currentSeqPage = page;
+            loadHistory();
+        }
+
+        function loadHistory() {
+            const container = document.getElementById("history-list-container");
+            container.style.opacity = "0.5";
+
+            fetch(subDomain + `/LotteryV2/Home/TermUserTicketHistory?termType=${currentTermType}&status=${currentStatus}&seqPage=${currentSeqPage}`)
+                .then(response => response.text())
+                .then(html => {
+                    container.innerHTML = html;
+                    container.style.opacity = "1";
+                    updatePaginationUI();
+                })
+                .catch(error => {
+                    console.error('Error fetching history:', error);
+                    container.style.opacity = "1";
+                });
+        }
+
+        function updatePaginationUI() {
+            const pageDisplay = document.getElementById("pageDisplay");
+            const prevBtn = document.getElementById("prevPage");
+            const nextBtn = document.getElementById("nextPage");
+            
+            if (pageDisplay) {
+                // Total pages might have changed after filter
+                // We'd need to get it from the partial view or another API call
+                // For now, assume it's stable or handled by the server
+                pageDisplay.innerText = `${currentSeqPage} / ${totalPages}`;
+            }
+            if (prevBtn) prevBtn.disabled = currentSeqPage <= 1;
+            if (nextBtn) nextBtn.disabled = currentSeqPage >= totalPages;
+        }
+    </script>
+}

+ 5 - 25
website/Areas/LotteryV2/Views/Home/Index.cshtml

@@ -11,8 +11,11 @@
 <link rel="stylesheet" href="/LotteryV2/css/site.css" />
 <link rel="stylesheet" href="/LotteryV2/css/site.css" />
 
 
 <div class="main-container animate__animated animate__fadeIn">
 <div class="main-container animate__animated animate__fadeIn">
-    <!-- Top Area Banner / Big Illustration with absolute Logo overlay -->
     <div class="relative w-full flex flex-col items-center pt-3">
     <div class="relative w-full flex flex-col items-center pt-3">
+        <a href="@Url.Action("ChooseApp", "Account", new { area = "" })" class="absolute left-4 top-4 z-20 w-10 h-10 bg-white/20 backdrop-blur-md rounded-full flex items-center justify-center text-white border border-white/20 hover:bg-white/30 transition-all shadow-lg active:scale-90">
+            <i class="fas fa-chevron-left text-lg"></i>
+        </a>
+
         <!-- Logo -->
         <!-- Logo -->
         <div class="w-56 z-10 filter drop-shadow-md">
         <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">
             <img src="/LotteryV2/img/logo.png" alt="Logo" class="w-full h-auto object-contain">
@@ -121,33 +124,10 @@
         </div>
         </div>
     </div>
     </div>
 
 
-    <!-- Bottom Navbar (Conforms exactly to Menu Node 96:260)
-    <div class="fixed bottom-0 left-1/2 -translate-x-1/2 w-full max-w-[414px] bg-gradient-to-r from-red-600 to-red-700 bg-white/10 backdrop-blur-md border-t border-white/20 p-2 flex justify-around items-center text-white z-50 rounded-t-2xl shadow-xl">
-        <div class="flex flex-col items-center text-yellow-300 cursor-pointer">
-            <i class="fas fa-home text-lg"></i>
-            <span class="text-[9px] mt-1 font-semibold">Trang chủ</span>
-        </div>
-        <div class="flex flex-col items-center text-white/70 cursor-pointer hover:text-white transition-colors">
-            <i class="fas fa-book-open text-lg"></i>
-            <span class="text-[9px] mt-1">Luật chơi</span>
-        </div>
-        <div class="flex flex-col items-center text-white/70 cursor-pointer hover:text-white transition-colors">
-            <i class="fas fa-history text-lg"></i>
-            <span class="text-[9px] mt-1">Lịch sử</span>
-        </div>
-        <div class="flex flex-col items-center text-white/70 cursor-pointer hover:text-white transition-colors">
-            <i class="fas fa-question-circle text-lg"></i>
-            <span class="text-[9px] mt-1">FAQs</span>
-        </div>
-        <div class="flex flex-col items-center text-white/70 cursor-pointer hover:text-white transition-colors">
-            <i class="fas fa-ellipsis-h text-lg"></i>
-            <span class="text-[9px] mt-1">Thêm</span>
-        </div>
-    </div> -->
 </div>
 </div>
 <script>
 <script>
     function changeGame() {
     function changeGame() {
             var termType = $("#MEGA_LOTO_ID").val();
             var termType = $("#MEGA_LOTO_ID").val();
-            location.href = '@Url.Action("GameHome", "Home", new { area = "LotteryV2" })?termType=' + termType;
+            location.href = subDomain + '@Url.Action("GameHome", "Home", new { area = "LotteryV2" })?termType=' + termType;
         }
         }
 </script>
 </script>

+ 2 - 1
website/Areas/LotteryV2/Views/Home/More.cshtml

@@ -92,12 +92,13 @@
 <partial name="_BottomNavbar" />
 <partial name="_BottomNavbar" />
 
 
 <script>
 <script>
+
     function toggleLanguage() {
     function toggleLanguage() {
         // Toggle language based on current system culture
         // Toggle language based on current system culture
         let currentLang = '@System.Threading.Thread.CurrentThread.CurrentCulture.Name';
         let currentLang = '@System.Threading.Thread.CurrentThread.CurrentCulture.Name';
         let newLang = currentLang === 'en' ? 'fr' : 'en'; // Switch between en and fr
         let newLang = currentLang === 'en' ? 'fr' : 'en'; // Switch between en and fr
 
 
-        fetch('/Home/SetCulture?lang=' + newLang)
+        fetch(subDomain + '/Home/SetCulture?lang=' + newLang)
             .then(response => {
             .then(response => {
                 location.reload();
                 location.reload();
             })
             })

+ 168 - 17
website/Areas/LotteryV2/Views/Home/Profile.cshtml

@@ -12,14 +12,18 @@
 
 
 <!-- Add custom font Bricolage Grotesque to match Figma styling -->
 <!-- Add custom font Bricolage Grotesque to match Figma styling -->
 <link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;700;800&display=swap" rel="stylesheet">
 <link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;700;800&display=swap" rel="stylesheet">
+<!-- Flatpickr for premium calendar -->
+<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
+<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.js"></script>
+<link rel="stylesheet" href="/LotteryV2/css/results.css" />
 <style>
 <style>
     .font-bricolage { font-family: 'Bricolage Grotesque', sans-serif; }
     .font-bricolage { font-family: 'Bricolage Grotesque', sans-serif; }
 </style>
 </style>
 
 
 <div class="main-container animate__animated animate__fadeIn min-h-screen relative flex flex-col pb-24 font-bricolage" style="background-color: #EAEAEA !important;">
 <div class="main-container animate__animated animate__fadeIn min-h-screen relative flex flex-col pb-24 font-bricolage" style="background-color: #EAEAEA !important;">
     
     
-    <!-- Header (Red Background) -->
-    <div class="w-full bg-[#EE0033] h-[52px] flex items-center justify-between px-4 sticky top-0 z-50">
+    <!-- Header (Red Background) - Fixed -->
+    <div class="fixed top-0 left-1/2 -translate-x-1/2 w-full max-w-[414px] bg-[#EE0033] h-[52px] flex items-center justify-between px-4 z-[100] shadow-sm">
         <!-- Back Button -->
         <!-- Back Button -->
         <button onclick="window.location.href='/LotteryV2/Home/More'" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-colors z-10 text-white">
         <button onclick="window.location.href='/LotteryV2/Home/More'" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-colors z-10 text-white">
             <i class="fa-solid fa-arrow-left text-[24px]"></i>
             <i class="fa-solid fa-arrow-left text-[24px]"></i>
@@ -30,6 +34,9 @@
         </div>
         </div>
     </div>
     </div>
 
 
+    <!-- Header Spacer (~52px) -->
+    <div class="h-[52px]"></div>
+
     <!-- Content Form -->
     <!-- Content Form -->
     <div class="w-full flex flex-col items-center px-5 py-6 gap-3 flex-1 overflow-x-hidden">
     <div class="w-full flex flex-col items-center px-5 py-6 gap-3 flex-1 overflow-x-hidden">
         
         
@@ -45,30 +52,32 @@
         <div class="w-full flex flex-col gap-2 mt-2">
         <div class="w-full flex flex-col gap-2 mt-2">
             <label class="font-bold text-[#534A4A] text-[14px]">@Lang.name</label>
             <label class="font-bold text-[#534A4A] text-[14px]">@Lang.name</label>
             <div class="w-full bg-transparent border border-[#8F8F8F] rounded-[8px] h-[50px] px-3 flex items-center">
             <div class="w-full bg-transparent border border-[#8F8F8F] rounded-[8px] h-[50px] px-3 flex items-center">
-                <input type="text" class="w-full bg-transparent font-[800] text-[20px] text-black outline-none tracking-wide" value="@(Model?.profile?.fullName ?? "User")" />
+                <input type="text" id="txtFullName" class="w-full bg-transparent font-[800] text-[20px] text-black outline-none tracking-wide" value="@(Model?.profile?.fullName ?? "User")" />
             </div>
             </div>
         </div>
         </div>
 
 
-        <!-- Date of birth Field -->
         <div class="w-full flex flex-col gap-2 mt-2">
         <div class="w-full flex flex-col gap-2 mt-2">
             <label class="font-bold text-[#534A4A] text-[14px]">@Lang.dateOfBirth</label>
             <label class="font-bold text-[#534A4A] text-[14px]">@Lang.dateOfBirth</label>
-            <div class="w-full bg-transparent border border-[#8F8F8F] rounded-[8px] h-[50px] px-3 flex items-center justify-between">
-                <input type="text" class="w-full bg-transparent font-[800] text-[20px] text-black outline-none tracking-wide flex-1" value="29/02/2000" disabled />
-                <i class="fa-regular fa-calendar text-[#534A4A] text-[20px]"></i>
+            @{
+                string birthdayVal = Model?.profile?.birthday ?? "2000-01-01";
+                if (birthdayVal.Contains("/")) {
+                    try {
+                        var parts = birthdayVal.Split('/');
+                        if (parts.Length == 3) { birthdayVal = $"{parts[2]}-{parts[1]}-{parts[0]}"; }
+                    } catch { birthdayVal = "2000-01-01"; }
+                }
+            }
+            <div class="w-full bg-transparent rounded-[8px] flex items-center justify-between relative cursor-pointer" onclick="document.getElementById('txtBirthday')._flatpickr.open()">
+                <input type="text" id="txtBirthday" class="w-full bg-transparent font-[800] text-[20px] text-black outline-none tracking-wide flex-1" 
+                       value="@birthdayVal" readonly />
+                <i class="fa-regular fa-calendar text-[#534A4A] text-[20px] pointer-events-none absolute right-3"></i>
             </div>
             </div>
         </div>
         </div>
 
 
-        <!-- Password Field -->
-        <div class="w-full flex flex-col gap-2 mt-2">
-            <label class="font-bold text-[#534A4A] text-[14px]">@Lang.password</label>
-            <div class="w-full bg-transparent border border-[#8F8F8F] rounded-[8px] h-[50px] px-3 flex items-center">
-                <input type="password" class="w-full bg-transparent font-[800] text-[20px] text-black tracking-[4px] outline-none" value="******" disabled />
-            </div>
-        </div>
-        
+
         <!-- Update Button -->
         <!-- Update Button -->
         <div class="w-full flex justify-center mt-8">
         <div class="w-full flex justify-center mt-8">
-            <button class="w-[300px] max-w-full bg-[#EE0033] text-white font-[800] text-[20px] py-[10px] rounded-[12px] shadow-[0px_3px_8px_rgba(0,0,0,0.25)] hover:bg-red-700 active:scale-95 transition-all">
+            <button id="btnUpdateProfile" onclick="updateProfile(this)" class="w-[300px] max-w-full bg-[#EE0033] text-white font-[800] text-[20px] py-[10px] rounded-[12px] shadow-[0px_3px_8px_rgba(0,0,0,0.25)] hover:bg-red-700 active:scale-95 transition-all">
                 @Lang.update
                 @Lang.update
             </button>
             </button>
         </div>
         </div>
@@ -77,5 +86,147 @@
 
 
 </div>
 </div>
 
 
-<!-- Bottom Navbar shared component -->
+<!-- Success Modal Overlay -->
+<div id="successModal" class="fixed inset-0 z-[100] flex items-center justify-center hidden px-6 translate-y-0" style="background: linear-gradient(135deg, #1A1A2E 0%, #16213E 100%);">
+    <div class="w-full max-w-[343px] min-h-[520px] bg-white rounded-[20px] overflow-hidden flex flex-col items-center p-8 animate__animated animate__zoomIn animate__faster">
+        <div class="w-full flex flex-col items-center mb-5 mt-4">
+            <div class="relative w-full max-w-[343px] flex items-center justify-center">
+                <img src="/LotteryV2/img/modal/success_header.png" class="w-[280px] h-auto object-contain" />
+            </div>
+        </div>
+        <div class="px-5 text-center mb-10 mt-5">
+            <p class="text-black font-[700] text-[20px] font-bricolage leading-tight">
+                @Lang.update_successful
+            </p>
+        </div>
+        <div class="w-full mt-auto">
+            <button onclick="closeModalAndReload('/LotteryV2/Home/More')" class="w-full bg-[#EE0033] text-white font-[800] text-[20px] py-[10px] rounded-[12px] shadow-[0px_3px_8px_rgba(0,0,0,0.25)] hover:bg-red-700 active:scale-95 transition-all font-bricolage">
+                @Lang.back_to_homepage
+            </button>
+        </div>
+    </div>
+</div>
+
+<!-- Failure Modal Overlay -->
+<div id="failureModal" class="fixed inset-0 z-[100] flex items-center justify-center hidden px-6 translate-y-0" style="background: linear-gradient(135deg, #1A1A2E 0%, #16213E 100%);">
+    <div class="w-full max-w-[343px] min-h-[520px] bg-white rounded-[20px] overflow-hidden flex flex-col items-center p-8 animate__animated animate__zoomIn animate__faster">
+        <div class="w-full flex flex-col items-center mb-8 mt-10">
+            <div class="relative w-full max-w-[343px] flex items-center justify-center">
+                <img src="/LotteryV2/img/modal/fail_icon.png" class="w-[200px] h-auto object-contain" />
+            </div>
+        </div>
+        <div class="px-5 text-center mb-10 mt-5">
+            <p id="failErrorMessage" class="text-black font-[700] text-[20px] font-bricolage leading-tight">
+                @Lang.update_profile_error
+            </p>
+        </div>
+        <div class="w-full mt-auto">
+            <button onclick="closeFailureModal()" class="w-full bg-[#EE0033] text-white font-[800] text-[20px] py-[10px] rounded-[12px] shadow-[0px_3px_8_rgba(0,0,0,0.25)] hover:bg-red-700 active:scale-95 transition-all font-bricolage">
+                @Lang.try_again
+            </button>
+        </div>
+    </div>
+</div>
+
 <partial name="_BottomNavbar" />
 <partial name="_BottomNavbar" />
+
+<script>
+
+    function initBrandedFlatpickr(selector, yearStart, yearEnd) {
+        flatpickr(selector, {
+            dateFormat: "Y-m-d",
+            altInput: true,
+            altFormat: "d/m/Y",
+            altInputClass: "w-full bg-transparent font-[800] text-[20px] text-black outline-none tracking-wide cursor-pointer",
+            disableMobile: true,
+            monthSelectorType: "dropdown",
+            onReady: function (selectedDates, dateStr, instance) {
+                const yearInput = instance.calendarContainer.querySelector(".numInput.cur-year");
+                if (yearInput) {
+                    const yearSelect = document.createElement("select");
+                    yearSelect.className = "flatpickr-monthDropdown-months cur-year-select";
+                    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;";
+
+                    for (let y = yearEnd; y >= yearStart; y--) {
+                        const opt = document.createElement("option");
+                        opt.value = y;
+                        opt.text = y;
+                        opt.style.color = "#333";
+                        if (y === instance.currentYear) opt.selected = true;
+                        yearSelect.appendChild(opt);
+                    }
+
+                    yearSelect.addEventListener("change", function () {
+                        instance.changeYear(parseInt(this.value));
+                    });
+
+                    yearInput.style.display = "none";
+                    yearInput.parentNode.appendChild(yearSelect);
+                    
+                    instance.set("onChange", function(d, s, i) {
+                        yearSelect.value = i.currentYear;
+                    });
+                }
+            }
+        });
+    }
+
+    document.addEventListener('DOMContentLoaded', function() {
+        initBrandedFlatpickr("#txtBirthday", 1940, 2026);
+    });
+
+    function updateProfile(btn) {
+        var fullName = $("#txtFullName").val();
+        var birthday = $("#txtBirthday").val(); 
+
+        if (fullName == "") {
+            showFailureModal("@Lang.enter_name");
+            return;
+        }
+
+        // Prevent double-click
+        var $btn = $(btn);
+        var originalText = $btn.html();
+        $btn.prop('disabled', true).html('<i class="fa-solid fa-spinner fa-spin mr-2"></i> ...');
+
+        $.ajax({
+            url: subDomain + "/LotteryV2/Home/UserUpdateProfile",
+            type: "POST",
+            data: {
+                fullName: fullName,
+                birthday: birthday
+            },
+            success: function (response) {
+                $btn.prop('disabled', false).html(originalText);
+                if (response.status == "0") {
+                    showSuccessModal();
+                } else {
+                    showFailureModal(response.message || "Update failed");
+                }
+            },
+            error: function (error) {
+                $btn.prop('disabled', false).html(originalText);
+                showFailureModal("An error occurred during network request");
+                console.log(error);
+            }
+        });
+    }
+
+    function showSuccessModal() {
+        $("#successModal").removeClass("hidden").addClass("flex");
+    }
+
+    function showFailureModal(message) {
+        $("#failErrorMessage").text(message);
+        $("#failureModal").removeClass("hidden").addClass("flex");
+    }
+
+    function closeModalAndReload(url) {
+        $("#successModal").addClass("hidden").removeClass("flex");
+        window.location.href = url;
+    }
+
+    function closeFailureModal() {
+        $("#failureModal").addClass("hidden").removeClass("flex");
+    }
+</script>

+ 177 - 0
website/Areas/LotteryV2/Views/Home/Results.cshtml

@@ -0,0 +1,177 @@
+@model LotteryWebApp.Models.TermResultHistoryModel
+@{
+    ViewData["Title"] = "LotteryV2 - Results History";
+    Layout = "~/Areas/LotteryV2/Views/Shared/_Layout.cshtml";
+    ViewData["ActiveTab"] = "Results";
+}
+@using LotteryWebApp.Languages;
+
+@section Styles {
+    <script src="https://cdn.tailwindcss.com"></script>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
+    <!-- Flatpickr for premium calendar -->
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
+    <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
+    <link rel="stylesheet" href="/LotteryV2/css/site.css" />
+    <link rel="stylesheet" href="/LotteryV2/css/results.css" />
+}
+
+<div class="main-container results-container animate__animated animate__fadeIn pb-40 relative">
+    <!-- Header Group: Fixed at Top -->
+    <div class="fixed top-0 left-1/2 -translate-x-1/2 w-full max-w-[414px] z-[100] bg-[#F3F4F6] pb-2 shadow-md">
+        <!-- Header: Matches Figma (Right Image) -->
+        <div class="results-top-header">
+            <a href="javascript:history.back()" class="back-btn">
+                <i class="fas fa-arrow-left"></i>
+            </a>
+            <h1 class="font-bricolage">@Lang.results</h1>
+        </div>
+
+        <!-- Selection Bar: Side-by-side dates and search -->
+        <div class="selection-bar bg-white/50 backdrop-blur-sm px-4 pt-4 pb-2">
+            <div class="flex gap-3">
+                <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">
+                    <img src="/LotteryV2/img/icon_calendar.svg" class="w-5 h-5" />
+                    <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 />
+                    <i class="fas fa-caret-down text-gray-400"></i>
+                </div>
+                <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">
+                    <img src="/LotteryV2/img/icon_calendar.svg" class="w-5 h-5" />
+                    <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 />
+                    <i class="fas fa-caret-down text-gray-400"></i>
+                </div>
+                <button id="btnSearch" class="btn-search-red !w-12 !h-12 flex items-center justify-center bg-[#EE0033] text-white rounded-xl shadow-md" onclick="triggerSearch()">
+                    <i class="fas fa-search"></i>
+                </button>
+            </div>
+        </div>
+
+        <!-- Column Headers (Time & Results) -->
+        <div class="px-4 mt-2">
+            <div class="flex gap-3">
+                <div class="flex-1 bg-white rounded-xl py-2 text-center text-[11px] font-black text-gray-800 shadow-sm border border-gray-100">
+                    @Lang.time
+                </div>
+                <div class="flex-[2] bg-white rounded-xl py-2 text-center text-[11px] font-black text-[#EE0033] shadow-sm border border-gray-100">
+                    @Lang.results
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- Spacer to push content down below fixed header (~180px) -->
+    <div class="h-[180px]"></div>
+
+    <!-- Result List Container -->
+    <div id="results-list-container" class="results-items-list px-4 min-h-[300px]">
+        <partial name="_TermResultHistoryV2" model="Model" />
+    </div>
+
+    <!-- Bottom Promo Bar (Matches Bottom message with yellow text) -->
+    <div class="fixed bottom-[74px] left-1/2 -translate-x-1/2 w-full max-w-[414px] bg-[#EE0033] 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">
+         <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-[18px] font-black text-[#FBF3A7] mt-0.5">
+                  @Lang.jackpot_today_htg
+             </div>
+         </div>
+    </div>
+
+    <!-- Shared Bottom Navbar -->
+    <partial name="_BottomNavbar" />
+</div>
+
+@section Scripts {
+    <script>
+
+        function initBrandedFlatpickr(selector, yearStart, yearEnd) {
+            const container = document.querySelector(".results-container") || document.querySelector(".main-container");
+            flatpickr(selector, {
+                dateFormat: "Y-m-d", // Actual value used for search
+                altInput: true,
+                altFormat: "M d, Y", // Premium display format
+                altInputClass: "bg-transparent border-none outline-none font-bold text-[13px] w-full ml-1 cursor-pointer",
+                disableMobile: "true",
+                monthSelectorType: "dropdown",
+                appendTo: container,
+                onReady: function (selectedDates, dateStr, instance) {
+                    const yearInput = instance.calendarContainer.querySelector(".numInput.cur-year");
+                    if (yearInput) {
+                        const yearSelect = document.createElement("select");
+                        yearSelect.className = "flatpickr-monthDropdown-months cur-year-select";
+                        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;";
+
+                        for (let y = yearEnd; y >= yearStart; y--) {
+                            const opt = document.createElement("option");
+                            opt.value = y;
+                            opt.text = y;
+                            opt.style.color = "#333";
+                            if (y === instance.currentYear) opt.selected = true;
+                            yearSelect.appendChild(opt);
+                        }
+
+                        yearSelect.addEventListener("change", function () {
+                            instance.changeYear(parseInt(this.value));
+                        });
+
+                        yearInput.style.display = "none";
+                        yearInput.parentNode.appendChild(yearSelect);
+                        
+                        instance.set("onChange", function(d, s, i) {
+                            yearSelect.value = i.currentYear;
+                        });
+                    }
+                }
+            });
+        }
+
+        document.addEventListener('DOMContentLoaded', function() {
+            initBrandedFlatpickr("#fromDate", 2020, 2030);
+            initBrandedFlatpickr("#toDate", 2020, 2030);
+        });
+
+        function triggerSearch() {
+            const fromDate = document.getElementById("fromDate").value;
+            const toDate = document.getElementById("toDate").value;
+            const termType = "@Model.termType";
+            const btn = document.getElementById("btnSearch");
+            const container = document.getElementById("results-list-container");
+
+            // UI Feedback: Loading state
+            btn.disabled = true;
+            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
+            container.style.opacity = "0.5";
+
+            // AJAX Call to TermResultHistory
+            fetch(subDomain + `/LotteryV2/Home/TermResultHistory?termType=${termType}&fromDate=${fromDate}&toDate=${toDate}`)
+                .then(response => response.text())
+                .then(html => {
+                    container.innerHTML = html;
+                    container.style.opacity = "1";
+                    btn.disabled = false;
+                    btn.innerHTML = '<i class="fas fa-search"></i>';
+                })
+                .catch(error => {
+                    console.error('Error fetching results:', error);
+                    container.style.opacity = "1";
+                    btn.disabled = false;
+                    btn.innerHTML = '<i class="fas fa-search"></i>';
+                    alert('Error fetching draw results. Please try again.');
+                });
+        }
+
+        function switchMainTab(type, el) {
+            const btns = el.parentElement.querySelectorAll('.tab-btn');
+            btns.forEach(b => {
+                b.style.color = '#1F2937';
+                b.style.border = 'none';
+                b.classList.remove('active');
+            });
+            el.style.color = '#EE0033';
+            el.style.border = '1.5px solid #EE0033';
+            el.classList.add('active');
+        }
+    </script>
+}

+ 39 - 35
website/Areas/LotteryV2/Views/Home/Rule.cshtml

@@ -1,4 +1,4 @@
-@model LotteryWebApp.Models.HomeIndex_ViewModel
+@model LotteryWebApp.Models.HomeIndex_ViewModel
 @{
 @{
     ViewData["Title"] = "LotteryV2 - @Lang.rule_title";
     ViewData["Title"] = "LotteryV2 - @Lang.rule_title";
     ViewData["ActiveTab"] = "Rule";
     ViewData["ActiveTab"] = "Rule";
@@ -16,49 +16,52 @@
 
 
 <div class="main-container animate__animated animate__fadeIn min-h-screen relative flex flex-col pb-24 font-bricolage overflow-x-hidden" style="background-color: #F5F5F5 !important;">
 <div class="main-container animate__animated animate__fadeIn min-h-screen relative flex flex-col pb-24 font-bricolage overflow-x-hidden" style="background-color: #F5F5F5 !important;">
     
     
-    <!-- Header Block (Red) -->
-    <div class="w-full bg-[#EE0033] h-[52px] flex items-center justify-between px-4 sticky top-0 z-50 shadow-sm">
-        <!-- Back Button -->
-        <button onclick="window.history.back()" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-colors z-10 text-white cursor-pointer">
-            <i class="fa-solid fa-arrow-left text-[20px]"></i>
-        </button>
-        <!-- Title -->
-        <div class="absolute inset-0 flex items-center justify-center pointer-events-none">
-            <span class="text-white text-[24px] font-bold tracking-wide drop-shadow-sm">@Lang.rule_title</span>
+    <!-- Fixed Header & Tabs Group -->
+    <div class="fixed top-0 left-1/2 -translate-x-1/2 w-full max-w-[414px] z-[100] bg-white shadow-md">
+        <!-- Header Block (Red) -->
+        <div class="w-full bg-[#EE0033] h-[52px] flex items-center justify-between px-4 relative">
+            <!-- Back Button -->
+            <button onclick="window.history.back()" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-colors z-10 text-white cursor-pointer">
+                <i class="fa-solid fa-arrow-left text-[20px]"></i>
+            </button>
+            <!-- Title -->
+            <div class="absolute inset-0 flex items-center justify-center pointer-events-none">
+                <span class="text-white text-[24px] font-bold tracking-wide drop-shadow-sm">@Lang.rule_title</span>
+            </div>
         </div>
         </div>
-    </div>
 
 
-    <!-- Tabs Block Container -->
-    <div class="w-full bg-white flex items-center justify-between px-2 pt-3 relative shadow-sm z-40 transition-all">
-        <!-- Tab 1 -->
-        <div class="flex flex-col items-center gap-1 cursor-pointer flex-1 group" onclick="switchFAQTab('basic')">
-            <span id="tab-basic-label" class="text-[13px] font-bold text-[#534A4A] transition-colors whitespace-nowrap">@Lang.rule_classic_pick_10</span>
-            <div id="tab-basic-bar" class="w-full h-[3px] bg-[#EE0033] mt-1 drop-shadow-sm transition-all rounded-t-sm"></div>
-        </div>
+        <!-- Tabs Block Container -->
+        <div class="w-full bg-white flex items-center justify-between px-2 pt-3 pb-1 relative shadow-sm transition-all border-b border-gray-100">
+            <!-- Tab 1 -->
+            <div class="flex flex-col items-center gap-1 cursor-pointer flex-1 group" onclick="switchFAQTab('basic')">
+                <span id="tab-basic-label" class="text-[13px] font-bold text-[#534A4A] transition-colors whitespace-nowrap">@Lang.rule_classic_pick_10</span>
+                <div id="tab-basic-bar" class="w-full h-[3px] bg-[#EE0033] mt-1 drop-shadow-sm transition-all rounded-t-sm"></div>
+            </div>
 
 
-        <!-- Tab 2 -->
-        <div class="flex flex-col items-center gap-1 cursor-pointer flex-1 group relative" onclick="switchFAQTab('smallbig')">
-            <div class="flex flex-col items-center leading-tight">
-                <span id="tab-smallbig-label" class="text-[13px] font-bold text-[#909090] transition-colors whitespace-nowrap">@Lang.rule_big_small</span>
-                <span id="tab-smallbig-desc" class="text-[9px] text-[#909090] font-normal whitespace-nowrap transition-colors">@Lang.rule_13_numbers_game</span>
+            <!-- Tab 2 -->
+            <div class="flex flex-col items-center gap-1 cursor-pointer flex-1 group relative" onclick="switchFAQTab('smallbig')">
+                <div class="flex flex-col items-center leading-tight">
+                    <span id="tab-smallbig-label" class="text-[13px] font-bold text-[#909090] transition-colors whitespace-nowrap">@Lang.rule_big_small</span>
+                    <span id="tab-smallbig-desc" class="text-[9px] text-[#909090] font-normal whitespace-nowrap transition-colors">@Lang.rule_13_numbers_game</span>
+                </div>
+                <div id="tab-smallbig-bar" class="w-full h-0.5 bg-transparent mt-1 transition-all"></div>
             </div>
             </div>
-            <div id="tab-smallbig-bar" class="w-full h-0.5 bg-transparent mt-1 transition-all"></div>
-        </div>
 
 
-        <!-- Tab 3 -->
-        <div class="flex flex-col items-center gap-1 cursor-pointer flex-1 group" onclick="switchFAQTab('oddeven')">
-            <div class="flex flex-col items-center leading-tight">
-                <span id="tab-oddeven-label" class="text-[13px] font-bold text-[#909090] transition-colors whitespace-nowrap">@Lang.rule_odd_even</span>
-                <span id="tab-oddeven-desc" class="text-[9px] text-[#909090] font-normal whitespace-nowrap transition-colors">@Lang.rule_15_numbers_game</span>
+            <!-- Tab 3 -->
+            <div class="flex flex-col items-center gap-1 cursor-pointer flex-1 group" onclick="switchFAQTab('oddeven')">
+                <div class="flex flex-col items-center leading-tight">
+                    <span id="tab-oddeven-label" class="text-[13px] font-bold text-[#909090] transition-colors whitespace-nowrap">@Lang.rule_odd_even</span>
+                    <span id="tab-oddeven-desc" class="text-[9px] text-[#909090] font-normal whitespace-nowrap transition-colors">@Lang.rule_15_numbers_game</span>
+                </div>
+                <!-- Indicator Bar -->
+                <div id="tab-oddeven-bar" class="w-full h-0.5 bg-transparent mt-1 transition-all"></div>
             </div>
             </div>
-            <!-- Indicator Bar -->
-            <div id="tab-oddeven-bar" class="w-full h-0.5 bg-transparent mt-1 transition-all"></div>
         </div>
         </div>
-
-        <!-- Bottom Line for tabs -->
-        <div class="absolute bottom-0 left-2 right-2 h-[1px] bg-[#D9D9D9] -z-10"></div>
     </div>
     </div>
 
 
+    <!-- Spacer to push content down below fixed header (~96px) -->
+    <div class="h-[96px]"></div>
+
     <!-- Active Tab Content -->
     <!-- Active Tab Content -->
     <div id="tab-content-basic" class="w-full animate__animated animate__fadeIn pb-32">
     <div id="tab-content-basic" class="w-full animate__animated animate__fadeIn pb-32">
         
         
@@ -500,6 +503,7 @@
 </div>
 </div>
 
 
 <script>
 <script>
+
     function switchFAQTab(tabId) {
     function switchFAQTab(tabId) {
         // Simple mock tab visual switcher for now matching the exact styling requested
         // Simple mock tab visual switcher for now matching the exact styling requested
         ['basic', 'smallbig', 'oddeven'].forEach(t => {
         ['basic', 'smallbig', 'oddeven'].forEach(t => {

+ 350 - 0
website/Areas/LotteryV2/Views/Home/TransferWinMoney.cshtml

@@ -0,0 +1,350 @@
+@model LotteryWebApp.Models.HomeIndex_ViewModel
+@{
+    ViewData["Title"] = Lang.v2_transfer;
+    Layout = "~/Areas/LotteryV2/Views/Shared/_Layout.cshtml";
+}
+@using LotteryWebApp.Languages;
+
+<div class="main-container animate__animated animate__fadeIn bg-[#EAEAEA] min-h-screen font-bricolage overflow-x-hidden">
+    <!-- Standardized Header (Matches Profile/Rules) -->
+    <div class="fixed top-0 left-1/2 -translate-x-1/2 w-full max-w-[414px] bg-[#EE0033] h-[52px] flex items-center justify-between px-4 z-[100] shadow-sm">
+        <!-- Back Button -->
+        <button onclick="history.back()" class="w-10 h-10 flex items-center justify-center -ml-2 rounded-full active:bg-white/20 transition-colors z-10 text-white">
+            <i class="fa-solid fa-arrow-left text-[20px]"></i>
+        </button>
+        <!-- Title centered -->
+        <div class="absolute inset-0 flex items-center justify-center pointer-events-none">
+            <span class="font-bold text-[24px] text-white tracking-wide uppercase">@Lang.v2_transfer</span>
+        </div>
+    </div>
+
+    <!-- Header Spacer (52px) -->
+    <div class="h-[52px]"></div>
+
+    <div class="pt-[20px] px-4 pb-24 max-w-[420px] mx-auto">
+        <!-- Account Card Section -->
+        <div class="relative w-full aspect-[343/180] bg-[#EE0033] rounded-[24px] overflow-hidden shadow-xl mb-6 border border-white/20 p-6 flex flex-col justify-between">
+            <!-- Decorative Glitter/Light Background -->
+            <div class="absolute inset-0 opacity-40 pointer-events-none" style="background: url('/LotteryV2/img/transfer_account_card.png') no-repeat center center; background-size: cover;"></div>
+            
+            <!-- Floating Decorative Elements -->
+            <img src="/LotteryV2/img/transfer_gold_stack.png" alt="Decoration" class="absolute -top-2 -right-2 w-16 opacity-80 pointer-events-none" />
+            <img src="/LotteryV2/img/transfer_gold_coin.png" alt="Decoration" class="absolute bottom-4 right-4 w-12 opacity-60 pointer-events-none animate-pulse" />
+
+            <div class="relative z-10">
+                <p class="text-white/80 font-bold text-[14px] uppercase tracking-wider">@Lang.v2_account_name</p>
+                <div class="flex items-end gap-2 mt-2">
+                    <span class="text-white font-[900] text-[36px] leading-[0.9]">@String.Format("{0:N0}", double.TryParse(Model?.userStatus?.cash_coin, out var cc) ? cc : 0)</span>
+                    <span class="text-[#FBF3A7] font-[900] text-[16px] uppercase pb-1">htg</span>
+                </div>
+            </div>
+
+            <div class="relative z-10 flex items-center gap-3">
+                <div class="w-10 h-10 bg-white/20 backdrop-blur-md rounded-full flex items-center justify-center border border-white/30">
+                    <img src="/LotteryV2/img/transfer_wallet_icon.png" alt="Wallet" class="w-5 h-5 object-contain" />
+                </div>
+                <span class="text-white/90 font-bold text-[14px]">Available Balance</span>
+            </div>
+        </div>
+
+        <!-- Selection Area (Horizontal Cards) -->
+        <div class="mb-6">
+            <h2 class="text-[#534A4A] font-[900] text-[18px] mb-3 pl-1">@Lang.v2_choose_account</h2>
+            <div class="flex gap-3">
+                <!-- Basic Account Option (Selected by default) -->
+                <div class="flex-1 bg-white h-[76px] rounded-[18px] border-2 border-[#EE0033] shadow-md flex items-center px-3 gap-2 cursor-pointer relative">
+                    <!-- Selected Icon -->
+                    <div class="absolute -top-2 -right-1 bg-white rounded-full">
+                        <i class="fa-solid fa-circle-check text-[#00AF1B] text-[20px]"></i>
+                    </div>
+                    <span class="text-[#EE0033] font-[900] text-[15px] leading-tight flex-1">Basic<br/>Account</span>
+                    <img src="/LotteryV2/img/transfer_basic_icon.png" alt="Basic" class="w-12 h-10 object-contain" />
+                </div>
+                <!-- Natcash Card (Disabled/Dimmed as requested) -->
+                <div class="flex-1 bg-white h-[76px] rounded-[18px] border border-gray-100 shadow-sm flex items-center justify-center grayscale opacity-50 cursor-not-allowed overflow-hidden">
+                    <img src="/LotteryV2/img/transfer_other_card.png" alt="Natcash" class="w-full h-full object-contain" />
+                </div>
+            </div>
+        </div>
+
+        <!-- Form Fields Area -->
+        <div class="flex flex-col gap-5">
+            <!-- Sender Phone -->
+            <div class="flex flex-col gap-2">
+                <label class="text-[#534A4A] font-[900] text-[16px] px-1 capitalize">@Lang.v2_sender_phone</label>
+                <div class="relative w-full group">
+                    <input type="text" readonly value="@(Model?.userStatus?.msisdn ?? "0")" class="w-full bg-gray-100 border border-gray-300 text-[#534A4A] text-[17px] font-[800] rounded-[18px] py-[15px] px-5 outline-none transition-all cursor-not-allowed" />
+                    <div class="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400">
+                        <i class="fa-solid fa-lock text-[20px] opacity-40"></i>
+                    </div>
+                </div>
+            </div>
+
+            <!-- Receiver Phone (Mandatory same as sender) -->
+            <div class="flex flex-col gap-2">
+                <label class="text-[#534A4A] font-[900] text-[16px] px-1 capitalize">@Lang.v2_receiver_phone</label>
+                <div class="relative w-full">
+                    <input id="receiverPhone" type="tel" readonly value="@(Model?.userStatus?.msisdn ?? "0")" class="w-full bg-gray-100 border border-gray-300 text-[#534A4A] text-[17px] font-[800] rounded-[18px] py-[15px] px-5 outline-none transition-all cursor-not-allowed" />
+                    <div class="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400">
+                        <i class="fa-solid fa-lock text-[20px] opacity-40"></i>
+                    </div>
+                </div>
+            </div>
+
+            <!-- Amount -->
+            <div class="flex flex-col gap-2">
+                <label class="text-[#534A4A] font-[900] text-[16px] px-1 capitalize">@Lang.v2_amount_htg</label>
+                <div class="relative w-full">
+                    <input id="transferAmount" type="number" value="5000" placeholder="5,000" class="w-full bg-white border border-gray-300 focus:border-[#EE0033] focus:ring-2 focus:ring-[#EE0033]/10 text-[#EE0033] text-[17px] font-[800] rounded-[18px] py-[15px] px-5 outline-none transition-all placeholder:text-gray-300" />
+                    <span class="absolute right-5 top-1/2 -translate-y-1/2 text-gray-400 font-black">HTG</span>
+                </div>
+                <!-- Shortcut Buttons -->
+                <div class="flex gap-2 mt-1">
+                    <button onclick="setAmount(10, this)" class="amt-btn flex-1 py-1.5 border border-gray-300 rounded-lg text-[14px] font-black transition-all bg-white text-[#534A4A] flex items-center justify-center gap-1">
+                        10
+                        <i class="fa-solid fa-circle-check text-[#00AF1B] text-[14px] hidden"></i>
+                    </button>
+                    <button onclick="setAmount(1000, this)" class="amt-btn flex-1 py-1.5 border border-gray-300 rounded-lg text-[14px] font-black transition-all bg-white text-[#534A4A] flex items-center justify-center gap-1">
+                        1.000
+                        <i class="fa-solid fa-circle-check text-[#00AF1B] text-[14px] hidden"></i>
+                    </button>
+                    <button id="defaultAmt" onclick="setAmount(5000, this)" class="amt-btn flex-1 py-1.5 border-2 border-[#EE0033] bg-[#FEE2E2] rounded-lg text-[14px] font-black text-[#EE0033] transition-all flex items-center justify-center gap-1">
+                        5.000
+                        <i class="fa-solid fa-circle-check text-[#00AF1B] text-[14px]"></i>
+                    </button>
+                </div>
+
+                <!-- Fee Section (Newly placed on a new line) -->
+                <div class="mt-6 flex flex-col gap-1 px-1">
+                    <span class="text-gray-500 font-bold text-[14px]">@Lang.v2_fee</span>
+                    <span class="text-black font-black text-[28px] leading-none mt-1">@Lang.v2_free</span>
+                </div>
+            </div>
+        </div>
+
+        <!-- Main Action Button -->
+        <div class="mt-6">
+            <button id="btnContinue" class="w-full bg-[#EE0033] text-white font-[900] text-[18px] py-[18px] rounded-[22px] shadow-[0_8px_25px_rgba(238,0,51,0.3)] active:scale-95 transition-all uppercase tracking-wide">
+                @Lang.v2_continue
+            </button>
+        </div>
+    </div>
+
+    <!-- Failure Modal Overlay (Standardized Height as per user request) -->
+    <div id="failureModal" class="fixed inset-0 z-[110] flex items-center justify-center hidden px-6 translate-y-0" style="background: rgba(0,0,0,0.5);">
+        <div class="w-full max-w-[343px] min-h-[420px] bg-white rounded-[20px] overflow-hidden flex flex-col items-center p-8 animate__animated animate__zoomIn animate__faster shadow-2xl">
+            <div class="w-full flex flex-col items-center mb-6 mt-4">
+                <div class="relative w-full flex items-center justify-center">
+                    <img src="/LotteryV2/img/modal/fail_icon.png" class="w-[160px] h-auto object-contain" />
+                </div>
+            </div>
+            <div class="px-2 text-center mb-12 mt-2">
+                <p id="failErrorMessage" class="text-black font-[700] text-[20px] leading-tight">
+                    @Lang.v2_enter_valid_amount
+                </p>
+            </div>
+            <div class="w-full mt-auto">
+                <button onclick="closeFailureModal()" class="w-full bg-[#EE0033] text-white font-[800] text-[20px] py-[10px] rounded-[12px] shadow-[0px_3px_8px_rgba(0,0,0,0.25)] hover:bg-red-700 active:scale-95 transition-all">
+                    @Lang.try_again
+                </button>
+            </div>
+        </div>
+    </div>
+
+
+    <!-- OTP Modal Overlay -->
+    <div id="otpModal" class="fixed inset-0 z-[120] flex items-center justify-center hidden px-6 translate-y-0" style="background: rgba(0,0,0,0.5);">
+        <div class="w-full max-w-[343px] min-h-[420px] bg-white rounded-[20px] overflow-hidden flex flex-col items-center p-6 animate__animated animate__zoomIn animate__faster shadow-2xl relative">
+            <!-- Decorative Header Circle -->
+            <div class="absolute -top-12 left-1/2 -translate-x-1/2 w-[400px] h-[80px] bg-[#EE0033] rounded-full opacity-10"></div>
+            
+            <h3 class="text-[#534A4A] font-black text-[22px] mt-4 mb-2">@Lang.v2_confirm_transaction</h3>
+            <p class="text-gray-500 font-bold text-[14px] text-center px-4 mb-6">@Lang.v2_enter_otp_proceed</p>
+            
+            <!-- OTP Inputs -->
+            <div class="flex gap-3 mb-4" id="otpInputs">
+                <input type="tel" maxlength="1" pattern="[0-9]" inputmode="numeric" oninput="handleOtpInput(this)" onkeydown="handleOtpKeydown(event, this)" class="otp-digit w-12 h-14 bg-gray-100 border-2 border-transparent focus:border-[#EE0033] rounded-xl text-center text-[24px] font-black outline-none transition-all" />
+                <input type="tel" maxlength="1" pattern="[0-9]" inputmode="numeric" oninput="handleOtpInput(this)" onkeydown="handleOtpKeydown(event, this)" class="otp-digit w-12 h-14 bg-gray-100 border-2 border-transparent focus:border-[#EE0033] rounded-xl text-center text-[24px] font-black outline-none transition-all" />
+                <input type="tel" maxlength="1" pattern="[0-9]" inputmode="numeric" oninput="handleOtpInput(this)" onkeydown="handleOtpKeydown(event, this)" class="otp-digit w-12 h-14 bg-gray-100 border-2 border-transparent focus:border-[#EE0033] rounded-xl text-center text-[24px] font-black outline-none transition-all" />
+                <input type="tel" maxlength="1" pattern="[0-9]" inputmode="numeric" oninput="handleOtpInput(this)" onkeydown="handleOtpKeydown(event, this)" class="otp-digit w-12 h-14 bg-gray-100 border-2 border-transparent focus:border-[#EE0033] rounded-xl text-center text-[24px] font-black outline-none transition-all" />
+            </div>
+            
+            <span id="otpTimer" class="text-[#EE0033] font-black text-[16px] mb-8">60s</span>
+            
+            <div class="w-full flex gap-3 mt-auto">
+                <button onclick="closeOtpModal()" class="flex-1 bg-gray-200 text-[#534A4A] font-black py-3 rounded-xl active:scale-95 transition-all text-[18px]">@Lang.cancel</button>s
+                <button id="btnConfirmTransfer" class="flex-1 bg-[#0A9800] text-white font-black py-3 rounded-xl active:scale-95 transition-all text-[18px]">@Lang.confirm</button>
+            </div>
+        </div>
+    </div>
+
+    <!-- Bottom Navbar shared component -->
+    <partial name="_BottomNavbar" />
+</div>
+
+
+@section Scripts {
+    <script>
+        function setAmount(val, el) {
+            $("#transferAmount").val(val);
+            
+            // Update active state visuals
+            $(".amt-btn").removeClass("border-2 border-[#EE0033] bg-[#FEE2E2] text-[#EE0033]").addClass("border-gray-300 bg-white text-[#534A4A]");
+            $(".amt-btn i").addClass("hidden"); // hide all check icons
+            
+            $(el).removeClass("border-gray-300 bg-white text-[#534A4A]").addClass("border-2 border-[#EE0033] bg-[#FEE2E2] text-[#EE0033]");
+            $(el).find("i").removeClass("hidden"); // show current check icon
+        }
+
+        // Logic removed as fields are read-only
+
+        let timerInterval;
+        let isProcessing = false; // Global lock to prevent double-submit
+
+        $("#btnContinue").on("click", function() {
+            if (isProcessing) return; // Prevent double-click
+
+            const amount = parseFloat($("#transferAmount").val()) || 0;
+            const phone = $("#receiverPhone").val();
+            const winMoney = parseFloat("@(Model?.userStatus?.bet_coin ?? "0")");
+            
+            if(amount <= 0) {
+                showFailureModal("@Html.Raw(Lang.v2_enter_valid_amount)");
+                return;
+            }
+
+            if(amount > winMoney) {
+                showFailureModal("@Html.Raw(Lang.v2_insufficient_balance)");
+                return;
+            }
+
+            // Lock button + show loading
+            isProcessing = true;
+            const $btn = $(this);
+            const originalText = $btn.html();
+            $btn.prop('disabled', true).html('<i class="fa-solid fa-spinner fa-spin mr-2"></i> ...');
+
+            // Call sendotp API
+            $.ajax({
+                url: subDomain + "/LotteryV2/Home/SendOTP",
+                type: "POST",
+                data: { phone: phone, amount: amount },
+                success: function(res) {
+                    $btn.prop('disabled', false).html(originalText);
+                    isProcessing = false;
+                    if(res.status == "0" || res.status == 0) {
+                        openOtpModal();
+                    } else {
+                        showFailureModal(res.message || "Failed to send OTP");
+                    }
+                },
+                error: function() {
+                    $btn.prop('disabled', false).html(originalText);
+                    isProcessing = false;
+                    showFailureModal("Network error while sending OTP");
+                }
+            });
+        });
+
+        function openOtpModal() {
+            // Clear previous OTP values
+            $(".otp-digit").val("");
+            $("#otpModal").removeClass("hidden").addClass("flex");
+            $("#btnConfirmTransfer").prop('disabled', false).html('Confirm');
+            resetTimer();
+            $(".otp-digit").first().focus();
+        }
+
+        function closeOtpModal() {
+            $("#otpModal").addClass("hidden").removeClass("flex");
+            clearInterval(timerInterval);
+        }
+
+        // OTP input: enforce single digit, auto-advance
+        function handleOtpInput(el) {
+            // Allow only single digit
+            el.value = el.value.replace(/[^0-9]/g, '').slice(0, 1);
+            if (el.value.length === 1) {
+                $(el).next('.otp-digit').focus();
+            }
+        }
+
+        // OTP backspace: move to previous input
+        function handleOtpKeydown(e, el) {
+            if (e.key === 'Backspace' && el.value.length === 0) {
+                $(el).prev('.otp-digit').focus();
+            }
+        }
+
+        function resetTimer() {
+            let seconds = 60;
+            clearInterval(timerInterval);
+            $("#otpTimer").text("60s");
+            $("#btnConfirmTransfer").prop('disabled', false);
+            timerInterval = setInterval(() => {
+                seconds--;
+                $("#otpTimer").text(seconds + "s");
+                if (seconds <= 0) {
+                    clearInterval(timerInterval);
+                    $("#otpTimer").text("Expired");
+                    // Disable confirm when timer expired
+                    $("#btnConfirmTransfer").prop('disabled', true).addClass('opacity-50');
+                }
+            }, 1000);
+        }
+
+        $("#btnConfirmTransfer").on("click", function() {
+            if (isProcessing) return; // Prevent double-click
+
+            let otp = "";
+            $(".otp-digit").each(function() { otp += $(this).val(); });
+            
+            if(otp.length < 4) {
+                showFailureModal("Please enter 4-digit OTP");
+                return;
+            }
+
+            // Lock button + show loading
+            isProcessing = true;
+            const $btn = $(this);
+            const originalText = $btn.html();
+            $btn.prop('disabled', true).html('<i class="fa-solid fa-spinner fa-spin mr-2"></i> ...');
+            
+            // Call transfer confirm API
+            $.ajax({
+                url: subDomain + "/LotteryV2/Home/ConfirmTransfer",
+                type: "POST",
+                data: {
+                    otp: otp,
+                    phone: $("#receiverPhone").val(),
+                    amount: $("#transferAmount").val()
+                },
+                success: function(res) {
+                    $btn.prop('disabled', false).html(originalText);
+                    isProcessing = false;
+                    if(res.status == "0" || res.status == 0) {
+                        closeOtpModal();
+                        // Redirect to success or show success modal
+                        window.location.href = subDomain + "/LotteryV2/Home/GameHome";
+                    } else {
+                        showFailureModal(res.message || "Transfer failed");
+                    }
+                },
+                error: function() {
+                    $btn.prop('disabled', false).html(originalText);
+                    isProcessing = false;
+                    showFailureModal("Network error while confirming transfer");
+                }
+            });
+        });
+
+        function showFailureModal(message) {
+            $("#failErrorMessage").html(message);
+            $("#failureModal").removeClass("hidden").addClass("flex");
+        }
+
+        function closeFailureModal() {
+            $("#failureModal").addClass("hidden").removeClass("flex");
+        }
+    </script>
+}

+ 48 - 0
website/Areas/LotteryV2/Views/Home/_TermResultHistoryV2.cshtml

@@ -0,0 +1,48 @@
+@model LotteryWebApp.Models.TermResultHistoryModel
+@using LotteryWebApp.Languages
+@if (Model != null && Model.listTerm != null && Model.listTerm.Count > 0)
+{
+    foreach (var item in Model.listTerm)
+    {
+        <!-- Result Item Card -->
+        <div class="result-item-red animate__animated animate__fadeInUp">
+            <div class="item-date-text font-bricolage">
+                @{
+                    DateTime drawDate;
+                    if (DateTime.TryParse(item.date_random, out drawDate)) {
+                        <div class="day">@drawDate.ToString("dddd,", System.Globalization.CultureInfo.InvariantCulture)</div>
+                        <div class="date">@drawDate.ToString("MMM dd, yyyy", System.Globalization.CultureInfo.InvariantCulture)</div>
+                    } else {
+                        <div class="day">Draw Date:</div>
+                        <div class="date">@item.date_random</div>
+                    }
+                }
+            </div>
+            <div class="balls-container">
+                @if (!string.IsNullOrEmpty(item.result))
+                {
+                    var balls = item.result.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
+                    foreach (var ball in balls)
+                    {
+                        var cleanBall = ball.Trim();
+                        if (!string.IsNullOrEmpty(cleanBall))
+                        {
+                            <div class="yellow-ball">@cleanBall</div>
+                        }
+                    }
+                }
+                else
+                {
+                    <span class="text-white/70 italic text-[12px]">@Lang.waiting_for_result</span>
+                }
+            </div>
+        </div>
+    }
+}
+else
+{
+    <div class="w-full py-20 flex flex-col items-center justify-center text-gray-400 opacity-60">
+        <i class="fas fa-search text-5xl mb-4"></i>
+        <p class="font-bold">@Lang.no_results_found</p>
+    </div>
+}

+ 87 - 0
website/Areas/LotteryV2/Views/Home/_TermUserTicketHistory.cshtml

@@ -0,0 +1,87 @@
+@model LotteryWebApp.Models.UserTicketHistoryModel
+@using LotteryWebApp.Languages
+@using LotteryWebApp.Common
+
+@if (Model != null && Model.listTicket != null && Model.listTicket.Count > 0)
+{
+    foreach (var item in Model.listTicket)
+    {
+        <div class="ticket-card animate__animated animate__fadeInUp">
+            <div class="ticket-card-top">
+                <div class="ticket-header">
+                    <span class="ticket-id">#@item.seq</span>
+                    <div class="ticket-status @(item.status == Constants.WIN_CODE ? "status-win" : (item.status == Constants.NOT_DRAW_CODE ? "status-waiting" : "status-notwin"))">
+                        @if (item.status == Constants.WIN_CODE) {
+                            @Lang.v2_win
+                        } else if (item.status == Constants.NOT_DRAW_CODE) {
+                            @Lang.v2_waiting
+                        } else {
+                            @Lang.v2_not_win
+                        }
+                    </div>
+                </div>
+
+                <div class="ticket-numbers flex flex-wrap gap-2">
+                    @if (!string.IsNullOrEmpty(item.code))
+                    {
+                        var delimiters = new[] { ';', ',' };
+                        var balls = item.code.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
+                        
+                        // Prepare winning numbers for comparison
+                        var winningBalls = new HashSet<string>();
+                        if (!string.IsNullOrEmpty(item.termResult))
+                        {
+                            var winningSplit = item.termResult.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
+                            foreach (var wb in winningSplit) winningBalls.Add(wb.Trim());
+                        }
+
+                        foreach (var ball in balls)
+                        {
+                            var ballValue = ball.Trim();
+                            if (!string.IsNullOrEmpty(ballValue))
+                            {
+                                string ballClass = "";
+                                if (item.status == Constants.NOT_DRAW_CODE) {
+                                    ballClass = "ball-waiting";
+                                } else if (winningBalls.Contains(ballValue)) {
+                                    ballClass = "ball-win";
+                                } else {
+                                    ballClass = "ball-lose";
+                                }
+                                <div class="ticket-ball @ballClass">@ballValue</div>
+                            }
+                        }
+                    }
+                </div>
+            </div>
+
+            <div class="ticket-perforation"></div>
+
+            <div class="ticket-card-bottom">
+                <div class="ticket-info-grid">
+                    <div class="info-row">
+                        <span class="info-label">@Lang.v2_date_and_time</span>
+                        <span class="info-value">@item.createDate</span>
+                    </div>
+                    <div class="info-row">
+                        <span class="info-label">@Lang.v2_amount_played</span>
+                        <span class="info-value">@item.money HTG</span>
+                    </div>
+                    @if (item.status == Constants.WIN_CODE) {
+                        <div class="info-row">
+                            <span class="info-label">@Lang.v2_amount_won</span>
+                            <span class="info-value win-amount">@item.moneyWin HTG</span>
+                        </div>
+                    }
+                </div>
+            </div>
+        </div>
+    }
+}
+else
+{
+    <div class="w-full py-20 flex flex-col items-center justify-center text-gray-400 opacity-60">
+        <i class="fas fa-receipt text-5xl mb-4"></i>
+        <p class="font-bold">@Lang.no_results_found</p>
+    </div>
+}

+ 1 - 1
website/Areas/LotteryV2/Views/Shared/_BottomNavbar.cshtml

@@ -20,7 +20,7 @@
         <span class="text-[10px] mt-1 @(activePage == "Rule" ? "font-extrabold" : "font-bold")" style="@(activePage == "Rule" ? "color: #EE0033;" : "")">@Lang.rules</span>
         <span class="text-[10px] mt-1 @(activePage == "Rule" ? "font-extrabold" : "font-bold")" style="@(activePage == "Rule" ? "color: #EE0033;" : "")">@Lang.rules</span>
     </a>
     </a>
 
 
-    <a href="#" class="flex flex-col items-center @(activePage == "History" ? "text-[var(--primary)]" : "text-gray-400 hover:text-[var(--primary)]") cursor-pointer relative transition-colors no-underline">
+    <a href="/LotteryV2/Home/History" class="flex flex-col items-center @(activePage == "History" ? "text-[var(--primary)]" : "text-gray-400 hover:text-[var(--primary)]") cursor-pointer relative transition-colors no-underline">
         @if(activePage == "History") {
         @if(activePage == "History") {
             <div class="absolute -top-[14px] left-1/2 -translate-x-1/2 w-8 h-[2px] bg-[#EE0033] rounded-sm"></div>
             <div class="absolute -top-[14px] left-1/2 -translate-x-1/2 w-8 h-[2px] bg-[#EE0033] rounded-sm"></div>
         }
         }

+ 32 - 0
website/Areas/LotteryV2/Views/Shared/_Layout.cshtml

@@ -1,3 +1,4 @@
+@inject Microsoft.Extensions.Configuration.IConfiguration configuration
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
 <head>
 <head>
@@ -11,11 +12,24 @@
     <!-- Isolated CSS just for LotteryV2 -->
     <!-- Isolated CSS just for LotteryV2 -->
     <link rel="stylesheet" href="/LotteryV2/css/site.css" />
     <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" />
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
+    <script src="https://cdn.tailwindcss.com"></script>
+    <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; }
+    </style>
     
     
     @RenderSection("Styles", required: false)
     @RenderSection("Styles", required: false)
 </head>
 </head>
 <body class="lottery-v2-bg">
 <body class="lottery-v2-bg">
     @Html.AntiForgeryToken()
     @Html.AntiForgeryToken()
+    <input type="hidden" id="subDomain" value="@(configuration["subDomain"] ?? "")" />
+    <script>
+        var subDomain = document.getElementById("subDomain").value || "";
+    </script>
+    <div id="loading-overlay" class="hidden">
+        <div class="loading-spinner"></div>
+    </div>
 
 
     @RenderBody()
     @RenderBody()
 
 
@@ -26,6 +40,24 @@
     <!-- Isolated JS just for LotteryV2 -->
     <!-- Isolated JS just for LotteryV2 -->
     <script src="/LotteryV2/js/site.js"></script>
     <script src="/LotteryV2/js/site.js"></script>
 
 
+    <script>
+        // Global Loading Helpers
+        function showLoading() {
+            $('#loading-overlay').removeClass('hidden').addClass('flex');
+        }
+        function hideLoading() {
+            $('#loading-overlay').removeClass('flex').addClass('hidden');
+        }
+
+        // Auto-show for all AJAX calls
+        $(document).ajaxStart(function() {
+            showLoading();
+        }).ajaxStop(function() {
+            hideLoading();
+        });
+    </script>
+
+
     @RenderSection("Scripts", required: false)
     @RenderSection("Scripts", required: false)
 </body>
 </body>
 </html>
 </html>

+ 7 - 1
website/Common/Constants.cs

@@ -70,8 +70,8 @@ namespace LotteryWebApp.Common
         public const string FLORIDA_MAYRAJ_CODE = "8";
         public const string FLORIDA_MAYRAJ_CODE = "8";
         public const string FLORIDA_LOTTO3_CODE = "9";
         public const string FLORIDA_LOTTO3_CODE = "9";
 
 
-        public const string MEGA_LOTO = "12";
 
 
+        
 
 
         public const string GEORGIA_BOLET_CODE = "12";
         public const string GEORGIA_BOLET_CODE = "12";
         public const string GEORGIA_MAYRAJ_CODE = "13";
         public const string GEORGIA_MAYRAJ_CODE = "13";
@@ -83,6 +83,12 @@ namespace LotteryWebApp.Common
         public const string TENNESSEE_MAYRAJ_CODE = "19";
         public const string TENNESSEE_MAYRAJ_CODE = "19";
         public const string TENNESSEE_LOTTO3_CODE = "20";
         public const string TENNESSEE_LOTTO3_CODE = "20";
 
 
+        public const string MEGA_LOTO = "87";
+        public const string PIC10_BASIC_CODE = "30";
+        public const string PIC10_BIGSMALL_CODE = "31";
+        public const string PIC10_ODDEVEN_CODE = "32";
+
+
         public const string TERM_HAS_RESULT_TYPE = "1";
         public const string TERM_HAS_RESULT_TYPE = "1";
         public const string TERM_HAS_NOT_RESULT_TYPE = "0";
         public const string TERM_HAS_NOT_RESULT_TYPE = "0";
 
 

+ 537 - 6
website/Languages/Lang.Designer.cs

@@ -141,6 +141,15 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to Back to homepage.
+        /// </summary>
+        public static string back_to_homepage {
+            get {
+                return ResourceManager.GetString("back_to_homepage", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to Kont de Baz.
         ///   Looks up a localized string similar to Kont de Baz.
         /// </summary>
         /// </summary>
@@ -800,6 +809,15 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to Echec !.
+        /// </summary>
+        public static string fail_exclamation {
+            get {
+                return ResourceManager.GetString("fail_exclamation", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to FAQ.
         ///   Looks up a localized string similar to FAQ.
         /// </summary>
         /// </summary>
@@ -810,7 +828,7 @@ namespace LotteryWebApp.Languages {
         }
         }
         
         
         /// <summary>
         /// <summary>
-        ///   Looks up a localized string similar to Pick 10 numbers from 1 to 80 or choose the Quick Pick option. Purchase your ticket and wait for the draw..
+        ///   Looks up a localized string similar to Choisissez 10 numéros de 1 à 80 ou l&apos;option Choix rapide. Achetez votre billet et attendez le tirage..
         /// </summary>
         /// </summary>
         public static string faq_a1 {
         public static string faq_a1 {
             get {
             get {
@@ -819,7 +837,7 @@ namespace LotteryWebApp.Languages {
         }
         }
         
         
         /// <summary>
         /// <summary>
-        ///   Looks up a localized string similar to Draws take place every day at 8:30 p.m. Ticket sales stop at 8:00 p.m..
+        ///   Looks up a localized string similar to Les tirages ont lieu tous les jours à 20h30. Les ventes de billets s&apos;arrêtent à 20h00..
         /// </summary>
         /// </summary>
         public static string faq_a2 {
         public static string faq_a2 {
             get {
             get {
@@ -828,7 +846,7 @@ namespace LotteryWebApp.Languages {
         }
         }
         
         
         /// <summary>
         /// <summary>
-        ///   Looks up a localized string similar to The odds of winning the top Pick 10 prize are 1 in 8,911,711..
+        ///   Looks up a localized string similar to Les chances de gagner le premier prix du Pick 10 sont de 1 sur 8 911 711..
         /// </summary>
         /// </summary>
         public static string faq_a3 {
         public static string faq_a3 {
             get {
             get {
@@ -837,7 +855,7 @@ namespace LotteryWebApp.Languages {
         }
         }
         
         
         /// <summary>
         /// <summary>
-        ///   Looks up a localized string similar to How do I play the Pick 10 game?.
+        ///   Looks up a localized string similar to Comment jouer au jeu Pick 10 ?.
         /// </summary>
         /// </summary>
         public static string faq_q1 {
         public static string faq_q1 {
             get {
             get {
@@ -846,7 +864,7 @@ namespace LotteryWebApp.Languages {
         }
         }
         
         
         /// <summary>
         /// <summary>
-        ///   Looks up a localized string similar to When do Pick 10 draws take place?.
+        ///   Looks up a localized string similar to C&apos;est quand les tirages de Pick 10 ?.
         /// </summary>
         /// </summary>
         public static string faq_q2 {
         public static string faq_q2 {
             get {
             get {
@@ -855,7 +873,7 @@ namespace LotteryWebApp.Languages {
         }
         }
         
         
         /// <summary>
         /// <summary>
-        ///   Looks up a localized string similar to What are the chances of winning the top prize?.
+        ///   Looks up a localized string similar to Quelles sont les chances de gagner le premier prix ?.
         /// </summary>
         /// </summary>
         public static string faq_q3 {
         public static string faq_q3 {
             get {
             get {
@@ -1097,6 +1115,15 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to 100.000 HTG jodi a !.
+        /// </summary>
+        public static string jackpot_today_htg {
+            get {
+                return ResourceManager.GetString("jackpot_today_htg", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to Lang.
         ///   Looks up a localized string similar to Lang.
         /// </summary>
         /// </summary>
@@ -1322,6 +1349,15 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to No results found.
+        /// </summary>
+        public static string no_results_found {
+            get {
+                return ResourceManager.GetString("no_results_found", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to not defined.
         ///   Looks up a localized string similar to not defined.
         /// </summary>
         /// </summary>
@@ -1664,6 +1700,15 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to Random.
+        /// </summary>
+        public static string Random {
+            get {
+                return ResourceManager.GetString("Random", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to Benefisye.
         ///   Looks up a localized string similar to Benefisye.
         /// </summary>
         /// </summary>
@@ -3041,6 +3086,15 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to Try again.
+        /// </summary>
+        public static string try_again {
+            get {
+                return ResourceManager.GetString("try_again", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to Tip.
         ///   Looks up a localized string similar to Tip.
         /// </summary>
         /// </summary>
@@ -3059,6 +3113,15 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to An error occurred while updating your profile..
+        /// </summary>
+        public static string update_profile_error {
+            get {
+                return ResourceManager.GetString("update_profile_error", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to Mizajou reyisi.
         ///   Looks up a localized string similar to Mizajou reyisi.
         /// </summary>
         /// </summary>
@@ -3077,6 +3140,474 @@ namespace LotteryWebApp.Languages {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to Kont Bee Lotto.
+        /// </summary>
+        public static string v2_account_name {
+            get {
+                return ResourceManager.GetString("v2_account_name", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Ajoute plis tikè.
+        /// </summary>
+        public static string v2_add_more_ticket {
+            get {
+                return ResourceManager.GetString("v2_add_more_ticket", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Tout.
+        /// </summary>
+        public static string v2_all {
+            get {
+                return ResourceManager.GetString("v2_all", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Montant.
+        /// </summary>
+        public static string v2_amount {
+            get {
+                return ResourceManager.GetString("v2_amount", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Montan (HTG).
+        /// </summary>
+        public static string v2_amount_htg {
+            get {
+                return ResourceManager.GetString("v2_amount_htg", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Montan jwe.
+        /// </summary>
+        public static string v2_amount_played {
+            get {
+                return ResourceManager.GetString("v2_amount_played", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Montan genyen.
+        /// </summary>
+        public static string v2_amount_won {
+            get {
+                return ResourceManager.GetString("v2_amount_won", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to back.
+        /// </summary>
+        public static string v2_back {
+            get {
+                return ResourceManager.GetString("v2_back", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Big / Small.
+        /// </summary>
+        public static string v2_big_small {
+            get {
+                return ResourceManager.GetString("v2_big_small", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Achte Classic Pick 10.
+        /// </summary>
+        public static string v2_buy_classic_pick_10 {
+            get {
+                return ResourceManager.GetString("v2_buy_classic_pick_10", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Achte tikè.
+        /// </summary>
+        public static string v2_buy_ticket_label {
+            get {
+                return ResourceManager.GetString("v2_buy_ticket_label", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Annuler.
+        /// </summary>
+        public static string v2_cancel {
+            get {
+                return ResourceManager.GetString("v2_cancel", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Chwazi kont la.
+        /// </summary>
+        public static string v2_choose_account {
+            get {
+                return ResourceManager.GetString("v2_choose_account", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Classic Pick 10.
+        /// </summary>
+        public static string v2_classic_pick_10 {
+            get {
+                return ResourceManager.GetString("v2_classic_pick_10", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Confirmer.
+        /// </summary>
+        public static string v2_confirm {
+            get {
+                return ResourceManager.GetString("v2_confirm", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Confirmer l&apos;achat.
+        /// </summary>
+        public static string v2_confirm_purchase {
+            get {
+                return ResourceManager.GetString("v2_confirm_purchase", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Confirm transaction.
+        /// </summary>
+        public static string v2_confirm_transaction {
+            get {
+                return ResourceManager.GetString("v2_confirm_transaction", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Kontinye.
+        /// </summary>
+        public static string v2_continue {
+            get {
+                return ResourceManager.GetString("v2_continue", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Dat ak Lè.
+        /// </summary>
+        public static string v2_date_and_time {
+            get {
+                return ResourceManager.GetString("v2_date_and_time", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Efase.
+        /// </summary>
+        public static string v2_delete {
+            get {
+                return ResourceManager.GetString("v2_delete", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Modifye.
+        /// </summary>
+        public static string v2_edit {
+            get {
+                return ResourceManager.GetString("v2_edit", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Please confirm and enter OTP to proceed..
+        /// </summary>
+        public static string v2_enter_otp_proceed {
+            get {
+                return ResourceManager.GetString("v2_enter_otp_proceed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Please enter a valid amount..
+        /// </summary>
+        public static string v2_enter_valid_amount {
+            get {
+                return ResourceManager.GetString("v2_enter_valid_amount", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Pri tikè estime.
+        /// </summary>
+        public static string v2_estimated_ticket_price {
+            get {
+                return ResourceManager.GetString("v2_estimated_ticket_price", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Frais.
+        /// </summary>
+        public static string v2_fee {
+            get {
+                return ResourceManager.GetString("v2_fee", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Gratuit.
+        /// </summary>
+        public static string v2_free {
+            get {
+                return ResourceManager.GetString("v2_free", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Jwèt sa a fèmen kounye a..
+        /// </summary>
+        public static string v2_game_locked {
+            get {
+                return ResourceManager.GetString("v2_game_locked", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to You do not have enough win money..
+        /// </summary>
+        public static string v2_insufficient_balance {
+            get {
+                return ResourceManager.GetString("v2_insufficient_balance", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Pa genyen.
+        /// </summary>
+        public static string v2_not_win {
+            get {
+                return ResourceManager.GetString("v2_not_win", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Odd / Even.
+        /// </summary>
+        public static string v2_odd_even {
+            get {
+                return ResourceManager.GetString("v2_odd_even", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Veuillez confirmer et saisir l&apos;OTP pour continuer..
+        /// </summary>
+        public static string v2_otp_instruction {
+            get {
+                return ResourceManager.GetString("v2_otp_instruction", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Kole.
+        /// </summary>
+        public static string v2_paste {
+            get {
+                return ResourceManager.GetString("v2_paste", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Peman.
+        /// </summary>
+        public static string v2_payment {
+            get {
+                return ResourceManager.GetString("v2_payment", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Peman reyisi.
+        /// </summary>
+        public static string v2_payment_successfully {
+            get {
+                return ResourceManager.GetString("v2_payment_successfully", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Pri siw genyen.
+        /// </summary>
+        public static string v2_prize_if_win {
+            get {
+                return ResourceManager.GetString("v2_prize_if_win", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to 💰 Nimewo k&apos;ap resevwa.
+        /// </summary>
+        public static string v2_receiver_phone {
+            get {
+                return ResourceManager.GetString("v2_receiver_phone", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Demander un nouvel OTP.
+        /// </summary>
+        public static string v2_request_new_otp {
+            get {
+                return ResourceManager.GetString("v2_request_new_otp", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Wonn.
+        /// </summary>
+        public static string v2_round {
+            get {
+                return ResourceManager.GetString("v2_round", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Save.
+        /// </summary>
+        public static string v2_save {
+            get {
+                return ResourceManager.GetString("v2_save", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Chwazi.
+        /// </summary>
+        public static string v2_select {
+            get {
+                return ResourceManager.GetString("v2_select", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Chwazi chif chans.
+        /// </summary>
+        public static string v2_select_10_lucky_numbers {
+            get {
+                return ResourceManager.GetString("v2_select_10_lucky_numbers", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Te Chwazi.
+        /// </summary>
+        public static string v2_selected {
+            get {
+                return ResourceManager.GetString("v2_selected", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Selected Tickets.
+        /// </summary>
+        public static string v2_selected_ticket {
+            get {
+                return ResourceManager.GetString("v2_selected_ticket", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to 💸 Nimewo k&apos;ap voye.
+        /// </summary>
+        public static string v2_sender_phone {
+            get {
+                return ResourceManager.GetString("v2_sender_phone", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Billet.
+        /// </summary>
+        public static string v2_ticket {
+            get {
+                return ResourceManager.GetString("v2_ticket", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Ticket not valid.
+        /// </summary>
+        public static string v2_ticket_not_valid {
+            get {
+                return ResourceManager.GetString("v2_ticket_not_valid", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Transfè.
+        /// </summary>
+        public static string v2_transfer {
+            get {
+                return ResourceManager.GetString("v2_transfer", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Rezilta yo ap mete ajou..
+        /// </summary>
+        public static string v2_updating_results {
+            get {
+                return ResourceManager.GetString("v2_updating_results", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to An atant.
+        /// </summary>
+        public static string v2_waiting {
+            get {
+                return ResourceManager.GetString("v2_waiting", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Genyen.
+        /// </summary>
+        public static string v2_win {
+            get {
+                return ResourceManager.GetString("v2_win", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Ou chwazi.
+        /// </summary>
+        public static string v2_you_choose {
+            get {
+                return ResourceManager.GetString("v2_you_choose", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Chwa ou.
+        /// </summary>
+        public static string v2_your_choice {
+            get {
+                return ResourceManager.GetString("v2_your_choice", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to Verifye kont wap konekte a.
         ///   Looks up a localized string similar to Verifye kont wap konekte a.
         /// </summary>
         /// </summary>

+ 185 - 11
website/Languages/Lang.fr.resx

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <root>
 <root>
   <!-- 
   <!-- 
     Microsoft ResX Schema 
     Microsoft ResX Schema 
@@ -791,6 +791,18 @@ We’ll help you create an account in a few easy steps.</value>
   <data name="odd_even" xml:space="preserve">
   <data name="odd_even" xml:space="preserve">
     <value>Odd / Even</value>
     <value>Odd / Even</value>
   </data>
   </data>
+  <data name="v2_select" xml:space="preserve">
+    <value>Select</value>
+  </data>
+  <data name="v2_selected" xml:space="preserve">
+    <value>Selected</value>
+  </data>
+  <data name="v2_prize_if_win" xml:space="preserve">
+    <value>Prize if win</value>
+  </data>
+  <data name="v2_you_choose" xml:space="preserve">
+    <value>choose</value>
+  </data>
   <data name="how_to_play_pick10" xml:space="preserve">
   <data name="how_to_play_pick10" xml:space="preserve">
     <value>How to play Pick 10</value>
     <value>How to play Pick 10</value>
   </data>
   </data>
@@ -807,22 +819,22 @@ We’ll help you create an account in a few easy steps.</value>
     <value>Bet</value>
     <value>Bet</value>
   </data>
   </data>
   <data name="faq_q1" xml:space="preserve">
   <data name="faq_q1" xml:space="preserve">
-    <value>Comment jouer au jeu Pick 10 ?</value>
+    <value>How do I play the Pick 10 game?</value>
   </data>
   </data>
   <data name="faq_a1" xml:space="preserve">
   <data name="faq_a1" xml:space="preserve">
-    <value>Choisissez 10 numéros de 1 à 80 ou l'option Choix rapide. Achetez votre billet et attendez le tirage.</value>
+    <value>Pick 10 numbers from 1 to 80 or choose the Quick Pick option. Purchase your ticket and wait for the draw.</value>
   </data>
   </data>
   <data name="faq_q2" xml:space="preserve">
   <data name="faq_q2" xml:space="preserve">
-    <value>C'est quand les tirages de Pick 10 ?</value>
+    <value>When do Pick 10 draws take place?</value>
   </data>
   </data>
   <data name="faq_a2" xml:space="preserve">
   <data name="faq_a2" xml:space="preserve">
-    <value>Les tirages ont lieu tous les jours à 20h30. Les ventes de billets s'arrêtent à 20h00.</value>
+    <value>Draws take place every day at 8:30 p.m. Ticket sales stop at 8:00 p.m.</value>
   </data>
   </data>
   <data name="faq_q3" xml:space="preserve">
   <data name="faq_q3" xml:space="preserve">
-    <value>Quelles sont les chances de gagner le premier prix ?</value>
+    <value>What are the chances of winning the top prize?</value>
   </data>
   </data>
   <data name="faq_a3" xml:space="preserve">
   <data name="faq_a3" xml:space="preserve">
-    <value>Les chances de gagner le premier prix du Pick 10 sont de 1 sur 8 911 711.</value>
+    <value>The odds of winning the top Pick 10 prize are 1 in 8,911,711.</value>
   </data>
   </data>
   <data name="rule_payment_shortly" xml:space="preserve">
   <data name="rule_payment_shortly" xml:space="preserve">
     <value>Payments successfully completed shortly after 20:00 may still be accepted for the current draw.</value>
     <value>Payments successfully completed shortly after 20:00 may still be accepted for the current draw.</value>
@@ -1163,7 +1175,169 @@ We’ll help you create an account in a few easy steps.</value>
   <data name="rule_valid_one_draw" xml:space="preserve">
   <data name="rule_valid_one_draw" xml:space="preserve">
     <value>Each ticket is valid for one draw only.</value>
     <value>Each ticket is valid for one draw only.</value>
   </data>
   </data>
-</root>
-
-
-
+  <data name="fail_exclamation" xml:space="preserve">
+    <value>Fail !</value>
+  </data>
+  <data name="back_to_homepage" xml:space="preserve">
+    <value>Back to homepage</value>
+  </data>
+  <data name="try_again" xml:space="preserve">
+    <value>Try again</value>
+  </data>
+  <data name="update_profile_error" xml:space="preserve">
+    <value>Une erreur est survenue lors de la mise à jour de votre profil.</value>
+  </data>
+  <data name="jackpot_today_htg" xml:space="preserve">
+    <value>100.000 HTG today !</value>
+  </data>
+  <data name="no_results_found" xml:space="preserve">
+    <value>No results found</value>
+  </data>
+  <data name="v2_win" xml:space="preserve">
+    <value>Win</value>
+  </data>
+  <data name="v2_not_win" xml:space="preserve">
+    <value>Not Win</value>
+  </data>
+  <data name="v2_waiting" xml:space="preserve">
+    <value>Waiting</value>
+  </data>
+  <data name="v2_all" xml:space="preserve">
+    <value>All</value>
+  </data>
+  <data name="v2_classic_pick_10" xml:space="preserve">
+    <value>Classic Pick 10</value>
+  </data>
+  <data name="v2_big_small" xml:space="preserve">
+    <value>Big / Small</value>
+  </data>
+  <data name="v2_odd_even" xml:space="preserve">
+    <value>Odd / Even</value>
+  </data>
+  <data name="v2_amount_played" xml:space="preserve">
+    <value>Amount played</value>
+  </data>
+  <data name="v2_amount_won" xml:space="preserve">
+    <value>Amount won</value>
+  </data>
+  <data name="v2_date_and_time" xml:space="preserve">
+    <value>Date and Time</value>
+  </data>
+  <data name="v2_game_locked" xml:space="preserve">
+    <value>This game is currently locked.</value>
+  </data>
+  <data name="v2_updating_results" xml:space="preserve">
+    <value>Results are being updated.</value>
+  </data>
+  <data name="v2_buy_classic_pick_10" xml:space="preserve">
+    <value>Buy Classic Pick 10</value>
+  </data>
+  <data name="v2_select_10_lucky_numbers" xml:space="preserve">
+    <value>Select Lucky Numbers</value>
+  </data>
+  <data name="v2_add_more_ticket" xml:space="preserve">
+    <value>Add more Ticket</value>
+  </data>
+  <data name="v2_estimated_ticket_price" xml:space="preserve">
+    <value>Estimated Ticket Price</value>
+  </data>
+  <data name="v2_payment" xml:space="preserve">
+    <value>Payment</value>
+  </data>
+  <data name="v2_round" xml:space="preserve">
+    <value>Round</value>
+  </data>
+  <data name="v2_edit" xml:space="preserve">
+    <value>Edit</value>
+  </data>
+  <data name="v2_delete" xml:space="preserve">
+    <value>Delete</value>
+  </data>
+  <data name="v2_back" xml:space="preserve">
+    <value>back</value>
+  </data>
+  <data name="Random" xml:space="preserve">
+    <value>Random</value>
+  </data>
+  <data name="v2_save" xml:space="preserve">
+    <value>Save</value>
+  </data>
+  <data name="v2_selected_ticket" xml:space="preserve">
+    <value>Selected Tickets</value>
+  </data>
+  <data name="v2_ticket_not_valid" xml:space="preserve">
+    <value>Ticket not valid</value>
+  </data>
+  <data name="v2_confirm_purchase" xml:space="preserve">
+    <value>Confirm Purchase</value>
+  </data>
+  <data name="v2_ticket" xml:space="preserve">
+    <value>Ticket</value>
+  </data>
+  <data name="v2_amount" xml:space="preserve">
+    <value>Amount</value>
+  </data>
+  <data name="v2_otp_instruction" xml:space="preserve">
+    <value>Please confirm and enter OTP to proceed.</value>
+  </data>
+  <data name="v2_request_new_otp" xml:space="preserve">
+    <value>Request new OTP</value>
+  </data>
+  <data name="v2_cancel" xml:space="preserve">
+    <value>Cancel</value>
+  </data>
+  <data name="v2_confirm" xml:space="preserve">
+    <value>Confirm</value>
+  </data>
+  <data name="v2_payment_successfully" xml:space="preserve">
+    <value>Payment Successfully</value>
+  </data>
+  <data name="v2_your_choice" xml:space="preserve">
+    <value>Your choice</value>
+  </data>
+  <data name="v2_buy_ticket_label" xml:space="preserve">
+    <value>Buy ticket</value>
+  </data>
+  <data name="v2_transfer" xml:space="preserve">
+    <value>Transfer</value>
+  </data>
+  <data name="v2_choose_account" xml:space="preserve">
+    <value>Choose the account</value>
+  </data>
+  <data name="v2_sender_phone" xml:space="preserve">
+    <value>💸 Sender phone</value>
+  </data>
+  <data name="v2_receiver_phone" xml:space="preserve">
+    <value>💰 Receiver phone</value>
+  </data>
+  <data name="v2_amount_htg" xml:space="preserve">
+    <value>Amount (HTG)</value>
+  </data>
+  <data name="v2_paste" xml:space="preserve">
+    <value>Paste</value>
+  </data>
+  <data name="v2_continue" xml:space="preserve">
+    <value>Continue</value>
+  </data>
+  <data name="v2_account_name" xml:space="preserve">
+    <value>Bee Lotto’s Account</value>
+  </data>
+  <data name="v2_fee" xml:space="preserve">
+    <value>Fee</value>
+  </data>
+  <data name="v2_free" xml:space="preserve">
+    <value>Free</value>
+  </data>
+  <data name="v2_enter_valid_amount" xml:space="preserve">
+    <value>Please enter a valid amount.</value>
+  </data>
+  <data name="v2_insufficient_balance" xml:space="preserve">
+    <value>The winnings balance is insufficient.</value>
+  </data>
+  <data name="v2_confirm_transaction" xml:space="preserve">
+    <value>Confirm transaction</value>
+  </data>
+  <data name="v2_enter_otp_proceed" xml:space="preserve">
+    <value>Please confirm and enter OTP to proceed</value>
+  </data>
+</root>

+ 185 - 11
website/Languages/Lang.resx

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <root>
 <root>
   <!-- 
   <!-- 
     Microsoft ResX Schema 
     Microsoft ResX Schema 
@@ -791,6 +791,18 @@ We’ll help you create an account in a few easy steps.</value>
   <data name="odd_even" xml:space="preserve">
   <data name="odd_even" xml:space="preserve">
     <value>Pè / Enpè</value>
     <value>Pè / Enpè</value>
   </data>
   </data>
+  <data name="v2_select" xml:space="preserve">
+    <value>Chwazi</value>
+  </data>
+  <data name="v2_selected" xml:space="preserve">
+    <value>Te Chwazi</value>
+  </data>
+  <data name="v2_prize_if_win" xml:space="preserve">
+    <value>Pri siw genyen</value>
+  </data>
+  <data name="v2_you_choose" xml:space="preserve">
+    <value>Ou chwazi</value>
+  </data>
   <data name="how_to_play_pick10" xml:space="preserve">
   <data name="how_to_play_pick10" xml:space="preserve">
     <value>Koman jwe Pick 10</value>
     <value>Koman jwe Pick 10</value>
   </data>
   </data>
@@ -807,22 +819,22 @@ We’ll help you create an account in a few easy steps.</value>
     <value>Bet</value>
     <value>Bet</value>
   </data>
   </data>
   <data name="faq_q1" xml:space="preserve">
   <data name="faq_q1" xml:space="preserve">
-    <value>How do I play the Pick 10 game?</value>
+    <value>Comment jouer au jeu Pick 10 ?</value>
   </data>
   </data>
   <data name="faq_a1" xml:space="preserve">
   <data name="faq_a1" xml:space="preserve">
-    <value>Pick 10 numbers from 1 to 80 or choose the Quick Pick option. Purchase your ticket and wait for the draw.</value>
+    <value>Choisissez 10 numéros de 1 à 80 ou l'option Choix rapide. Achetez votre billet et attendez le tirage.</value>
   </data>
   </data>
   <data name="faq_q2" xml:space="preserve">
   <data name="faq_q2" xml:space="preserve">
-    <value>When do Pick 10 draws take place?</value>
+    <value>C'est quand les tirages de Pick 10 ?</value>
   </data>
   </data>
   <data name="faq_a2" xml:space="preserve">
   <data name="faq_a2" xml:space="preserve">
-    <value>Draws take place every day at 8:30 p.m. Ticket sales stop at 8:00 p.m.</value>
+    <value>Les tirages ont lieu tous les jours à 20h30. Les ventes de billets s'arrêtent à 20h00.</value>
   </data>
   </data>
   <data name="faq_q3" xml:space="preserve">
   <data name="faq_q3" xml:space="preserve">
-    <value>What are the chances of winning the top prize?</value>
+    <value>Quelles sont les chances de gagner le premier prix ?</value>
   </data>
   </data>
   <data name="faq_a3" xml:space="preserve">
   <data name="faq_a3" xml:space="preserve">
-    <value>The odds of winning the top Pick 10 prize are 1 in 8,911,711.</value>
+    <value>Les chances de gagner le premier prix du Pick 10 sont de 1 sur 8 911 711.</value>
   </data>
   </data>
   <data name="rule_payment_shortly" xml:space="preserve">
   <data name="rule_payment_shortly" xml:space="preserve">
     <value>Payments successfully completed shortly after 20:00 may still be accepted for the current draw.</value>
     <value>Payments successfully completed shortly after 20:00 may still be accepted for the current draw.</value>
@@ -1163,7 +1175,169 @@ We’ll help you create an account in a few easy steps.</value>
   <data name="rule_valid_one_draw" xml:space="preserve">
   <data name="rule_valid_one_draw" xml:space="preserve">
     <value>Each ticket is valid for one draw only.</value>
     <value>Each ticket is valid for one draw only.</value>
   </data>
   </data>
-</root>
-
-
-
+  <data name="fail_exclamation" xml:space="preserve">
+    <value>Echec !</value>
+  </data>
+  <data name="back_to_homepage" xml:space="preserve">
+    <value>Back to homepage</value>
+  </data>
+  <data name="try_again" xml:space="preserve">
+    <value>Try again</value>
+  </data>
+  <data name="update_profile_error" xml:space="preserve">
+    <value>An error occurred while updating your profile.</value>
+  </data>
+  <data name="jackpot_today_htg" xml:space="preserve">
+    <value>100.000 HTG jodi a !</value>
+  </data>
+  <data name="no_results_found" xml:space="preserve">
+    <value>No results found</value>
+  </data>
+  <data name="v2_win" xml:space="preserve">
+    <value>Genyen</value>
+  </data>
+  <data name="v2_not_win" xml:space="preserve">
+    <value>Pa genyen</value>
+  </data>
+  <data name="v2_waiting" xml:space="preserve">
+    <value>An atant</value>
+  </data>
+  <data name="v2_all" xml:space="preserve">
+    <value>Tout</value>
+  </data>
+  <data name="v2_classic_pick_10" xml:space="preserve">
+    <value>Classic Pick 10</value>
+  </data>
+  <data name="v2_big_small" xml:space="preserve">
+    <value>Big / Small</value>
+  </data>
+  <data name="v2_odd_even" xml:space="preserve">
+    <value>Odd / Even</value>
+  </data>
+  <data name="v2_amount_played" xml:space="preserve">
+    <value>Montan jwe</value>
+  </data>
+  <data name="v2_amount_won" xml:space="preserve">
+    <value>Montan genyen</value>
+  </data>
+  <data name="v2_date_and_time" xml:space="preserve">
+    <value>Dat ak Lè</value>
+  </data>
+  <data name="v2_game_locked" xml:space="preserve">
+    <value>Jwèt sa a fèmen kounye a.</value>
+  </data>
+  <data name="v2_updating_results" xml:space="preserve">
+    <value>Rezilta yo ap mete ajou.</value>
+  </data>
+  <data name="v2_buy_classic_pick_10" xml:space="preserve">
+    <value>Achte Classic Pick 10</value>
+  </data>
+  <data name="v2_select_10_lucky_numbers" xml:space="preserve">
+    <value>Chwazi chif chans</value>
+  </data>
+  <data name="v2_add_more_ticket" xml:space="preserve">
+    <value>Ajoute plis tikè</value>
+  </data>
+  <data name="v2_estimated_ticket_price" xml:space="preserve">
+    <value>Pri tikè estime</value>
+  </data>
+  <data name="v2_payment" xml:space="preserve">
+    <value>Peman</value>
+  </data>
+  <data name="v2_round" xml:space="preserve">
+    <value>Wonn</value>
+  </data>
+  <data name="v2_edit" xml:space="preserve">
+    <value>Modifye</value>
+  </data>
+  <data name="v2_delete" xml:space="preserve">
+    <value>Efase</value>
+  </data>
+  <data name="v2_back" xml:space="preserve">
+    <value>back</value>
+  </data>
+  <data name="Random" xml:space="preserve">
+    <value>Random</value>
+  </data>
+  <data name="v2_save" xml:space="preserve">
+    <value>Save</value>
+  </data>
+  <data name="v2_selected_ticket" xml:space="preserve">
+    <value>Selected Tickets</value>
+  </data>
+  <data name="v2_ticket_not_valid" xml:space="preserve">
+    <value>Ticket not valid</value>
+  </data>
+  <data name="v2_confirm_purchase" xml:space="preserve">
+    <value>Confirmer l'achat</value>
+  </data>
+  <data name="v2_ticket" xml:space="preserve">
+    <value>Billet</value>
+  </data>
+  <data name="v2_amount" xml:space="preserve">
+    <value>Montant</value>
+  </data>
+  <data name="v2_otp_instruction" xml:space="preserve">
+    <value>Veuillez confirmer et saisir l'OTP pour continuer.</value>
+  </data>
+  <data name="v2_request_new_otp" xml:space="preserve">
+    <value>Demander un nouvel OTP</value>
+  </data>
+  <data name="v2_cancel" xml:space="preserve">
+    <value>Annuler</value>
+  </data>
+  <data name="v2_confirm" xml:space="preserve">
+    <value>Confirmer</value>
+  </data>
+  <data name="v2_payment_successfully" xml:space="preserve">
+    <value>Peman reyisi</value>
+  </data>
+  <data name="v2_your_choice" xml:space="preserve">
+    <value>Chwa ou</value>
+  </data>
+  <data name="v2_buy_ticket_label" xml:space="preserve">
+    <value>Achte tikè</value>
+  </data>
+  <data name="v2_transfer" xml:space="preserve">
+    <value>Transfè</value>
+  </data>
+  <data name="v2_choose_account" xml:space="preserve">
+    <value>Chwazi kont la</value>
+  </data>
+  <data name="v2_sender_phone" xml:space="preserve">
+    <value>💸 Nimewo k'ap voye</value>
+  </data>
+  <data name="v2_receiver_phone" xml:space="preserve">
+    <value>💰 Nimewo k'ap resevwa</value>
+  </data>
+  <data name="v2_amount_htg" xml:space="preserve">
+    <value>Montan (HTG)</value>
+  </data>
+  <data name="v2_paste" xml:space="preserve">
+    <value>Kole</value>
+  </data>
+  <data name="v2_continue" xml:space="preserve">
+    <value>Kontinye</value>
+  </data>
+  <data name="v2_account_name" xml:space="preserve">
+    <value>Kont Bee Lotto</value>
+  </data>
+  <data name="v2_fee" xml:space="preserve">
+    <value>Frais</value>
+  </data>
+  <data name="v2_free" xml:space="preserve">
+    <value>Gratuit</value>
+  </data>
+  <data name="v2_enter_valid_amount" xml:space="preserve">
+    <value>Please enter a valid amount.</value>
+  </data>
+  <data name="v2_insufficient_balance" xml:space="preserve">
+    <value>You do not have enough win money.</value>
+  </data>
+  <data name="v2_confirm_transaction" xml:space="preserve">
+    <value>Confirm transaction</value>
+  </data>
+  <data name="v2_enter_otp_proceed" xml:space="preserve">
+    <value>Please confirm and enter OTP to proceed.</value>
+  </data>
+</root>

+ 1 - 2
website/LotteryWebApp.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Web">
 
 
   <PropertyGroup>
   <PropertyGroup>
     <TargetFramework>net7.0</TargetFramework>
     <TargetFramework>net7.0</TargetFramework>
@@ -47,7 +47,6 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <EmbeddedResource Update="Languages\Lang.fr.resx">
     <EmbeddedResource Update="Languages\Lang.fr.resx">
-      <Generator>PublicResXFileCodeGenerator</Generator>
     </EmbeddedResource>
     </EmbeddedResource>
     <EmbeddedResource Update="Languages\Lang.resx">
     <EmbeddedResource Update="Languages\Lang.resx">
       <Generator>PublicResXFileCodeGenerator</Generator>
       <Generator>PublicResXFileCodeGenerator</Generator>

+ 10 - 1
website/Models/HomeViewModel.cs

@@ -1,4 +1,4 @@
-using LotteryWebApp.Service;
+using LotteryWebApp.Service;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
@@ -57,4 +57,13 @@ namespace LotteryWebApp.Models
 
 
     }
     }
 
 
+    public class UserTicketHistoryModel
+    {
+        public List<Ticket> listTicket { get; set; }
+        public string termType { get; set; }
+        public string status { get; set; }
+        public string totalPage { get; set; }
+        public string seqPage { get; set; }
+    }
+
 }
 }

+ 55 - 0
website/wwwroot/LotteryV2/css/buy-ticket.css

@@ -0,0 +1,55 @@
+.font-bricolage {
+    font-family: 'Bricolage Grotesque', sans-serif;
+}
+
+.ticket-card {
+    background: url('/LotteryV2/img/Rectangle 132.svg') no-repeat center center;
+    background-size: 100% 100%;
+    padding: 15px 12px 20px 12px;
+    position: relative;
+    margin-top: 5px;
+    margin-bottom: 5px;
+    border: none;
+    background-color: transparent !important;
+}
+
+.ball-circle {
+    width: 24px;
+    height: 24px;
+    background: #EAEAEA;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-weight: 800;
+    font-size: 10px;
+    color: #333;
+    box-shadow: inset 0px -2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.bg-green-main {
+    background-color: #1AB13C;
+}
+
+.text-brown-main {
+    color: #994900;
+}
+
+.ball-empty {
+    background: #dbd6d6 !important;
+    border: 1px solid #746c6c !important;
+    box-shadow: inset 0px 2px 4px rgba(0, 0, 0, 0.05) !important;
+}
+
+.ball-filled {
+    background: radial-gradient(circle at 30% 30%, #ffffff 0%, #ffcbd4 100%) !important;
+    border: 2px solid #EE0033 !important;
+    color: #333 !important;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important;
+    font-weight: 900 !important;
+}
+
+/* Custom scrollbar to match mobile feel */
+::-webkit-scrollbar {
+    display: none;
+}

+ 185 - 0
website/wwwroot/LotteryV2/css/history.css

@@ -0,0 +1,185 @@
+/* History specific styles */
+.history-game-tabs {
+    display: flex;
+    padding: 0 16px;
+    gap: 8px;
+    margin-top: 20px;
+    overflow-x: auto;
+    padding-bottom: 8px;
+}
+.history-game-tabs::-webkit-scrollbar { display: none; }
+.game-tab {
+    flex: none;
+    padding: 10px 18px;
+    background: white;
+    border-radius: 14px;
+    font-size: 13px;
+    font-weight: 800;
+    color: #4B5563;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+    border: 1.5px solid transparent;
+    transition: all 0.2s;
+    cursor: pointer;
+    white-space: nowrap;
+}
+.game-tab.active {
+    color: #EE0033;
+    border-color: #EE0033;
+    background: #FFF5F5;
+}
+
+.status-filters {
+    display: flex;
+    padding: 0 16px;
+    gap: 4px;
+    margin-top: 12px;
+    background: white;
+    margin-left: 16px;
+    margin-right: 16px;
+    border-radius: 12px;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.03);
+}
+.status-filter {
+    flex: 1;
+    padding: 12px 4px;
+    text-align: center;
+    font-size: 12px;
+    font-weight: 700;
+    color: #9CA3AF;
+    position: relative;
+    cursor: pointer;
+    transition: all 0.2s;
+}
+.status-filter.active {
+    color: #EE0033;
+}
+.status-filter.active::after {
+    content: '';
+    position: absolute;
+    bottom: 6px;
+    left: 20%;
+    right: 20%;
+    height: 3px;
+    background: #EE0033;
+    border-radius: 2px;
+}
+
+/* Ticket Card */
+.ticket-card {
+    background: white;
+    border-radius: 12px;
+    margin: 16px 0;
+    padding: 0;
+    box-shadow: 0 8px 25px rgba(0,0,0,0.06);
+    position: relative;
+    border: 1px solid #F1F1F1;
+    overflow: hidden;
+}
+
+.ticket-card-top {
+    padding: 20px;
+    padding-bottom: 24px;
+    background: white;
+    position: relative;
+}
+
+.ticket-perforation {
+    height: 4px;
+    background-image: radial-gradient(circle, #F3F4F6 6px, transparent 6px);
+    background-size: 24px 24px;
+    background-position: center;
+    background-repeat: repeat-x;
+    position: relative;
+    margin: 0 -10px;
+}
+
+.ticket-card-bottom {
+    padding: 20px;
+    background: #FDFDFD;
+    border-top: 1px dashed #E5E7EB;
+}
+
+.ticket-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+}
+.ticket-id { 
+    font-size: 13px; 
+    color: #9CA3AF; 
+    font-weight: 700;
+    font-family: 'Bricolage Grotesque', sans-serif;
+}
+.ticket-status {
+    padding: 6px 14px;
+    border-radius: 30px;
+    font-size: 11px;
+    font-weight: 900;
+    text-transform: uppercase;
+    letter-spacing: 0.5px;
+}
+.status-waiting { background: #FFF9C4; color: #B45309; }
+.status-win { background: #DCFCE7; color: #15803D; }
+.status-notwin { background: #FEE2E2; color: #B91C1C; }
+
+.ticket-numbers {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 10px;
+    padding: 0;
+    background: transparent;
+}
+.ticket-ball {
+    width: 32px;
+    height: 32px;
+    background: #F3F4F6;
+    border: 1px solid #E5E7EB;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 13px;
+    font-weight: 800;
+    color: #4B5563;
+    transition: all 0.2s;
+    flex-shrink: 0;
+}
+
+.ticket-ball.ball-win {
+    background: #10B981;
+    color: white;
+    border-color: #059669;
+    box-shadow: 0 4px 10px rgba(16, 185, 129, 0.3);
+}
+
+.ticket-ball.ball-lose {
+    background: #EF4444;
+    color: white;
+    border-color: #DC2626;
+    box-shadow: 0 4px 10px rgba(239, 68, 68, 0.3);
+}
+
+.ticket-ball.ball-waiting {
+    background: #F3F4F6;
+    color: #9CA3AF;
+    border: 1px dashed #D1D5DB;
+}
+
+.ticket-info-grid {
+    display: flex;
+    flex-direction: column;
+    gap: 14px;
+}
+.info-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+.info-label { font-size: 12px; color: #9CA3AF; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; }
+.info-value { font-size: 14px; color: #1F2937; font-weight: 900; }
+.win-amount { color: #EE0033; font-size: 18px; }
+
+.history-items-list {
+    padding-bottom: 150px;
+}

+ 221 - 0
website/wwwroot/LotteryV2/css/results.css

@@ -0,0 +1,221 @@
+.results-container {
+    background-color: #F3F4F6;
+    min-height: 100vh;
+}
+
+.sticky-top-section {
+    position: sticky;
+    top: 0;
+    z-index: 100;
+}
+
+.results-top-header {
+    background-color: #EE0033;
+    padding: 12px 16px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: relative;
+}
+
+.results-top-header h1 {
+    color: white;
+    font-size: 28px;
+    font-weight: 800;
+}
+
+.results-top-header .back-btn {
+    position: absolute;
+    left: 16px;
+    color: white;
+    font-size: 20px;
+}
+
+/* Date Selection Bar */
+.selection-bar {
+    display: flex;
+    padding: 16px;
+    gap: 12px;
+    align-items: center;
+}
+
+.date-pick-input {
+    flex: 1;
+    background: white;
+    border: 1px solid #D1D5DB;
+    border-radius: 8px;
+    padding: 8px 10px;
+    display: flex;
+    align-items: center;
+    gap: 4px;
+    font-size: 13px;
+    font-weight: 700;
+    color: #374151;
+}
+
+.btn-search-red {
+    background-color: #EE0033;
+    width: 54px;
+    height: 54px;
+    border-radius: 12px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: white;
+    font-size: 24px;
+    box-shadow: 0 4px 10px rgba(238, 0, 51, 0.2);
+}
+
+/* Tabs */
+.tab-switcher {
+    display: flex;
+    padding: 0 16px;
+    gap: 12px;
+    margin-bottom: 16px;
+}
+
+.tab-btn {
+    flex: 1;
+    background: white;
+    border-radius: 12px;
+    padding: 14px;
+    text-align: center;
+    font-weight: 800;
+    color: #1F2937;
+    font-size: 14px;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+}
+
+/* Result Item Cards */
+.result-item-red {
+    background: linear-gradient(135deg, #FF3D63 0%, #E3132D 60%, #BA0F21 100%);
+    border-radius: 16px;
+    margin: 0 16px 16px 16px;
+    padding: 16px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    box-shadow: 0 8px 24px rgba(211, 29, 40, 0.25);
+    position: relative;
+    overflow: hidden;
+    border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.result-item-red::before {
+    content: '';
+    position: absolute;
+    top: -50%;
+    left: -10%;
+    width: 50%;
+    height: 150%;
+    background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 50%, transparent 100%);
+    pointer-events: none;
+    transform: rotate(20deg);
+}
+
+.item-date-text {
+    flex: 0 0 90px;
+    color: white;
+    line-height: 1.2;
+    font-weight: 700;
+}
+
+.item-date-text .day { font-size: 14px; margin-bottom: 2px; }
+.item-date-text .date { font-size: 12px; font-weight: 400; opacity: 0.8; }
+
+.balls-container {
+    flex: 1;
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: flex-end;
+    gap: 4px;
+    padding: 2px 0;
+}
+
+.yellow-ball {
+    width: 26px;
+    height: 26px;
+    background: radial-gradient(circle at 35% 35%, #FFE082 0%, #FFD54F 40%, #FFB300 70%, #FFA000 100%);
+    border: 1.2px solid #FFECB3;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 10px;
+    font-weight: 900;
+    color: #1a1a1a;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.15), inset 0 -1px 2px rgba(0,0,0,0.1);
+}
+
+.yellow-ball:hover {
+    transform: scale(1.1);
+    box-shadow: 0 4px 8px rgba(0,0,0,0.25);
+}
+
+.results-items-list {
+    padding-bottom: 140px;
+}
+
+/* Bottom Promo Bar */
+.bottom-promo-red {
+    background-color: #EE0033;
+    padding: 12px;
+    text-align: center;
+    position: fixed;
+    bottom: 74px;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 100%;
+    max-width: 414px;
+    z-index: 40;
+}
+
+.promo-text {
+    color: white;
+    font-size: 12px;
+    font-weight: 700;
+}
+
+.promo-highlight {
+    display: block;
+    color: #FFE600;
+    font-size: 18px;
+    font-weight: 900;
+    margin-top: 2px;
+}
+
+/* Modern Flatpickr Red Theme */
+.flatpickr-calendar {
+    background: #fff;
+    border-radius: 16px;
+    box-shadow: 0 10px 25px rgba(0,0,0,0.1);
+    border: 1px solid #eee;
+}
+.flatpickr-day.selected {
+    background: #EE0033 !important;
+    border-color: #EE0033 !important;
+    color: #fff !important;
+}
+.flatpickr-months .flatpickr-month {
+    background: #EE0033;
+    color: #fff;
+    fill: #fff;
+    border-radius: 16px 16px 0 0;
+    height: 50px;
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months { 
+    font-weight: 800; 
+    color: #fff !important;
+    background: transparent;
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month {
+    background-color: #fff;
+    color: #333;
+}
+.numInputWrapper span.arrowUp:after { border-bottom-color: #fff; }
+.numInputWrapper span.arrowDown:after { border-top-color: #fff; }
+.flatpickr-current-month input.cur-year { color: #fff !important; font-weight: 800; }
+.flatpickr-weekdays { background: #EE0033; border-radius: 0; }
+.flatpickr-weekday { background: #EE0033; color: rgba(255,255,255,0.9) !important; font-weight: 700; }
+.flatpickr-day.today { border-color: #EE0033 !important; }
+.flatpickr-day:hover { background: #ffebee !important; }

+ 42 - 1
website/wwwroot/LotteryV2/css/site.css

@@ -144,4 +144,45 @@ body::-webkit-scrollbar {
 
 
 .animate-slide-up {
 .animate-slide-up {
     animation: slide-up 2s ease-in-out infinite;
     animation: slide-up 2s ease-in-out infinite;
-}
+}
+/* Global Loading Overlay */
+#loading-overlay {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, 0.3);
+    backdrop-filter: blur(2px);
+    display: none;
+    align-items: center;
+    justify-content: center;
+    z-index: 9999;
+    transition: opacity 0.3s ease;
+}
+
+.loading-spinner {
+    width: 48px;
+    height: 48px;
+    border: 5px solid rgba(255, 255, 255, 0.2);
+    border-radius: 50%;
+    border-top-color: #fff;
+    animation: spin 0.8s linear infinite;
+    box-shadow: 0 0 20px rgba(0,0,0,0.1);
+}
+
+@keyframes spin {
+    to { transform: rotate(360deg); }
+}
+
+/* Hide Spinners for input number */
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+  -webkit-appearance: none;
+  margin: 0;
+}
+input[type=number] {
+  appearance: textfield;
+  -moz-appearance: textfield;
+}
+

Fichier diff supprimé car celui-ci est trop grand
+ 2 - 0
website/wwwroot/LotteryV2/img/Rectangle 132.svg


BIN
website/wwwroot/LotteryV2/img/bigsmall/ball_1_big.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/ball_42_dark.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/ball_54_dark.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/ball_5_blue.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/ball_88_big.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/ball_8_pink.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/bg_curve.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/card_big_full.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/card_small_full.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/light_effect_1.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/light_effect_2.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/select_btn.png


BIN
website/wwwroot/LotteryV2/img/bigsmall/selected_btn.png


BIN
website/wwwroot/LotteryV2/img/modal/fail_icon.png


BIN
website/wwwroot/LotteryV2/img/modal/otp_coins.png


BIN
website/wwwroot/LotteryV2/img/modal/otp_glitter.png


+ 48 - 0
website/wwwroot/LotteryV2/img/modal/otp_light_1.svg

@@ -0,0 +1,48 @@
+<svg width="578" height="43" viewBox="0 0 578 43" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g opacity="0.7" style="mix-blend-mode:screen">
+<path d="M289 43C448.61 43 578 33.3741 578 21.5C578 9.62588 448.61 0 289 0C129.39 0 0 9.62588 0 21.5C0 33.3741 129.39 43 289 43Z" fill="url(#paint0_radial_213_4740)" style="mix-blend-mode:screen"/>
+<path d="M289 43C448.61 43 578 33.3741 578 21.5C578 9.62588 448.61 0 289 0C129.39 0 0 9.62588 0 21.5C0 33.3741 129.39 43 289 43Z" fill="url(#paint1_radial_213_4740)" fill-opacity="0.5" style="mix-blend-mode:screen"/>
+<path d="M289 43C448.61 43 578 33.3741 578 21.5C578 9.62588 448.61 0 289 0C129.39 0 0 9.62588 0 21.5C0 33.3741 129.39 43 289 43Z" fill="url(#paint2_radial_213_4740)" fill-opacity="0.3" style="mix-blend-mode:screen"/>
+</g>
+<defs>
+<radialGradient id="paint0_radial_213_4740" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(289.899 20.7222) scale(288.982 21.4163)">
+<stop offset="0.11" stop-color="#FF9500"/>
+<stop offset="0.15" stop-color="#D37B00"/>
+<stop offset="0.2" stop-color="#A76200"/>
+<stop offset="0.25" stop-color="#7F4A00"/>
+<stop offset="0.31" stop-color="#5C3600"/>
+<stop offset="0.37" stop-color="#3F2500"/>
+<stop offset="0.44" stop-color="#281700"/>
+<stop offset="0.51" stop-color="#160C00"/>
+<stop offset="0.61" stop-color="#090500"/>
+<stop offset="0.73" stop-color="#020100"/>
+<stop offset="1"/>
+</radialGradient>
+<radialGradient id="paint1_radial_213_4740" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(289.899 20.7222) scale(288.982 21.4163)">
+<stop offset="0.11" stop-color="#FF9500"/>
+<stop offset="0.15" stop-color="#D37B00"/>
+<stop offset="0.2" stop-color="#A76200"/>
+<stop offset="0.25" stop-color="#7F4A00"/>
+<stop offset="0.31" stop-color="#5C3600"/>
+<stop offset="0.37" stop-color="#3F2500"/>
+<stop offset="0.44" stop-color="#281700"/>
+<stop offset="0.51" stop-color="#160C00"/>
+<stop offset="0.61" stop-color="#090500"/>
+<stop offset="0.73" stop-color="#020100"/>
+<stop offset="1"/>
+</radialGradient>
+<radialGradient id="paint2_radial_213_4740" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(289.899 20.7222) scale(288.982 21.4163)">
+<stop offset="0.11" stop-color="#FF9500"/>
+<stop offset="0.15" stop-color="#D37B00"/>
+<stop offset="0.2" stop-color="#A76200"/>
+<stop offset="0.25" stop-color="#7F4A00"/>
+<stop offset="0.31" stop-color="#5C3600"/>
+<stop offset="0.37" stop-color="#3F2500"/>
+<stop offset="0.44" stop-color="#281700"/>
+<stop offset="0.51" stop-color="#160C00"/>
+<stop offset="0.61" stop-color="#090500"/>
+<stop offset="0.73" stop-color="#020100"/>
+<stop offset="1"/>
+</radialGradient>
+</defs>
+</svg>

+ 48 - 0
website/wwwroot/LotteryV2/img/modal/otp_light_2.svg

@@ -0,0 +1,48 @@
+<svg width="578" height="29" viewBox="0 0 578 29" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g opacity="0.7" style="mix-blend-mode:screen">
+<path d="M289 29C448.61 29 578 22.5081 578 14.5C578 6.49187 448.61 0 289 0C129.39 0 0 6.49187 0 14.5C0 22.5081 129.39 29 289 29Z" fill="url(#paint0_radial_213_4741)" style="mix-blend-mode:screen"/>
+<path d="M289 29C448.61 29 578 22.5081 578 14.5C578 6.49187 448.61 0 289 0C129.39 0 0 6.49187 0 14.5C0 22.5081 129.39 29 289 29Z" fill="url(#paint1_radial_213_4741)" fill-opacity="0.5" style="mix-blend-mode:screen"/>
+<path d="M289 29C448.61 29 578 22.5081 578 14.5C578 6.49187 448.61 0 289 0C129.39 0 0 6.49187 0 14.5C0 22.5081 129.39 29 289 29Z" fill="url(#paint2_radial_213_4741)" fill-opacity="0.3" style="mix-blend-mode:screen"/>
+</g>
+<defs>
+<radialGradient id="paint0_radial_213_4741" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(289.899 13.9754) scale(288.982 14.4435)">
+<stop offset="0.11" stop-color="#FF9500"/>
+<stop offset="0.15" stop-color="#D37B00"/>
+<stop offset="0.2" stop-color="#A76200"/>
+<stop offset="0.25" stop-color="#7F4A00"/>
+<stop offset="0.31" stop-color="#5C3600"/>
+<stop offset="0.37" stop-color="#3F2500"/>
+<stop offset="0.44" stop-color="#281700"/>
+<stop offset="0.51" stop-color="#160C00"/>
+<stop offset="0.61" stop-color="#090500"/>
+<stop offset="0.73" stop-color="#020100"/>
+<stop offset="1"/>
+</radialGradient>
+<radialGradient id="paint1_radial_213_4741" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(289.899 13.9754) scale(288.982 14.4435)">
+<stop offset="0.11" stop-color="#FF9500"/>
+<stop offset="0.15" stop-color="#D37B00"/>
+<stop offset="0.2" stop-color="#A76200"/>
+<stop offset="0.25" stop-color="#7F4A00"/>
+<stop offset="0.31" stop-color="#5C3600"/>
+<stop offset="0.37" stop-color="#3F2500"/>
+<stop offset="0.44" stop-color="#281700"/>
+<stop offset="0.51" stop-color="#160C00"/>
+<stop offset="0.61" stop-color="#090500"/>
+<stop offset="0.73" stop-color="#020100"/>
+<stop offset="1"/>
+</radialGradient>
+<radialGradient id="paint2_radial_213_4741" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(289.899 13.9754) scale(288.982 14.4435)">
+<stop offset="0.11" stop-color="#FF9500"/>
+<stop offset="0.15" stop-color="#D37B00"/>
+<stop offset="0.2" stop-color="#A76200"/>
+<stop offset="0.25" stop-color="#7F4A00"/>
+<stop offset="0.31" stop-color="#5C3600"/>
+<stop offset="0.37" stop-color="#3F2500"/>
+<stop offset="0.44" stop-color="#281700"/>
+<stop offset="0.51" stop-color="#160C00"/>
+<stop offset="0.61" stop-color="#090500"/>
+<stop offset="0.73" stop-color="#020100"/>
+<stop offset="1"/>
+</radialGradient>
+</defs>
+</svg>

BIN
website/wwwroot/LotteryV2/img/modal/otp_shield.png


Fichier diff supprimé car celui-ci est trop grand
+ 9 - 0
website/wwwroot/LotteryV2/img/modal/otp_sparkle_1.svg


Fichier diff supprimé car celui-ci est trop grand
+ 9 - 0
website/wwwroot/LotteryV2/img/modal/otp_sparkle_2.svg


Fichier diff supprimé car celui-ci est trop grand
+ 9 - 0
website/wwwroot/LotteryV2/img/modal/otp_sparkle_3.svg


BIN
website/wwwroot/LotteryV2/img/modal/otp_success.png


BIN
website/wwwroot/LotteryV2/img/modal/success_footer.png


BIN
website/wwwroot/LotteryV2/img/modal/success_header.png


BIN
website/wwwroot/LotteryV2/img/oddeven/ball_1.png


BIN
website/wwwroot/LotteryV2/img/oddeven/ball_19.png


BIN
website/wwwroot/LotteryV2/img/oddeven/ball_3.png


BIN
website/wwwroot/LotteryV2/img/oddeven/ball_66.png


BIN
website/wwwroot/LotteryV2/img/oddeven/ball_68.png


BIN
website/wwwroot/LotteryV2/img/oddeven/ball_88.png


BIN
website/wwwroot/LotteryV2/img/transfer_account_card.png


BIN
website/wwwroot/LotteryV2/img/transfer_arrow_left.png


BIN
website/wwwroot/LotteryV2/img/transfer_basic_icon.png


BIN
website/wwwroot/LotteryV2/img/transfer_gold_coin.png


BIN
website/wwwroot/LotteryV2/img/transfer_gold_stack.png


BIN
website/wwwroot/LotteryV2/img/transfer_other_card.png


BIN
website/wwwroot/LotteryV2/img/transfer_wallet_icon.png


Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff