render top banner from new "ّFooladinfo" category

This commit is contained in:
Mohamad Mahdi Jebeli 2026-06-23 09:16:41 +03:30
parent 064e3d7343
commit c60c081f99
2 changed files with 75 additions and 0 deletions

View File

@ -195,6 +195,38 @@ class _InfographyScreenState extends State<InfographyScreen> {
value: context.watch<InfographyScreenState>().lastSearch,
isFiltered: context.watch<InfographyScreenState>().filtering),
),
// پوستر بالای صفحه از دستهی «بنر فولادینفو» کشیده میشود.
// اگر هیچ آیتم منتشرشدهای در آن دسته نباشد، چیزی نمایش داده نمیشود.
Builder(builder: (context) {
final bannerUrl =
context.watch<InfographyScreenState>().topBannerImageUrl;
if (bannerUrl == null || bannerUrl.isEmpty) {
return const SizedBox.shrink();
}
return Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: AspectRatio(
aspectRatio: 16 / 7,
child: Image.network(
bannerUrl,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const SizedBox.shrink(),
loadingBuilder: (context, child, progress) {
if (progress == null) return child;
return Container(
color: Theme.of(context)
.colorScheme
.surface
.withOpacity(0.4),
);
},
),
),
),
);
}),
StateHandler<InfographyScreenState>(
placeholder: SingleChildScrollView(
child: Column(

View File

@ -72,6 +72,15 @@ class InfographyScreenState extends CoreProvier {
static const String _infographyCategoryId =
'3e53627d-9a18-4bad-b4ae-1f0c55438147';
/// شناسهی دستهی «بنر فولادینفو» تصویر کاور آخرین content این دسته
/// بهعنوان پوستر بالای صفحهی فولادینفو در اپ نمایش داده میشود.
static const String _foladinfoBannerCategoryId =
'd1a5e9b3-6f47-4c82-9e1d-3b8f2c5a4d76';
/// URL تصویر بنر فولادینفو که در بالای صفحه نمایش داده میشود؛
/// اگر null یا خالی بود، بنر اصلاً رندر نمیشود.
String? topBannerImageUrl;
/// فقط محتوای منتشرشده/تأییدشده. status فقط IN دارد.
static const String _visibleStatusFilter = '\$in:accepted,published';
@ -167,6 +176,39 @@ class InfographyScreenState extends CoreProvier {
appState = AppState.idle;
}
/// آخرین content منتشرشده در دستهی «بنر فولادینفو» را میگیریم و
/// `coverImage` آن را در [topBannerImageUrl] میگذاریم. در صورت خطا
/// یا خالیبودن، بنر نمایش داده نمیشود (مقدار null میماند).
Future<void> _fetchTopBanner() async {
try {
final res = await ContentService.instance.getContents(
page: 1,
limit: 1,
filterStatus: _visibleStatusFilter,
categoryId: _foladinfoBannerCategoryId,
sortBy: const [MapEntry('createdAt', 'DESC')],
);
if (!res.isSuccess || res.data == null || res.data!.data.isEmpty) {
topBannerImageUrl = null;
update();
return;
}
final first = res.data!.data.first;
// The list endpoint may already include coverImage; if not, fetch detail.
String? cover = first.coverImage;
if (cover == null || cover.isEmpty) {
final detail = await ContentService.instance.getContent(first.id);
if (detail.isSuccess && detail.data != null) {
cover = detail.data!.coverImage;
}
}
topBannerImageUrl = (cover != null && cover.isNotEmpty) ? cover : null;
update();
} catch (_) {
topBannerImageUrl = null;
}
}
void resetFilters(bool isInit) {
selectedCats.clear();
selectedTags.clear();
@ -184,6 +226,7 @@ class InfographyScreenState extends CoreProvier {
resetFilters(true);
Future.delayed(Duration.zero, () {
getInfographyContent(page: 1);
_fetchTopBanner();
});
categories = [
CategoryData(