From db7d00e4738bfb7d2882fcf4e565a90e6915a9af Mon Sep 17 00:00:00 2001 From: "amirhosein.ashourloo" Date: Sun, 6 Sep 2026 07:22:54 +0330 Subject: [PATCH] Add about/contact/installments pages, fix category slot bugs, wire live branding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Enlarge category carousel thumbnails (90px -> 104-140px responsive) and confirm the slider/categories/banner static-image slots are all reading correctly from the CMS (verified live, not a wiring bug) - Fix installments page dropping "هندزفری و هدفون": it's a level-3 category, not level-2, so level2.find() silently missed it - use findNode() over the whole tree instead - Extend gen-category-placeholders.mjs to generate a placeholder for every category at every level (was level-2 only), needed for the fix above - Add /about, /contact, /installments pages - About: real copy transcribed from the live moalem.shop theme, real product photos from the API, text-only brand strip (no scraped logos) - Contact: ContactForm.tsx posts to the real POST /contact-submissions, branch cards with key-less Google Maps embeds - Installments: flat brand-colored hero (no photo/gradient), category highlights reusing the same categories slot images as the homepage - Replace the placeholder header/footer phone number with the real one, add real branch addresses and Instagram/Telegram links (src/data/site.ts), pulled from the live theme's footer - Wire logo/favicon to GET /website/favicon (getFavicon() in api.ts) instead of the static bundled files, so a dashboard upload now shows automatically; layout.tsx metadata is now generateMetadata() to support this. The tenant's uploaded logo/favicon currently belongs to a different business - the wiring is correct and will self-correct once that's fixed in the dashboard Co-Authored-By: Claude Sonnet 5 --- AGENTS.md | 48 +++++++-- public/images/categories/1227.svg | 6 ++ public/images/categories/1228.svg | 6 ++ public/images/categories/1229.svg | 6 ++ public/images/categories/1230.svg | 6 ++ public/images/categories/1231.svg | 6 ++ public/images/categories/1232.svg | 6 ++ public/images/categories/1233.svg | 6 ++ public/images/categories/1234.svg | 6 ++ public/images/categories/1235.svg | 6 ++ public/images/categories/1236.svg | 6 ++ public/images/categories/1237.svg | 6 ++ public/images/categories/1238.svg | 6 ++ public/images/categories/1239.svg | 6 ++ public/images/categories/1240.svg | 6 ++ public/images/categories/1241.svg | 6 ++ public/images/categories/1242.svg | 6 ++ public/images/categories/1243.svg | 6 ++ public/images/categories/1244.svg | 6 ++ public/images/categories/1245.svg | 6 ++ public/images/categories/1246.svg | 6 ++ public/images/categories/1247.svg | 6 ++ public/images/categories/1248.svg | 6 ++ public/images/categories/1249.svg | 6 ++ public/images/categories/1250.svg | 6 ++ public/images/categories/1252.svg | 6 ++ public/images/categories/1257.svg | 6 ++ public/images/categories/1262.svg | 6 ++ public/images/categories/1265.svg | 6 ++ public/images/categories/1266.svg | 6 ++ public/images/categories/1267.svg | 6 ++ public/images/categories/1270.svg | 6 ++ scripts/gen-category-placeholders.mjs | 20 ++-- src/app/about/page.tsx | 141 ++++++++++++++++++++++++++ src/app/contact/page.tsx | 100 ++++++++++++++++++ src/app/installments/page.tsx | 138 +++++++++++++++++++++++++ src/app/layout.tsx | 66 +++++++----- src/components/CategoryCarousel.tsx | 14 +-- src/components/ContactForm.tsx | 88 ++++++++++++++++ src/components/Footer.tsx | 37 ++++++- src/components/Header.tsx | 14 ++- src/components/icons.tsx | 43 ++++++++ src/components/ui/TrustBadges.tsx | 26 +++++ src/data/site.ts | 28 ++++- src/lib/api.ts | 8 ++ src/lib/types.ts | 10 ++ 46 files changed, 913 insertions(+), 54 deletions(-) create mode 100644 public/images/categories/1227.svg create mode 100644 public/images/categories/1228.svg create mode 100644 public/images/categories/1229.svg create mode 100644 public/images/categories/1230.svg create mode 100644 public/images/categories/1231.svg create mode 100644 public/images/categories/1232.svg create mode 100644 public/images/categories/1233.svg create mode 100644 public/images/categories/1234.svg create mode 100644 public/images/categories/1235.svg create mode 100644 public/images/categories/1236.svg create mode 100644 public/images/categories/1237.svg create mode 100644 public/images/categories/1238.svg create mode 100644 public/images/categories/1239.svg create mode 100644 public/images/categories/1240.svg create mode 100644 public/images/categories/1241.svg create mode 100644 public/images/categories/1242.svg create mode 100644 public/images/categories/1243.svg create mode 100644 public/images/categories/1244.svg create mode 100644 public/images/categories/1245.svg create mode 100644 public/images/categories/1246.svg create mode 100644 public/images/categories/1247.svg create mode 100644 public/images/categories/1248.svg create mode 100644 public/images/categories/1249.svg create mode 100644 public/images/categories/1250.svg create mode 100644 public/images/categories/1252.svg create mode 100644 public/images/categories/1257.svg create mode 100644 public/images/categories/1262.svg create mode 100644 public/images/categories/1265.svg create mode 100644 public/images/categories/1266.svg create mode 100644 public/images/categories/1267.svg create mode 100644 public/images/categories/1270.svg create mode 100644 src/app/about/page.tsx create mode 100644 src/app/contact/page.tsx create mode 100644 src/app/installments/page.tsx create mode 100644 src/components/ContactForm.tsx create mode 100644 src/components/ui/TrustBadges.tsx diff --git a/AGENTS.md b/AGENTS.md index 9aa3e90..16b231a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ fallbacks should update it. empty or failing module degrades one section instead of the page. - Never invent CMS/admin endpoints. If OpenAPI and any prose conflict, OpenAPI wins. -### What the tenant actually returns today (2026-08-31) +### What the tenant actually returns today (2026-09-06) | Endpoint | State | |---|---| @@ -27,9 +27,10 @@ fallbacks should update it. | `/products` | **479 items**, real titles, images, categories | | `/categories?entityType=product` | **48 items**, 3 levels under «کالای دیجیتال». Products are filed on **leaf** categories only — a parent category page/carousel must query its whole subtree (`subtreeIds`/`subtreeIdsAll` in `src/lib/categoryTree.ts`). | | `/store-items`, `/store-specials` | **empty** → no prices, no discounts, everything `inStock:false`. `/store-items/by-product/{id}` returns a single `{ storeItem }` (or null) — for a product's full variant list use `/store-items?productId=&pageSize=100` (`{ items }`) instead, see `getStoreItemsByProduct` in `src/lib/api.ts`. | -| `/website/sliders`, `/website/static-images`, `/website/category-groups` | **empty** | +| `/website/sliders`, `/website/category-groups` | **empty** | +| `/website/static-images` | **filled** — `slider` (2), `categories` (8 of 15), `one/two/three-banner-bg` all have real images. Verified live and rendering correctly; if a future check finds otherwise, suspect a stale build/deploy before suspecting the wiring. | | `/blogs` | **empty** (module enabled) | -| `/website/business-info`, `/website/favicon` | present but blank (no logo, no phone, no socials) | +| `/website/business-info` | phones/addresses/socialMedia still empty; `logoUrl`/`faviconUrl` are now set but point to a **different business's** mark (see "Brand") | | `/products/by-id/{id}/technical-info` | `{ form: null, values: [] }` — empty on every product checked so far | | `/comments` | **empty**, but `POST` works (no bearer required by the API itself) | @@ -38,18 +39,31 @@ fallbacks should update it. | Gap | Fallback | Remove when | |---|---|---| | No prices | `src/lib/demoPricing.ts`, gated by `NEXT_PUBLIC_DEMO_PRICING=1` — deterministic price per product id | store-items exist | -| No sliders | `src/app/page.tsx`'s local `FALLBACK_SLIDES` (banners downloaded from the live moalem.shop theme into `public/images/banners/`) — used only when the `slider` static-image slot is also empty, see "Static-image slots" below | `/website/sliders` or the `slider` slot returns items | | No blog posts | `src/data/fallbackBlogs.ts` — the real posts from moalem.shop/articles, shown on the homepage and `/blog` as non-clickable cards (no real detail page exists for them) | `/blogs` returns items | -| No category art | placeholder SVGs in `public/images/categories/{id}.svg`, generated by `scripts/gen-category-placeholders.mjs` — overridden per-slide by the `categories` static-image slot when it has images | real thumbnails are dropped in, or the `categories` slot is filled | -| No branding in API | logo/favicon copied from the live theme into `public/` | `logoUrl` is set on the tenant | -| No banner art (`one/two/three-banner-bg`) | `src/components/PromoBanners.tsx` renders a flat dashed placeholder per slot cell, labelled with the recommended size/ratio | the matching static-image slot is filled | +| No category art past slot position 8 | placeholder SVGs in `public/images/categories/{id}.svg`, generated by `scripts/gen-category-placeholders.mjs` for every category at every level, not just level-2 | the `categories` slot has an image for that position | +| Wrong logo/favicon in API | `getFavicon()` is wired live (see "Brand") but the uploaded asset itself is wrong; no code fallback needed once the dashboard upload is fixed | the correct asset is uploaded | ## Brand -Taken from the live moalem.shop theme, not invented: +Colors taken from the live moalem.shop theme, not invented: primary `#E51E22`, dark `#B10123`, ink `#2E2E2E`, body `#7C7C7C`. Fonts: IRANYekan (fa, local `public/fonts`) + Montserrat (latin, next/font). +- Logo/favicon: `getFavicon()` in `src/lib/api.ts` reads + `GET /tenants/moalem.shop/website/favicon` — the documented single source — + and `Header.tsx`/`Footer.tsx`/`generateMetadata()` in `layout.tsx` all use + it, falling back to the bundled `/images/logo.png` / `/favicon.png` only + when the API field is null. **As of 2026-09-06 the dashboard has a logo/ + favicon uploaded, but it's the wrong business's** (a home-appliances store's + mark, not موبایل معلم) — the wiring is correct and will pick up the right + asset automatically the moment it's replaced in the dashboard; don't + "fix" this by hardcoding the local fallback again. +- Contact data (phone, mobile, branch addresses, Instagram/Telegram) in + `src/data/site.ts` is real, pulled from the live theme's footer — `GET + /website/business-info` still returns empty `phoneNumbers`/`addresses`/ + `socialMedia` for this tenant, so these stay hand-maintained here until + that's filled in. Update both together when it is. + ## Layout conventions - Content width `--container-boxed: 1200px`, applied with the `boxed` utility. @@ -127,6 +141,24 @@ layout): hero → categories → hot deals → **three-banner-bg** → موبا carousel → **two-banner-bg** → لوازم جانبی → لپ تاپ → **one-banner-bg** → کنسول بازی → مجله. +## Static pages + +- `/about` — real copy transcribed from the live moalem.shop theme's + about-us module (verified against its cached HTML, not invented); brand + strip is plain text wordmarks (no scraped logo images — avoids a + trademark/asset-licensing headache for names we don't have real logo files + for) with real product photos pulled from the API. +- `/contact` — `ContactForm.tsx` posts to the real `POST /contact-submissions` + (no bearer required); branch cards use `BRANCHES` from `src/data/site.ts` + plus a key-less Google Maps `output=embed` iframe per branch (no API key + needed for a query-based embed). +- `/installments` — flat, brand-colored hero (no photo, no gradient — this + site stays flat) instead of the reference design's photographic banner; + category highlights reuse the same `categories` static-image slot images + as the homepage carousel, matched by the same positional index. One + reference category ("خانه هوشمند") has no equivalent on this tenant and is + swapped for "لوازم برقی" — see `HIGHLIGHT_IDS` in the page for the mapping. + ## Product / blog pages - `/products` — full catalog, `?name=` search, `?page=`. diff --git a/public/images/categories/1227.svg b/public/images/categories/1227.svg new file mode 100644 index 0000000..52cce2a --- /dev/null +++ b/public/images/categories/1227.svg @@ -0,0 +1,6 @@ + + + + کابل و را + 1227 + diff --git a/public/images/categories/1228.svg b/public/images/categories/1228.svg new file mode 100644 index 0000000..6c331da --- /dev/null +++ b/public/images/categories/1228.svg @@ -0,0 +1,6 @@ + + + + پاور بانک + 1228 + diff --git a/public/images/categories/1229.svg b/public/images/categories/1229.svg new file mode 100644 index 0000000..c6a4f98 --- /dev/null +++ b/public/images/categories/1229.svg @@ -0,0 +1,6 @@ + + + + کارت حافظ + 1229 + diff --git a/public/images/categories/1230.svg b/public/images/categories/1230.svg new file mode 100644 index 0000000..e447fec --- /dev/null +++ b/public/images/categories/1230.svg @@ -0,0 +1,6 @@ + + + + شارژر موب + 1230 + diff --git a/public/images/categories/1231.svg b/public/images/categories/1231.svg new file mode 100644 index 0000000..403349b --- /dev/null +++ b/public/images/categories/1231.svg @@ -0,0 +1,6 @@ + + + + اسپیکر سی + 1231 + diff --git a/public/images/categories/1232.svg b/public/images/categories/1232.svg new file mode 100644 index 0000000..1009fd2 --- /dev/null +++ b/public/images/categories/1232.svg @@ -0,0 +1,6 @@ + + + + هندزفری و + 1232 + diff --git a/public/images/categories/1233.svg b/public/images/categories/1233.svg new file mode 100644 index 0000000..fc85788 --- /dev/null +++ b/public/images/categories/1233.svg @@ -0,0 +1,6 @@ + + + + هدفون بلو + 1233 + diff --git a/public/images/categories/1234.svg b/public/images/categories/1234.svg new file mode 100644 index 0000000..9a95ad8 --- /dev/null +++ b/public/images/categories/1234.svg @@ -0,0 +1,6 @@ + + + + هدفون سیم + 1234 + diff --git a/public/images/categories/1235.svg b/public/images/categories/1235.svg new file mode 100644 index 0000000..59d18e2 --- /dev/null +++ b/public/images/categories/1235.svg @@ -0,0 +1,6 @@ + + + + قاب و کیف + 1235 + diff --git a/public/images/categories/1236.svg b/public/images/categories/1236.svg new file mode 100644 index 0000000..b983e60 --- /dev/null +++ b/public/images/categories/1236.svg @@ -0,0 +1,6 @@ + + + + محافظ صفح + 1236 + diff --git a/public/images/categories/1237.svg b/public/images/categories/1237.svg new file mode 100644 index 0000000..192629a --- /dev/null +++ b/public/images/categories/1237.svg @@ -0,0 +1,6 @@ + + + + لوازم جان + 1237 + diff --git a/public/images/categories/1238.svg b/public/images/categories/1238.svg new file mode 100644 index 0000000..4ebaa87 --- /dev/null +++ b/public/images/categories/1238.svg @@ -0,0 +1,6 @@ + + + + محافظ صفح + 1238 + diff --git a/public/images/categories/1239.svg b/public/images/categories/1239.svg new file mode 100644 index 0000000..7c2d465 --- /dev/null +++ b/public/images/categories/1239.svg @@ -0,0 +1,6 @@ + + + + قاب و کیف + 1239 + diff --git a/public/images/categories/1240.svg b/public/images/categories/1240.svg new file mode 100644 index 0000000..d208d6c --- /dev/null +++ b/public/images/categories/1240.svg @@ -0,0 +1,6 @@ + + + + هارد اکست + 1240 + diff --git a/public/images/categories/1241.svg b/public/images/categories/1241.svg new file mode 100644 index 0000000..94d3fbb --- /dev/null +++ b/public/images/categories/1241.svg @@ -0,0 +1,6 @@ + + + + فلش مموری + 1241 + diff --git a/public/images/categories/1242.svg b/public/images/categories/1242.svg new file mode 100644 index 0000000..08b8cd3 --- /dev/null +++ b/public/images/categories/1242.svg @@ -0,0 +1,6 @@ + + + + باطری + 1242 + diff --git a/public/images/categories/1243.svg b/public/images/categories/1243.svg new file mode 100644 index 0000000..32accc5 --- /dev/null +++ b/public/images/categories/1243.svg @@ -0,0 +1,6 @@ + + + + گارد هندز + 1243 + diff --git a/public/images/categories/1244.svg b/public/images/categories/1244.svg new file mode 100644 index 0000000..3127090 --- /dev/null +++ b/public/images/categories/1244.svg @@ -0,0 +1,6 @@ + + + + تبدیل + 1244 + diff --git a/public/images/categories/1245.svg b/public/images/categories/1245.svg new file mode 100644 index 0000000..e02e457 --- /dev/null +++ b/public/images/categories/1245.svg @@ -0,0 +1,6 @@ + + + + ماوس + 1245 + diff --git a/public/images/categories/1246.svg b/public/images/categories/1246.svg new file mode 100644 index 0000000..dd25a9c --- /dev/null +++ b/public/images/categories/1246.svg @@ -0,0 +1,6 @@ + + + + لوازم جان + 1246 + diff --git a/public/images/categories/1247.svg b/public/images/categories/1247.svg new file mode 100644 index 0000000..ca79bad --- /dev/null +++ b/public/images/categories/1247.svg @@ -0,0 +1,6 @@ + + + + کول پد + 1247 + diff --git a/public/images/categories/1248.svg b/public/images/categories/1248.svg new file mode 100644 index 0000000..5e26c3a --- /dev/null +++ b/public/images/categories/1248.svg @@ -0,0 +1,6 @@ + + + + هندزفری ب + 1248 + diff --git a/public/images/categories/1249.svg b/public/images/categories/1249.svg new file mode 100644 index 0000000..46c11fb --- /dev/null +++ b/public/images/categories/1249.svg @@ -0,0 +1,6 @@ + + + + هندزفری گ + 1249 + diff --git a/public/images/categories/1250.svg b/public/images/categories/1250.svg new file mode 100644 index 0000000..d0361b0 --- /dev/null +++ b/public/images/categories/1250.svg @@ -0,0 +1,6 @@ + + + + هارد اینت + 1250 + diff --git a/public/images/categories/1252.svg b/public/images/categories/1252.svg new file mode 100644 index 0000000..2c7b83c --- /dev/null +++ b/public/images/categories/1252.svg @@ -0,0 +1,6 @@ + + + + گوشی های + 1252 + diff --git a/public/images/categories/1257.svg b/public/images/categories/1257.svg new file mode 100644 index 0000000..a489def --- /dev/null +++ b/public/images/categories/1257.svg @@ -0,0 +1,6 @@ + + + + لوازم جان + 1257 + diff --git a/public/images/categories/1262.svg b/public/images/categories/1262.svg new file mode 100644 index 0000000..99131ef --- /dev/null +++ b/public/images/categories/1262.svg @@ -0,0 +1,6 @@ + + + + دوربین عک + 1262 + diff --git a/public/images/categories/1265.svg b/public/images/categories/1265.svg new file mode 100644 index 0000000..7d20c21 --- /dev/null +++ b/public/images/categories/1265.svg @@ -0,0 +1,6 @@ + + + + رینگ لایت + 1265 + diff --git a/public/images/categories/1266.svg b/public/images/categories/1266.svg new file mode 100644 index 0000000..aadc5df --- /dev/null +++ b/public/images/categories/1266.svg @@ -0,0 +1,6 @@ + + + + نگهدارنده + 1266 + diff --git a/public/images/categories/1267.svg b/public/images/categories/1267.svg new file mode 100644 index 0000000..493b761 --- /dev/null +++ b/public/images/categories/1267.svg @@ -0,0 +1,6 @@ + + + + میکروفون + 1267 + diff --git a/public/images/categories/1270.svg b/public/images/categories/1270.svg new file mode 100644 index 0000000..1f6f23f --- /dev/null +++ b/public/images/categories/1270.svg @@ -0,0 +1,6 @@ + + + + خطوط کارک + 1270 + diff --git a/scripts/gen-category-placeholders.mjs b/scripts/gen-category-placeholders.mjs index 2251efa..800c8f0 100644 --- a/scripts/gen-category-placeholders.mjs +++ b/scripts/gen-category-placeholders.mjs @@ -1,6 +1,9 @@ -// Writes one placeholder thumbnail per top-level product category into -// public/images/categories/{id}.svg. They are meant to be replaced with real -// artwork one file at a time — the carousel reads the same paths either way. +// Writes one placeholder thumbnail per product category (every level, not +// just level-2) into public/images/categories/{id}.svg. They are meant to be +// replaced with real artwork one file at a time — the carousel and any other +// page that links a specific category id (e.g. /installments) read the same +// paths either way, so every id needs a file, not just the level-2 ones the +// homepage carousel shows by default. // Run: node scripts/gen-category-placeholders.mjs import { mkdir, writeFile } from "node:fs/promises"; @@ -12,14 +15,17 @@ const res = await fetch( ); const { items } = await res.json(); -const roots = items.filter((c) => c.parentId === null).map((c) => c.id); -const level2 = items.filter((c) => c.parentId && roots.includes(c.parentId)); +// Root categories (parentId === null) have no icon of their own on this +// site — nothing links directly to "کالای دیجیتال" itself — so only their +// descendants get a placeholder. +const roots = new Set(items.filter((c) => c.parentId === null).map((c) => c.id)); +const withIcons = items.filter((c) => !roots.has(c.id)); await mkdir(OUT, { recursive: true }); const escape = (s) => s.replace(/&/g, "&").replace(//g, ">"); -for (const cat of level2) { +for (const cat of withIcons) { const label = escape(cat.nameFa || cat.name); const svg = ` @@ -31,4 +37,4 @@ for (const cat of level2) { await writeFile(new URL(`${cat.id}.svg`, OUT), svg, "utf8"); } -console.log(`wrote ${level2.length} placeholders to public/images/categories/`); +console.log(`wrote ${withIcons.length} placeholders to public/images/categories/`); diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx new file mode 100644 index 0000000..acf7df9 --- /dev/null +++ b/src/app/about/page.tsx @@ -0,0 +1,141 @@ +import type { Metadata } from "next"; +import Image from "next/image"; +import Link from "next/link"; +import Breadcrumbs from "@/components/Breadcrumbs"; +import { CheckIcon } from "@/components/icons"; +import { FALLBACK_BLOGS } from "@/data/fallbackBlogs"; + +export const metadata: Metadata = { + title: "درباره ما", + description: + "فروشگاه اینترنتی موبایل معلم، بیش از دو دهه تجربه در عرضه موبایل، لپ‌تاپ، کنسول بازی و لوازم جانبی دیجیتال با ضمانت اصالت کالا.", +}; + +// Real copy transcribed from the live moalem.shop theme's about-us module — +// see the paragraph match confirmed against the cached homepage HTML. +const INTRO = + "فروشگاه اینترنتی موبایل معلم با گستره‌ای از کالاهای متنوع در زمینه دیجیتال، برای کاربران خود «تجربه‌ای لذت‌بخش از یک خرید اینترنتی» را تداعی می‌کند. ارسال سریع، ضمانت بهترین قیمت و تضمین اصل بودن کالا، سه اصل اولیه‌ای است که ما از نخستین روز سعی کرده‌ایم به آن پایبند باشیم. فروشگاه موبایل معلم فعالیت خود را از سال ۱۳۸۰ با دو دهه تجربه در صنف موبایل آغاز نمود. این شرکت مفتخر است که با بهره‌گیری از کادری متخصص و مجرب، توانسته گام‌های بلندی در زمینه تامین و پخش تلفن همراه، لپ‌تاپ، کنسول بازی، دوربین دیجیتال و انواع تجهیزات و اکسسوری کالای دیجیتال بردارد و سهم شایسته‌ای در حوزه موبایل و رایانه را به خود اختصاص دهد."; + +const ACTIVITIES = [ + "عرضه انواع گوشی‌های موبایل و تبلت برندهای اصلی", + "عرضه و فروش انواع لپ‌تاپ‌های ایسوس و لنوو", + "عرضه انواع کنسول بازی و دوربین‌های دیجیتال", + "فروش و عرضه انواع اکسسوری موبایل در بندهای مختلف", + "ارائه پشتیبانی و خدمات پس از فروش مناسب با نیاز مشتریان", + "تعمیرات تخصصی انواع لپ‌تاپ، موبایل و…", + "فروش اقساطی تمامی کالاهای دیجیتال", + "فروش آنلاین به همکاران عزیز و مشتریان گرامی", +]; + +const BRANDS = ["Samsung", "Apple", "Xiaomi", "Huawei", "Asus", "Lenovo", "Nokia"]; + +export default function AboutPage() { + return ( +
+ +

