Double desktop header logo, add English caption under each carousel title
- Header logo (desktop variant) doubled: 40/48px -> 80/96px. - Each dynamic store-specials carousel now shows an English caption under its title at 50% opacity, derived from the group's real `key` (e.g. "top-selling" -> "TOP SELLING") rather than inventing a translation of the Persian title, which the API doesn't provide. New SectionTitle `enSubtitle` prop (separate from the existing inline `enTitle`) carries this. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
7c04316f3a
commit
0de5abb879
+8
-1
@@ -222,7 +222,14 @@ time the page renders, with zero code changes.
|
|||||||
|
|
||||||
`SectionTitle`'s `enTitle` prop is optional for exactly this reason — these
|
`SectionTitle`'s `enTitle` prop is optional for exactly this reason — these
|
||||||
dynamic groups only have one `title` string from the API, not a Persian/
|
dynamic groups only have one `title` string from the API, not a Persian/
|
||||||
English pair, so the small English-caps subtitle just doesn't render for them.
|
English pair, so the inline English-caps subtitle just doesn't render for
|
||||||
|
them. Instead, each carousel shows an English caption *under* the title
|
||||||
|
(`SectionTitle`'s separate `enSubtitle` prop, `opacity-50`, its own line) —
|
||||||
|
`StoreSpecialCarousels.englishLabelFromKey()` formats the group's `key`
|
||||||
|
(e.g. `top-selling` → "TOP SELLING") rather than inventing a translation of
|
||||||
|
`title`; there's no real localized-English field to translate from, and a
|
||||||
|
made-up translation would be fabricated data. Skips rendering if the key
|
||||||
|
has no letters at all (fell back to a bare numeric id).
|
||||||
|
|
||||||
**Banner interleaving**: the two static-image banner sections (`TwoBanners`,
|
**Banner interleaving**: the two static-image banner sections (`TwoBanners`,
|
||||||
`ThreeBanners`) are rendered *inside* `StoreSpecialCarousels`, one inserted
|
`ThreeBanners`) are rendered *inside* `StoreSpecialCarousels`, one inserted
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function Logo({ src, large = false }: { src?: string | null; large?: boolean })
|
|||||||
className={
|
className={
|
||||||
large
|
large
|
||||||
? "h-[42px] w-auto object-contain md:h-[46px]"
|
? "h-[42px] w-auto object-contain md:h-[46px]"
|
||||||
: "h-10 w-auto object-contain md:h-12"
|
: "h-20 w-auto object-contain md:h-24"
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -6,6 +6,18 @@ import { TwoBanners } from "@/components/home/TwoBanners";
|
|||||||
import { ThreeBanners } from "@/components/home/ThreeBanners";
|
import { ThreeBanners } from "@/components/home/ThreeBanners";
|
||||||
import { productHref, type ProductGroup, type StaticImageWithUrl } from "@/lib/meshkee";
|
import { productHref, type ProductGroup, type StaticImageWithUrl } from "@/lib/meshkee";
|
||||||
|
|
||||||
|
// The API only gives one `title` string per group (sometimes already
|
||||||
|
// English, e.g. "Special Sale", sometimes Persian) — there's no separate
|
||||||
|
// localized English field to pull a real translation from, and inventing
|
||||||
|
// one would be fabricated data. `key` is real data and usually a readable
|
||||||
|
// English slug (e.g. "top-selling"), so it's what gets formatted into the
|
||||||
|
// English caption under the title. Skip it if the key has no letters at
|
||||||
|
// all (e.g. it fell back to a bare numeric id).
|
||||||
|
function englishLabelFromKey(key: string): string | undefined {
|
||||||
|
const label = key.replace(/[-_]+/g, " ").trim();
|
||||||
|
return /[a-zA-Z]/.test(label) ? label.toUpperCase() : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
// Renders every admin-managed carousel from GET /store-specials — whatever
|
// Renders every admin-managed carousel from GET /store-specials — whatever
|
||||||
// groups exist there, in their configured order. Nothing here is keyed off
|
// groups exist there, in their configured order. Nothing here is keyed off
|
||||||
// a specific group id/key/title, so a new carousel created in the Meshkee
|
// a specific group id/key/title, so a new carousel created in the Meshkee
|
||||||
@@ -46,6 +58,7 @@ export function StoreSpecialCarousels({
|
|||||||
<div className="mx-auto max-w-7xl px-4">
|
<div className="mx-auto max-w-7xl px-4">
|
||||||
<SectionTitle
|
<SectionTitle
|
||||||
title={group.title}
|
title={group.title}
|
||||||
|
enSubtitle={englishLabelFromKey(group.key)}
|
||||||
action="مشاهده همه"
|
action="مشاهده همه"
|
||||||
actionHref={`/products?specialId=${group.id}`}
|
actionHref={`/products?specialId=${group.id}`}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
type SectionTitleProps = {
|
type SectionTitleProps = {
|
||||||
title: string;
|
title: string;
|
||||||
enTitle?: string;
|
enTitle?: string;
|
||||||
|
// Shown on its own line under the title (not inline like enTitle), at 50%
|
||||||
|
// opacity — used for the homepage's dynamic store-specials carousels.
|
||||||
|
enSubtitle?: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
action?: string;
|
action?: string;
|
||||||
actionHref?: string;
|
actionHref?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function SectionTitle({ title, enTitle, subtitle, action, actionHref }: SectionTitleProps) {
|
export function SectionTitle({
|
||||||
|
title,
|
||||||
|
enTitle,
|
||||||
|
enSubtitle,
|
||||||
|
subtitle,
|
||||||
|
action,
|
||||||
|
actionHref,
|
||||||
|
}: SectionTitleProps) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-6 flex items-end justify-between gap-4">
|
<div className="mb-6 flex items-end justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -22,6 +32,15 @@ export function SectionTitle({ title, enTitle, subtitle, action, actionHref }: S
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{enSubtitle && (
|
||||||
|
<p
|
||||||
|
className="font-display mt-1 text-xs font-semibold tracking-wide text-foreground uppercase opacity-50 md:text-sm"
|
||||||
|
lang="en"
|
||||||
|
dir="ltr"
|
||||||
|
>
|
||||||
|
{enSubtitle}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
{subtitle && (
|
{subtitle && (
|
||||||
<p className="mt-1 text-sm text-muted">{subtitle}</p>
|
<p className="mt-1 text-sm text-muted">{subtitle}</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user