diff --git a/prompt.txt b/prompt.txt new file mode 100644 index 0000000..ed5a22d --- /dev/null +++ b/prompt.txt @@ -0,0 +1,33 @@ +Create a website for kids and infants clothes store +nininaderi.com + +Create sample content +Lang:fa +Directions: rtl +Use next js +Color palette is purple cyan red - light theme + +Design only homepage +Use Persian font like iran-yekan or kalameh or iran sans and some cool kids like English font +Do not use images - show only placeholders with sizes +Do not use text over the images or banners - even slider + +Sections are: +1.Top header bar +2. Header +3. Slider with two banner beside - height should be equal +4. Featured categories +5. Four features of our website : +ارسال رایگان بالاتر از ۵ میلیون تومان +ضمانت اصالت کالا +امکان مرجوعی کالا +رنگ بندی کامل + +6. Product Special sale carousel +7. Two banner +8. Product Top selling carousel +9. 3 banner +10. Yeganeh brand product carousel +11. About nini Naderi +12. Latest blog carousel +13. footer \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..bc10306 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,139 @@ @import "tailwindcss"; :root { - --background: #ffffff; - --foreground: #171717; + --purple-50: #f6f1ff; + --purple-100: #ede4ff; + --purple-200: #d8c6ff; + --purple-300: #c4a5ff; + --purple-500: #8b5cf6; + --purple-600: #7c3aed; + --purple-700: #6d28d9; + --purple-800: #5b21b6; + --purple-900: #3b0764; + --cyan-50: #ecfeff; + --cyan-100: #cffafe; + --cyan-200: #a5f3fc; + --cyan-300: #67e8f9; + --cyan-400: #22d3ee; + --cyan-500: #06b6d4; + --cyan-600: #0891b2; + --rose-50: #fff1f2; + --rose-100: #ffe4e6; + --rose-200: #fecdd3; + --rose-300: #fda4af; + --rose-500: #f43f5e; + --rose-600: #e11d48; + --ink: #2a1838; + --muted: #6d5b78; + --line: #efe6f5; + --paper: #fffafd; } @theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); + --color-purple-50: var(--purple-50); + --color-purple-100: var(--purple-100); + --color-purple-200: var(--purple-200); + --color-purple-300: var(--purple-300); + --color-purple-500: var(--purple-500); + --color-purple-600: var(--purple-600); + --color-purple-700: var(--purple-700); + --color-purple-800: var(--purple-800); + --color-purple-900: var(--purple-900); + --color-cyan-50: var(--cyan-50); + --color-cyan-100: var(--cyan-100); + --color-cyan-200: var(--cyan-200); + --color-cyan-300: var(--cyan-300); + --color-cyan-400: var(--cyan-400); + --color-cyan-500: var(--cyan-500); + --color-cyan-600: var(--cyan-600); + --color-rose-50: var(--rose-50); + --color-rose-100: var(--rose-100); + --color-rose-200: var(--rose-200); + --color-rose-300: var(--rose-300); + --color-rose-500: var(--rose-500); + --color-rose-600: var(--rose-600); + --color-ink: var(--ink); + --color-muted: var(--muted); + --color-line: var(--line); + --color-paper: var(--paper); + --font-sans: var(--font-vazirmatn), "IranYekan", "IRANSans", Tahoma, sans-serif; + --font-display: var(--font-fredoka), "Fredoka", "Comic Sans MS", cursive; + --shadow-card: 0 10px 30px -18px rgb(91 33 182 / 0.28); + --shadow-soft: 0 8px 24px -16px rgb(42 24 56 / 0.18); } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +html { + scroll-behavior: smooth; } body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + background-color: var(--paper); + background-image: + radial-gradient(ellipse 90% 42% at 10% 8%, rgb(237 228 255 / 0.9), transparent 70%), + radial-gradient(ellipse 80% 38% at 92% 6%, rgb(207 250 254 / 0.85), transparent 68%), + radial-gradient(ellipse 85% 40% at 78% 28%, rgb(255 228 230 / 0.8), transparent 70%), + radial-gradient(ellipse 70% 28% at 18% 36%, rgb(237 228 255 / 0.55), transparent 72%), + linear-gradient(to bottom, transparent 0%, transparent 62%, var(--paper) 100%); + background-repeat: no-repeat; + background-size: 100% 2200px; + background-position: top center; + color: var(--ink); + font-family: var(--font-sans); +} + +.glass-box { + background: rgb(255 255 255 / 0.58); + backdrop-filter: blur(18px); + -webkit-backdrop-filter: blur(18px); + border: 1px solid rgb(255 255 255 / 0.72); +} + +.font-display { + font-family: var(--font-display); +} + +.font-count { + font-family: var(--font-count), var(--font-vazirmatn), sans-serif; +} + +.container-nn { + margin-inline: auto; + width: 100%; + max-width: 1280px; + padding-inline: 1rem; +} + +@media (min-width: 768px) { + .container-nn { + padding-inline: 1.25rem; + } +} + +.placeholder-grid { + background-image: linear-gradient(135deg, rgb(255 255 255 / 0.22) 0%, transparent 48%); + background-repeat: no-repeat; +} + +.hide-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; +} + +.hide-scrollbar::-webkit-scrollbar { + display: none; +} + +.slider-fade { + animation: slider-in 520ms ease; +} + +@keyframes slider-in { + from { + opacity: 0; + transform: translateX(18px); + } + to { + opacity: 1; + transform: translateX(0); + } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9852c15..23af5a8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,29 +1,40 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { Baloo_Bhaijaan_2, Fredoka, Vazirmatn } from "next/font/google"; import "./globals.css"; -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], +const vazirmatn = Vazirmatn({ + subsets: ["arabic", "latin"], + variable: "--font-vazirmatn", + display: "swap", }); -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", +const fredoka = Fredoka({ subsets: ["latin"], + variable: "--font-fredoka", + display: "swap", +}); + +const baloo = Baloo_Bhaijaan_2({ + subsets: ["arabic", "latin"], + variable: "--font-count", + display: "swap", }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "نینی نادری | فروشگاه پوشاک نوزاد و کودک", + description: + "فروشگاه نینی نادری؛ لباس نوزاد، دخترانه و پسرانه با رنگ‌بندی کامل، ضمانت اصالت و ارسال رایگان بالای ۵ میلیون تومان.", + metadataBase: new URL("https://nininaderi.com"), }; export default function RootLayout({ children }: LayoutProps<"/">) { return ( - {children} + {children} ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index c887311..420f456 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,69 +1,49 @@ -import Image from "next/image"; +import { About } from "@/components/About"; +import { DualBanners, TripleBanners } from "@/components/Banners"; +import { BlogCarousel } from "@/components/BlogCarousel"; +import { FeaturedCategories } from "@/components/FeaturedCategories"; +import { Features } from "@/components/Features"; +import { Footer } from "@/components/Footer"; +import { Header } from "@/components/Header"; +import { Hero } from "@/components/Hero"; +import { ProductCarousel } from "@/components/ProductCarousel"; +import { TopHeader } from "@/components/TopHeader"; +import { saleProducts, topProducts, yeganehProducts } from "@/data/content"; export default function Home() { return ( -
-
- Next.js logo + +
+
+ + + + -
-

- To get started, edit the{" "} - - page.tsx - {" "} - file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
- + + + + + +
+
); } diff --git a/src/components/About.tsx b/src/components/About.tsx new file mode 100644 index 0000000..07ef2fe --- /dev/null +++ b/src/components/About.tsx @@ -0,0 +1,40 @@ +import { about } from "@/data/content"; +import { Placeholder } from "./Placeholder"; + +export function About() { + return ( +
+
+
+
+

{about.english}

+

{about.title}

+ +
+ {about.paragraphs.map((paragraph) => ( +

{paragraph}

+ ))} +
+
+ {about.stats.map((stat) => ( +
+

{stat.value}

+

{stat.label}

+
+ ))} +
+
+
+ +
+
+
+
+ ); +} diff --git a/src/components/Banners.tsx b/src/components/Banners.tsx new file mode 100644 index 0000000..ea75c18 --- /dev/null +++ b/src/components/Banners.tsx @@ -0,0 +1,30 @@ +import { dualBanners, tripleBanners } from "@/data/content"; +import { Placeholder } from "./Placeholder"; + +export function DualBanners() { + return ( +
+
+ {dualBanners.map((banner) => ( + + + + ))} +
+
+ ); +} + +export function TripleBanners() { + return ( +
+
+ {tripleBanners.map((banner) => ( + + + + ))} +
+
+ ); +} diff --git a/src/components/BlogCarousel.tsx b/src/components/BlogCarousel.tsx new file mode 100644 index 0000000..f25c0ce --- /dev/null +++ b/src/components/BlogCarousel.tsx @@ -0,0 +1,33 @@ +import { posts } from "@/data/content"; +import { Carousel } from "./Carousel"; +import { Placeholder } from "./Placeholder"; +import { SectionHeading } from "./SectionHeading"; + +export function BlogCarousel() { + return ( +
+ + + {posts.map((post) => ( + + ))} + +
+ ); +} diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx new file mode 100644 index 0000000..97c57c2 --- /dev/null +++ b/src/components/Carousel.tsx @@ -0,0 +1,48 @@ +"use client"; + +import { useRef, type ReactNode } from "react"; +import { IconChevron } from "./Icons"; + +type Props = { + children: ReactNode; +}; + +export function Carousel({ children }: Props) { + const scroller = useRef(null); + + const move = (direction: 1 | -1) => { + const el = scroller.current; + if (!el) return; + const card = el.querySelector("[data-card]"); + const amount = (card?.offsetWidth ?? 260) + 16; + const rtl = getComputedStyle(el).direction === "rtl"; + el.scrollBy({ left: amount * direction * (rtl ? -1 : 1), behavior: "smooth" }); + }; + + return ( +
+ + +
+ {children} +
+
+ ); +} diff --git a/src/components/FeaturedCategories.tsx b/src/components/FeaturedCategories.tsx new file mode 100644 index 0000000..a981efc --- /dev/null +++ b/src/components/FeaturedCategories.tsx @@ -0,0 +1,30 @@ +import { categories } from "@/data/content"; +import { toFaDigits } from "@/lib/format"; +import { Placeholder } from "./Placeholder"; +import { SectionHeading } from "./SectionHeading"; + +export function FeaturedCategories() { + return ( +
+ +
+ {categories.map((category) => ( + + +

{category.title}

+

{toFaDigits(category.count)} مدل

+
+ ))} +
+
+ ); +} diff --git a/src/components/Features.tsx b/src/components/Features.tsx new file mode 100644 index 0000000..e6e10a5 --- /dev/null +++ b/src/components/Features.tsx @@ -0,0 +1,41 @@ +import { features } from "@/data/content"; +import { IconPalette, IconReturn, IconShield, IconTruck } from "./Icons"; + +const icons = { + truck: IconTruck, + shield: IconShield, + return: IconReturn, + palette: IconPalette, +}; + +export function Features() { + return ( +
+
+ {features.map((feature, index) => { + const Icon = icons[feature.icon]; + const colors = [ + "bg-purple-50 text-purple-700", + "bg-cyan-50 text-cyan-600", + "bg-rose-50 text-rose-600", + "bg-purple-50 text-cyan-600", + ]; + return ( +
+ + + +
+

{feature.title}

+

{feature.text}

+
+
+ ); + })} +
+
+ ); +} diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 0000000..27f6a74 --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,76 @@ +import Link from "next/link"; +import { footer } from "@/data/content"; +import { IconInstagram, IconPhone } from "./Icons"; +import { Placeholder } from "./Placeholder"; + +export function Footer() { + return ( +
+
+
+ + + NN + + + Nini Naderi + نینی نادری + + +

{footer.blurb}

+
+ + {footer.contact.phone} +
+ + + nininaderi + +
+ + + + + +
+

تماس و اعتماد

+

{footer.contact.address}

+

{footer.contact.email}

+
+
+ +

اینماد

+
+
+ +

ساماندهی

+
+
+
+
+
+
+

© ۱۴۰۵ نینی نادری — nininaderi.com — همه حقوق محفوظ است.

+

Made for little wardrobes

+
+
+
+ ); +} + +function FooterList({ title, items }: { title: string; items: string[] }) { + return ( +
+

{title}

+ +
+ ); +} diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..c8ffcd6 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,109 @@ +"use client"; + +import Link from "next/link"; +import { useState } from "react"; +import { navLinks } from "@/data/content"; +import { IconBag, IconClose, IconHeart, IconMenu, IconSearch, IconUser } from "./Icons"; + +export function Header() { + const [open, setOpen] = useState(false); + + return ( +
+
+
+ + + + + NN + + + Nini Naderi + نینی نادری + + + +
+ + + + +
+ + +
+ +
+
+ + + + +
+
+ + +
+ + {open ? ( +
+ +
+ ) : null} +
+ ); +} diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx new file mode 100644 index 0000000..2c7a3ff --- /dev/null +++ b/src/components/Hero.tsx @@ -0,0 +1,62 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { sideBanners, slides } from "@/data/content"; +import { Placeholder } from "./Placeholder"; + +export function Hero() { + const [index, setIndex] = useState(0); + const slide = slides[index]; + + useEffect(() => { + const timer = window.setInterval(() => { + setIndex((current) => (current + 1) % slides.length); + }, 5200); + return () => window.clearInterval(timer); + }, []); + + return ( +
+
+
+ +
+ {slides.map((item, itemIndex) => ( + + ))} +
+
+ + {sideBanners.map((banner) => ( + + + + ))} +
+
+ ); +} diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx new file mode 100644 index 0000000..fd3bd25 --- /dev/null +++ b/src/components/Icons.tsx @@ -0,0 +1,161 @@ +type IconProps = { className?: string }; + +export function IconSearch({ className = "size-5" }: IconProps) { + return ( + + + + + ); +} + +export function IconUser({ className = "size-5" }: IconProps) { + return ( + + + + + ); +} + +export function IconHeart({ className = "size-5" }: IconProps) { + return ( + + + + ); +} + +export function IconBag({ className = "size-5" }: IconProps) { + return ( + + + + + ); +} + +export function IconPhone({ className = "size-4" }: IconProps) { + return ( + + + + ); +} + +export function IconTruck({ className = "size-7" }: IconProps) { + return ( + + + + + + + ); +} + +export function IconShield({ className = "size-7" }: IconProps) { + return ( + + + + + ); +} + +export function IconReturn({ className = "size-7" }: IconProps) { + return ( + + + + + ); +} + +export function IconPalette({ className = "size-7" }: IconProps) { + return ( + + + + + + + ); +} + +export function IconChevron({ className = "size-5" }: IconProps) { + return ( + + + + ); +} + +export function IconMenu({ className = "size-6" }: IconProps) { + return ( + + + + ); +} + +export function IconClose({ className = "size-6" }: IconProps) { + return ( + + + + ); +} + +export function IconInstagram({ className = "size-4" }: IconProps) { + return ( + + + + + + ); +} diff --git a/src/components/Placeholder.tsx b/src/components/Placeholder.tsx new file mode 100644 index 0000000..6439cb6 --- /dev/null +++ b/src/components/Placeholder.tsx @@ -0,0 +1,41 @@ +import type { Tone } from "@/data/content"; + +const tones: Record = { + purple: "bg-purple-200 from-purple-300 via-purple-200 to-purple-100 text-purple-800", + cyan: "bg-cyan-100 from-cyan-300 via-cyan-200 to-cyan-100 text-cyan-800", + rose: "bg-rose-100 from-rose-300 via-rose-200 to-rose-100 text-rose-700", +}; + +type Props = { + width: number; + height: number; + tone?: Tone; + className?: string; + rounded?: string; + fill?: boolean; + showSize?: boolean; +}; + +export function Placeholder({ + width, + height, + tone = "purple", + className = "", + rounded = "rounded-2xl", + fill = false, + showSize = true, +}: Props) { + return ( +
+ {showSize ? ( + + {width} × {height} + + ) : null} +
+ ); +} diff --git a/src/components/ProductCard.tsx b/src/components/ProductCard.tsx new file mode 100644 index 0000000..f5e6bcd --- /dev/null +++ b/src/components/ProductCard.tsx @@ -0,0 +1,67 @@ +import type { Product } from "@/data/content"; +import { formatPrice } from "@/lib/format"; +import { Placeholder } from "./Placeholder"; + +type Props = { + product: Product; +}; + +export function ProductCard({ product }: Props) { + return ( +
+ +
+
+

{product.brand}

+ {product.badge ? ( + + {product.badge} + + ) : null} +
+

+ {product.title} +

+
+ {product.colors.map((color) => ( + + ))} +
+
+
+ {product.oldPrice ? ( +

{formatPrice(product.oldPrice)}

+ ) : null} +

{formatPrice(product.price)}

+
+ +
+
+
+ ); +} diff --git a/src/components/ProductCarousel.tsx b/src/components/ProductCarousel.tsx new file mode 100644 index 0000000..c53f95d --- /dev/null +++ b/src/components/ProductCarousel.tsx @@ -0,0 +1,109 @@ +"use client"; + +import { useEffect, useState } from "react"; +import type { Product } from "@/data/content"; +import { toFaDigits } from "@/lib/format"; +import { Carousel } from "./Carousel"; +import { Placeholder } from "./Placeholder"; +import { ProductCard } from "./ProductCard"; +import { SectionHeading } from "./SectionHeading"; + +type Props = { + id?: string; + english: string; + title: string; + products: Product[]; + countdown?: boolean; + leadBanner?: boolean; +}; + +export function ProductCarousel({ + id, + english, + title, + products, + countdown, + leadBanner, +}: Props) { + return ( +
+ + {countdown ? : null} + + + {leadBanner ? ( + + + + ) : null} + {products.map((product) => ( + + ))} + +
+ ); +} + +function SaleTimer() { + const [left, setLeft] = useState({ h: 11, m: 42, s: 18 }); + + useEffect(() => { + const timer = window.setInterval(() => { + setLeft((current) => { + let { h, m, s } = current; + if (s > 0) s -= 1; + else if (m > 0) { + s = 59; + m -= 1; + } else if (h > 0) { + s = 59; + m = 59; + h -= 1; + } else { + h = 11; + m = 59; + s = 59; + } + return { h, m, s }; + }); + }, 1000); + return () => window.clearInterval(timer); + }, []); + + const cells = [ + { label: "ساعت", value: left.h }, + { label: "دقیقه", value: left.m }, + { label: "ثانیه", value: left.s }, + ]; + + return ( +
+ {cells.map((cell, index) => ( +
+ {index > 0 ? ( + : + ) : null} +
+

+ {toFaDigits(String(cell.value).padStart(2, "0"))} +

+

{cell.label}

+
+
+ ))} +
+ ); +} diff --git a/src/components/SectionHeading.tsx b/src/components/SectionHeading.tsx new file mode 100644 index 0000000..b160775 --- /dev/null +++ b/src/components/SectionHeading.tsx @@ -0,0 +1,29 @@ +import type { ReactNode } from "react"; + +type Props = { + english: string; + title: string; + href?: string; + children?: ReactNode; +}; + +export function SectionHeading({ english, title, href = "#", children }: Props) { + return ( +
+
+

{english}

+

{title}

+ +
+
+ {children} + + مشاهده همه + +
+
+ ); +} diff --git a/src/components/TopHeader.tsx b/src/components/TopHeader.tsx new file mode 100644 index 0000000..55e9e10 --- /dev/null +++ b/src/components/TopHeader.tsx @@ -0,0 +1,21 @@ +import { IconInstagram, IconPhone } from "./Icons"; + +export function TopHeader() { + return ( +
+
+

ارسال رایگان برای خریدهای بالای ۵ میلیون تومان

+ +
+
+ ); +} diff --git a/src/data/content.ts b/src/data/content.ts new file mode 100644 index 0000000..bbe14d7 --- /dev/null +++ b/src/data/content.ts @@ -0,0 +1,430 @@ +export type Tone = "purple" | "cyan" | "rose"; + +export type Product = { + id: string; + title: string; + brand: string; + price: number; + oldPrice?: number; + colors: string[]; + tone: Tone; + badge?: string; +}; + +export const navLinks = [ + { href: "#", label: "صفحه اصلی" }, + { href: "#categories", label: "نوزاد" }, + { href: "#categories", label: "دخترانه" }, + { href: "#categories", label: "پسرانه" }, + { href: "#yeganeh", label: "برند یگانه" }, + { href: "#sale", label: "فروش ویژه" }, + { href: "#blog", label: "وبلاگ" }, +]; + +export const slides = [ + { + id: "s1", + tone: "purple" as Tone, + kicker: "Summer 1405", + title: "کالکشن تابستان نینی‌ها", + text: "لباس‌های نخی سبک برای بازی، خواب و گردش‌های گرم. رنگ‌بندی کامل از یاسی تا فیروزه‌ای.", + cta: "مشاهده کالکشن", + size: "960 × 420", + }, + { + id: "s2", + tone: "rose" as Tone, + kicker: "Newborn Sale", + title: "تخفیف ویژه نوزادی تا ۴۰٪", + text: "بادی، سرهمی و ست بیمارستانی برای روزهای اول. نرم روی پوست و آماده هدیه.", + cta: "خرید نوزادی", + size: "960 × 420", + }, + { + id: "s3", + tone: "cyan" as Tone, + kicker: "Yeganeh", + title: "برند یگانه حالا در نینی نادری", + text: "دوخت تمیز، پارچه لطیف و ست‌های خواهر و برادری که با هم جور می‌شوند.", + cta: "محصولات یگانه", + size: "960 × 420", + }, +]; + +export const sideBanners = [ + { + id: "sb1", + tone: "cyan" as Tone, + title: "ست خواهر و برادری", + text: "جفت‌های رنگی برای عکس‌های خانوادگی", + size: "360 × 200", + }, + { + id: "sb2", + tone: "rose" as Tone, + title: "کفش اولین قدم", + text: "پاپوش نرم برای نوپاهای کنجکاو", + size: "360 × 200", + }, +]; + +export const categories = [ + { id: "c1", title: "لباس نوزاد", count: 86, tone: "purple" as Tone, size: "160 × 160" }, + { id: "c2", title: "دخترانه", count: 124, tone: "rose" as Tone, size: "160 × 160" }, + { id: "c3", title: "پسرانه", count: 118, tone: "cyan" as Tone, size: "160 × 160" }, + { id: "c4", title: "ست و راحتی", count: 64, tone: "purple" as Tone, size: "160 × 160" }, + { id: "c5", title: "کفش و پاپوش", count: 41, tone: "cyan" as Tone, size: "160 × 160" }, + { id: "c6", title: "اکسسوری", count: 37, tone: "rose" as Tone, size: "160 × 160" }, + { id: "c7", title: "حمام و حوله", count: 22, tone: "purple" as Tone, size: "160 × 160" }, + { id: "c8", title: "مهمانی", count: 29, tone: "rose" as Tone, size: "160 × 160" }, +]; + +export const features = [ + { + id: "f1", + title: "ارسال رایگان بالاتر از ۵ میلیون تومان", + text: "سفارش‌های بالای پنج میلیون، رایگان تا در خانه.", + icon: "truck" as const, + }, + { + id: "f2", + title: "ضمانت اصالت کالا", + text: "هر تگ و دوخت را قبل از ارسال بررسی می‌کنیم.", + icon: "shield" as const, + }, + { + id: "f3", + title: "امکان مرجوعی کالا", + text: "تا ۷ روز اگر سایز یا رنگ جور نبود برمی‌گردد.", + icon: "return" as const, + }, + { + id: "f4", + title: "رنگ بندی کامل", + text: "از یاسی و سرخابی تا فیروزه؛ برای هر سلیقه‌ای.", + icon: "palette" as const, + }, +]; + +export const saleProducts: Product[] = [ + { + id: "p1", + title: "سرهمی نخی نوزاد یاسی", + brand: "نینی نادری", + price: 890000, + oldPrice: 1290000, + colors: ["#C4B5FD", "#F9A8D4", "#67E8F9"], + tone: "purple", + badge: "۳۱٪", + }, + { + id: "p2", + title: "پیراهن چین‌دار دخترانه", + brand: "یگانه", + price: 1450000, + oldPrice: 1890000, + colors: ["#FB7185", "#DDD6FE", "#FDE68A"], + tone: "rose", + badge: "۲۳٪", + }, + { + id: "p3", + title: "تیشرت طرح دایناسور", + brand: "نینی نادری", + price: 620000, + oldPrice: 840000, + colors: ["#22D3EE", "#34D399", "#F97316"], + tone: "cyan", + badge: "۲۶٪", + }, + { + id: "p4", + title: "بادی آستین بلند ارگانیک", + brand: "یگانه", + price: 540000, + oldPrice: 780000, + colors: ["#E9D5FF", "#FECDD3", "#A5F3FC"], + tone: "purple", + badge: "۳۱٪", + }, + { + id: "p5", + title: "شلوار اسلش راحتی", + brand: "نینی نادری", + price: 710000, + oldPrice: 980000, + colors: ["#5B21B6", "#164E63", "#9F1239"], + tone: "cyan", + badge: "۲۸٪", + }, + { + id: "p6", + title: "کت بافت پاییزه خردلی", + brand: "یگانه", + price: 1680000, + oldPrice: 2190000, + colors: ["#FBBF24", "#C4B5FD", "#FDA4AF"], + tone: "rose", + badge: "۲۳٪", + }, + { + id: "p7", + title: "ست بیمارستانی نوزاد", + brand: "نینی نادری", + price: 1120000, + oldPrice: 1590000, + colors: ["#F5D0FE", "#BAE6FD", "#FEF3C7"], + tone: "purple", + badge: "۳۰٪", + }, + { + id: "p8", + title: "کفش پارچه‌ای نوپا", + brand: "یگانه", + price: 980000, + oldPrice: 1350000, + colors: ["#F43F5E", "#06B6D4", "#7C3AED"], + tone: "cyan", + badge: "۲۷٪", + }, +]; + +export const dualBanners = [ + { + id: "db1", + tone: "purple" as Tone, + kicker: "Party Edit", + title: "کالکشن مهمانی کوچولوها", + text: "پیراهن، سارافون و کت‌های نرم برای جشن تولد", + size: "640 × 280", + }, + { + id: "db2", + tone: "cyan" as Tone, + kicker: "Bedtime", + title: "لباس خواب نخی", + text: "شب‌های آرام با پارچه سبک و دوخت بدون خارش", + size: "640 × 280", + }, +]; + +export const topProducts: Product[] = [ + { + id: "t1", + title: "ست خواهر برادری راه راه", + brand: "یگانه", + price: 1980000, + colors: ["#7C3AED", "#06B6D4", "#F43F5E"], + tone: "purple", + badge: "پرفروش", + }, + { + id: "t2", + title: "سارافون جین دخترانه", + brand: "نینی نادری", + price: 1320000, + colors: ["#93C5FD", "#F9A8D4", "#FDE68A"], + tone: "cyan", + badge: "پرفروش", + }, + { + id: "t3", + title: "هودی گوش‌دار خرسی", + brand: "یگانه", + price: 1540000, + colors: ["#FDBA74", "#C4B5FD", "#67E8F9"], + tone: "rose", + badge: "پرفروش", + }, + { + id: "t4", + title: "بادی دکمه فشاری سه‌تایی", + brand: "نینی نادری", + price: 870000, + colors: ["#FDE68A", "#DDD6FE", "#A7F3D0"], + tone: "purple", + badge: "پرفروش", + }, + { + id: "t5", + title: "شلوارک کتان پسرانه", + brand: "یگانه", + price: 760000, + colors: ["#155E75", "#44403C", "#7C3AED"], + tone: "cyan", + badge: "پرفروش", + }, + { + id: "t6", + title: "کلاه و دستکش ست", + brand: "نینی نادری", + price: 390000, + colors: ["#FBCFE8", "#C4B5FD", "#A5F3FC"], + tone: "rose", + badge: "پرفروش", + }, + { + id: "t7", + title: "پیراهن لینن تابستانه", + brand: "یگانه", + price: 1410000, + colors: ["#FDE68A", "#FECDD3", "#C7D2FE"], + tone: "purple", + badge: "پرفروش", + }, + { + id: "t8", + title: "جوراب ساق‌بلند رنگی", + brand: "نینی نادری", + price: 210000, + colors: ["#F43F5E", "#06B6D4", "#8B5CF6"], + tone: "cyan", + badge: "پرفروش", + }, +]; + +export const tripleBanners = [ + { + id: "tb1", + tone: "rose" as Tone, + title: "دخترانه بهاری", + text: "گل‌گلی، چین‌دار و روشن", + size: "420 × 240", + }, + { + id: "tb2", + tone: "cyan" as Tone, + title: "پسرانه اسپرت", + text: "هودی، تیشرت و شلوارک بازی", + size: "420 × 240", + }, + { + id: "tb3", + tone: "purple" as Tone, + title: "نوزادی ارگانیک", + text: "پنبه لطیف برای پوست حساس", + size: "420 × 240", + }, +]; + +export const yeganehProducts: Product[] = [ + { + id: "y1", + title: "سرهمی یگانه طرح ستاره", + brand: "یگانه", + price: 1180000, + colors: ["#7C3AED", "#F472B6", "#22D3EE"], + tone: "purple", + badge: "یگانه", + }, + { + id: "y2", + title: "ست دوتکه یگانه دخترانه", + brand: "یگانه", + price: 1720000, + colors: ["#FB7185", "#C4B5FD", "#FDE68A"], + tone: "rose", + badge: "یگانه", + }, + { + id: "y3", + title: "پولوشرت یگانه پسرانه", + brand: "یگانه", + price: 990000, + colors: ["#0891B2", "#1E3A5F", "#F43F5E"], + tone: "cyan", + badge: "یگانه", + }, + { + id: "y4", + title: "بادی یگانه بسته دوتایی", + brand: "یگانه", + price: 860000, + colors: ["#E9D5FF", "#A5F3FC", "#FECDD3"], + tone: "purple", + badge: "یگانه", + }, + { + id: "y5", + title: "پیراهن یقه ب ب یگانه", + brand: "یگانه", + price: 1390000, + colors: ["#F9A8D4", "#FDE68A", "#C4B5FD"], + tone: "rose", + badge: "یگانه", + }, + { + id: "y6", + title: "شلوار جین نرم یگانه", + brand: "یگانه", + price: 1250000, + colors: ["#93C5FD", "#64748B", "#7C3AED"], + tone: "cyan", + badge: "یگانه", + }, +]; + +export const about = { + title: "درباره نینی نادری", + english: "About Nini Naderi", + paragraphs: [ + "نینی نادری از یک دغدغه ساده شروع شد: پیدا کردن لباسی که هم روی پوست نوزاد نرم باشد، هم رنگش زنده بماند و هم بعد از چند بار شست‌وشو از ریخت نیفتد. ما فروشگاه تخصصی پوشاک نوزاد و کودک هستیم؛ از بادی روزهای اول تا کفش اولین قدم.", + "برند یگانه یکی از ثابت‌های قفسه ماست؛ به‌خاطر دوخت تمیز و رنگ‌بندی کاملی که برای خواهر و برادرها جور درمی‌آید. کنار آن، انتخاب‌های خود نینی نادری را با پارچه‌های نخی و سایزبندی دقیق کنار هم چیده‌ایم.", + "هر سفارش با ضمانت اصالت ارسال می‌شود، امکان مرجوعی دارید و برای خریدهای بالای ۵ میلیون تومان پیک رایگان است. اگر سایز شک دارید، پشتیبانی نینی نادری کمکتان می‌کند.", + ], + stats: [ + { value: "۱۲ سال", label: "همراه خانواده‌ها" }, + { value: "+۴۰۰", label: "مدل فعال" }, + { value: "۲۴ ساعته", label: "پاسخگویی سفارش" }, + ], + imageSize: "560 × 400", +}; + +export const posts = [ + { + id: "b1", + tone: "purple" as Tone, + date: "۲۳ مرداد ۱۴۰۵", + title: "چطور سایز لباس نوزاد را درست حدس بزنیم؟", + excerpt: "جدول دور سینه، قد و وزن؛ بدون خرید اشتباه و مرجوعی اضافه.", + size: "360 × 220", + }, + { + id: "b2", + tone: "cyan" as Tone, + date: "۱۸ مرداد ۱۴۰۵", + title: "پارچه نخی بهتر است یا پنبه ارگانیک؟", + excerpt: "برای پوست حساس تابستان، کدام بافت خنک‌تر و کم‌حساسیت‌تر است.", + size: "360 × 220", + }, + { + id: "b3", + tone: "rose" as Tone, + date: "۹ مرداد ۱۴۰۵", + title: "کفش اولین قدم؛ نرم باشد یا محکم؟", + excerpt: "پاپوش مناسب نوپا باید قوزک را نگه دارد اما انگشت را آزاد بگذارد.", + size: "360 × 220", + }, + { + id: "b4", + tone: "purple" as Tone, + date: "۱ مرداد ۱۴۰۵", + title: "ست خواهر و برادری برای عکس تولد", + excerpt: "چطور رنگ‌ها را با هم هماهنگ کنیم بدون اینکه لباس‌ها شبیه یونیفرم شوند.", + size: "360 × 220", + }, +]; + +export const footer = { + blurb: + "فروشگاه پوشاک نوزاد و کودک نینی نادری. لباس نرم، رنگ زنده، ارسال سریع.", + shop: ["نوزاد", "دخترانه", "پسرانه", "برند یگانه", "فروش ویژه"], + help: ["پیگیری سفارش", "راهنمای سایز", "مرجوعی کالا", "سوالات پرتکرار", "تماس با ما"], + about: ["داستان نینی نادری", "شعب حضوری", "فرصت همکاری", "قوانین و حریم خصوصی"], + contact: { + phone: "۰۲۱-۹۱۰۰۱۲۳۴", + mobile: "۰۹۱۲۳۴۵۶۷۸۹", + email: "hello@nininaderi.com", + address: "تهران، خیابان شریعتی، بالاتر از میرداماد، پلاک ۲۴۸", + }, +}; diff --git a/src/lib/format.ts b/src/lib/format.ts new file mode 100644 index 0000000..1df65bf --- /dev/null +++ b/src/lib/format.ts @@ -0,0 +1,9 @@ +const FA_DIGITS = ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"]; + +export function toFaDigits(value: number | string) { + return String(value).replace(/\d/g, (digit) => FA_DIGITS[Number(digit)]); +} + +export function formatPrice(value: number) { + return `${toFaDigits(value.toLocaleString("en-US"))} تومان`; +}