Browse Source

no message

student 8 giờ trước cách đây
mục cha
commit
3755d7942c

+ 167 - 0
website/Areas/Millions/Controllers/HomeController.cs

@@ -438,6 +438,173 @@ namespace LotteryWebApp.Areas.Millions.Controllers
             return View(model);
         }
 
+        public IActionResult JackpotResults(string termType, string fromFormatted, string toFormatted)
+        {
+            HomeIndex_ViewModel model = new HomeIndex_ViewModel();
+            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.userStatus = userStatus;
+                model.profile = profile;
+                model.bolet = HttpContext.Session.GetString("bolet");
+                model.lastResult = HttpContext.Session.GetString("lastResult");
+                model.lastResultDate = HttpContext.Session.GetString("lastResultDate");
+                model.nextRoundDate = HttpContext.Session.GetString("nextRoundDate");
+                model.termType = !string.IsNullOrEmpty(termType)
+                    ? termType
+                    : (HttpContext.Session.GetString("termType") ?? Constants.Millions_CODE);
+
+                string lang = CultureInfo.CurrentCulture.Name;
+                string langValue = (lang.StartsWith("en") || lang.StartsWith("fr")) ? "0" : "1";
+
+                // Default: last 7 days if filter not provided
+                if (string.IsNullOrEmpty(fromFormatted))
+                {
+                    fromFormatted = DateTime.Now.AddDays(-365).ToString("yyyy-MM-dd");
+                }
+                if (string.IsNullOrEmpty(toFormatted))
+                {
+                    toFormatted = DateTime.Now.ToString("yyyy-MM-dd");
+                }
+
+                ViewBag.FromFormatted = fromFormatted;
+                ViewBag.ToFormatted = toFormatted;
+
+                RpSearchDetailTicketRequest request = new RpSearchDetailTicketRequest
+                {
+                    requestId = DateTime.Now.Ticks.ToString(),
+                    msisdn = "-1",
+                    gameId = model.termType,
+                    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"),
+                    prize = "JACKPOT",
+                    language = langValue,
+                    token = token
+                };
+
+                RpSearchDetailTicketResponse result = api.RpSearchDetailTicketApi(configuration, request);
+                log.Debug("RpSearchDetailTicket response: " + JsonConvert.SerializeObject(result));
+
+                model.listTerm = new List<Term>();
+                var winnersByDraw = new Dictionary<string, List<JackpotWinnerItem>>();
+
+                if (result != null && result.responseCode == Code.SUCCESS && result.list != null)
+                {
+                    // Group winners by randomId -> one draw card per group
+                    var grouped = result.list
+                        .GroupBy(w => w.randomId)
+                        .OrderByDescending(g => ParseDrawDate(g.First().randomDate));
+
+                    foreach (var group in grouped)
+                    {
+                        var first = group.First();
+                        DateTime drawDt = ParseDrawDate(first.randomDate);
+
+                        long totalPrize = 0;
+                        foreach (var w in group)
+                        {
+                            long m;
+                            if (long.TryParse(w.moneyWin, out m)) totalPrize += m;
+                        }
+
+                        Term term = new Term
+                        {
+                            id = first.randomId,
+                            seq = first.randomId,
+                            date_random = drawDt != DateTime.MinValue ? drawDt.ToString("dd/MM/yyyy HH:mm:ss") : first.randomDate,
+                            date_start = first.startDate,
+                            date_end = first.endDate,
+                            result = first.result,
+                            money_winner = totalPrize.ToString(),
+                            bolet = totalPrize.ToString(),
+                            split = group.Count().ToString(),
+                            gameId = model.termType
+                        };
+                        model.listTerm.Add(term);
+
+                        winnersByDraw[first.randomId] = group.ToList();
+                    }
+                }
+
+                // Cache winners by draw id so JackpotDetail can render them
+                HttpContext.Session.SetComplexData("jackpotWinners", winnersByDraw);
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                model.listTerm = new List<Term>();
+            }
+            return View(model);
+        }
+
+        private static DateTime ParseDrawDate(string raw)
+        {
+            if (string.IsNullOrEmpty(raw)) return DateTime.MinValue;
+            string[] formats = {
+                "M/d/yyyy h:mm:ss tt",
+                "MM/dd/yyyy h:mm:ss tt",
+                "M/d/yyyy hh:mm:ss tt",
+                "dd/MM/yyyy HH:mm:ss",
+                "yyyy-MM-dd HH:mm:ss"
+            };
+            DateTime dt;
+            if (DateTime.TryParseExact(raw, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
+            {
+                return dt;
+            }
+            if (DateTime.TryParse(raw, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
+            {
+                return dt;
+            }
+            return DateTime.MinValue;
+        }
+
+        public IActionResult JackpotDetail(string id, string termType)
+        {
+            HomeIndex_ViewModel model = new HomeIndex_ViewModel();
+            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.userStatus = userStatus;
+                model.profile = profile;
+                model.bolet = HttpContext.Session.GetString("bolet");
+                model.lastResult = HttpContext.Session.GetString("lastResult");
+                model.lastResultDate = HttpContext.Session.GetString("lastResultDate");
+                model.termType = !string.IsNullOrEmpty(termType)
+                    ? termType
+                    : (HttpContext.Session.GetString("termType") ?? Constants.Millions_CODE);
+                ViewBag.DrawId = id;
+
+                var cache = HttpContext.Session.GetComplexData<Dictionary<string, List<JackpotWinnerItem>>>("jackpotWinners");
+                List<JackpotWinnerItem> winners = null;
+                if (cache != null && !string.IsNullOrEmpty(id) && cache.ContainsKey(id))
+                {
+                    winners = cache[id];
+                }
+                ViewBag.Winners = winners ?? new List<JackpotWinnerItem>();
+            }
+            catch (Exception ex)
+            {
+                log.Error(ex);
+                ViewBag.Winners = new List<JackpotWinnerItem>();
+            }
+            return View(model);
+        }
+
         public IActionResult HowToPlay()
         {
             HomeIndex_ViewModel model = new HomeIndex_ViewModel();

+ 9 - 5
website/Areas/Millions/Views/Home/GameHome.cshtml

@@ -14,9 +14,13 @@
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     <link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@600;700;800&family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700;12..96,800&display=swap" rel="stylesheet">
     <link rel="stylesheet" href="/Millions/css/all.min.css"/>
+    <style>
+        html, body.millions-bg { background: #f5f7fb !important; }
+        .main-content { background: #f5f7fb !important; }
+    </style>
 }
 
-<div class="main-content h-dvh w-full max-w-[430px] mx-auto bg-[#f5f7fb] relative overflow-hidden font-bricolage">
+<div class="main-content h-dvh w-full max-w-[430px] mx-auto bg-[#f5f7fb] relative overflow-hidden font-bricolage" style="background-color:#f5f7fb;">
 
     <!-- Scrollable content area -->
     @{
@@ -28,7 +32,7 @@
             resultBalls = temp;
         }
     }
-    <div class="absolute inset-x-0 top-0 bottom-[88px] overflow-y-auto flex flex-col">
+    <div class="absolute inset-x-0 top-0 bottom-[64px] overflow-y-auto flex flex-col" style="background-color:#f5f7fb; overscroll-behavior:contain;">
 
         <!-- Top section with header + cards -->
         <div class="relative">
@@ -129,7 +133,7 @@
 
         <!-- Mega Jackpot banner -->
         <div class="px-2 mt-6">
-            <div class="mega-banner relative rounded-[20px] overflow-hidden px-4 py-3 flex flex-col">
+            <a href="@Url.Action("JackpotResults", "Home", new { area = "Millions", termType = Model.termType })" class="mega-banner relative rounded-[20px] overflow-hidden px-4 py-3 flex flex-col">
                 <span class="mega-glow" style="left:-79px; top:-101px;"></span>
                 <span class="mega-glow" style="right:-78px; top:9px;"></span>
                 <span class="mega-glow" style="right:-107px; top:20px;"></span>
@@ -146,11 +150,11 @@
 
                 <!-- Decorative elements -->
                 <img src="/Millions/assets/images/crown-balls.png" alt="" class="absolute right-2 top-1/2 -translate-y-1/2 w-44 h-auto pointer-events-none"/>
-            </div>
+            </a>
         </div>
 
         <!-- Play now button + decorative balls -->
-        <div class="relative shrink-0 mt-8 z-10">
+        <div class="relative shrink-0 mt-4 z-10">
             <img src="/Millions/assets/images/play-decor.png" alt="" class="block w-full h-auto pointer-events-none"/>
 
             <a onclick="checkTerm('@Constants.Millions_CODE')" class="play-now-outer rounded-full animate-pulse-play" style="position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); width:155px; height:155px; padding:11px; cursor:pointer;">

+ 181 - 0
website/Areas/Millions/Views/Home/JackpotDetail.cshtml

@@ -0,0 +1,181 @@
+@model LotteryWebApp.Models.HomeIndex_ViewModel
+@using System
+@using System.Globalization
+@using System.Collections.Generic
+@using LotteryWebApp.Common
+@using LotteryWebApp.Languages
+@using LotteryWebApp.Service
+@{
+    ViewData["Title"] = "Millions - Jackpot Detail";
+    Layout = "~/Areas/Millions/Views/Shared/_Layout.cshtml";
+    var drawId = (ViewBag.DrawId as string) ?? "";
+    var winners = ViewBag.Winners as List<JackpotWinnerItem> ?? new List<JackpotWinnerItem>();
+    var firstWinner = winners.Count > 0 ? winners[0] : null;
+
+    var mainBalls = new string[5];
+    var mbBall = "0";
+    var resultStr = firstWinner != null ? firstWinner.result : "";
+    var balls = !string.IsNullOrEmpty(resultStr) ? resultStr.Split(',') : new string[0];
+    for (int i = 0; i < 5; i++)
+    {
+        mainBalls[i] = i < balls.Length ? balls[i].Trim() : "0";
+    }
+    if (balls.Length >= 6) mbBall = balls[5].Trim();
+
+    string drawDateFmt = "";
+    string drawDateLong = "";
+    string drawTime = "";
+    DateTime drawDt;
+    string rawDate = firstWinner != null ? firstWinner.randomDate : "";
+    string[] tryFormats = { "M/d/yyyy h:mm:ss tt", "MM/dd/yyyy h:mm:ss tt", "dd/MM/yyyy HH:mm:ss", "yyyy-MM-dd HH:mm:ss" };
+    if (!string.IsNullOrEmpty(rawDate)
+        && (DateTime.TryParseExact(rawDate, tryFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out drawDt)
+            || DateTime.TryParse(rawDate, CultureInfo.InvariantCulture, DateTimeStyles.None, out drawDt)))
+    {
+        drawDateFmt = drawDt.ToString("MMM dd, yyyy", new CultureInfo("en-US"));
+        drawDateLong = drawDt.ToString("dddd, MMM dd, yyyy", new CultureInfo("en-US"));
+        drawTime = drawDt.ToString("HH:mm");
+    }
+
+    long jackpotPrizeTotal = 0;
+    foreach (var w in winners)
+    {
+        long m;
+        if (long.TryParse(w.moneyWin, out m)) jackpotPrizeTotal += m;
+    }
+    var jackpotPrize = jackpotPrizeTotal.ToString();
+    var winnersCount = winners.Count;
+}
+
+@section Styles {
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+    <link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@600;700;800&family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700;12..96,800&display=swap" rel="stylesheet">
+    <link rel="stylesheet" href="/Millions/css/all.min.css"/>
+    <link rel="stylesheet" href="/Millions/css/jackpot.css"/>
+}
+
+<div class="main-content h-dvh w-full max-w-[430px] mx-auto bg-[#f5f7fb] relative overflow-hidden font-bricolage">
+
+    <!-- Header gradient -->
+    <div class="header-bg absolute inset-x-0 top-0 h-[160px] flex flex-col items-center pt-4 px-3 z-0">
+        <div class="w-full flex items-center justify-between">
+            <button onclick="location.href=subDomain + '@Url.Action("JackpotResults", "Home", new { area = "Millions", termType = Model.termType })';" class="js-back w-6 h-6 flex items-center justify-center">
+                <img src="/Millions/assets/icons/arrow-left.svg" alt="Back" class="w-6 h-6"/>
+            </button>
+            <p class="text-white text-base font-bold">@Lang.millions_jackpot_results_title</p>
+            <span class="w-6 h-6"></span>
+        </div>
+        <p class="text-white/80 text-xs -mt-1">@Lang.millions_draw_no_short<span class="font-bold">@drawId</span></p>
+    </div>
+
+    <!-- White rounded body (overlaps header, scrollable) -->
+    <div class="absolute inset-x-0 top-[56px] bottom-0 bg-white rounded-t-[40px] flex flex-col gap-2 px-3 pt-4 pb-[96px] overflow-y-auto hide-scrollbar z-10" style="box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.1);">
+
+        <!-- Top: Draw info + MB ball + Jackpot prize -->
+        <div class="flex items-start justify-between shrink-0">
+            <div class="flex flex-col gap-1 items-start">
+                <span class="bg-[#0062ff] text-white text-base font-bold rounded-xl px-2 py-1">@Lang.millions_draw_no_short@drawId</span>
+                <div class="flex items-center gap-1">
+                    <img src="/Millions/assets/icons/calendar.png" alt="" class="w-5 h-5"/>
+                    <span class="text-xs text-black">@drawDateLong</span>
+                </div>
+                <div class="flex items-center gap-1">
+                    <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="#0062ff" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2" stroke-linecap="round"/></svg>
+                    <span class="text-xs text-black">@drawTime</span>
+                </div>
+            </div>
+
+            <div class="flex items-center gap-2 relative">
+                <div class="relative">
+                    <img src="/Millions/assets/icons/crown.png" alt="" class="absolute -top-3 -right-1 w-5 h-auto rotate-[15deg] z-0 pointer-events-none"/>
+                    <div class="ball ball-mb relative z-10" style="width:52px;height:52px;font-size:22px;">@mbBall</div>
+                    <span class="absolute -bottom-1 -right-1 bg-[#ee0033] text-white text-[10px] font-bold px-1 py-0.5 rounded z-20">MB</span>
+                </div>
+                <div class="flex flex-col">
+                    <span class="text-xs font-bold text-black">@Lang.millions_jackpot_prize</span>
+                    <p class="leading-none mt-1">
+                        <span class="text-[28px] font-condensed font-bold text-[#002bff] tracking-tight">@Utils.FormatMoney(jackpotPrize)</span><span class="text-xs font-bold text-black ml-1 align-top">@Lang.v2_htg</span>
+                    </p>
+                    <span class="text-[8px] font-bold text-[#8e8e93] mt-1">@Lang.millions_mega_jackpot</span>
+                </div>
+            </div>
+        </div>
+
+        <!-- Winning Numbers box -->
+        <div class="result-box rounded-[32px] py-3 flex flex-col gap-2 shrink-0">
+            <p class="text-xs font-bold text-black text-center">@Lang.millions_winning_numbers</p>
+            <div class="flex items-center justify-center gap-3 px-4">
+                @for (int i = 0; i < 5; i++)
+                {
+                    <div class="ball ball-blue">@mainBalls[i]</div>
+                }
+                <div class="relative">
+                    <img src="/Millions/assets/icons/crown.png" alt="" class="absolute -top-4 -right-1 w-7 h-auto rotate-[15deg] z-0 pointer-events-none"/>
+                    <div class="ball ball-mb relative z-10">@mbBall</div>
+                    <span class="absolute -bottom-1 -right-2 bg-[#ee0033] text-white text-[8px] font-bold px-1.5 py-0.5 rounded z-20">MB</span>
+                </div>
+            </div>
+        </div>
+
+        <!-- Winning Subscribes -->
+        <div class="result-box rounded-xl py-3 flex flex-col gap-2 shrink-0">
+            <div class="flex flex-col px-3 gap-1">
+                <p class="text-xs font-bold text-black">@Lang.millions_winning_subscribes (@winnersCount)</p>
+                <p class="text-xs text-black">@string.Format(Lang.millions_subscribers_won_jackpot, winnersCount)</p>
+            </div>
+            <div class="grid grid-cols-2 gap-2 px-3">
+                @{ int idx = 0; }
+                @foreach (var w in winners)
+                {
+                    idx++;
+                    var phone = w.msisdn ?? "";
+                    string masked = phone;
+                    if (phone.Length >= 7)
+                    {
+                        masked = "+" + phone.Substring(0, 3) + " " + phone.Substring(3, 2) + "****" + phone.Substring(phone.Length - 2);
+                    }
+                    <div class="flex items-center gap-2 border border-[#ccc] rounded-lg px-2 py-1.5"><span class="bg-[#0062ff] text-white text-xs font-bold rounded-lg w-4 h-4 flex items-center justify-center">@idx</span><span class="text-xs font-bold text-black">@masked</span></div>
+                }
+                @if (winnersCount == 0)
+                {
+                    <p class="text-xs text-[#8e8e93] col-span-2 text-center py-2">@Lang.millions_no_winners</p>
+                }
+            </div>
+        </div>
+
+        <!-- Draw information -->
+        <div class="result-box rounded-xl py-3 flex flex-col gap-2 px-3">
+            <p class="text-xs font-bold text-black">@Lang.millions_draw_information</p>
+            <div class="grid grid-cols-2 gap-x-1 gap-y-1 text-xs">
+                <p class="text-[#8e8e93]">@Lang.millions_game_type</p>
+                <p class="font-bold text-black">@Lang.millions_mega_jackpot</p>
+                <p class="text-[#8e8e93]">@Lang.millions_total_winners</p>
+                <p class="font-bold text-black">@winnersCount</p>
+                <p class="text-[#8e8e93]">@Lang.millions_draw_date_time</p>
+                <p class="font-bold text-black">@drawDateFmt - @drawTime</p>
+            </div>
+        </div>
+
+        <!-- Note -->
+        <div class="bg-[#ecf3fd] rounded-xl px-3 py-2 flex flex-col gap-1 shrink-0">
+            <div class="flex items-center gap-1">
+                <span class="bg-[#0062ff] text-white text-sm font-bold rounded-xl w-[17px] h-5 flex items-center justify-center leading-none">i</span>
+                <p class="text-[10px] font-bold text-[#0062ff]">@Lang.millions_note</p>
+            </div>
+            <div class="text-xs text-[#8e8e93] leading-tight">
+                <p>@Lang.millions_note_results_public</p>
+                <p>@Lang.millions_note_thank_you</p>
+            </div>
+        </div>
+
+        <!-- Back button -->
+        <a href="@Url.Action("JackpotResults", "Home", new { area = "Millions", termType = Model.termType })" class="bg-[#0062ff] text-white text-sm font-bold text-center rounded-xl px-3 py-3 mt-2 mb-1 shrink-0">@Lang.millions_back_to_results_list</a>
+
+    </div>
+
+</div>
+
+@section Scripts {
+    <script src="/Millions/js/all.min.js"></script>
+}

+ 233 - 0
website/Areas/Millions/Views/Home/JackpotResults.cshtml

@@ -0,0 +1,233 @@
+@model LotteryWebApp.Models.HomeIndex_ViewModel
+@{
+    ViewData["Title"] = "Millions - Kết quả Jackpot";
+    Layout = "~/Areas/Millions/Views/Shared/_Layout.cshtml";
+}
+@using System
+@using System.Globalization
+@using LotteryWebApp.Languages;
+@using LotteryWebApp.Controllers;
+@using LotteryWebApp.Common;
+
+@section Styles {
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+    <link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@600;700;800&family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700;12..96,800&display=swap" rel="stylesheet">
+    <link rel="stylesheet" href="/Millions/css/all.min.css"/>
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.css"/>
+    <link rel="stylesheet" href="/Millions/css/jackpot.css"/>
+}
+
+<div class="main-content h-dvh w-full max-w-[430px] mx-auto bg-[#0062ff] relative overflow-hidden font-bricolage">
+
+    <!-- Header gradient -->
+    <div class="header-bg absolute inset-x-0 top-0 h-[160px] flex items-start justify-between px-3 pt-4 z-0">
+        <button onclick="location.href=subDomain + '@Url.Action("GameHome", "Home", new { area = "Millions" })';" class="js-back w-6 h-6 flex items-center justify-center">
+            <img src="/Millions/assets/icons/arrow-left.svg" alt="Back" class="w-6 h-6"/>
+        </button>
+        <p class="text-white text-base font-bold">@Lang.millions_jackpot_results_title</p>
+        <span class="w-6 h-6"></span>
+    </div>
+
+    <!-- White rounded body (overlaps header, scrollable) -->
+    <div class="absolute inset-x-0 top-[56px] bottom-0 bg-white rounded-t-[40px] flex flex-col gap-3 px-3 pt-4 pb-[96px] overflow-y-auto hide-scrollbar z-10" style="box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.1);">
+
+        <!-- Date filter + search -->
+        @{
+            var fromFormatted = ViewBag.FromFormatted as string;
+            var toFormatted = ViewBag.ToFormatted as string;
+            var fromDisplay = DateTime.ParseExact(fromFormatted, "yyyy-MM-dd", CultureInfo.InvariantCulture).ToString("dd/MM/yyyy");
+            var toDisplay = DateTime.ParseExact(toFormatted, "yyyy-MM-dd", CultureInfo.InvariantCulture).ToString("dd/MM/yyyy");
+        }
+        <form id="jackpotFilterForm" method="get" action="@Url.Action("JackpotResults", "Home", new { area = "Millions" })" class="flex items-center justify-between gap-3 shrink-0">
+            <input type="hidden" name="termType" value="@Model.termType"/>
+            <div class="relative flex-1">
+                <button type="button" id="dateRangeToggle" class="date-range-toggle">
+                    <img src="/Millions/assets/icons/calendar.png" alt="" class="w-5 h-5"/>
+                    <span id="dateRangeLabel" class="text-xs font-bold text-black whitespace-nowrap">@fromDisplay - @toDisplay</span>
+                    <img src="/Millions/assets/icons/chevron-down-2.svg" alt="" class="w-3 h-3 ml-auto"/>
+                </button>
+                <div id="dateRangePanel" class="date-range-panel">
+                    <div class="row">
+                        <label>From</label>
+                        <input type="date" id="fromInput" name="fromFormatted" value="@fromFormatted" class="date-input"/>
+                    </div>
+                    <div class="row">
+                        <label>To</label>
+                        <input type="date" id="toInput" name="toFormatted" value="@toFormatted" class="date-input"/>
+                    </div>
+                    <div class="date-range-actions">
+                        <button type="button" id="dateRangeCancel" class="btn-cancel">Cancel</button>
+                        <button type="submit" class="btn-apply">Apply</button>
+                    </div>
+                </div>
+            </div>
+            <button type="submit" class="bg-[#0062ff] rounded-lg w-8 h-8 flex items-center justify-center shrink-0">
+                <img src="/Millions/assets/icons/search.svg" alt="" class="w-4 h-4"/>
+            </button>
+        </form>
+
+        <script src="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.js"></script>
+        <script>
+            (function() {
+                var toggle = document.getElementById('dateRangeToggle');
+                var panel = document.getElementById('dateRangePanel');
+                var cancelBtn = document.getElementById('dateRangeCancel');
+                if (!toggle || !panel) return;
+
+                function openPanel() {
+                    panel.classList.add('open');
+                    toggle.classList.add('open');
+                }
+                function closePanel() {
+                    panel.classList.remove('open');
+                    toggle.classList.remove('open');
+                }
+
+                toggle.addEventListener('click', function(e) {
+                    e.stopPropagation();
+                    if (panel.classList.contains('open')) {
+                        closePanel();
+                    } else {
+                        openPanel();
+                    }
+                });
+
+                cancelBtn.addEventListener('click', function(e) {
+                    e.stopPropagation();
+                    closePanel();
+                });
+
+                panel.addEventListener('click', function(e) { e.stopPropagation(); });
+
+                document.addEventListener('click', function(e) {
+                    if (!panel.contains(e.target) && !toggle.contains(e.target)) {
+                        closePanel();
+                    }
+                });
+
+                // Init Flatpickr on both date inputs (fully styled calendar)
+                if (window.flatpickr) {
+                    var fpOpts = {
+                        dateFormat: "Y-m-d",
+                        disableMobile: true,
+                        appendTo: panel,
+                        static: false,
+                        positionElement: toggle
+                    };
+                    flatpickr(document.getElementById('fromInput'), fpOpts);
+                    flatpickr(document.getElementById('toInput'), fpOpts);
+                }
+            })();
+        </script>
+
+        <!-- Mega Jackpot banner -->
+        <div class="mega-banner relative rounded-[12px] overflow-hidden px-4 py-3 border-2 border-white/70 flex flex-col shrink-0">
+            <span class="mega-glow" style="left:-79px; top:-101px;"></span>
+            <span class="mega-glow" style="right:-78px; top:9px;"></span>
+            <span class="mega-glow" style="right:-107px; top:20px;"></span>
+            <p class="mega-title relative inline-block text-white text-[22px] font-futura leading-none">
+                <img src="/Millions/assets/icons/crown.png" alt="" class="absolute -top-[5px] left-[26px] w-[12px] h-auto rotate-[10deg] pointer-events-none"/>
+                @Lang.millions_mega_jackpot
+            </p>
+            <p class="text-white text-xs mt-2">@Lang.millions_estimate_jackpot_prize</p>
+            <p class="leading-none mt-1 flex items-start" style="margin-bottom:18px;">
+                <span class="mega-amount text-[40px] font-condensed text-gold-gradient tracking-tight leading-none">@Utils.FormatMoney(Model.bolet ?? "30000000")</span>
+                <span class="text-gold-gradient text-sm font-bold uppercase ml-1">@Lang.v2_htg</span>
+            </p>
+            <p class="text-white text-[10px] mt-1">@Lang.millions_be_the_next_millionaire</p>
+            <img src="/Millions/assets/images/crown-balls.png" alt="" class="absolute right-2 top-1/2 -translate-y-1/2 w-44 h-auto pointer-events-none"/>
+        </div>
+
+        <!-- List heading -->
+        <div class="px-2 shrink-0">
+            <div class="flex items-center justify-between font-bold">
+                <p class="text-sm text-black">@Lang.millions_list_jackpot_results</p>
+                <p class="text-xs text-[#0062ff]">@string.Format(Lang.millions_total_draws, Model.listTerm?.Count ?? 0)</p>
+            </div>
+
+            <!-- Results list -->
+            <div class="flex flex-col gap-2 pb-2">
+
+                @if (Model.listTerm != null && Model.listTerm.Count > 0)
+                {
+                    foreach (var term in Model.listTerm)
+                    {
+                        var balls = !string.IsNullOrEmpty(term.result) ? term.result.Split(',') : new string[0];
+                        var mainBalls = new string[5];
+                        var mbBall = "0";
+                        for (int i = 0; i < 5; i++)
+                        {
+                            mainBalls[i] = i < balls.Length ? balls[i].Trim() : "0";
+                        }
+                        if (balls.Length >= 6)
+                        {
+                            mbBall = balls[5].Trim();
+                        }
+
+                        string dayOfWeek = "";
+                        string datePart = "";
+                        string timePart = "";
+                        DateTime drawDt;
+                        if (!string.IsNullOrEmpty(term.date_random) &&
+                            DateTime.TryParseExact(term.date_random, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out drawDt))
+                        {
+                            dayOfWeek = drawDt.ToString("dddd", new CultureInfo("vi-VN"));
+                            dayOfWeek = char.ToUpper(dayOfWeek[0]) + dayOfWeek.Substring(1);
+                            datePart = drawDt.ToString("dd/MM/yyyy");
+                            timePart = drawDt.ToString("HH:mm");
+                        }
+
+                        <a href="@Url.Action("JackpotDetail", "Home", new { area = "Millions", id = term.id, termType = Model.termType })" class="result-card bg-white rounded-xl flex items-center justify-between px-3 py-2 gap-2">
+                            <div class="flex flex-col gap-0.5 items-start shrink-0">
+                                <span class="bg-[#0062ff] text-white text-[10px] font-bold rounded px-1 py-0.5">@Lang.millions_draw_no_short@term.seq</span>
+                                <span class="text-xs text-[#8e8e93]">@dayOfWeek</span>
+                                <span class="text-[8px] font-bold text-[#8e8e93]">@datePart</span>
+                                <span class="text-[8px] font-bold text-[#8e8e93]">@timePart</span>
+                            </div>
+                            <div class="grid grid-cols-3 gap-1">
+                                @for (int i = 0; i < 5; i++)
+                                {
+                                    <div class="ball ball-blue ball-mini">@mainBalls[i]</div>
+                                }
+                                <div class="relative">
+                                    <img src="/Millions/assets/icons/crown.png" alt="" class="absolute -top-2.5 -right-1 w-4 h-auto rotate-[15deg] pointer-events-none z-0"/>
+                                    <div class="ball ball-mb ball-mini relative z-10">@mbBall</div>
+                                    <span class="absolute -bottom-1 -right-1 bg-[#ee0033] text-white text-[6px] font-bold px-1 rounded z-20">MB</span>
+                                </div>
+                            </div>
+                            <div class="flex flex-col gap-0.5 items-start shrink-0">
+                                <span class="text-xs font-bold text-black">@Lang.millions_jackpot</span>
+                                <p class="leading-none">
+                                    <span class="text-base font-extrabold text-[#002bff]">@Utils.FormatMoney(term.bolet ?? term.money_winner ?? "0")</span><span class="text-[10.32px] font-extrabold text-black align-top">@Lang.v2_htg</span>
+                                </p>
+                                @if (!string.IsNullOrEmpty(term.split))
+                                {
+                                    <span class="text-[8px] text-black">@string.Format(Lang.millions_subscribers_won, term.split)</span>
+                                }
+                            </div>
+                            <img src="/Millions/assets/icons/chevron-right.svg" alt="" class="w-2 h-3 shrink-0"/>
+                        </a>
+                    }
+                }
+
+            </div>
+
+            <!-- Note -->
+            <div class="flex items-center gap-2 bg-[#e6f0ff] rounded-lg px-3 py-2 mb-2 shrink-0">
+                <svg class="w-4 h-4 shrink-0" viewBox="0 0 24 24" fill="#0062ff"><path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 5a1.25 1.25 0 1 1 0 2.5A1.25 1.25 0 0 1 12 7Zm1 10h-2v-6h2v6Z"/></svg>
+                <p class="text-[10px] font-bold text-[#0062ff]">@Lang.millions_note_results_updated</p>
+            </div>
+        </div>
+    </div>
+
+    @{
+        ViewData["ActiveTab"] = "Home";
+    }
+    @await Html.PartialAsync("~/Areas/Millions/Views/Shared/_BottomNavbar.cshtml")
+
+</div>
+
+@section Scripts {
+    <script src="/Millions/js/all.min.js"></script>
+}

+ 189 - 0
website/Languages/Lang.Designer.cs

@@ -1593,6 +1593,15 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Back to Results list.
+        /// </summary>
+        public static string millions_back_to_results_list {
+            get {
+                return ResourceManager.GetString("millions_back_to_results_list", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Be the next millionaire.
         /// </summary>
@@ -1773,6 +1782,15 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Date &amp; Heure du tirage.
+        /// </summary>
+        public static string millions_draw_date_time {
+            get {
+                return ResourceManager.GetString("millions_draw_date_time", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Draw frequency: 2 times per week (Tuesday &amp; Friday).
         /// </summary>
@@ -1782,6 +1800,24 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Informations sur le tirage.
+        /// </summary>
+        public static string millions_draw_information {
+            get {
+                return ResourceManager.GetString("millions_draw_information", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Tirage #.
+        /// </summary>
+        public static string millions_draw_no_short {
+            get {
+                return ResourceManager.GetString("millions_draw_no_short", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Draw Schedule.
         /// </summary>
@@ -1890,6 +1926,15 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Game Type.
+        /// </summary>
+        public static string millions_game_type {
+            get {
+                return ResourceManager.GetString("millions_game_type", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to How to play.
         /// </summary>
@@ -1917,6 +1962,15 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Jackpot.
+        /// </summary>
+        public static string millions_jackpot {
+            get {
+                return ResourceManager.GetString("millions_jackpot", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Jackpot.
         /// </summary>
@@ -1926,6 +1980,24 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Prix Jackpot.
+        /// </summary>
+        public static string millions_jackpot_prize {
+            get {
+                return ResourceManager.GetString("millions_jackpot_prize", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Résultats Jackpot.
+        /// </summary>
+        public static string millions_jackpot_results_title {
+            get {
+                return ResourceManager.GetString("millions_jackpot_results_title", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to 30.000.000 HTG jodia  !.
         /// </summary>
@@ -1935,6 +2007,15 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Liste des résultats Jackpot.
+        /// </summary>
+        public static string millions_list_jackpot_results {
+            get {
+                return ResourceManager.GetString("millions_list_jackpot_results", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to 1 + Mega Ball.
         /// </summary>
@@ -2061,6 +2142,24 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Aucun résultat Jackpot.
+        /// </summary>
+        public static string millions_no_jackpot_results {
+            get {
+                return ResourceManager.GetString("millions_no_jackpot_results", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Pas encore de gagnants.
+        /// </summary>
+        public static string millions_no_winners {
+            get {
+                return ResourceManager.GetString("millions_no_winners", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Pedi.
         /// </summary>
@@ -2070,6 +2169,42 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Note.
+        /// </summary>
+        public static string millions_note {
+            get {
+                return ResourceManager.GetString("millions_note", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Le résultat est annoncé publiquement et vérifié.
+        /// </summary>
+        public static string millions_note_results_public {
+            get {
+                return ResourceManager.GetString("millions_note_results_public", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Note: Les résultats sont mis à jour après chaque tirage..
+        /// </summary>
+        public static string millions_note_results_updated {
+            get {
+                return ResourceManager.GetString("millions_note_results_updated", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Merci pour votre confiance et votre soutien.
+        /// </summary>
+        public static string millions_note_thank_you {
+            get {
+                return ResourceManager.GetString("millions_note_thank_you", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to now.
         /// </summary>
@@ -2340,6 +2475,24 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to {0} subscribers won.
+        /// </summary>
+        public static string millions_subscribers_won {
+            get {
+                return ResourceManager.GetString("millions_subscribers_won", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to {0} abonnés ont gagné le jackpot.
+        /// </summary>
+        public static string millions_subscribers_won_jackpot {
+            get {
+                return ResourceManager.GetString("millions_subscribers_won_jackpot", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Touche pouw we detay .
         /// </summary>
@@ -2412,6 +2565,24 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Total {0} draws.
+        /// </summary>
+        public static string millions_total_draws {
+            get {
+                return ResourceManager.GetString("millions_total_draws", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Total Winners.
+        /// </summary>
+        public static string millions_total_winners {
+            get {
+                return ResourceManager.GetString("millions_total_winners", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Transfere.
         /// </summary>
@@ -2448,6 +2619,24 @@ namespace LotteryWebApp.Languages {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Numéros gagnants.
+        /// </summary>
+        public static string millions_winning_numbers {
+            get {
+                return ResourceManager.GetString("millions_winning_numbers", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Abonnés gagnants.
+        /// </summary>
+        public static string millions_winning_subscribes {
+            get {
+                return ResourceManager.GetString("millions_winning_subscribes", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Winnings are calculated based on matching numbers and Mega Ball..
         /// </summary>

+ 64 - 1
website/Languages/Lang.fr.resx

@@ -1614,7 +1614,7 @@ We’ll help you create an account in a few easy steps.</value>
     <value>Continue</value>
   </data>
   <data name="millions_account_name" xml:space="preserve">
-    <value>Bee Lotto’s Account</value>
+    <value>Bee Lotto Account</value>
   </data>
   <data name="millions_fee" xml:space="preserve">
     <value>Fee</value>
@@ -1843,4 +1843,67 @@ We’ll help you create an account in a few easy steps.</value>
   <data name="millions_be_the_next_millionaire" xml:space="preserve">
     <value>Be the next millionaire</value>
   </data>
+  <data name="millions_jackpot_results_title" xml:space="preserve">
+    <value>Jackpot results</value>
+  </data>
+  <data name="millions_list_jackpot_results" xml:space="preserve">
+    <value>List of Jackpot results</value>
+  </data>
+  <data name="millions_total_draws" xml:space="preserve">
+    <value>Total {0} tirages</value>
+  </data>
+  <data name="millions_draw_no_short" xml:space="preserve">
+    <value>Draw #</value>
+  </data>
+  <data name="millions_jackpot" xml:space="preserve">
+    <value>Jackpot</value>
+  </data>
+  <data name="millions_subscribers_won" xml:space="preserve">
+    <value>{0} abonnés gagnants</value>
+  </data>
+  <data name="millions_no_jackpot_results" xml:space="preserve">
+    <value>No Jackpot results</value>
+  </data>
+  <data name="millions_note_results_updated" xml:space="preserve">
+    <value>Note: Results are updated after each draw.</value>
+  </data>
+  <data name="millions_jackpot_prize" xml:space="preserve">
+    <value>Jackpot Prize</value>
+  </data>
+  <data name="millions_winning_numbers" xml:space="preserve">
+    <value>Winning Numbers</value>
+  </data>
+  <data name="millions_winning_subscribes" xml:space="preserve">
+    <value>Winning Subscribes</value>
+  </data>
+  <data name="millions_subscribers_won_jackpot" xml:space="preserve">
+    <value>{0} subscribers won the jackpot prize</value>
+  </data>
+  <data name="millions_no_winners" xml:space="preserve">
+    <value>No winners yet</value>
+  </data>
+  <data name="millions_draw_information" xml:space="preserve">
+    <value>Draw information</value>
+  </data>
+  <data name="millions_game_type" xml:space="preserve">
+    <value>Game Type</value>
+  </data>
+  <data name="millions_total_winners" xml:space="preserve">
+    <value>Total gagnants</value>
+  </data>
+  <data name="millions_draw_date_time" xml:space="preserve">
+    <value>Draw Date &amp; Time</value>
+  </data>
+  <data name="millions_note" xml:space="preserve">
+    <value>Note</value>
+  </data>
+  <data name="millions_note_results_public" xml:space="preserve">
+    <value>The result is public announced and verified</value>
+  </data>
+  <data name="millions_note_thank_you" xml:space="preserve">
+    <value>Thank you for your trust and support</value>
+  </data>
+  <data name="millions_back_to_results_list" xml:space="preserve">
+    <value>Retour à la liste des résultats</value>
+  </data>
 </root>

+ 63 - 0
website/Languages/Lang.resx

@@ -1844,4 +1844,67 @@ Apre yo fin tire 20 nimewo, sistem nan konte konbyen nimewo ki enpe oswa pe: &lt
   <data name="millions_be_the_next_millionaire" xml:space="preserve">
     <value>Be the next millionaire</value>
   </data>
+  <data name="millions_jackpot_results_title" xml:space="preserve">
+    <value>Résultats Jackpot</value>
+  </data>
+  <data name="millions_list_jackpot_results" xml:space="preserve">
+    <value>Liste des résultats Jackpot</value>
+  </data>
+  <data name="millions_total_draws" xml:space="preserve">
+    <value>Total {0} draws</value>
+  </data>
+  <data name="millions_draw_no_short" xml:space="preserve">
+    <value>Tirage #</value>
+  </data>
+  <data name="millions_jackpot" xml:space="preserve">
+    <value>Jackpot</value>
+  </data>
+  <data name="millions_subscribers_won" xml:space="preserve">
+    <value>{0} subscribers won</value>
+  </data>
+  <data name="millions_no_jackpot_results" xml:space="preserve">
+    <value>Aucun résultat Jackpot</value>
+  </data>
+  <data name="millions_note_results_updated" xml:space="preserve">
+    <value>Note: Les résultats sont mis à jour après chaque tirage.</value>
+  </data>
+  <data name="millions_jackpot_prize" xml:space="preserve">
+    <value>Prix Jackpot</value>
+  </data>
+  <data name="millions_winning_numbers" xml:space="preserve">
+    <value>Numéros gagnants</value>
+  </data>
+  <data name="millions_winning_subscribes" xml:space="preserve">
+    <value>Abonnés gagnants</value>
+  </data>
+  <data name="millions_subscribers_won_jackpot" xml:space="preserve">
+    <value>{0} abonnés ont gagné le jackpot</value>
+  </data>
+  <data name="millions_no_winners" xml:space="preserve">
+    <value>Pas encore de gagnants</value>
+  </data>
+  <data name="millions_draw_information" xml:space="preserve">
+    <value>Informations sur le tirage</value>
+  </data>
+  <data name="millions_game_type" xml:space="preserve">
+    <value>Game Type</value>
+  </data>
+  <data name="millions_total_winners" xml:space="preserve">
+    <value>Total Winners</value>
+  </data>
+  <data name="millions_draw_date_time" xml:space="preserve">
+    <value>Date &amp; Heure du tirage</value>
+  </data>
+  <data name="millions_note" xml:space="preserve">
+    <value>Note</value>
+  </data>
+  <data name="millions_note_results_public" xml:space="preserve">
+    <value>Le résultat est annoncé publiquement et vérifié</value>
+  </data>
+  <data name="millions_note_thank_you" xml:space="preserve">
+    <value>Merci pour votre confiance et votre soutien</value>
+  </data>
+  <data name="millions_back_to_results_list" xml:space="preserve">
+    <value>Back to Results list</value>
+  </data>
 </root>

+ 11 - 0
website/Service/ApiFunctions.cs

@@ -134,6 +134,17 @@ namespace LotteryWebApp.Service
             return deptObj;
         }
 
+        public RpSearchDetailTicketResponse RpSearchDetailTicketApi(IConfiguration configuration, RpSearchDetailTicketRequest request)
+        {
+            request.serviceId = ApiConstants.SERVICE_ID;
+            request.channel = configuration.GetSection("channel").Value;
+
+            String url = configuration.GetSection("rp_search_detail_ticket").Value;
+            String jsonData = SendPost(request, ApiConstants.SERVICE_ID, url);
+            RpSearchDetailTicketResponse deptObj = JsonSerializer.Deserialize<RpSearchDetailTicketResponse>(jsonData);
+            return deptObj;
+        }
+
 
         public TransferMoneyResponse TransferMoneyApi(IConfiguration configuration, TransferMoneyRequest transferMoneyRequest)
         {

+ 36 - 0
website/Service/ApiModels.cs

@@ -142,6 +142,42 @@ namespace LotteryWebApp.Service
         public string responseMessage { get; set; }
     }
 
+    public class RpSearchDetailTicketRequest : Posting
+    {
+        public string requestId { get; set; }
+        public string msisdn { get; set; }
+        public string gameId { get; set; }
+        public string fromDate { get; set; }
+        public string toDate { get; set; }
+        public string prize { get; set; }
+        public string language { get; set; }
+        public string channel { get; set; }
+        public string token { get; set; }
+    }
+
+    public class JackpotWinnerItem
+    {
+        public string msisdn { get; set; }
+        public string ticketId { get; set; }
+        public string ticket { get; set; }
+        public string dateBuy { get; set; }
+        public string money { get; set; }
+        public string channelBuy { get; set; }
+        public string moneyWin { get; set; }
+        public string randomId { get; set; }
+        public string startDate { get; set; }
+        public string endDate { get; set; }
+        public string randomDate { get; set; }
+        public string result { get; set; }
+    }
+
+    public class RpSearchDetailTicketResponse
+    {
+        public string responseCode { get; set; }
+        public string responseMessage { get; set; }
+        public List<JackpotWinnerItem> list { get; set; }
+    }
+
     public class UserStatusRequest : Posting
     {
         public string users { get; set; }

+ 1 - 0
website/appsettings.json

@@ -22,6 +22,7 @@
   "user_update_profile": "http://171.244.50.177:8900/api/userApi/usersUpdateProfile/data",
   "user_pic_upload": "http://171.244.50.177:8900/api/userApi/usersPicUpload/data",
   "get_result_of_term": "http://171.244.50.177:8900/api/luckyGame/getResultOfTerm/data",
+  "rp_search_detail_ticket": "http://171.244.50.177:8900/api/loto/rpSearchDetailTicketEx/data",
   "get_user_status": "http://171.244.50.177:8900/api/userApi/usersCheckStatus/data",
   "transfer_money": "http://171.244.50.177:8900/api/loto/convertMoneyByUser/data",
   "get_transaction_info": "http://171.244.50.177:8900/api/loto/getListConvertByUser/data",

+ 246 - 0
website/wwwroot/Millions/css/jackpot.css

@@ -0,0 +1,246 @@
+/* ===== Jackpot pages (Results + Detail) ===== */
+
+/* Hide scrollbar on the scroll wrapper */
+.hide-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
+.hide-scrollbar::-webkit-scrollbar { display: none; width: 0; height: 0; }
+
+/* ===== Date range picker ===== */
+.date-range-toggle {
+    display: flex; align-items: center; gap: 12px;
+    width: 100%; height: 32px; padding: 0 12px;
+    background: #fff;
+    border: 1px solid #b9b9b9;
+    border-radius: 8px;
+    cursor: pointer;
+    transition: border-color .15s ease, box-shadow .15s ease;
+}
+.date-range-toggle:hover { border-color: #0062ff; }
+.date-range-toggle.open {
+    border-color: #0062ff;
+    box-shadow: 0 0 0 3px rgba(0, 98, 255, 0.12);
+}
+
+.date-range-panel {
+    position: absolute;
+    top: calc(100% + 6px); left: 0;
+    min-width: 280px;
+    background: #fff;
+    border-radius: 14px;
+    padding: 14px;
+    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18),
+                0 0 0 1px rgba(0, 98, 255, 0.08);
+    z-index: 50;
+    display: none;
+    /* Tint native date picker (Chrome/Edge/Safari) */
+    accent-color: #0062ff;
+    color-scheme: light;
+}
+.date-range-panel.open {
+    display: block;
+    animation: ddrFade .15s ease-out;
+}
+@keyframes ddrFade {
+    from { opacity: 0; transform: translateY(-4px); }
+    to   { opacity: 1; transform: translateY(0); }
+}
+
+.date-range-panel label {
+    display: block;
+    font-size: 11px; font-weight: 700;
+    color: #0062ff;
+    margin-bottom: 4px;
+    letter-spacing: .02em;
+    text-transform: uppercase;
+}
+.date-range-panel .row + .row { margin-top: 10px; }
+
+.date-input {
+    width: 100%;
+    font-size: 13px; font-weight: 600;
+    color: #1a1a1a;
+    background: #f5f7fb;
+    border: 1px solid #e1e5ee;
+    border-radius: 10px;
+    padding: 8px 10px;
+    outline: none;
+    transition: border-color .15s ease,
+                box-shadow .15s ease,
+                background-color .15s ease;
+    font-family: inherit;
+    accent-color: #0062ff;
+    color-scheme: light;
+}
+.date-input:hover { background: #fff; }
+.date-input:focus {
+    border-color: #0062ff;
+    background: #fff;
+    box-shadow: 0 0 0 3px rgba(0, 98, 255, 0.15);
+}
+.date-input::-webkit-calendar-picker-indicator {
+    cursor: pointer;
+    /* Tint the calendar icon to project blue */
+    filter: invert(28%) sepia(99%) saturate(2670%)
+            hue-rotate(213deg) brightness(99%) contrast(105%);
+    opacity: .85;
+}
+.date-input::-webkit-calendar-picker-indicator:hover { opacity: 1; }
+
+.date-range-actions {
+    display: flex; gap: 8px; margin-top: 12px;
+}
+.date-range-actions button {
+    flex: 1;
+    font-size: 12px; font-weight: 700;
+    padding: 8px 10px;
+    border-radius: 10px;
+    border: none; cursor: pointer;
+    transition: transform .05s ease, opacity .15s ease, background-color .15s ease;
+    font-family: inherit;
+}
+.date-range-actions .btn-apply {
+    background: linear-gradient(180deg, #1a75ff 0%, #0062ff 100%);
+    color: #fff;
+    box-shadow: 0 4px 10px rgba(0, 98, 255, 0.25);
+}
+.date-range-actions .btn-apply:hover { opacity: .94; }
+.date-range-actions .btn-cancel {
+    background: #f0f2f7;
+    color: #1a1a1a;
+}
+.date-range-actions .btn-cancel:hover { background: #e6e9f0; }
+.date-range-actions button:active { transform: scale(.98); }
+
+/* ===== Flatpickr theme override (blue project tone) ===== */
+.flatpickr-calendar {
+    border-radius: 14px !important;
+    box-shadow: 0 14px 36px rgba(0, 0, 0, 0.18),
+                0 0 0 1px rgba(0, 98, 255, 0.10) !important;
+    font-family: inherit !important;
+    padding: 6px !important;
+    background: #fff !important;
+    border: none !important;
+}
+.flatpickr-calendar::before,
+.flatpickr-calendar::after { display: none !important; }
+
+.flatpickr-months {
+    padding: 6px 4px 4px;
+    align-items: center;
+}
+.flatpickr-month {
+    color: #1a1a1a !important;
+    height: auto !important;
+    border-radius: 10px;
+}
+.flatpickr-current-month {
+    font-size: 14px !important;
+    font-weight: 700 !important;
+    padding: 4px 0 6px !important;
+    color: #1a1a1a !important;
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months {
+    font-weight: 700 !important;
+    color: #1a1a1a !important;
+    background: transparent !important;
+    border-radius: 6px;
+    padding: 2px 4px !important;
+}
+.flatpickr-current-month .flatpickr-monthDropdown-months:hover {
+    background: rgba(0, 98, 255, 0.08) !important;
+}
+.flatpickr-current-month input.cur-year {
+    font-weight: 700 !important;
+    color: #1a1a1a !important;
+}
+
+.flatpickr-prev-month,
+.flatpickr-next-month {
+    fill: #0062ff !important;
+    color: #0062ff !important;
+    padding: 8px !important;
+    border-radius: 8px;
+    transition: background-color .15s ease;
+}
+.flatpickr-prev-month:hover,
+.flatpickr-next-month:hover {
+    background: rgba(0, 98, 255, 0.10) !important;
+    fill: #0062ff !important;
+}
+.flatpickr-prev-month svg,
+.flatpickr-next-month svg {
+    fill: #0062ff !important;
+}
+
+.flatpickr-weekdays { background: transparent !important; }
+.flatpickr-weekday {
+    color: #8e8e93 !important;
+    font-weight: 700 !important;
+    font-size: 11px !important;
+    letter-spacing: .04em;
+    text-transform: uppercase;
+    background: transparent !important;
+}
+
+.flatpickr-days { padding: 4px 0; }
+.dayContainer { padding: 0 2px; }
+
+.flatpickr-day {
+    border-radius: 50% !important;
+    color: #1a1a1a !important;
+    font-weight: 500 !important;
+    font-size: 13px !important;
+    height: 36px !important;
+    line-height: 36px !important;
+    max-width: 36px !important;
+    transition: background-color .12s ease, color .12s ease, transform .05s ease;
+}
+.flatpickr-day:hover {
+    background: rgba(0, 98, 255, 0.10) !important;
+    border-color: transparent !important;
+    color: #0062ff !important;
+}
+.flatpickr-day.today {
+    border: 1.5px solid #0062ff !important;
+    color: #0062ff !important;
+    font-weight: 700 !important;
+}
+.flatpickr-day.today:hover { background: rgba(0, 98, 255, 0.10) !important; }
+
+.flatpickr-day.selected,
+.flatpickr-day.startRange,
+.flatpickr-day.endRange,
+.flatpickr-day.selected.inRange,
+.flatpickr-day.startRange.inRange,
+.flatpickr-day.endRange.inRange {
+    background: linear-gradient(180deg, #1a75ff 0%, #0062ff 100%) !important;
+    border-color: transparent !important;
+    color: #fff !important;
+    font-weight: 700 !important;
+    box-shadow: 0 4px 10px rgba(0, 98, 255, 0.30);
+}
+.flatpickr-day.selected:hover { color: #fff !important; }
+
+.flatpickr-day.inRange {
+    background: rgba(0, 98, 255, 0.10) !important;
+    border-color: transparent !important;
+    color: #0062ff !important;
+    box-shadow: none !important;
+}
+
+.flatpickr-day.flatpickr-disabled,
+.flatpickr-day.prevMonthDay,
+.flatpickr-day.nextMonthDay {
+    color: #c5c8d0 !important;
+}
+.flatpickr-day.flatpickr-disabled:hover { background: transparent !important; }
+
+.flatpickr-day:active { transform: scale(.95); }
+
+/* Center the calendar inside the dropdown panel */
+.date-range-panel .flatpickr-calendar {
+    position: relative !important;
+    top: auto !important;
+    left: auto !important;
+    margin: 8px auto 0;
+    width: 100% !important;
+}