}
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);
+ }
+}