feat(landing): настоящие логотипы продуктов и карточки в их фирменных цветах

Две одинаковые серые плитки не давали понять, что это разные приложения,
а у Бонитировки стояла служебная заглушка вместо логотипа.

- logo_url и brand_color у продукта; логотипы взяты из самих приложений;
- фон и рамка карточки — мягкий градиент фирменного цвета, ссылка тоже;
- в шапке было «1 — ФЛАГМАНСКИЙ ПРОДУКТ», стало «2 — ПРОДУКТА В PRODUCTION».
This commit is contained in:
2026-08-20 00:15:21 +03:00
parent b117f3a740
commit 3199b681a2
5 changed files with 30 additions and 6 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ publicRouter.get('/content', async (_req, res) => {
query<unknown>( query<unknown>(
`SELECT id, slug, title, subtitle, description, `SELECT id, slug, title, subtitle, description,
status, audience, icon_key, tags, sort_order, site_url, status, audience, icon_key, tags, sort_order, site_url,
title_en, subtitle_en, description_en title_en, subtitle_en, description_en, logo_url, brand_color
FROM products FROM products
WHERE is_published = true WHERE is_published = true
ORDER BY sort_order ASC` ORDER BY sort_order ASC`
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

+2
View File
@@ -15,6 +15,8 @@ export interface Product {
title_en?: string | null; title_en?: string | null;
subtitle_en?: string | null; subtitle_en?: string | null;
description_en?: string | null; description_en?: string | null;
logo_url?: string | null;
brand_color?: string | null;
} }
export interface ApproachItem { export interface ApproachItem {
+24 -2
View File
@@ -163,7 +163,18 @@ export function Landing() {
? (STATUS_LABELS_EN[p.status] || STATUS_LABELS_EN.planned) ? (STATUS_LABELS_EN[p.status] || STATUS_LABELS_EN.planned)
: statusBadge.text; : statusBadge.text;
return ( return (
<div key={p.id} className="bg-gradient-to-br from-slate-50 to-brand-50 border border-slate-200 rounded-3xl p-8 grid md:grid-cols-2 gap-7 items-center"> <div
key={p.id}
className="border rounded-3xl p-8 grid md:grid-cols-2 gap-7 items-center transition-shadow hover:shadow-md"
style={{
// Карточка в цвете самого продукта: две одинаковые серые
// плитки не давали понять, что это разные приложения.
background: p.brand_color
? `linear-gradient(135deg, ${p.brand_color}0D 0%, ${p.brand_color}1A 100%)`
: undefined,
borderColor: p.brand_color ? `${p.brand_color}33` : undefined,
}}
>
<div> <div>
<div className="flex gap-2 mb-4"> <div className="flex gap-2 mb-4">
<span className={`text-xs px-2.5 py-1 rounded font-medium ${statusBadge.cls}`}>{badgeText}</span> <span className={`text-xs px-2.5 py-1 rounded font-medium ${statusBadge.cls}`}>{badgeText}</span>
@@ -172,9 +183,19 @@ export function Landing() {
)} )}
</div> </div>
<div className="flex items-center gap-3 mb-3"> <div className="flex items-center gap-3 mb-3">
{p.logo_url ? (
<img
src={p.logo_url}
alt={String(pick(p, 'title') || '')}
width={48}
height={48}
className="w-12 h-12 rounded-xl object-contain bg-white border border-slate-200/70 p-1"
/>
) : (
<div className="w-12 h-12 bg-brand-800 rounded-xl flex items-center justify-center text-white"> <div className="w-12 h-12 bg-brand-800 rounded-xl flex items-center justify-center text-white">
<ProductIcon name={p.icon_key || ''} size={24} /> <ProductIcon name={p.icon_key || ''} size={24} />
</div> </div>
)}
<div> <div>
<div className="text-2xl font-medium text-brand-900 tracking-tight">{pick(p, 'title')}</div> <div className="text-2xl font-medium text-brand-900 tracking-tight">{pick(p, 'title')}</div>
{pick(p, 'subtitle') && ( {pick(p, 'subtitle') && (
@@ -193,7 +214,8 @@ export function Landing() {
href={p.site_url} href={p.site_url}
target="_blank" target="_blank"
rel="noopener" rel="noopener"
className="inline-flex items-center gap-1.5 mt-5 text-sm font-medium text-brand-900 border-b border-brand-900/30 hover:border-brand-900 transition-colors" className="inline-flex items-center gap-1.5 mt-5 text-sm font-medium border-b transition-colors"
style={{ color: p.brand_color || undefined, borderColor: p.brand_color ? `${p.brand_color}55` : undefined }}
> >
{p.site_url.replace(/^https?:\/\//, '')} {p.site_url.replace(/^https?:\/\//, '')}
<ArrowRightIcon width={14} height={14} /> <ArrowRightIcon width={14} height={14} />