diff --git a/src/components/DiscoverySearchToolbar.tsx b/src/components/DiscoverySearchToolbar.tsx index 0d47d4c9..07c3f90b 100644 --- a/src/components/DiscoverySearchToolbar.tsx +++ b/src/components/DiscoverySearchToolbar.tsx @@ -133,7 +133,14 @@ export function DiscoverySearchToolbar({ key={value} checked={sort === value} onCheckedChange={(checked) => { + // `checked === false` means the user clicked the + // currently-active item — return to the curated + // `default` view (featured-first) rather than leaving + // them stuck on Top/New with no exit affordance now + // that `default` is no longer an exposed option in the + // dropdown. if (checked) onSortChange(value); + else onSortChange('default'); }} // The checkbox slot on the left is hidden in favour of an // explicit `Check` on the right (matches the diff --git a/src/locales/ar.json b/src/locales/ar.json index 29d7685a..9eeeebe2 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -216,8 +216,8 @@ "myPledgesTagline": "التعهدات التي أنشأتها.", "featuredPledges": "تعهدات مميزة", "featuredPledgesTagline": "تعهدات يسلّط فريق {{appName}} الضوء عليها.", - "allPledges": "كل التعهدات", - "allPledgesTagline": "تصفّح كل تعهد على الشبكة.", + "allPledges": "التعهدات", + "allPledgesTagline": "مختارة من قِبل المشرفين. ابحث أو رتّب لتصفّح كل تعهد.", "sectionActive": "التعهدات النشطة", "sectionUpcoming": "التعهدات القادمة", "sectionPast": "التعهدات السابقة", @@ -347,8 +347,8 @@ "myGroupsTagline": "المجموعات التي أسستها أو تشرف عليها أو تتابعها.", "featuredGroups": "المجموعات المميزة", "featuredGroupsTagline": "مجموعات بارزة تستحق اهتمامك.", - "allGroups": "كل المجموعات", - "allGroupsTagline": "تصفّح المجموعات أو ابحث.", + "allGroups": "المجموعات", + "allGroupsTagline": "مختارة من قِبل المشرفين. ابحث أو رتّب لتصفّح كل مجموعة.", "loginToSeeTitle": "سجّل الدخول لرؤية مجموعاتك", "loginToSeeBody": "ستظهر هنا المجموعات التي أسستها أو التي تشرف عليها.", "noGroupsTitle": "لا توجد مجموعات بعد", @@ -704,10 +704,10 @@ "emptyHint": "كن أول من يبدأ حملة تمويل على {{appName}}. اروِ قصتك، اختر المستفيدين، وشارك الرابط." }, "all": { - "title": "كل الحملات", + "title": "الحملات", "seoTitle": "كل الحملات", "description": "تصفّح كل الحملات المنشورة على Agora.", - "sectionTagline": "تصفّح كل قضيّة على الشبكة.", + "sectionTagline": "مختارة من قِبل المشرفين. ابحث أو رتّب لتصفّح الشبكة بأكملها.", "heroKicker": "الحملات", "heroHeading": "كل قضيّة،", "heroHeadingLine2": "في مكان واحد.", diff --git a/src/locales/en.json b/src/locales/en.json index 0f74c846..d2932e16 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -644,8 +644,8 @@ "myPledgesTagline": "Pledges you've created.", "featuredPledges": "Featured pledges", "featuredPledgesTagline": "Pledges highlighted by the {{appName}} team.", - "allPledges": "All pledges", - "allPledgesTagline": "Browse every pledge on the network.", + "allPledges": "Pledges", + "allPledgesTagline": "Highlighted by moderators. Search or sort to browse every pledge.", "sectionActive": "Active pledges", "sectionUpcoming": "Upcoming pledges", "sectionPast": "Past pledges", @@ -779,8 +779,8 @@ "myGroupsTagline": "Groups you've founded, moderate, or follow.", "featuredGroups": "Featured groups", "featuredGroupsTagline": "Standout groups worth your attention.", - "allGroups": "All groups", - "allGroupsTagline": "Browse groups or search.", + "allGroups": "Groups", + "allGroupsTagline": "Highlighted by moderators. Search or sort to browse every group.", "searchPlaceholder": "Search groups\u2026", "searchAriaLabel": "Search groups", "noMatch": "No groups match \u201c{{query}}\u201d", @@ -1144,10 +1144,10 @@ "emptyHint": "Be the first to start a fundraiser on {{appName}}. Tell your story, choose your beneficiaries, and share the link." }, "all": { - "title": "All Campaigns", + "title": "Campaigns", "seoTitle": "All campaigns", "description": "Browse every campaign published on Agora.", - "sectionTagline": "Browse every cause on the network.", + "sectionTagline": "Highlighted by moderators. Search or sort to browse the full network.", "heroKicker": "Campaigns", "heroHeading": "Every cause,", "heroHeadingLine2": "in one place.", diff --git a/src/locales/es.json b/src/locales/es.json index d45fef47..1966cf8a 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -220,8 +220,8 @@ "myPledgesTagline": "Promesas que has creado.", "featuredPledges": "Promesas destacadas", "featuredPledgesTagline": "Promesas destacadas por el equipo de {{appName}}.", - "allPledges": "Todas las promesas", - "allPledgesTagline": "Explora todas las promesas de la red.", + "allPledges": "Promesas", + "allPledgesTagline": "Destacadas por los moderadores. Busca u ordena para explorar todas las promesas.", "sectionActive": "Promesas activas", "sectionUpcoming": "Promesas próximas", "sectionPast": "Promesas pasadas", @@ -355,8 +355,8 @@ "myGroupsTagline": "Grupos que fundaste, moderas o sigues.", "featuredGroups": "Grupos destacados", "featuredGroupsTagline": "Grupos destacados que merecen tu atención.", - "allGroups": "Todos los grupos", - "allGroupsTagline": "Explora grupos o busca.", + "allGroups": "Grupos", + "allGroupsTagline": "Destacados por los moderadores. Busca u ordena para explorar todos los grupos.", "loginToSeeTitle": "Inicia sesión para ver tus grupos", "loginToSeeBody": "Los grupos que fundaste o moderas aparecerán aquí.", "noGroupsTitle": "Aún no hay grupos", @@ -720,10 +720,10 @@ "noMatchHint": "Prueba con otro término de búsqueda o bórrala." }, "all": { - "title": "Todas las campañas", + "title": "Campañas", "seoTitle": "Todas las campañas", "description": "Explora todas las campañas publicadas en Agora.", - "sectionTagline": "Explora cada causa en la red.", + "sectionTagline": "Destacadas por los moderadores. Busca u ordena para explorar toda la red.", "heroKicker": "Campañas", "heroHeading": "Cada causa,", "heroHeadingLine2": "en un solo lugar.", diff --git a/src/locales/fa.json b/src/locales/fa.json index 75e593c5..9d12c314 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -220,8 +220,8 @@ "myPledgesTagline": "تعهدهایی که ایجاد کرده‌ای.", "featuredPledges": "تعهدهای ویژه", "featuredPledgesTagline": "تعهدهایی که تیم {{appName}} برجسته کرده است.", - "allPledges": "همهٔ تعهدها", - "allPledgesTagline": "همهٔ تعهدهای موجود در شبکه را مرور کن.", + "allPledges": "تعهدها", + "allPledgesTagline": "برگزیده‌ٔ ناظران. برای مرور همهٔ تعهدها جستجو یا مرتب‌سازی کن.", "sectionActive": "تعهدهای فعال", "sectionUpcoming": "تعهدهای پیش‌رو", "sectionPast": "تعهدهای گذشته", @@ -355,8 +355,8 @@ "myGroupsTagline": "گروه‌هایی که ساخته‌ای، مدیریت می‌کنی یا دنبال می‌کنی.", "featuredGroups": "گروه‌های ویژه", "featuredGroupsTagline": "گروه‌های برجسته‌ای که ارزش توجه تو را دارند.", - "allGroups": "همهٔ گروه‌ها", - "allGroupsTagline": "گروه‌ها را مرور کن یا جستجو کن.", + "allGroups": "گروه‌ها", + "allGroupsTagline": "برگزیده‌ٔ ناظران. برای مرور همهٔ گروه‌ها جستجو یا مرتب‌سازی کن.", "loginToSeeTitle": "برای دیدن گروه‌هایت وارد شو", "loginToSeeBody": "گروه‌هایی که ساخته‌ای یا مدیریت می‌کنی اینجا ظاهر می‌شوند.", "noGroupsTitle": "هنوز گروهی نیست", @@ -720,10 +720,10 @@ "noMatchHint": "عبارت جستجوی دیگری را امتحان کنید، یا جستجو را پاک کنید." }, "all": { - "title": "همه کمپین‌ها", + "title": "کمپین‌ها", "seoTitle": "همه کمپین‌ها", "description": "همه کمپین‌های منتشرشده در Agora را مرور کنید.", - "sectionTagline": "هر هدفی را در شبکه مرور کنید.", + "sectionTagline": "برگزیده‌ٔ ناظران. برای مرور کل شبکه جستجو یا مرتب‌سازی کن.", "heroKicker": "کمپین‌ها", "heroHeading": "هر هدف،", "heroHeadingLine2": "در یک جا.", diff --git a/src/locales/fr.json b/src/locales/fr.json index 68a33531..50b5c1fd 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -642,8 +642,8 @@ "myPledgesTagline": "Les promesses que vous avez créées.", "featuredPledges": "Promesses en vedette", "featuredPledgesTagline": "Promesses mises en avant par l'équipe {{appName}}.", - "allPledges": "Toutes les promesses", - "allPledgesTagline": "Parcourez toutes les promesses du réseau.", + "allPledges": "Promesses", + "allPledgesTagline": "Sélectionnées par les modérateurs. Recherchez ou triez pour parcourir toutes les promesses.", "sectionActive": "Promesses actives", "sectionUpcoming": "Promesses à venir", "sectionPast": "Promesses passées", @@ -777,8 +777,8 @@ "myGroupsTagline": "Les groupes que vous avez fondés, modérez ou suivez.", "featuredGroups": "Groupes mis en avant", "featuredGroupsTagline": "Des groupes remarquables qui méritent votre attention.", - "allGroups": "Tous les groupes", - "allGroupsTagline": "Parcourez les groupes ou recherchez.", + "allGroups": "Groupes", + "allGroupsTagline": "Sélectionnés par les modérateurs. Recherchez ou triez pour parcourir tous les groupes.", "loginToSeeTitle": "Connectez-vous pour voir vos groupes", "loginToSeeBody": "Les groupes que vous avez fondés ou modérés apparaîtront ici.", "noGroupsTitle": "Aucun groupe pour l'instant", @@ -1142,10 +1142,10 @@ "noMatchHint": "Essayez un autre terme de recherche, ou effacez la recherche." }, "all": { - "title": "Toutes les campagnes", + "title": "Campagnes", "seoTitle": "Toutes les campagnes", "description": "Parcourez toutes les campagnes publiées sur Agora.", - "sectionTagline": "Parcourez toutes les causes du réseau.", + "sectionTagline": "Sélectionnées par les modérateurs. Recherchez ou triez pour parcourir tout le réseau.", "heroKicker": "Campagnes", "heroHeading": "Chaque cause,", "heroHeadingLine2": "au même endroit.", diff --git a/src/locales/hi.json b/src/locales/hi.json index edaf17e6..1877ec6e 100644 --- a/src/locales/hi.json +++ b/src/locales/hi.json @@ -652,8 +652,8 @@ "myPledgesTagline": "आपके बनाए हुए प्लेज।", "featuredPledges": "विशेष प्लेज", "featuredPledgesTagline": "{{appName}} टीम द्वारा चुने गए प्लेज।", - "allPledges": "सभी प्लेज", - "allPledgesTagline": "नेटवर्क पर मौजूद हर प्लेज देखें।", + "allPledges": "प्लेज", + "allPledgesTagline": "मॉडरेटर द्वारा चयनित। हर प्लेज देखने के लिए खोजें या क्रमबद्ध करें।", "sectionActive": "सक्रिय प्लेज", "sectionUpcoming": "आने वाले प्लेज", "sectionPast": "पिछले प्लेज", @@ -787,8 +787,8 @@ "myGroupsTagline": "जिन ग्रुप को आपने बनाया, मॉडरेट किया, या फ़ॉलो किया है।", "featuredGroups": "फ़ीचर्ड ग्रुप", "featuredGroupsTagline": "आपके ध्यान के लायक ख़ास ग्रुप।", - "allGroups": "सभी ग्रुप", - "allGroupsTagline": "ग्रुप ब्राउज़ करें या खोजें।", + "allGroups": "ग्रुप", + "allGroupsTagline": "मॉडरेटर द्वारा चयनित। हर ग्रुप देखने के लिए खोजें या क्रमबद्ध करें।", "loginToSeeTitle": "अपने ग्रुप देखने के लिए लॉग इन करें", "loginToSeeBody": "आपने जो ग्रुप बनाए या मॉडरेट किए हैं वे यहाँ दिखेंगे।", "noGroupsTitle": "अभी कोई ग्रुप नहीं", @@ -1152,10 +1152,10 @@ "noMatchHint": "अलग खोज शब्द आज़माएँ, या खोज साफ़ करें।" }, "all": { - "title": "सभी कैंपेन", + "title": "कैंपेन", "seoTitle": "सभी कैंपेन", "description": "Agora पर पब्लिश हुए हर कैंपेन को देखें।", - "sectionTagline": "नेटवर्क पर हर मक़सद को देखें।", + "sectionTagline": "मॉडरेटर द्वारा चयनित। पूरे नेटवर्क को देखने के लिए खोजें या क्रमबद्ध करें।", "heroKicker": "कैंपेन", "heroHeading": "हर मक़सद,", "heroHeadingLine2": "एक ही जगह।", diff --git a/src/locales/id.json b/src/locales/id.json index a439b56f..2079bb2c 100644 --- a/src/locales/id.json +++ b/src/locales/id.json @@ -652,8 +652,8 @@ "myPledgesTagline": "Ikrar yang Anda buat.", "featuredPledges": "Ikrar pilihan", "featuredPledgesTagline": "Ikrar yang disorot oleh tim {{appName}}.", - "allPledges": "Semua ikrar", - "allPledgesTagline": "Jelajahi setiap ikrar di jaringan.", + "allPledges": "Ikrar", + "allPledgesTagline": "Disorot oleh moderator. Cari atau urutkan untuk menjelajahi setiap ikrar.", "sectionActive": "Ikrar aktif", "sectionUpcoming": "Ikrar mendatang", "sectionPast": "Ikrar lampau", @@ -787,8 +787,8 @@ "myGroupsTagline": "Grup yang Anda dirikan, moderasi, atau ikuti.", "featuredGroups": "Grup unggulan", "featuredGroupsTagline": "Grup menonjol yang layak Anda perhatikan.", - "allGroups": "Semua grup", - "allGroupsTagline": "Jelajahi grup atau cari.", + "allGroups": "Grup", + "allGroupsTagline": "Disorot oleh moderator. Cari atau urutkan untuk menjelajahi setiap grup.", "loginToSeeTitle": "Masuk untuk melihat grup Anda", "loginToSeeBody": "Grup yang Anda dirikan atau moderasi akan muncul di sini.", "noGroupsTitle": "Belum ada grup", @@ -1152,10 +1152,10 @@ "noMatchHint": "Coba kata pencarian lain, atau bersihkan pencarian." }, "all": { - "title": "Semua Kampanye", + "title": "Kampanye", "seoTitle": "Semua kampanye", "description": "Telusuri setiap kampanye yang dipublikasikan di Agora.", - "sectionTagline": "Jelajahi setiap aksi di jaringan.", + "sectionTagline": "Disorot oleh moderator. Cari atau urutkan untuk menjelajahi seluruh jaringan.", "heroKicker": "Kampanye", "heroHeading": "Setiap aksi,", "heroHeadingLine2": "dalam satu tempat.", diff --git a/src/locales/km.json b/src/locales/km.json index 7c4ddb93..8ea9366d 100644 --- a/src/locales/km.json +++ b/src/locales/km.json @@ -220,8 +220,8 @@ "myPledgesTagline": "ការសន្យាដែលអ្នកបានបង្កើត។", "featuredPledges": "ការសន្យាលេចធ្លោ", "featuredPledgesTagline": "ការសន្យាដែលត្រូវបានរំលេចដោយក្រុម {{appName}}។", - "allPledges": "ការសន្យាទាំងអស់", - "allPledgesTagline": "រកមើលការសន្យាគ្រប់ៗមួយនៅលើបណ្ដាញ។", + "allPledges": "ការសន្យា", + "allPledgesTagline": "រំលេចដោយអ្នកសម្របសម្រួល។ ស្វែងរក ឬតម្រៀបដើម្បីរកមើលការសន្យាគ្រប់ៗមួយ។", "sectionActive": "ការសន្យាសកម្ម", "sectionUpcoming": "ការសន្យាខាងមុខ", "sectionPast": "ការសន្យាកន្លងមក", @@ -355,8 +355,8 @@ "myGroupsTagline": "ក្រុមដែលអ្នកបានបង្កើត គ្រប់គ្រង ឬដាក់តាមដាន។", "featuredGroups": "ក្រុមលេចធ្លោ", "featuredGroupsTagline": "ក្រុមលេចធ្លោដែលសក្តិសមនឹងការយកចិត្តទុកដាក់របស់អ្នក។", - "allGroups": "ក្រុមទាំងអស់", - "allGroupsTagline": "រកមើលក្រុម ឬស្វែងរក។", + "allGroups": "ក្រុម", + "allGroupsTagline": "រំលេចដោយអ្នកសម្របសម្រួល។ ស្វែងរក ឬតម្រៀបដើម្បីរកមើលក្រុមគ្រប់ៗមួយ។", "loginToSeeTitle": "ចូលដើម្បីមើលក្រុមរបស់អ្នក", "loginToSeeBody": "ក្រុមដែលអ្នកបានបង្កើត ឬគ្រប់គ្រងនឹងបង្ហាញនៅទីនេះ។", "noGroupsTitle": "មិនទាន់មានក្រុមទេ", @@ -720,10 +720,10 @@ "noMatchHint": "សាកល្បងពាក្យស្វែងរកផ្សេង ឬសម្អាតការស្វែងរក។" }, "all": { - "title": "យុទ្ធនាការទាំងអស់", + "title": "យុទ្ធនាការ", "seoTitle": "យុទ្ធនាការទាំងអស់", "description": "រកមើលរាល់យុទ្ធនាការដែលផ្សព្វផ្សាយលើ Agora។", - "sectionTagline": "រកមើលរាល់បុព្វហេតុនៅលើបណ្ដាញ។", + "sectionTagline": "រំលេចដោយអ្នកសម្របសម្រួល។ ស្វែងរក ឬតម្រៀបដើម្បីរកមើលបណ្ដាញទាំងមូល។", "heroKicker": "យុទ្ធនាការ", "heroHeading": "រាល់បុព្វហេតុ", "heroHeadingLine2": "នៅកន្លែងតែមួយ។", diff --git a/src/locales/ps.json b/src/locales/ps.json index 802841f2..3581a33f 100644 --- a/src/locales/ps.json +++ b/src/locales/ps.json @@ -220,8 +220,8 @@ "myPledgesTagline": "هغه ژمنې چې تاسو جوړې کړې دي.", "featuredPledges": "ځانګړې ژمنې", "featuredPledgesTagline": "هغه ژمنې چې د {{appName}} ټیم په ګوته کړې دي.", - "allPledges": "ټولې ژمنې", - "allPledgesTagline": "په شبکه کې هره ژمنه وګورئ.", + "allPledges": "ژمنې", + "allPledgesTagline": "د څارونکو لخوا ځانګړې شوې. د ټولو ژمنو لیدلو لپاره لټون یا ترتیب وکړئ.", "sectionActive": "فعالې ژمنې", "sectionUpcoming": "راتلونکې ژمنې", "sectionPast": "تېرې ژمنې", @@ -355,8 +355,8 @@ "myGroupsTagline": "هغه ډلې چې تاسو یې جوړې کړي، اداره کوئ، یا یې تعقیبوئ.", "featuredGroups": "ځانګړې ډلې", "featuredGroupsTagline": "ځانګړې ډلې چې ستاسو د پاملرنې وړ دي.", - "allGroups": "ټولې ډلې", - "allGroupsTagline": "ډلې وڅیړئ یا لټون وکړئ.", + "allGroups": "ډلې", + "allGroupsTagline": "د څارونکو لخوا ځانګړې شوې. د ټولو ډلو لیدلو لپاره لټون یا ترتیب وکړئ.", "loginToSeeTitle": "د خپلو ډلو لیدلو لپاره ننوځئ", "loginToSeeBody": "هغه ډلې چې تاسو یې جوړې کړي یا یې اداره کوئ به دلته راڅرګندې شي.", "noGroupsTitle": "تر اوسه ډلې نشته", @@ -726,10 +726,10 @@ "heroBody": "په Nostr کې خپور شوی هر د مرستو راټولولو کمپاین په یوه ځای کې راټول شوی. د بشپړې شبکې لټون وکړئ، هغه هدف ومومئ چې درته اهمیت لري، او په مستقیم ډول یې د بټکوین له لارې ملاتړ وکړئ.", "campaignsCount_one": "په شبکه کې کمپاین", "campaignsCount_other": "په شبکه کې کمپاینونه", - "title": "ټول کمپاینونه", + "title": "کمپاینونه", "seoTitle": "ټول کمپاینونه", "description": "په Agora کې خپور شوي ټول کمپاینونه وګورئ.", - "sectionTagline": "په شبکه کې هر هدف وپلټئ.", + "sectionTagline": "د څارونکو لخوا ځانګړي شوي. د ټولې شبکې لیدلو لپاره لټون یا ترتیب وکړئ.", "searchAriaLabel": "د کمپاینونو لټون", "searchPlaceholder": "د کمپاینونو لټون…", "clearSearch": "د لټون پاکول", diff --git a/src/locales/pt.json b/src/locales/pt.json index 3705cee7..3d230be5 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -652,8 +652,8 @@ "myPledgesTagline": "Promessas que você criou.", "featuredPledges": "Promessas em destaque", "featuredPledgesTagline": "Promessas destacadas pela equipe do {{appName}}.", - "allPledges": "Todas as promessas", - "allPledgesTagline": "Explore todas as promessas da rede.", + "allPledges": "Promessas", + "allPledgesTagline": "Destacadas pelos moderadores. Pesquise ou ordene para explorar todas as promessas.", "sectionActive": "Promessas ativas", "sectionUpcoming": "Promessas futuras", "sectionPast": "Promessas passadas", @@ -787,8 +787,8 @@ "myGroupsTagline": "Grupos que você fundou, modera ou segue.", "featuredGroups": "Grupos em destaque", "featuredGroupsTagline": "Grupos que se destacam e merecem sua atenção.", - "allGroups": "Todos os grupos", - "allGroupsTagline": "Explore os grupos ou pesquise.", + "allGroups": "Grupos", + "allGroupsTagline": "Destacados pelos moderadores. Pesquise ou ordene para explorar todos os grupos.", "loginToSeeTitle": "Entre para ver seus grupos", "loginToSeeBody": "Grupos que você fundou ou modera aparecerão aqui.", "noGroupsTitle": "Nenhum grupo ainda", @@ -1152,10 +1152,10 @@ "noMatchHint": "Tente um termo de pesquisa diferente, ou limpe a pesquisa." }, "all": { - "title": "Todas as campanhas", + "title": "Campanhas", "seoTitle": "Todas as campanhas", "description": "Navegue por todas as campanhas publicadas no Agora.", - "sectionTagline": "Conheça todas as causas da rede.", + "sectionTagline": "Destacadas pelos moderadores. Pesquise ou ordene para explorar toda a rede.", "heroKicker": "Campanhas", "heroHeading": "Cada causa,", "heroHeadingLine2": "em um só lugar.", diff --git a/src/locales/ru.json b/src/locales/ru.json index 0b2586b0..03d3d1b4 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -652,8 +652,8 @@ "myPledgesTagline": "Обещания, которые вы создали.", "featuredPledges": "Избранные обещания", "featuredPledgesTagline": "Обещания, отмеченные командой {{appName}}.", - "allPledges": "Все обещания", - "allPledgesTagline": "Просматривайте все обещания в сети.", + "allPledges": "Обещания", + "allPledgesTagline": "Отмечено модераторами. Используйте поиск или сортировку, чтобы просмотреть все обещания.", "sectionActive": "Активные обещания", "sectionUpcoming": "Предстоящие обещания", "sectionPast": "Прошлые обещания", @@ -787,8 +787,8 @@ "myGroupsTagline": "Группы, которые вы основали, модерируете или на которые подписаны.", "featuredGroups": "Избранные группы", "featuredGroupsTagline": "Заметные группы, достойные вашего внимания.", - "allGroups": "Все группы", - "allGroupsTagline": "Просматривайте группы или ищите.", + "allGroups": "Группы", + "allGroupsTagline": "Отмечено модераторами. Используйте поиск или сортировку, чтобы просмотреть все группы.", "loginToSeeTitle": "Войдите, чтобы увидеть свои группы", "loginToSeeBody": "Группы, которые вы основали или модерируете, появятся здесь.", "noGroupsTitle": "Пока нет групп", @@ -1152,10 +1152,10 @@ "noMatchHint": "Попробуйте другой поисковый запрос или очистите поиск." }, "all": { - "title": "Все кампании", + "title": "Кампании", "seoTitle": "Все кампании", "description": "Просмотрите все кампании, опубликованные на Agora.", - "sectionTagline": "Просмотрите каждое дело в сети.", + "sectionTagline": "Отмечено модераторами. Используйте поиск или сортировку, чтобы просмотреть всю сеть.", "heroKicker": "Кампании", "heroHeading": "Каждое дело —", "heroHeadingLine2": "в одном месте.", diff --git a/src/locales/sn.json b/src/locales/sn.json index 9c1e1ab7..bcfd48e5 100644 --- a/src/locales/sn.json +++ b/src/locales/sn.json @@ -220,8 +220,8 @@ "myPledgesTagline": "Zvitsidziro zvawakagadzira.", "featuredPledges": "Zvitsidziro zvakasarudzwa", "featuredPledgesTagline": "Zvitsidziro zvakasimudzirwa nechikwata che{{appName}}.", - "allPledges": "Zvitsidziro zvose", - "allPledgesTagline": "Tarisa chitsidziro chega chega chiri pamutambo wenetiweki.", + "allPledges": "Zvitsidziro", + "allPledgesTagline": "Zvakatarisirwa nevatariri. Tsvaga kana kuronga kuti utarise chitsidziro chega chega.", "sectionActive": "Zvitsidziro zviri kushanda", "sectionUpcoming": "Zvitsidziro zviri kuuya", "sectionPast": "Zvitsidziro zvapfuura", @@ -355,8 +355,8 @@ "myGroupsTagline": "Mapoka awakatanga, aunotungamira, kana aunotevera.", "featuredGroups": "Mapoka anokurumbira", "featuredGroupsTagline": "Mapoka anobudirira anokodzera kutariswa nemi.", - "allGroups": "Mapoka ose", - "allGroupsTagline": "Tarisa mapoka kana kutsvaga.", + "allGroups": "Mapoka", + "allGroupsTagline": "Zvakatarisirwa nevatariri. Tsvaga kana kuronga kuti utarise boka rega rega.", "loginToSeeTitle": "Pinda kuti uone mapoka ako", "loginToSeeBody": "Mapoka awakatanga kana aunotungamira achaonekwa pano.", "noGroupsTitle": "Hapana mapoka parizvino", @@ -720,10 +720,10 @@ "noMatchHint": "Edza chimwe chinotsvagwa, kana ubvise kutsvaga." }, "all": { - "title": "Mishandirapamwe Yose", + "title": "Mishandirapamwe", "seoTitle": "Mishandirapamwe yose", "description": "Tarisa mishandirapamwe yose yakaiswa paAgora.", - "sectionTagline": "Tarisa chinangwa chimwe nechimwe panetwork.", + "sectionTagline": "Zvakatarisirwa nevatariri. Tsvaga kana kuronga kuti utarise netiweki yose.", "heroKicker": "Mishandirapamwe", "heroHeading": "Chinangwa chimwe nechimwe,", "heroHeadingLine2": "panzvimbo imwe chete.", diff --git a/src/locales/sw.json b/src/locales/sw.json index 3c71bc27..490cfa64 100644 --- a/src/locales/sw.json +++ b/src/locales/sw.json @@ -651,8 +651,8 @@ "myPledgesTagline": "Ahadi ulizounda.", "featuredPledges": "Ahadi maalum", "featuredPledgesTagline": "Ahadi zilizoangaziwa na timu ya {{appName}}.", - "allPledges": "Ahadi zote", - "allPledgesTagline": "Vinjari kila ahadi kwenye mtandao.", + "allPledges": "Ahadi", + "allPledgesTagline": "Zimeangaziwa na wasimamizi. Tafuta au panga ili kuvinjari kila ahadi.", "sectionActive": "Ahadi zinazoendelea", "sectionUpcoming": "Ahadi zijazo", "sectionPast": "Ahadi zilizopita", @@ -786,8 +786,8 @@ "myGroupsTagline": "Vikundi ulivyounda, unavyosimamia, au unavyofuata.", "featuredGroups": "Vikundi maarufu", "featuredGroupsTagline": "Vikundi vinavyojitokeza vinavyostahili usikivu wako.", - "allGroups": "Vikundi vyote", - "allGroupsTagline": "Vinjari vikundi au tafuta.", + "allGroups": "Vikundi", + "allGroupsTagline": "Vimeangaziwa na wasimamizi. Tafuta au panga ili kuvinjari kila kikundi.", "loginToSeeTitle": "Ingia ili kuona vikundi vyako", "loginToSeeBody": "Vikundi ulivyounda au unavyosimamia vitaonekana hapa.", "noGroupsTitle": "Hakuna vikundi bado", @@ -1151,10 +1151,10 @@ "noMatchHint": "Jaribu neno tofauti la utafutaji, au futa utafutaji." }, "all": { - "title": "Kampeni Zote", + "title": "Kampeni", "seoTitle": "Kampeni zote", "description": "Vinjari kila kampeni iliyochapishwa kwenye Agora.", - "sectionTagline": "Vinjari kila lengo kwenye mtandao.", + "sectionTagline": "Zimeangaziwa na wasimamizi. Tafuta au panga ili kuvinjari mtandao mzima.", "searchAriaLabel": "Tafuta kampeni", "searchPlaceholder": "Tafuta kampeni…", "clearSearch": "Futa utafutaji", diff --git a/src/locales/tr.json b/src/locales/tr.json index e4be9272..ad4d573d 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -651,8 +651,8 @@ "myPledgesTagline": "Oluşturduğunuz taahhütler.", "featuredPledges": "Öne çıkan taahhütler", "featuredPledgesTagline": "{{appName}} ekibinin öne çıkardığı taahhütler.", - "allPledges": "Tüm taahhütler", - "allPledgesTagline": "Ağdaki her taahhüde göz atın.", + "allPledges": "Taahhütler", + "allPledgesTagline": "Moderatörler tarafından öne çıkarıldı. Her taahhüde göz atmak için arama yapın veya sıralayın.", "sectionActive": "Aktif taahhütler", "sectionUpcoming": "Yaklaşan taahhütler", "sectionPast": "Geçmiş taahhütler", @@ -786,8 +786,8 @@ "myGroupsTagline": "Kurduğunuz, yönettiğiniz veya takip ettiğiniz gruplar.", "featuredGroups": "Öne çıkan gruplar", "featuredGroupsTagline": "Dikkatinize değer öne çıkan gruplar.", - "allGroups": "Tüm gruplar", - "allGroupsTagline": "Gruplara göz atın veya arama yapın.", + "allGroups": "Gruplar", + "allGroupsTagline": "Moderatörler tarafından öne çıkarıldı. Her gruba göz atmak için arama yapın veya sıralayın.", "loginToSeeTitle": "Gruplarınızı görmek için giriş yapın", "loginToSeeBody": "Kurduğunuz veya yönettiğiniz gruplar burada görünecek.", "noGroupsTitle": "Henüz grup yok", @@ -1151,10 +1151,10 @@ "noMatchHint": "Farklı bir arama terimi deneyin ya da aramayı temizleyin." }, "all": { - "title": "Tüm Kampanyalar", + "title": "Kampanyalar", "seoTitle": "Tüm kampanyalar", "description": "Agora'da yayımlanmış her kampanyaya göz atın.", - "sectionTagline": "Ağdaki her davaya göz atın.", + "sectionTagline": "Moderatörler tarafından öne çıkarıldı. Ağın tamamına göz atmak için arama yapın veya sıralayın.", "searchAriaLabel": "Kampanyaları ara", "searchPlaceholder": "Kampanya ara…", "clearSearch": "Aramayı temizle", diff --git a/src/locales/zh-Hant.json b/src/locales/zh-Hant.json index 6ea3e6dd..8d9e9d9c 100644 --- a/src/locales/zh-Hant.json +++ b/src/locales/zh-Hant.json @@ -220,8 +220,8 @@ "myPledgesTagline": "你建立的懸賞。", "featuredPledges": "精選懸賞", "featuredPledgesTagline": "{{appName}} 團隊重點推薦的懸賞。", - "allPledges": "全部懸賞", - "allPledgesTagline": "瀏覽網路上的每一個懸賞。", + "allPledges": "懸賞", + "allPledgesTagline": "由版主重點推薦。搜尋或排序以瀏覽所有懸賞。", "sectionActive": "進行中的懸賞", "sectionUpcoming": "即將開始的懸賞", "sectionPast": "已結束的懸賞", @@ -355,8 +355,8 @@ "myGroupsTagline": "你建立、管理或追蹤的群組。", "featuredGroups": "精選群組", "featuredGroupsTagline": "值得你關注的出色群組。", - "allGroups": "全部群組", - "allGroupsTagline": "瀏覽群組或搜尋。", + "allGroups": "群組", + "allGroupsTagline": "由版主重點推薦。搜尋或排序以瀏覽所有群組。", "loginToSeeTitle": "登入以檢視你的群組", "loginToSeeBody": "你建立或管理的群組會顯示在這裡。", "noGroupsTitle": "還沒有群組", @@ -720,10 +720,10 @@ "noMatchHint": "請嘗試不同的搜尋字詞,或清除搜尋。" }, "all": { - "title": "所有活動", + "title": "活動", "seoTitle": "所有活動", "description": "瀏覽 Agora 上釋出的所有活動。", - "sectionTagline": "瀏覽網路上的每一項事業。", + "sectionTagline": "由版主重點推薦。搜尋或排序以瀏覽整個網路。", "heroKicker": "活動", "heroHeading": "每一份心意,", "heroHeadingLine2": "匯聚於此。", diff --git a/src/locales/zh.json b/src/locales/zh.json index 3794e5f5..db6b35c7 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -220,8 +220,8 @@ "myPledgesTagline": "你创建的悬赏。", "featuredPledges": "精选悬赏", "featuredPledgesTagline": "{{appName}} 团队重点推荐的悬赏。", - "allPledges": "全部悬赏", - "allPledgesTagline": "浏览网络上的每一个悬赏。", + "allPledges": "悬赏", + "allPledgesTagline": "由版主精选推荐。可搜索或排序以浏览全部悬赏。", "sectionActive": "进行中的悬赏", "sectionUpcoming": "即将开始的悬赏", "sectionPast": "已结束的悬赏", @@ -355,8 +355,8 @@ "myGroupsTagline": "你创建、管理或关注的群组。", "featuredGroups": "精选群组", "featuredGroupsTagline": "值得你关注的出色群组。", - "allGroups": "全部群组", - "allGroupsTagline": "浏览群组或搜索。", + "allGroups": "群组", + "allGroupsTagline": "由版主精选推荐。可搜索或排序以浏览全部群组。", "loginToSeeTitle": "登录以查看你的群组", "loginToSeeBody": "你创建或管理的群组会显示在这里。", "noGroupsTitle": "还没有群组", @@ -720,10 +720,10 @@ "noMatchHint": "尝试其他搜索词,或清除搜索。" }, "all": { - "title": "所有活动", + "title": "活动", "seoTitle": "所有活动", "description": "浏览 Agora 上发布的所有活动。", - "sectionTagline": "浏览网络上的每一项事业。", + "sectionTagline": "由版主精选推荐。可搜索或排序以浏览整个网络。", "heroKicker": "活动", "heroHeading": "每一个理念,", "heroHeadingLine2": "汇聚于此。", diff --git a/src/pages/ActionsPage.tsx b/src/pages/ActionsPage.tsx index be5534ba..18d1c60c 100644 --- a/src/pages/ActionsPage.tsx +++ b/src/pages/ActionsPage.tsx @@ -36,7 +36,7 @@ import { import { HandHeart, PlusCircle, ChevronDown, ChevronUp, Loader2, Link as LinkIcon, Check, MoreHorizontal, Trash2, - Megaphone, Sparkles, EyeOff, + Megaphone, EyeOff, } from 'lucide-react'; // ───────────────────────────────────────────────────────────────────────────── @@ -323,6 +323,10 @@ export default function ActionsPage() { return { searchHits: visible, searchHiddenCount: hidden }; }, [searchHitsRaw, pledgeModeration, canShowHidden]); + // `actions` is the chronological pledge list filtered by country, with + // moderator-hidden items dropped (unless `showHidden` is on). Featured + // pledges are NOT excluded here — the idle render path pulls them + // separately, and the active render path shows the full list. const { actions, listHiddenCount } = useMemo(() => { if (!rawActions) return { actions: undefined, listHiddenCount: 0 }; const hiddenCoords = pledgeModeration?.hiddenCoords ?? new Set(); @@ -365,16 +369,18 @@ export default function ActionsPage() { const DEFAULT_VISIBLE = 4; const [showAllMine, setShowAllMine] = useState(false); - const [showAllFeatured, setShowAllFeatured] = useState(false); - const [showAllPledges, setShowAllPledges] = useState(false); - const allPledges = useMemo( - () => (actions ?? []).filter((action) => !featuredPledgeCoordSet.has(getPledgeCoord(action))), - [actions, featuredPledgeCoordSet], - ); const visibleMine = showAllMine ? (myPledges ?? []) : (myPledges ?? []).slice(0, DEFAULT_VISIBLE); - const visibleFeatured = showAllFeatured ? orderedFeaturedPledges : orderedFeaturedPledges.slice(0, DEFAULT_VISIBLE); - const visibleAllPledges = showAllPledges ? allPledges : allPledges.slice(0, DEFAULT_VISIBLE); + + // Idle list: featured first; if none are featured, fall back to the + // chronological all-pledges grid so the page is never blank. + const idlePledges = useMemo(() => { + if (orderedFeaturedPledges.length > 0) return orderedFeaturedPledges; + return (actions ?? []).filter( + (action) => !featuredPledgeCoordSet.has(getPledgeCoord(action)), + ); + }, [orderedFeaturedPledges, actions, featuredPledgeCoordSet]); + const hiddenPledges = useMemo(() => { if (!isMod || !pledgeModerationReady) return []; return (allPledgesForMods ?? []).filter((pledge) => pledgeModeration.hiddenCoords.has(getPledgeCoord(pledge))); @@ -386,6 +392,7 @@ export default function ActionsPage() { onQueryChange={setSearchInput} sort={sortMode} onSortChange={setSortMode} + sortOptions={['top', 'new']} searchPlaceholderKey="pledges.list.searchPlaceholder" searchAriaLabelKey="pledges.list.searchAriaLabel" showHidden={isMod ? { @@ -424,37 +431,18 @@ export default function ActionsPage() { )} - {orderedFeaturedPledges.length > 0 && ( -
-
-

- - {t('pledges.list.featuredPledges')} -

-

{t('pledges.list.featuredPledgesTagline')}

-
- setShowAllFeatured(!showAllFeatured)} - btcPrice={btcPrice} - /> -
- )} - + {/* Unified Pledges section. + - Idle (no search / no sort / no country): renders the + moderator-featured grid, or a chronological fallback when + no pledges are featured yet. + - Active: renders the full search/sort/country result set. */}

{trimmedSearch ? t('common.search') - : isSearching && sortMode === 'top' - ? t('common.sortTop') - : isSearching && sortMode === 'new' - ? t('common.sortNew') - : t('pledges.list.allPledges')} + : t('pledges.list.allPledges')}

