From c8782e73e279e7b7e9e5c8f38c3cf7da0a7f23a7 Mon Sep 17 00:00:00 2001 From: Hamid Reza Mohammadi Date: Sun, 16 Aug 2026 17:40:26 +0330 Subject: [PATCH] tajik home page --- TajikGanjoor/Pages/Index.cshtml | 90 ++++++++++++++-------- TajikGanjoor/Pages/Index.cshtml.cs | 22 ++++++ TajikGanjoor/wwwroot/css/tajik-ganjoor.css | 32 ++++++++ TajikGanjoor/wwwroot/js/site.js | 24 ++++++ 4 files changed, 135 insertions(+), 33 deletions(-) diff --git a/TajikGanjoor/Pages/Index.cshtml b/TajikGanjoor/Pages/Index.cshtml index 77d35a28..1d4563ef 100644 --- a/TajikGanjoor/Pages/Index.cshtml +++ b/TajikGanjoor/Pages/Index.cshtml @@ -59,48 +59,25 @@ { var popularGroup = Model.PoetGroups.SingleOrDefault(g => g.Id == 0); var centuryGroups = Model.PoetGroups.Where(g => g.Id != 0).ToList(); - @if (popularGroup != null) - { -
Шоирони маъмул
-
- @foreach (var poet in popularGroup.Poets) - { - - - @poet.Nickname - - @poet.Nickname - - } -
- } - @if (centuryGroups.Count > 0) - { -
Гурӯҳбандӣ бар асоси аср
-
- @foreach (var g in centuryGroups) - { - @(g.HalfCenturyOrder + 2) - } -
+
+ + +
- @foreach (var century in centuryGroups) +
+ @if (popularGroup != null) { - @if (century.ShowInTimeLine) - { -
@century.Name
- } +
Шоирони маъмул
- @foreach (var poet in century.Poets) + @foreach (var poet in popularGroup.Poets) { - + @poet.Nickname @@ -110,7 +87,54 @@ }
} - } + + @if (centuryGroups.Count > 0) + { +
Гурӯҳбандӣ бар асоси аср
+
+ + @foreach (var century in centuryGroups) + { + @if (century.ShowInTimeLine) + { +
@century.Name
+ } +
+ @foreach (var poet in century.Poets) + { + + + @poet.Nickname + + @poet.Nickname + + } +
+ } + } +
+ + } else { diff --git a/TajikGanjoor/Pages/Index.cshtml.cs b/TajikGanjoor/Pages/Index.cshtml.cs index d2347fdd..af60c6cb 100644 --- a/TajikGanjoor/Pages/Index.cshtml.cs +++ b/TajikGanjoor/Pages/Index.cshtml.cs @@ -38,6 +38,13 @@ namespace TajikGanjoor.Pages /// poets grouped by century, shown on the home page - mirrors GanjooRazor's Index.cshtml.cs /// public List PoetGroups { get; set; } + + /// + /// all translated poets, sorted alphabetically by Tajik nickname - alternate flat view, + /// switched to on the home page instead of the century grouping + /// + public List AlphabeticalPoets { get; set; } + public async Task OnGetAsync() { if (bool.Parse(Configuration["MaintenanceMode"] ?? false.ToString())) @@ -58,6 +65,21 @@ namespace TajikGanjoor.Pages { return Page(); } + // plain ordinal sort gets this wrong: the six Tajik-specific letters + // (ғ ӣ қ ӯ ҳ ҷ) sit outside the main Cyrillic code point block, so they'd + // sort out of alphabetical order (e.g. after "я") under Ordinal - a + // culture-aware comparer places them correctly relative to their base + // letter (ғ after г, etc). Falls back to Ordinal if "tg-TJ" collation + // data isn't available on the server, rather than failing the page. + try + { + var tajikCulture = System.Globalization.CultureInfo.GetCultureInfo("tg-TJ"); + AlphabeticalPoets = Poets.OrderBy(p => p.Nickname, StringComparer.Create(tajikCulture, false)).ToList(); + } + catch (System.Globalization.CultureNotFoundException) + { + AlphabeticalPoets = Poets.OrderBy(p => p.Nickname, StringComparer.Ordinal).ToList(); + } } int pageNumber = 1; if (IsSearchPage) diff --git a/TajikGanjoor/wwwroot/css/tajik-ganjoor.css b/TajikGanjoor/wwwroot/css/tajik-ganjoor.css index f9ec9a82..139073a9 100644 --- a/TajikGanjoor/wwwroot/css/tajik-ganjoor.css +++ b/TajikGanjoor/wwwroot/css/tajik-ganjoor.css @@ -693,6 +693,38 @@ html, body { margin-top: 14px; } +/* century-grouped vs. alphabetical homepage view switch */ +.tg-view-switch { + display: flex; + justify-content: center; + gap: 8px; + max-width: 480px; + margin: 18px auto 0 auto; + padding: 0 8px; +} + +.tg-view-switch-btn { + font-family: 'PT Sans', sans-serif; + font-size: 0.9rem; + padding: 7px 16px; + border: 1px solid var(--tg-rule); + border-radius: 20px; + background: var(--tg-surface); + color: var(--tg-ink-soft); + cursor: pointer; +} + +.tg-view-switch-btn:hover { + border-color: var(--tg-accent); + color: var(--tg-accent-deep); +} + +.tg-view-switch-btn.active { + background: var(--tg-accent-deep); + border-color: var(--tg-accent-deep); + color: #fff; +} + /* ---------- error page ---------- */ .text-danger { diff --git a/TajikGanjoor/wwwroot/js/site.js b/TajikGanjoor/wwwroot/js/site.js index 3d0d6cb1..dbb53788 100644 --- a/TajikGanjoor/wwwroot/js/site.js +++ b/TajikGanjoor/wwwroot/js/site.js @@ -6,6 +6,10 @@ // clones the matches into the results container. No numeral conversion needed here (unlike the // Persian site, which converts typed digits to Persian-Indic numerals first) since Tajik Cyrillic // uses plain Western digits. +// +// A "popular" poet's card appears more than once in the page (once in the popular-poets section, +// again in their real century group, and again in the alphabetical listing) - deduped here by +// data-poet-id so a matching search doesn't show the same poet two or three times. function tgInlineSearch(value) { var resultsNode = document.getElementById('tg-found-poets'); if (!resultsNode) return; @@ -14,10 +18,30 @@ function tgInlineSearch(value) { var needle = value.toLowerCase(); var cards = document.querySelectorAll('.tg-poet-card[data-value]'); + var seenIds = {}; for (var i = 0; i < cards.length; i++) { + var poetId = cards[i].getAttribute('data-poet-id'); + if (poetId && seenIds[poetId]) continue; + var haystack = cards[i].getAttribute('data-value').toLowerCase(); if (haystack.indexOf(needle) !== -1) { resultsNode.appendChild(cards[i].cloneNode(true)); + if (poetId) seenIds[poetId] = true; } } } + +// Toggles the homepage between the century-grouped view and the flat alphabetical listing. +function tgSwitchView(view) { + var centuryView = document.getElementById('tg-view-century'); + var alphaView = document.getElementById('tg-view-alpha'); + if (!centuryView || !alphaView) return; + + centuryView.style.display = view === 'century' ? '' : 'none'; + alphaView.style.display = view === 'alpha' ? '' : 'none'; + + var buttons = document.querySelectorAll('.tg-view-switch-btn'); + for (var i = 0; i < buttons.length; i++) { + buttons[i].classList.toggle('active', buttons[i].getAttribute('data-view') === view); + } +}