diff --git a/CONTEXT.md b/CONTEXT.md index 4de95c3..b6dfcac 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -210,13 +210,23 @@ catalog data. `STATIC_IMAGE_SLOT_CATALOG` in `meshkee.ts` is the source of truth for which slots exist; publishing it via `src/app/meshkee/static-image-slots/route.ts` (`/meshkee/static-image-slots`) is how the admin dashboard's "refresh" imports new keys. Current keys: -`home-hero`, `two-banner`, `three-banner-row`, `featured-categories`. Adding +`home-hero`, `two-banner`, `three-banner-row`, `featured-categories`, +`about-us-image`. `about-us-image` is a homepage `single` slot with a `14:9` +ratio (the original 560×360 frame). `AboutSanihome` uses its first image, +prefers `titleFa`, then `titleEn`, then `subtext` for alt text, wraps the image +with `linkUrl` when present, and preserves `/images/about.svg` as the empty/error +fallback. Adding a slot here does **not** make images appear — someone still has to upload them in the dashboard; the code path just needs to fall back to whatever the "current" behavior was before the slot existed when it's empty (see `FeaturedCategories.tsx` for the pattern: real slot images when present, else the pre-existing UI unchanged). +**Static-image sizing rule:** whenever a slot's rendered image dimensions or +aspect ratio change during development, update the matching +`STATIC_IMAGE_SLOT_CATALOG` entry (`aspectRatio` and `recommendedWidth`) in the +same change so `/meshkee/static-image-slots` stays accurate for the dashboard. + ## Homepage product carousels — fully dynamic, don't hardcode a name/key `GET /tenants/{domain}/store-specials` returns **every** admin-managed named diff --git a/public/images/logo.png b/public/images/logo.png index 028bd26..7e4ecdc 100644 Binary files a/public/images/logo.png and b/public/images/logo.png differ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index d56df75..9fba2c4 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -30,7 +30,7 @@ const syne = Syne({ export async function generateMetadata(): Promise { const businessInfo = await getBusinessInfo(); return { - title: "سانی‌هوم | فروشگاه لوازم خانگی", + title: "صنیع هوم | فروشگاه لوازم خانگی", description: "فروشگاه آنلاین لوازم خانگی — یخچال، لباسشویی، تلویزیون و بیشتر", icons: businessInfo?.faviconUrl ? [{ url: businessInfo.faviconUrl }] : undefined, }; diff --git a/src/app/page.tsx b/src/app/page.tsx index fd31add..041a3b3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,6 +10,7 @@ import { getCategories, getStoreSpecials, getStaticImageSlots, + firstImageForSlot, imagesForSlot, STATIC_IMAGE_KEYS, } from "@/lib/meshkee"; @@ -44,7 +45,12 @@ export default async function Home() { threeBannerAspectRatio={threeBannerSlot?.aspectRatio} /> - + slot.key === STATIC_IMAGE_KEYS.aboutUsImage, + )?.aspectRatio} + /> ); diff --git a/src/components/home/AboutSanihome.tsx b/src/components/home/AboutSanihome.tsx index c252ff5..0150421 100644 --- a/src/components/home/AboutSanihome.tsx +++ b/src/components/home/AboutSanihome.tsx @@ -1,6 +1,13 @@ -import { Placeholder } from "@/components/ui/Placeholder"; +import { AboutSlotImage } from "@/components/home/AboutSlotImage"; +import type { StaticImageWithUrl } from "@/lib/meshkee"; -export function AboutSanihome() { +export function AboutSanihome({ + image, + aspectRatio, +}: { + image?: StaticImageWithUrl; + aspectRatio?: string; +}) { return (
@@ -8,7 +15,7 @@ export function AboutSanihome() {

- درباره سانی‌هوم + درباره صنیع هوم

- سانی‌هوم از سال ۱۳۹۰ به عنوان یکی از معتبرترین فروشگاه‌های آنلاین لوازم + صنیع هوم از سال ۱۳۹۰ به عنوان یکی از معتبرترین فروشگاه‌های آنلاین لوازم خانگی در ایران فعالیت می‌کند. ما با ارائه محصولات اصل از برندهای معتبر جهانی، گارانتی رسمی و خدمات پس از فروش، تجربه‌ای مطمئن برای خرید لوازم خانگی فراهم کرده‌ایم. @@ -43,14 +50,7 @@ export function AboutSanihome() { ))}

- +
diff --git a/src/components/home/AboutSlotImage.tsx b/src/components/home/AboutSlotImage.tsx new file mode 100644 index 0000000..0d16e0b --- /dev/null +++ b/src/components/home/AboutSlotImage.tsx @@ -0,0 +1,42 @@ +"use client"; + +import { useState } from "react"; +import { Placeholder } from "@/components/ui/Placeholder"; +import type { StaticImageWithUrl } from "@/lib/meshkee"; + +export function AboutSlotImage({ + image, + aspectRatio, +}: { + image?: StaticImageWithUrl; + aspectRatio?: string; +}) { + const [failed, setFailed] = useState(false); + + if (!image || failed) { + return ( + + ); + } + + const frame = ( + // Meshkee slot URLs are rendered as-is; a failed remote image falls back locally. + // eslint-disable-next-line @next/next/no-img-element + {image.titleFa setFailed(true)} + style={{ aspectRatio: (aspectRatio ?? "14:9").replace(":", " / ") }} + className="h-auto w-full rounded-2xl object-cover" + /> + ); + + return image.linkUrl ? {frame} : frame; +} diff --git a/src/components/home/Footer.tsx b/src/components/home/Footer.tsx index d4ed3fe..f3af195 100644 --- a/src/components/home/Footer.tsx +++ b/src/components/home/Footer.tsx @@ -28,7 +28,7 @@ export function Footer({ return (