{isSearching && searchHits @@ -521,15 +509,31 @@ export default function ActionsPage() {

{Array.from({ length: 8 }).map((_, i) => )}
- ) : allPledges.length > 0 ? ( - setShowAllPledges(!showAllPledges)} - btcPrice={btcPrice} - /> + ) : idlePledges.length > 0 ? ( +
+ {idlePledges.map((action) => ( + + + + + } + /> + ))} +
) : (
diff --git a/src/pages/AllCampaignsPage.tsx b/src/pages/AllCampaignsPage.tsx index 5e5e55cc..acb903a5 100644 --- a/src/pages/AllCampaignsPage.tsx +++ b/src/pages/AllCampaignsPage.tsx @@ -23,38 +23,47 @@ import { cn } from '@/lib/utils'; import type { Nip50Sort } from '@/hooks/useNip50Search'; import type { ParsedCampaign } from '@/lib/campaign'; -/** Type-guard for the `?sort=` URL param. Default is `top` (most-zapped). */ -function parseSort(value: string | null): CampaignSort { - return value === 'none' ? 'none' : 'top'; +/** + * Type-guard for the `?sort=` URL param. + * + * - `top` and `new` map to the toolbar's active sort modes. + * - Anything else (missing, empty, legacy values) collapses to + * `'default'`, the curated featured-first idle state. + */ +function parseSort(value: string | null): Nip50Sort { + if (value === 'top') return 'top'; + if (value === 'new') return 'new'; + return 'default'; } /** - * Map between the shared toolbar's sort vocabulary (`default` / `top` / - * `new`) and the `useAllCampaigns` hook's vocabulary (`top` / `none`). - * - * AllCampaignsPage doesn't have a curated/default layout — it's the - * "show me everything" page — so the toolbar's 'default' option falls - * through to 'top' here, the page's canonical ranked view. The legacy - * `none` value is preserved on the URL so existing share links keep - * working. + * Map the toolbar's sort vocabulary (`default` / `top` / `new`) to the + * `useAllCampaigns` hook's vocabulary (`top` / `none`). `'new'` and + * `'default'` both map to `'none'` (chronological) — the page handles + * the "show featured only" framing on top of that. */ -const toToolbarSort = (s: CampaignSort): Nip50Sort => (s === 'none' ? 'new' : 'top'); -const toQuerySort = (s: Nip50Sort): CampaignSort => (s === 'new' ? 'none' : 'top'); +const toQuerySort = (s: Nip50Sort): CampaignSort => (s === 'top' ? 'top' : 'none'); /** - * Lists every campaign found on relays. Two sort modes: + * Lists every campaign found on relays. The page has two display modes: * - * - **Top** (default): ranked by total sats raised (kind 8333 donation receipts). - * - **New**: chronological by `created_at`. + * 1. **Idle** (no search, no sort, no country picked) — shows + * moderator-featured campaigns only. If there are no featured + * campaigns, falls back to the latest chronological grid so the page + * is never blank. + * 2. **Active** (user typed a query, picked Top/New, or chose a + * country) — shows the full set, ranked by sats raised (Top) or + * chronological (New / search default). * - * Both modes share a free-text search bar that filters across title, - * summary, story, location, and category tags client-side. + * Search filters across title, summary, story, location, and category + * tags client-side. * * Hidden campaigns are excluded by default — flip the "Show hidden" * toggle (inside the toolbar's filter popover) to include them. * - * URL state: `?sort=none&q=`. Default values are stripped so the - * canonical URL stays clean. Useful for sharing search results. + * URL state: `?sort=top|new&q=&country=`. Default values + * are stripped so the canonical URL stays clean. Useful for sharing + * search results. */ export function AllCampaignsPage() { const { t } = useTranslation(); @@ -79,7 +88,7 @@ export function AllCampaignsPage() { // Sync the debounced search → URL. Empty / default values are stripped // so the canonical URL is `/campaigns/all` (not - // `/campaigns/all?sort=none&q=`). + // `/campaigns/all?sort=&q=`). useEffect(() => { const next = new URLSearchParams(searchParams); const trimmed = debouncedSearch.trim(); @@ -102,8 +111,8 @@ export function AllCampaignsPage() { const setSortFromToolbar = (value: Nip50Sort) => { const next = new URLSearchParams(searchParams); - const queryValue = toQuerySort(value); - if (queryValue === 'none') next.set('sort', 'none'); + if (value === 'top') next.set('sort', 'top'); + else if (value === 'new') next.set('sort', 'new'); else next.delete('sort'); setSearchParams(next, { replace: true }); }; @@ -118,7 +127,7 @@ export function AllCampaignsPage() { }; const { data: campaigns, isLoading } = useAllCampaigns({ - sort, + sort: toQuerySort(sort), search: debouncedSearch.trim(), countryCode: urlCountry, limit: 200, @@ -148,10 +157,21 @@ export function AllCampaignsPage() { description: t('campaigns.all.description'), }); + const activeQuery = debouncedSearch.trim(); + + // The unified section is in "active" mode when the user has expressed + // intent to browse the full set: typed a query, picked Top/New, or + // chosen a country. Otherwise it's the curated featured-first view. + const isActive = activeQuery !== '' || sort !== 'default' || !!urlCountry; + + // Visible campaigns in the **active** branch: every campaign matching + // the search/sort/country, minus hidden (unless the moderator opted + // in to seeing hidden). Featured items are intentionally NOT pulled + // out of this list — when the user is actively browsing, they want a + // ranked or chronological grid, not the curated shelf. const { visible, hiddenCount, hiddenCampaigns } = useMemo(() => { const all = campaigns ?? []; const hiddenCoords = moderation?.hiddenCoords ?? new Set(); - const featuredCoordSet = new Set(featuredCoords); let hiddenCount = 0; const visible: ParsedCampaign[] = []; const hiddenCampaigns: ParsedCampaign[] = []; @@ -161,13 +181,13 @@ export function AllCampaignsPage() { hiddenCount += 1; hiddenCampaigns.push(c); if (isMod && showHidden) visible.push(c); - } else if (!featuredCoordSet.has(c.aTag)) { + } else { visible.push(c); } } return { visible, hiddenCount, hiddenCampaigns }; - }, [campaigns, featuredCoords, isMod, moderation, showHidden]); + }, [campaigns, isMod, moderation, showHidden]); const orderedFeaturedCampaigns = useMemo(() => { if (!featuredCampaigns) return [] as ParsedCampaign[]; @@ -176,19 +196,23 @@ export function AllCampaignsPage() { ); }, [featuredCampaigns, moderation]); + // Idle-mode list: featured first; if none are featured, fall back to + // the latest chronological grid so the page never lands on an empty + // state when there's content to show. + const idleCampaigns = useMemo(() => { + if (orderedFeaturedCampaigns.length > 0) return orderedFeaturedCampaigns; + return visible; + }, [orderedFeaturedCampaigns, visible]); + const DEFAULT_VISIBLE = 4; const [showAllMine, setShowAllMine] = useState(false); - const [showAllFeatured, setShowAllFeatured] = useState(false); const visibleMine = showAllMine ? (myCampaigns ?? []) : (myCampaigns ?? []).slice(0, DEFAULT_VISIBLE); - const visibleFeatured = showAllFeatured ? orderedFeaturedCampaigns : orderedFeaturedCampaigns.slice(0, DEFAULT_VISIBLE); const showSkeleton = isLoading || !moderationReady; - const activeQuery = debouncedSearch.trim(); - const totalCampaigns = campaigns?.length ?? 0; return (
- +
{user && myCampaigns && myCampaigns.length > 0 && ( @@ -211,118 +235,100 @@ export function AllCampaignsPage() {
)} - {orderedFeaturedCampaigns.length > 0 && ( -
+ {/* Unified Campaigns section. + - Idle (no search / no sort / no country): renders the + moderator-curated featured grid, or a chronological + fallback if nothing is featured yet. + - Active: renders the full search/sort/country result set. */} +
+

- {t('campaigns.home.featured')} + {activeQuery + ? t('common.search') + : t('campaigns.all.title')}

- {t('campaigns.home.featuredDesc', { appName: config.appName })} + {activeQuery + ? t('common.searchResultsCount', { count: visible.length }) + : t('campaigns.all.sectionTagline')}

- setShowAllFeatured(!showAllFeatured)} + -
- )} + - {/* Section heading — matches the `/pledges` and `/groups` pages - so the discovery surfaces all share the same large-bold - section header pattern. Title switches between Search / Top / - New based on toolbar state; tagline stays constant. - Search input + filter button cluster on the right, paired - with the heading on the left in a single row. */} -
-
-

- {activeQuery - ? t('common.search') - : t('campaigns.all.title')} -

-

- {activeQuery - ? t('common.searchResultsCount', { count: visible.length }) - : t('campaigns.all.sectionTagline')} -

-
- -
- - {/* Grid — widens to 3 columns at lg and 4 at xl so desktop users - can scan more campaigns at once, matching the Pledge index's - card density. Mobile and small tablets stay single / double - column so the cards keep their tappable size. */} - {showSkeleton ? ( -
- {Array.from({ length: 8 }).map((_, i) => ( - - ))} -
- ) : visible.length === 0 ? ( - - - -
- {activeQuery ? ( - <> -

- {t('campaigns.all.noMatch', { query: activeQuery })} -

-

- {t('campaigns.all.noMatchHint')} -

- - ) : hiddenCount > 0 && !showHidden ? ( - <> -

{t('campaigns.all.allHidden')}

-

- {t('campaigns.all.allHiddenHint')} -

- - ) : ( - <> -

{t('campaigns.all.empty')}

-

- {t('campaigns.all.emptyHint')} -

- - )} -
- -
-
- ) : ( -
- {visible.map((campaign) => ( - - ))} -
- )} + {/* Grid — widens to 3 columns at lg and 4 at xl so desktop + users can scan more campaigns at once, matching the Pledge + index's card density. Mobile and small tablets stay + single / double column so the cards keep their tappable + size. */} + {showSkeleton ? ( +
+ {Array.from({ length: 8 }).map((_, i) => ( + + ))} +
+ ) : (isActive ? visible : idleCampaigns).length === 0 ? ( + + + +
+ {activeQuery ? ( + <> +

+ {t('campaigns.all.noMatch', { query: activeQuery })} +

+

+ {t('campaigns.all.noMatchHint')} +

+ + ) : hiddenCount > 0 && !showHidden ? ( + <> +

{t('campaigns.all.allHidden')}

+

+ {t('campaigns.all.allHiddenHint')} +

+ + ) : ( + <> +

{t('campaigns.all.empty')}

+

+ {t('campaigns.all.emptyHint')} +

+ + )} +
+ +
+
+ ) : ( +
+ {(isActive ? visible : idleCampaigns).map((campaign) => ( + + ))} +
+ )} +
{/* Moderator-only: every hidden campaign on the network. Mirrors the section on `/campaigns` so moderators see the same diff --git a/src/pages/CommunitiesPage.tsx b/src/pages/CommunitiesPage.tsx index c877edfa..7fd3b614 100644 --- a/src/pages/CommunitiesPage.tsx +++ b/src/pages/CommunitiesPage.tsx @@ -65,8 +65,9 @@ export function CommunitiesPage() { // On-page NIP-50 search + sort + show-hidden toolbar state. // - // Default sort, empty query → curated "My groups" / "Featured" / - // moderator shelves below. + // Default sort, empty query → curated featured-first idle view. + // If no groups are featured yet, falls back to the chronological + // "all groups" grid so the page is never blank. // Default sort, with query → relay search for kind 34550, results // post-filtered against name/description/content client-side. // Top / New → always active. Top sends `sort:top`; @@ -122,9 +123,14 @@ export function CommunitiesPage() { }, [searchHitsRaw, orgModeration, showHidden]); const { data: allOrgs, isLoading: allOrgsLoading } = useDiscoverCommunities({ limit: 200 }); + // `allGroups` is the chronological "every Agora-tagged group" list, + // used both as the fallback for the idle view (when nothing is + // featured yet) and as the result list when the user switches to + // Top/New sort with no typed query. Featured groups are NOT removed + // here — when the user is actively browsing they want the full set; + // the idle-mode rendering path handles the featured-first framing. const { allGroups, allHiddenCount, hiddenGroups } = useMemo(() => { const hiddenCoords = orgModeration?.hiddenCoords ?? new Set(); - const featuredCoords = orgModeration?.featuredCoords ?? new Set(); let hidden = 0; const visible: ParsedCommunity[] = []; const hiddenList: ParsedCommunity[] = []; @@ -133,20 +139,34 @@ export function CommunitiesPage() { hidden += 1; hiddenList.push(org); if (isMod && showHidden) visible.push(org); - } else if (hasAgoraTag(org.tags) && !featuredCoords.has(org.aTag)) { + } else if (hasAgoraTag(org.tags)) { visible.push(org); } } return { allGroups: visible, allHiddenCount: hidden, hiddenGroups: hiddenList }; }, [allOrgs, isMod, orgModeration, showHidden]); - // Search + sort + show-hidden cluster for the All section. + // Featured groups for the idle view. When there are none, the idle + // view falls back to `allGroups` so users always see something. + const { data: featuredOrgs } = useFeaturedOrganizations(); + const featuredGroups = useMemo(() => { + if (!featuredOrgs) return []; + const hiddenCoords = orgModeration?.hiddenCoords ?? new Set(); + return featuredOrgs + .map((entry) => entry.community) + .filter((c) => !hiddenCoords.has(c.aTag)); + }, [featuredOrgs, orgModeration]); + + const idleGroups = featuredGroups.length > 0 ? featuredGroups : allGroups; + + // Search + sort + show-hidden cluster for the unified section. const searchToolbar = ( - - + {/* Unified Groups section. + - Idle (no search / no sort): renders moderator-featured + groups, or the chronological "all groups" fallback when + nothing is featured yet. + - Active: renders the full search/sort result set. */}

{trimmedSearch ? t('common.search') - : isSearching && sortMode === 'top' - ? t('common.sortTop') - : isSearching && sortMode === 'new' - ? t('common.sortNew') - : t('groups.list.allGroups')} + : t('groups.list.allGroups')}

{isSearching && searchHits @@ -234,9 +253,9 @@ export function CommunitiesPage() { ))} - ) : allGroups.length > 0 ? ( + ) : idleGroups.length > 0 ? ( - {allGroups.map((community) => ( + {idleGroups.map((community) => ( - - - {featured.map((entry) => ( - - ))} - -

- ); -} -function FeaturedOrganizationsHeading() { - const { t } = useTranslation(); - return ( -
-

- {t('groups.list.featuredGroups')} -

-

- {t('groups.list.featuredGroupsTagline')} -

-
- ); -} +