درباره ما

+ + {/* Intro */} +
+
+ + بیش از ۱۰۰+ فروش موفق + +

فروشگاه موبایل معلم را بیشتر بشناسید

+

{INTRO}

+
+
+ گوشی موبایل از فروشگاه موبایل معلم +
+
+ + {/* Brand strip */} +
+ {BRANDS.map((b) => ( + + {b} + + ))} +
+ + {/* Activities */} +
+
+ ساعت هوشمند از فروشگاه موبایل معلم +
+ +
+

از ما بیشتر بدانید

+

زمینه فعالیت شرکت به شرح زیر می‌باشد:

+
    + {ACTIVITIES.map((item, i) => ( +
  • + + {item} +
  • + ))} +
+ + همین حالا با ما تماس بگیرید + +
+
+ + {/* Magazine highlight */} +
+

از مجله معلم بخوانید

+
+
    + {FALLBACK_BLOGS.slice(0, 3).map((post) => ( +
  • + + {post.title} + +
    + {post.category} +

    {post.title}

    +
    +
  • + ))} +
+ +
+ + {FALLBACK_BLOGS[0].title} + {/* Flat overlay, not a gradient — this site's design keeps to flat fills. */} + + + {FALLBACK_BLOGS[0].category} + +

+ {FALLBACK_BLOGS[0].title} +

+
+
+
+
+
+ + ); +} diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx new file mode 100644 index 0000000..9cf1814 --- /dev/null +++ b/src/app/contact/page.tsx @@ -0,0 +1,100 @@ +import type { Metadata } from "next"; +import Breadcrumbs from "@/components/Breadcrumbs"; +import ContactForm from "@/components/ContactForm"; +import { InstagramIcon, MailIcon, MapPinIcon, PhoneIcon, TelegramIcon } from "@/components/icons"; +import { BRANCHES, MOBILE, MOBILE_HREF, PHONE, PHONE_HREF, SOCIAL } from "@/data/site"; + +export const metadata: Metadata = { + title: "تماس با ما", + description: "راه‌های تماس با فروشگاه موبایل معلم — شماره تماس، آدرس شعب و فرم ارسال پیام.", +}; + +export default function ContactPage() { + return ( +
+ +

تماس با ما

+

+ سوالی دارید؟ فرم زیر را پر کنید یا مستقیم با ما تماس بگیرید. +

+ +
+
+

فرم ارسال پیام

+ +
+ +
+
+

راه‌های ارتباطی

+ + + +
+ + {BRANCHES.map((branch) => ( +
+
+ + + +
+

{branch.title}

+

{branch.address}

+
+
+