diff --git a/next.config.ts b/next.config.ts index 6832aa2..ae2d0e2 100644 --- a/next.config.ts +++ b/next.config.ts @@ -3,11 +3,6 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { images: { remotePatterns: [ - { - protocol: "https", - hostname: "meshkee-templates.sas.amin.parminstorage.ir", - pathname: "/**", - }, { protocol: "https", hostname: "meshkee-storage.sas.amin.parminstorage.ir", diff --git a/public/assets/images b/public/assets/images new file mode 120000 index 0000000..4b50e11 --- /dev/null +++ b/public/assets/images @@ -0,0 +1 @@ +../../src/assets/images \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..8edfe81 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/favicon.png b/public/favicon.png new file mode 100644 index 0000000..c09db35 Binary files /dev/null and b/public/favicon.png differ diff --git a/public/images/brand/favicon.png b/public/images/brand/favicon.png new file mode 100755 index 0000000..526698f Binary files /dev/null and b/public/images/brand/favicon.png differ diff --git a/public/images/brand/meshkee-mark.svg b/public/images/brand/meshkee-mark.svg new file mode 100644 index 0000000..3488931 --- /dev/null +++ b/public/images/brand/meshkee-mark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/apple-icon.png b/src/app/apple-icon.png old mode 100755 new mode 100644 index ee9f056..4259ec3 Binary files a/src/app/apple-icon.png and b/src/app/apple-icon.png differ diff --git a/src/app/blog/[slug]/page.tsx b/src/app/blog/[slug]/page.tsx index 4a38888..483f0de 100644 --- a/src/app/blog/[slug]/page.tsx +++ b/src/app/blog/[slug]/page.tsx @@ -59,7 +59,7 @@ export default async function BlogDetailPage({ params }: BlogDetailPageProps) { {blog.categoryName ? ( -

+

{blog.categoryName}

) : null} diff --git a/src/app/blog/page.tsx b/src/app/blog/page.tsx index 666b695..5e5b6bc 100644 --- a/src/app/blog/page.tsx +++ b/src/app/blog/page.tsx @@ -5,8 +5,9 @@ import { Pagination } from "@/components/Pagination"; import { getBlogCoverImage, getBlogs } from "@/lib/api"; export const metadata: Metadata = { - title: "مقالات | مشکی", + title: "مقالات", description: "آخرین مقالات آموزشی و انگیزشی تیم مشکی.", + alternates: { canonical: "/blog" }, }; const PAGE_SIZE = 12; @@ -39,7 +40,7 @@ export default async function BlogListPage({ searchParams }: BlogPageProps) {

رشدنامه، آموزشی و انگیزشی

-

+

Our Blog

diff --git a/src/app/cms-website/page.tsx b/src/app/cms-website/page.tsx index e042528..fa95c14 100644 --- a/src/app/cms-website/page.tsx +++ b/src/app/cms-website/page.tsx @@ -9,14 +9,23 @@ import { import { images } from "@/data/assets"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; const ASSETS = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets"; + "/assets/images"; export const metadata: Metadata = { - title: "وبسایت CMS | مشکی", + title: "طراحی وبسایت با Meshkee CMS", description: "طراحی وبسایت روی سیستم مدیریت محتوای مشکی؛ ویرایش زنده، اتصال به پلتفرم‌ها و کدنویسی اختصاصی.", + alternates: { canonical: "/cms-website" }, + openGraph: { + title: "طراحی وبسایت با Meshkee CMS", + description: + "طراحی وبسایت روی سیستم مدیریت محتوای مشکی؛ ویرایش زنده، اتصال به پلتفرم‌ها و کدنویسی اختصاصی.", + url: "/cms-website", + type: "website", + locale: "fa_IR", + }, }; export default function CmsWebsitePage() { diff --git a/src/app/dedicated-application/page.tsx b/src/app/dedicated-application/page.tsx index 522371d..cd91b75 100644 --- a/src/app/dedicated-application/page.tsx +++ b/src/app/dedicated-application/page.tsx @@ -8,11 +8,12 @@ import { import { images } from "@/data/assets"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; export const metadata: Metadata = { - title: "طراحی اختصاصی اپلیکیشن | مشکی", + title: "طراحی اختصاصی اپلیکیشن", description: "طراحی و توسعه اپلیکیشن موبایل iOS و Android توسط تیم اختصاصی مشکی.", + alternates: { canonical: "/dedicated-application" }, }; export default function DedicatedApplicationPage() { diff --git a/src/app/favicon.ico b/src/app/favicon.ico index 718d6fe..8edfe81 100644 Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ diff --git a/src/app/globals.css b/src/app/globals.css index b06775d..0a76cc9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -85,6 +85,25 @@ h4 { letter-spacing: 0.04em; } +/* English subtitle under FA titles */ +:is(h1, h2):has(+ .title-en) { + margin-bottom: 0 !important; +} + +.title-en { + margin-top: 0.25rem; + font-size: 0.8125rem; + letter-spacing: 0.28em; + text-transform: uppercase; +} + +.title-en-sm { + margin-top: 0.15rem; + font-size: 0.7rem; + letter-spacing: 0.22em; + text-transform: uppercase; +} + .text-body { text-align: justify; text-justify: inter-word; @@ -267,6 +286,8 @@ a.group-border-hover:hover { color: var(--ink-soft); font-size: 0.975rem; line-height: 2; + text-align: justify; + text-justify: inter-word; } .prose-content > *:first-child { diff --git a/src/app/graphic-designer/page.tsx b/src/app/graphic-designer/page.tsx index 5a25ec2..48245a1 100644 --- a/src/app/graphic-designer/page.tsx +++ b/src/app/graphic-designer/page.tsx @@ -10,13 +10,14 @@ import { import { images } from "@/data/assets"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; const ASSETS = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets"; + "/assets/images"; export const metadata: Metadata = { - title: "طراحی گرافیک و هویت بصری | مشکی", + title: "طراحی گرافیک و هویت بصری", description: "طراحی لوگو، هویت بصری، کاتالوگ، بروشور و گرافیک شبکه‌های اجتماعی توسط تیم مشکی.", + alternates: { canonical: "/graphic-designer" }, }; export default function GraphicDesignerPage() { diff --git a/src/app/icon.png b/src/app/icon.png old mode 100755 new mode 100644 index ee9f056..c190c48 Binary files a/src/app/icon.png and b/src/app/icon.png differ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index de76373..e766f29 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -14,13 +14,75 @@ const montserrat = Montserrat({ display: "swap", }); +const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "https://www.meshkee.com"; + export const metadata: Metadata = { - title: "تیم برنامه‌نویسی و تجارت الکترونیک مشکی | Meshkee", + metadataBase: new URL(siteUrl), + title: { + default: "تیم برنامه‌نویسی و تجارت الکترونیک مشکی | Meshkee", + template: "%s | مشکی", + }, description: "راهکارهای مدرن برای تجارت شما — طراحی وبسایت، اپلیکیشن، سیستم‌های مدیریتی، سئو و گرافیک توسط تیم مشکی.", + applicationName: "Meshkee", + authors: [{ name: "Meshkee", url: siteUrl }], + creator: "Meshkee", + publisher: "Meshkee", + keywords: [ + "مشکی", + "Meshkee", + "طراحی وبسایت", + "طراحی اپلیکیشن", + "سئو", + "CMS", + "قم", + ], icons: { - icon: "/images/brand/mark-black.png", - apple: "/images/brand/mark-black.png", + icon: [ + { url: "/images/brand/meshkee-mark.svg", type: "image/svg+xml" }, + { url: "/favicon.ico", sizes: "any" }, + { url: "/images/brand/favicon.png", type: "image/png", sizes: "512x512" }, + ], + apple: [{ url: "/images/brand/favicon.png", type: "image/png", sizes: "512x512" }], + shortcut: ["/favicon.ico"], + }, + openGraph: { + type: "website", + locale: "fa_IR", + url: siteUrl, + siteName: "Meshkee", + title: "تیم برنامه‌نویسی و تجارت الکترونیک مشکی | Meshkee", + description: + "راهکارهای مدرن برای تجارت شما — طراحی وبسایت، اپلیکیشن، سیستم‌های مدیریتی، سئو و گرافیک توسط تیم مشکی.", + images: [ + { + url: "/images/brand/favicon.png", + width: 512, + height: 512, + alt: "لوگوی مشکی", + }, + ], + }, + twitter: { + card: "summary", + title: "تیم برنامه‌نویسی و تجارت الکترونیک مشکی | Meshkee", + description: + "راهکارهای مدرن برای تجارت شما — طراحی وبسایت، اپلیکیشن، سیستم‌های مدیریتی، سئو و گرافیک توسط تیم مشکی.", + images: ["/images/brand/favicon.png"], + }, + robots: { + index: true, + follow: true, + googleBot: { + index: true, + follow: true, + "max-image-preview": "large", + "max-snippet": -1, + "max-video-preview": -1, + }, + }, + alternates: { + canonical: "/", }, }; diff --git a/src/app/meshkee-cms/page.tsx b/src/app/meshkee-cms/page.tsx index d57f209..ddb804e 100644 --- a/src/app/meshkee-cms/page.tsx +++ b/src/app/meshkee-cms/page.tsx @@ -4,14 +4,15 @@ import { GraphicBrands, cmsBrands } from "@/components/GraphicBrands"; import { images } from "@/data/assets"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; const ASSETS = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets"; + "/assets/images"; export const metadata: Metadata = { - title: "سیستم مدیریت یکپارچه مشکی | Meshkee CMS", + title: "سیستم مدیریت یکپارچه مشکی", description: "سیستم مدیریت یکپارچه مشکی شامل فروشگاه، مالی، انبار، باشگاه مشتریان و محتوا.", + alternates: { canonical: "/meshkee-cms" }, }; export default function MeshkeeCmsPage() { diff --git a/src/app/portfolio/[slug]/page.tsx b/src/app/portfolio/[slug]/page.tsx index 76400f6..7237295 100644 --- a/src/app/portfolio/[slug]/page.tsx +++ b/src/app/portfolio/[slug]/page.tsx @@ -3,10 +3,20 @@ import Link from "next/link"; import { notFound } from "next/navigation"; import { ContentPageShell } from "@/components/ContentPageShell"; import { HtmlContent } from "@/components/HtmlContent"; +import { PortfolioGallery } from "@/components/PortfolioGallery"; +import { + categoryLabelFa, + findPortfolioCategory, + getRootCategories, + portfolioCategoryHref, + topPortfolioCategories, + type PortfolioCategory, +} from "@/data/portfolioCategories"; import { ApiNotFoundError, formatFaDate, getPortfolio, + getPortfolioCategories, getPortfolioCoverImage, } from "@/lib/api"; @@ -14,6 +24,36 @@ type PortfolioDetailPageProps = { params: Promise<{ slug: string }>; }; +function mapApiCategories( + items: Awaited>, +): PortfolioCategory[] { + return items.map((item) => ({ + id: String(item.id), + slug: item.slug, + nameEn: item.name, + nameFa: item.nameFa || item.name, + parentId: item.parentId, + sortOrder: item.sortOrder ?? 0, + })); +} + +function findRootForCategory( + categoryId: string | number | null | undefined, + categories: PortfolioCategory[], +): PortfolioCategory | undefined { + if (categoryId == null) return undefined; + let current = categories.find((c) => c.id === String(categoryId)); + if (!current) return undefined; + + while (current?.parentId) { + const parent = categories.find((c) => c.id === String(current?.parentId)); + if (!parent) break; + current = parent; + } + + return current; +} + export async function generateMetadata({ params, }: PortfolioDetailPageProps): Promise { @@ -47,6 +87,18 @@ export default async function PortfolioDetailPage({ const cover = getPortfolioCoverImage(portfolio); const date = formatFaDate(portfolio.publishedAt); const title = portfolio.titleFa || portfolio.title; + + let allCategories: PortfolioCategory[] = topPortfolioCategories; + try { + allCategories = mapApiCategories(await getPortfolioCategories()); + } catch { + allCategories = topPortfolioCategories; + } + + const categoryFa = categoryLabelFa(portfolio.categoryName, allCategories); + const rootCategory = + findRootForCategory(portfolio.categoryId, allCategories) ?? + findPortfolioCategory(portfolio.categoryName, getRootCategories(allCategories)); const gallery = (portfolio.gallery ?? []).filter( (item) => item.url !== cover, ); @@ -57,16 +109,18 @@ export default async function PortfolioDetailPage({

بازگشت به نمونه‌کارها - {portfolio.categoryName ? ( -

- {portfolio.categoryName} -

+ {categoryFa ? ( +

{categoryFa}

) : null}

@@ -74,13 +128,13 @@ export default async function PortfolioDetailPage({

{portfolio.titleEn ? ( -

+

{portfolio.titleEn}

) : null} {portfolio.abstract ? ( -

+

{portfolio.abstract}

) : null} @@ -95,32 +149,13 @@ export default async function PortfolioDetailPage({ ) : null}
- {cover ? ( -
- -
- ) : null} - - {gallery.length > 0 ? ( -
- {gallery.map((item) => ( -
- -
- ))} -
- ) : null} + ({ + id: item.mediaId, + url: item.url, + }))} + /> {portfolio.mainTextHtml ? (
diff --git a/src/app/portfolio/page.tsx b/src/app/portfolio/page.tsx index a02b744..9a1390d 100644 --- a/src/app/portfolio/page.tsx +++ b/src/app/portfolio/page.tsx @@ -2,46 +2,104 @@ import type { Metadata } from "next"; import Link from "next/link"; import { ContentPageShell } from "@/components/ContentPageShell"; import { Pagination } from "@/components/Pagination"; -import { getPortfolioCoverImage, getPortfolios } from "@/lib/api"; +import { + categoryLabelFa, + findPortfolioCategory, + getDescendantCategoryIds, + getRootCategories, + portfolioCategoryHref, + topPortfolioCategories, + type PortfolioCategory, +} from "@/data/portfolioCategories"; +import { + getPortfolioCategories, + getPortfolioCoverImage, + getPortfolios, + getPortfoliosByCategory, +} from "@/lib/api"; export const metadata: Metadata = { - title: "نمونه‌کارها | مشکی", + title: "نمونه‌کارها", description: "نمونه پروژه‌ها و کارهای انجام‌شده توسط تیم مشکی.", + alternates: { canonical: "/portfolio" }, }; const PAGE_SIZE = 12; type PortfolioPageProps = { - searchParams: Promise<{ page?: string }>; + searchParams: Promise<{ page?: string; category?: string }>; }; +function mapApiCategories( + items: Awaited>, +): PortfolioCategory[] { + return items.map((item) => ({ + id: String(item.id), + slug: item.slug, + nameEn: item.name, + nameFa: item.nameFa || item.name, + parentId: item.parentId, + sortOrder: item.sortOrder ?? 0, + })); +} + export default async function PortfolioListPage({ searchParams, }: PortfolioPageProps) { - const { page: pageParam } = await searchParams; + const { page: pageParam, category: categoryParam } = await searchParams; const page = Math.max(1, Number(pageParam) || 1); + let allCategories: PortfolioCategory[] = topPortfolioCategories; + try { + allCategories = mapApiCategories(await getPortfolioCategories()); + } catch { + allCategories = topPortfolioCategories; + } + + const rootCategories = getRootCategories(allCategories); + const activeCategory = + findPortfolioCategory(categoryParam, allCategories) ?? + findPortfolioCategory(categoryParam, rootCategories); + let items: Awaited>["items"] = []; let total = 0; try { - const data = await getPortfolios({ page, pageSize: PAGE_SIZE }); - items = data.items; - total = data.total; + if (activeCategory) { + const data = await getPortfoliosByCategory({ + categoryId: activeCategory.id, + categoryIds: getDescendantCategoryIds(allCategories, activeCategory.id), + page, + pageSize: PAGE_SIZE, + }); + items = data.items; + total = data.total; + } else { + const data = await getPortfolios({ page, pageSize: PAGE_SIZE }); + items = data.items; + total = data.total; + } } catch { items = []; total = 0; } + const paginationQuery = activeCategory + ? { category: activeCategory.slug } + : undefined; + + const filterCategories = + rootCategories.length > 0 ? rootCategories : topPortfolioCategories; + return (
-
+

نمونه‌کارها

-

+

Portfolio

@@ -49,19 +107,55 @@ export default async function PortfolioListPage({

+
+ + همه + + {filterCategories.map((category) => { + const active = activeCategory?.id === category.id; + return ( + + {category.nameFa} + + ); + })} +
+ {items.length === 0 ? (

نمونه‌کاری برای نمایش وجود ندارد.

) : ( -
+
{items.map((item, index) => { const image = getPortfolioCoverImage(item); + const categoryFa = categoryLabelFa( + item.categoryName, + allCategories, + ); return (
-
+
{image ? ( ) : null}
- {item.categoryName ? ( -

- {item.categoryName} -

- ) : null} -

- {item.titleFa || item.title} -

- {item.abstract ? ( -

- {item.abstract} -

- ) : null} +
+ {categoryFa ? ( +

+ {categoryFa} +

+ ) : null} +

+ {item.titleFa || item.title} +

+ {item.abstract ? ( +

+ {item.abstract} +

+ ) : null} +
); @@ -104,6 +200,7 @@ export default async function PortfolioListPage({ pageSize={PAGE_SIZE} total={total} basePath="/portfolio" + query={paginationQuery} />
diff --git a/src/app/robots.ts b/src/app/robots.ts new file mode 100644 index 0000000..b228014 --- /dev/null +++ b/src/app/robots.ts @@ -0,0 +1,14 @@ +import type { MetadataRoute } from "next"; + +export default function robots(): MetadataRoute.Robots { + const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "https://www.meshkee.com"; + + return { + rules: { + userAgent: "*", + allow: "/", + }, + sitemap: `${siteUrl}/sitemap.xml`, + host: siteUrl, + }; +} diff --git a/src/app/seo/page.tsx b/src/app/seo/page.tsx index 9a3dd79..a5848c1 100644 --- a/src/app/seo/page.tsx +++ b/src/app/seo/page.tsx @@ -5,11 +5,12 @@ import { ProjectsShowcase, seoProjects } from "@/components/WebsiteProjects"; import { images } from "@/data/assets"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; export const metadata: Metadata = { - title: "سئو و مدیریت وبسایت | مشکی", + title: "سئو و مدیریت وبسایت", description: "خدمات سئو حرفه‌ای، بهینه‌سازی موتور جستجو و مدیریت وبسایت توسط تیم مشکی.", + alternates: { canonical: "/seo" }, }; export default function SeoPage() { diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts new file mode 100644 index 0000000..d7db2c0 --- /dev/null +++ b/src/app/sitemap.ts @@ -0,0 +1,27 @@ +import type { MetadataRoute } from "next"; + +const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "https://www.meshkee.com"; + +const routes = [ + "/", + "/cms-website", + "/website-qom", + "/website", + "/seo", + "/dedicated-application", + "/meshkee-cms", + "/graphic-designer", + "/portfolio", + "/blog", +]; + +export default function sitemap(): MetadataRoute.Sitemap { + const lastModified = new Date(); + + return routes.map((path) => ({ + url: `${siteUrl}${path === "/" ? "" : path}`, + lastModified, + changeFrequency: path === "/" ? "weekly" : "monthly", + priority: path === "/" ? 1 : path === "/website-qom" || path === "/cms-website" ? 0.9 : 0.7, + })); +} diff --git a/src/app/website-qom/page.tsx b/src/app/website-qom/page.tsx index 8cdc543..64d256c 100644 --- a/src/app/website-qom/page.tsx +++ b/src/app/website-qom/page.tsx @@ -8,12 +8,28 @@ import { import { images } from "@/data/assets"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; export const metadata: Metadata = { title: "طراحی سایت در قم توسط تیم حرفه‌ای مشکی", description: "طراحی وبسایت در قم توسط تیم مشکی با استفاده از جدیدترین متدهای کدنویسی و CMS اختصاصی با بهترین قیمت.", + keywords: [ + "طراحی سایت در قم", + "طراحی وبسایت قم", + "شرکت طراحی سایت قم", + "مشکی", + "Meshkee", + ], + alternates: { canonical: "/website-qom" }, + openGraph: { + title: "طراحی سایت در قم توسط تیم حرفه‌ای مشکی", + description: + "طراحی وبسایت در قم توسط تیم مشکی با استفاده از جدیدترین متدهای کدنویسی و CMS اختصاصی با بهترین قیمت.", + url: "/website-qom", + type: "website", + locale: "fa_IR", + }, }; export default function WebsiteQomPage() { diff --git a/src/app/website/page.tsx b/src/app/website/page.tsx index 6e64eef..8674e6e 100644 --- a/src/app/website/page.tsx +++ b/src/app/website/page.tsx @@ -5,13 +5,14 @@ import { WebsiteCountries } from "@/components/WebsiteCountries"; import { images } from "@/data/assets"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; const ICONS = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/img/icons"; + "/assets/images/img/icons"; export const metadata: Metadata = { - title: "طراحی اختصاصی وبسایت | مشکی", + title: "طراحی اختصاصی وبسایت", description: "طراحی و توسعه وبسایت اختصاصی، فروشگاهی، شرکتی و خاص توسط تیم مشکی.", + alternates: { canonical: "/website" }, }; export default function WebsitePage() { diff --git a/src/assets/images/files/0tqujfS8AF.png b/src/assets/images/files/0tqujfS8AF.png new file mode 100644 index 0000000..755cd95 Binary files /dev/null and b/src/assets/images/files/0tqujfS8AF.png differ diff --git a/src/assets/images/files/0tvhyuFDLP.webp b/src/assets/images/files/0tvhyuFDLP.webp new file mode 100644 index 0000000..a6298c8 Binary files /dev/null and b/src/assets/images/files/0tvhyuFDLP.webp differ diff --git a/src/assets/images/files/2DTWtbL3CO.png b/src/assets/images/files/2DTWtbL3CO.png new file mode 100644 index 0000000..94ef314 Binary files /dev/null and b/src/assets/images/files/2DTWtbL3CO.png differ diff --git a/src/assets/images/files/2U9hcDxczB.png b/src/assets/images/files/2U9hcDxczB.png new file mode 100644 index 0000000..1817d61 Binary files /dev/null and b/src/assets/images/files/2U9hcDxczB.png differ diff --git a/src/assets/images/files/2zPgG5sBHm.webp b/src/assets/images/files/2zPgG5sBHm.webp new file mode 100644 index 0000000..2341206 Binary files /dev/null and b/src/assets/images/files/2zPgG5sBHm.webp differ diff --git a/src/assets/images/files/36sxKL78cP.png b/src/assets/images/files/36sxKL78cP.png new file mode 100644 index 0000000..833cc76 Binary files /dev/null and b/src/assets/images/files/36sxKL78cP.png differ diff --git a/src/assets/images/files/3U0BxgqRqV.png b/src/assets/images/files/3U0BxgqRqV.png new file mode 100644 index 0000000..8881540 Binary files /dev/null and b/src/assets/images/files/3U0BxgqRqV.png differ diff --git a/src/assets/images/files/3nrFfkfSdH.webp b/src/assets/images/files/3nrFfkfSdH.webp new file mode 100644 index 0000000..b39b78b Binary files /dev/null and b/src/assets/images/files/3nrFfkfSdH.webp differ diff --git a/src/assets/images/files/3xXv8TLPsX.jpg b/src/assets/images/files/3xXv8TLPsX.jpg new file mode 100644 index 0000000..4526a3e Binary files /dev/null and b/src/assets/images/files/3xXv8TLPsX.jpg differ diff --git a/src/assets/images/files/4j1aVADzm8.webp b/src/assets/images/files/4j1aVADzm8.webp new file mode 100644 index 0000000..712edfa Binary files /dev/null and b/src/assets/images/files/4j1aVADzm8.webp differ diff --git a/src/assets/images/files/4sgg4zQsTc.webp b/src/assets/images/files/4sgg4zQsTc.webp new file mode 100644 index 0000000..9805fcb Binary files /dev/null and b/src/assets/images/files/4sgg4zQsTc.webp differ diff --git a/src/assets/images/files/4t8563Kj9b.png b/src/assets/images/files/4t8563Kj9b.png new file mode 100644 index 0000000..7f6013a Binary files /dev/null and b/src/assets/images/files/4t8563Kj9b.png differ diff --git a/src/assets/images/files/5Lpd4SmeVJ.png b/src/assets/images/files/5Lpd4SmeVJ.png new file mode 100644 index 0000000..f3ba28b Binary files /dev/null and b/src/assets/images/files/5Lpd4SmeVJ.png differ diff --git a/src/assets/images/files/5UZE9slUzZ.png b/src/assets/images/files/5UZE9slUzZ.png new file mode 100644 index 0000000..4a16d40 Binary files /dev/null and b/src/assets/images/files/5UZE9slUzZ.png differ diff --git a/src/assets/images/files/5WVlYEa5gc.webp b/src/assets/images/files/5WVlYEa5gc.webp new file mode 100644 index 0000000..13a1422 Binary files /dev/null and b/src/assets/images/files/5WVlYEa5gc.webp differ diff --git a/src/assets/images/files/5j3to7r5sl.webp b/src/assets/images/files/5j3to7r5sl.webp new file mode 100644 index 0000000..78e1c5f Binary files /dev/null and b/src/assets/images/files/5j3to7r5sl.webp differ diff --git a/src/assets/images/files/6T7rUEjyqu.png b/src/assets/images/files/6T7rUEjyqu.png new file mode 100644 index 0000000..49d7afd Binary files /dev/null and b/src/assets/images/files/6T7rUEjyqu.png differ diff --git a/src/assets/images/files/6b7tBULBBg.png b/src/assets/images/files/6b7tBULBBg.png new file mode 100644 index 0000000..c4a2def Binary files /dev/null and b/src/assets/images/files/6b7tBULBBg.png differ diff --git a/src/assets/images/files/6kY5CQL4tj.png b/src/assets/images/files/6kY5CQL4tj.png new file mode 100644 index 0000000..3cac19b Binary files /dev/null and b/src/assets/images/files/6kY5CQL4tj.png differ diff --git a/src/assets/images/files/6xx1iavfkH.png b/src/assets/images/files/6xx1iavfkH.png new file mode 100644 index 0000000..a6b482e Binary files /dev/null and b/src/assets/images/files/6xx1iavfkH.png differ diff --git a/src/assets/images/files/75b5YGp21c.jpg b/src/assets/images/files/75b5YGp21c.jpg new file mode 100644 index 0000000..ee471c1 Binary files /dev/null and b/src/assets/images/files/75b5YGp21c.jpg differ diff --git a/src/assets/images/files/7mB2MENL8w.png b/src/assets/images/files/7mB2MENL8w.png new file mode 100644 index 0000000..d5331aa Binary files /dev/null and b/src/assets/images/files/7mB2MENL8w.png differ diff --git a/src/assets/images/files/8eNAfUtFNo.jpg b/src/assets/images/files/8eNAfUtFNo.jpg new file mode 100644 index 0000000..f110a6e Binary files /dev/null and b/src/assets/images/files/8eNAfUtFNo.jpg differ diff --git a/src/assets/images/files/8xlSNcn8cL.webp b/src/assets/images/files/8xlSNcn8cL.webp new file mode 100644 index 0000000..75aad45 Binary files /dev/null and b/src/assets/images/files/8xlSNcn8cL.webp differ diff --git a/src/assets/images/files/976xV2Uo03.png b/src/assets/images/files/976xV2Uo03.png new file mode 100644 index 0000000..bb04c07 Binary files /dev/null and b/src/assets/images/files/976xV2Uo03.png differ diff --git a/src/assets/images/files/9RT7qexPXH.jpg b/src/assets/images/files/9RT7qexPXH.jpg new file mode 100644 index 0000000..6eb0067 Binary files /dev/null and b/src/assets/images/files/9RT7qexPXH.jpg differ diff --git a/src/assets/images/files/9qN7ePr9EZ.png b/src/assets/images/files/9qN7ePr9EZ.png new file mode 100644 index 0000000..e806e53 Binary files /dev/null and b/src/assets/images/files/9qN7ePr9EZ.png differ diff --git a/src/assets/images/files/9xJXfsbuxO.webp b/src/assets/images/files/9xJXfsbuxO.webp new file mode 100644 index 0000000..78e1c5f Binary files /dev/null and b/src/assets/images/files/9xJXfsbuxO.webp differ diff --git a/src/assets/images/files/A2iAd7kEhm.webp b/src/assets/images/files/A2iAd7kEhm.webp new file mode 100644 index 0000000..f3f6cf0 Binary files /dev/null and b/src/assets/images/files/A2iAd7kEhm.webp differ diff --git a/src/assets/images/files/AE9rqD3RUQ.png b/src/assets/images/files/AE9rqD3RUQ.png new file mode 100644 index 0000000..8e28943 Binary files /dev/null and b/src/assets/images/files/AE9rqD3RUQ.png differ diff --git a/src/assets/images/files/ATolOFILtk.jpg b/src/assets/images/files/ATolOFILtk.jpg new file mode 100644 index 0000000..1314322 Binary files /dev/null and b/src/assets/images/files/ATolOFILtk.jpg differ diff --git a/src/assets/images/files/AV8xufJxJG.webp b/src/assets/images/files/AV8xufJxJG.webp new file mode 100644 index 0000000..4990461 Binary files /dev/null and b/src/assets/images/files/AV8xufJxJG.webp differ diff --git a/src/assets/images/files/AqWe2zfGLb.jpg b/src/assets/images/files/AqWe2zfGLb.jpg new file mode 100644 index 0000000..9c1c5d4 Binary files /dev/null and b/src/assets/images/files/AqWe2zfGLb.jpg differ diff --git a/src/assets/images/files/AwQyu8yGrW.png b/src/assets/images/files/AwQyu8yGrW.png new file mode 100644 index 0000000..7a98c54 Binary files /dev/null and b/src/assets/images/files/AwQyu8yGrW.png differ diff --git a/src/assets/images/files/AyPufsOe2U.webp b/src/assets/images/files/AyPufsOe2U.webp new file mode 100644 index 0000000..21b7042 Binary files /dev/null and b/src/assets/images/files/AyPufsOe2U.webp differ diff --git a/src/assets/images/files/B5lPbimKui.webp b/src/assets/images/files/B5lPbimKui.webp new file mode 100644 index 0000000..fbb475f Binary files /dev/null and b/src/assets/images/files/B5lPbimKui.webp differ diff --git a/src/assets/images/files/BUUvn1ssFu.webp b/src/assets/images/files/BUUvn1ssFu.webp new file mode 100644 index 0000000..d87372a Binary files /dev/null and b/src/assets/images/files/BUUvn1ssFu.webp differ diff --git a/src/assets/images/files/BvOvzV9Mdp.webp b/src/assets/images/files/BvOvzV9Mdp.webp new file mode 100644 index 0000000..915619a Binary files /dev/null and b/src/assets/images/files/BvOvzV9Mdp.webp differ diff --git a/src/assets/images/files/C5UA21d0NM.webp b/src/assets/images/files/C5UA21d0NM.webp new file mode 100644 index 0000000..5fdf597 Binary files /dev/null and b/src/assets/images/files/C5UA21d0NM.webp differ diff --git a/src/assets/images/files/CIWbgV8W2D.png b/src/assets/images/files/CIWbgV8W2D.png new file mode 100644 index 0000000..f37fdbe Binary files /dev/null and b/src/assets/images/files/CIWbgV8W2D.png differ diff --git a/src/assets/images/files/CxaE281imL.png b/src/assets/images/files/CxaE281imL.png new file mode 100644 index 0000000..b0b14be Binary files /dev/null and b/src/assets/images/files/CxaE281imL.png differ diff --git a/src/assets/images/files/D9hcX5CHuV.png b/src/assets/images/files/D9hcX5CHuV.png new file mode 100644 index 0000000..bf8d47c Binary files /dev/null and b/src/assets/images/files/D9hcX5CHuV.png differ diff --git a/src/assets/images/files/E9z3Do1CV9.webp b/src/assets/images/files/E9z3Do1CV9.webp new file mode 100644 index 0000000..8440372 Binary files /dev/null and b/src/assets/images/files/E9z3Do1CV9.webp differ diff --git a/src/assets/images/files/EGRdN6bXU2.jpg b/src/assets/images/files/EGRdN6bXU2.jpg new file mode 100644 index 0000000..36e7794 Binary files /dev/null and b/src/assets/images/files/EGRdN6bXU2.jpg differ diff --git a/src/assets/images/files/EIBhtiC5cG.png b/src/assets/images/files/EIBhtiC5cG.png new file mode 100644 index 0000000..d8f4e91 Binary files /dev/null and b/src/assets/images/files/EIBhtiC5cG.png differ diff --git a/src/assets/images/files/EVcpynPGpj.png b/src/assets/images/files/EVcpynPGpj.png new file mode 100644 index 0000000..7c2e2e9 Binary files /dev/null and b/src/assets/images/files/EVcpynPGpj.png differ diff --git a/src/assets/images/files/F4qO7A8vsU.webp b/src/assets/images/files/F4qO7A8vsU.webp new file mode 100644 index 0000000..b79ec80 Binary files /dev/null and b/src/assets/images/files/F4qO7A8vsU.webp differ diff --git a/src/assets/images/files/FBa1OV9ZIZ.png b/src/assets/images/files/FBa1OV9ZIZ.png new file mode 100644 index 0000000..7c2e2e9 Binary files /dev/null and b/src/assets/images/files/FBa1OV9ZIZ.png differ diff --git a/src/assets/images/files/FRhOrUDQxK.webp b/src/assets/images/files/FRhOrUDQxK.webp new file mode 100644 index 0000000..39aef5f Binary files /dev/null and b/src/assets/images/files/FRhOrUDQxK.webp differ diff --git a/src/assets/images/files/FmXwLrTfoV.webp b/src/assets/images/files/FmXwLrTfoV.webp new file mode 100644 index 0000000..ff3a8a6 Binary files /dev/null and b/src/assets/images/files/FmXwLrTfoV.webp differ diff --git a/src/assets/images/files/GBXyzVDokx.png b/src/assets/images/files/GBXyzVDokx.png new file mode 100644 index 0000000..168a745 Binary files /dev/null and b/src/assets/images/files/GBXyzVDokx.png differ diff --git a/src/assets/images/files/GPxuRIL3EC.png b/src/assets/images/files/GPxuRIL3EC.png new file mode 100644 index 0000000..506a11f Binary files /dev/null and b/src/assets/images/files/GPxuRIL3EC.png differ diff --git a/src/assets/images/files/Gm0XROiWuC.webp b/src/assets/images/files/Gm0XROiWuC.webp new file mode 100644 index 0000000..0f82bc6 Binary files /dev/null and b/src/assets/images/files/Gm0XROiWuC.webp differ diff --git a/src/assets/images/files/HP72QvIPPU.jpg b/src/assets/images/files/HP72QvIPPU.jpg new file mode 100644 index 0000000..05196a8 Binary files /dev/null and b/src/assets/images/files/HP72QvIPPU.jpg differ diff --git a/src/assets/images/files/HUMX0LgwBX.png b/src/assets/images/files/HUMX0LgwBX.png new file mode 100644 index 0000000..b219268 Binary files /dev/null and b/src/assets/images/files/HUMX0LgwBX.png differ diff --git a/src/assets/images/files/InxpMjzB8N.png b/src/assets/images/files/InxpMjzB8N.png new file mode 100644 index 0000000..71b8e3d Binary files /dev/null and b/src/assets/images/files/InxpMjzB8N.png differ diff --git a/src/assets/images/files/ItCvr2jXRu.webp b/src/assets/images/files/ItCvr2jXRu.webp new file mode 100644 index 0000000..097fc37 Binary files /dev/null and b/src/assets/images/files/ItCvr2jXRu.webp differ diff --git a/src/assets/images/files/JXLo625dyC.webp b/src/assets/images/files/JXLo625dyC.webp new file mode 100644 index 0000000..1f8d0c0 Binary files /dev/null and b/src/assets/images/files/JXLo625dyC.webp differ diff --git a/src/assets/images/files/KT8s6hyp0r.png b/src/assets/images/files/KT8s6hyp0r.png new file mode 100644 index 0000000..f30288c Binary files /dev/null and b/src/assets/images/files/KT8s6hyp0r.png differ diff --git a/src/assets/images/files/L3esyJkRFC.png b/src/assets/images/files/L3esyJkRFC.png new file mode 100644 index 0000000..71d255c Binary files /dev/null and b/src/assets/images/files/L3esyJkRFC.png differ diff --git a/src/assets/images/files/LIWk9CwaR5.webp b/src/assets/images/files/LIWk9CwaR5.webp new file mode 100644 index 0000000..646d240 Binary files /dev/null and b/src/assets/images/files/LIWk9CwaR5.webp differ diff --git a/src/assets/images/files/LNwzp6gYkX.webp b/src/assets/images/files/LNwzp6gYkX.webp new file mode 100644 index 0000000..4990461 Binary files /dev/null and b/src/assets/images/files/LNwzp6gYkX.webp differ diff --git a/src/assets/images/files/Lkhnnnh7Zs.png b/src/assets/images/files/Lkhnnnh7Zs.png new file mode 100644 index 0000000..45a47e0 Binary files /dev/null and b/src/assets/images/files/Lkhnnnh7Zs.png differ diff --git a/src/assets/images/files/LmtK7D8C3D.png b/src/assets/images/files/LmtK7D8C3D.png new file mode 100644 index 0000000..15e9c97 Binary files /dev/null and b/src/assets/images/files/LmtK7D8C3D.png differ diff --git a/src/assets/images/files/LsGKZlEgBH.png b/src/assets/images/files/LsGKZlEgBH.png new file mode 100644 index 0000000..1ce0e57 Binary files /dev/null and b/src/assets/images/files/LsGKZlEgBH.png differ diff --git a/src/assets/images/files/LyXnsTIXcB.png b/src/assets/images/files/LyXnsTIXcB.png new file mode 100644 index 0000000..4ddd216 Binary files /dev/null and b/src/assets/images/files/LyXnsTIXcB.png differ diff --git a/src/assets/images/files/MrKwuNTRVI.webp b/src/assets/images/files/MrKwuNTRVI.webp new file mode 100644 index 0000000..a6298c8 Binary files /dev/null and b/src/assets/images/files/MrKwuNTRVI.webp differ diff --git a/src/assets/images/files/Ms3NprhtRb.png b/src/assets/images/files/Ms3NprhtRb.png new file mode 100644 index 0000000..6852df8 Binary files /dev/null and b/src/assets/images/files/Ms3NprhtRb.png differ diff --git a/src/assets/images/files/NEa3xsnLkf.webp b/src/assets/images/files/NEa3xsnLkf.webp new file mode 100644 index 0000000..cb0efca Binary files /dev/null and b/src/assets/images/files/NEa3xsnLkf.webp differ diff --git a/src/assets/images/files/NKzmMPR8jR.png b/src/assets/images/files/NKzmMPR8jR.png new file mode 100644 index 0000000..81a9d31 Binary files /dev/null and b/src/assets/images/files/NKzmMPR8jR.png differ diff --git a/src/assets/images/files/Naov6IfDtS.png b/src/assets/images/files/Naov6IfDtS.png new file mode 100644 index 0000000..5a06e9e Binary files /dev/null and b/src/assets/images/files/Naov6IfDtS.png differ diff --git a/src/assets/images/files/OQ3Z8wgiIY.png b/src/assets/images/files/OQ3Z8wgiIY.png new file mode 100644 index 0000000..20412f8 Binary files /dev/null and b/src/assets/images/files/OQ3Z8wgiIY.png differ diff --git a/src/assets/images/files/OfPtIOoudd.webp b/src/assets/images/files/OfPtIOoudd.webp new file mode 100644 index 0000000..c3f2121 Binary files /dev/null and b/src/assets/images/files/OfPtIOoudd.webp differ diff --git a/src/assets/images/files/OzqPZwHJ0J.jpg b/src/assets/images/files/OzqPZwHJ0J.jpg new file mode 100644 index 0000000..a0ac08f Binary files /dev/null and b/src/assets/images/files/OzqPZwHJ0J.jpg differ diff --git a/src/assets/images/files/QGdeNr8xDF.png b/src/assets/images/files/QGdeNr8xDF.png new file mode 100644 index 0000000..319dc0e Binary files /dev/null and b/src/assets/images/files/QGdeNr8xDF.png differ diff --git a/src/assets/images/files/QaQZ3P79cR.png b/src/assets/images/files/QaQZ3P79cR.png new file mode 100644 index 0000000..1c62346 Binary files /dev/null and b/src/assets/images/files/QaQZ3P79cR.png differ diff --git a/src/assets/images/files/RWkgNv47kG.png b/src/assets/images/files/RWkgNv47kG.png new file mode 100644 index 0000000..3aab296 Binary files /dev/null and b/src/assets/images/files/RWkgNv47kG.png differ diff --git a/src/assets/images/files/RadFcgHFRX.png b/src/assets/images/files/RadFcgHFRX.png new file mode 100644 index 0000000..5564700 Binary files /dev/null and b/src/assets/images/files/RadFcgHFRX.png differ diff --git a/src/assets/images/files/RcsC6n31hO.webp b/src/assets/images/files/RcsC6n31hO.webp new file mode 100644 index 0000000..5fdf597 Binary files /dev/null and b/src/assets/images/files/RcsC6n31hO.webp differ diff --git a/src/assets/images/files/Rp3QX3m8FE.webp b/src/assets/images/files/Rp3QX3m8FE.webp new file mode 100644 index 0000000..e5540f3 Binary files /dev/null and b/src/assets/images/files/Rp3QX3m8FE.webp differ diff --git a/src/assets/images/files/ScJdqzoK18.png b/src/assets/images/files/ScJdqzoK18.png new file mode 100644 index 0000000..57e4232 Binary files /dev/null and b/src/assets/images/files/ScJdqzoK18.png differ diff --git a/src/assets/images/files/SwYRnHKWPd.png b/src/assets/images/files/SwYRnHKWPd.png new file mode 100644 index 0000000..37d33bf Binary files /dev/null and b/src/assets/images/files/SwYRnHKWPd.png differ diff --git a/src/assets/images/files/TMSkameY2t.webp b/src/assets/images/files/TMSkameY2t.webp new file mode 100644 index 0000000..4f02146 Binary files /dev/null and b/src/assets/images/files/TMSkameY2t.webp differ diff --git a/src/assets/images/files/TUY2u0GjZ2.png b/src/assets/images/files/TUY2u0GjZ2.png new file mode 100644 index 0000000..5325786 Binary files /dev/null and b/src/assets/images/files/TUY2u0GjZ2.png differ diff --git a/src/assets/images/files/Tjl5nlXtvN.webp b/src/assets/images/files/Tjl5nlXtvN.webp new file mode 100644 index 0000000..a6298c8 Binary files /dev/null and b/src/assets/images/files/Tjl5nlXtvN.webp differ diff --git a/src/assets/images/files/TzK4ghgvjU.webp b/src/assets/images/files/TzK4ghgvjU.webp new file mode 100644 index 0000000..d52803a Binary files /dev/null and b/src/assets/images/files/TzK4ghgvjU.webp differ diff --git a/src/assets/images/files/U06jlPumpi.png b/src/assets/images/files/U06jlPumpi.png new file mode 100644 index 0000000..acee059 Binary files /dev/null and b/src/assets/images/files/U06jlPumpi.png differ diff --git a/src/assets/images/files/U37sw2h61o.png b/src/assets/images/files/U37sw2h61o.png new file mode 100644 index 0000000..fec0feb Binary files /dev/null and b/src/assets/images/files/U37sw2h61o.png differ diff --git a/src/assets/images/files/U9VRzvYjIf.webp b/src/assets/images/files/U9VRzvYjIf.webp new file mode 100644 index 0000000..bc9ae5c Binary files /dev/null and b/src/assets/images/files/U9VRzvYjIf.webp differ diff --git a/src/assets/images/files/W4XcB33sfJ.png b/src/assets/images/files/W4XcB33sfJ.png new file mode 100644 index 0000000..7c2e2e9 Binary files /dev/null and b/src/assets/images/files/W4XcB33sfJ.png differ diff --git a/src/assets/images/files/W5V2j5WwJb.png b/src/assets/images/files/W5V2j5WwJb.png new file mode 100644 index 0000000..186fa26 Binary files /dev/null and b/src/assets/images/files/W5V2j5WwJb.png differ diff --git a/src/assets/images/files/X0Y7csP5LY.webp b/src/assets/images/files/X0Y7csP5LY.webp new file mode 100644 index 0000000..0c33b6d Binary files /dev/null and b/src/assets/images/files/X0Y7csP5LY.webp differ diff --git a/src/assets/images/files/XV96o9YJXK.webp b/src/assets/images/files/XV96o9YJXK.webp new file mode 100644 index 0000000..a6298c8 Binary files /dev/null and b/src/assets/images/files/XV96o9YJXK.webp differ diff --git a/src/assets/images/files/Xb2jVJV6kR.png b/src/assets/images/files/Xb2jVJV6kR.png new file mode 100644 index 0000000..e79144f Binary files /dev/null and b/src/assets/images/files/Xb2jVJV6kR.png differ diff --git a/src/assets/images/files/YXkBRpuDv9.webp b/src/assets/images/files/YXkBRpuDv9.webp new file mode 100644 index 0000000..f4e5c99 Binary files /dev/null and b/src/assets/images/files/YXkBRpuDv9.webp differ diff --git a/src/assets/images/files/YlvlN6fM25.png b/src/assets/images/files/YlvlN6fM25.png new file mode 100644 index 0000000..83d0a6b Binary files /dev/null and b/src/assets/images/files/YlvlN6fM25.png differ diff --git a/src/assets/images/files/Z6Xu9fMGjL.jpg b/src/assets/images/files/Z6Xu9fMGjL.jpg new file mode 100644 index 0000000..be6d91c Binary files /dev/null and b/src/assets/images/files/Z6Xu9fMGjL.jpg differ diff --git a/src/assets/images/files/Z8yZ4ZGj5f.webp b/src/assets/images/files/Z8yZ4ZGj5f.webp new file mode 100644 index 0000000..2b19735 Binary files /dev/null and b/src/assets/images/files/Z8yZ4ZGj5f.webp differ diff --git a/src/assets/images/files/ZDRTPm468U.png b/src/assets/images/files/ZDRTPm468U.png new file mode 100644 index 0000000..d2c5efe Binary files /dev/null and b/src/assets/images/files/ZDRTPm468U.png differ diff --git a/src/assets/images/files/ZQY2e6T3iC.png b/src/assets/images/files/ZQY2e6T3iC.png new file mode 100644 index 0000000..f18761b Binary files /dev/null and b/src/assets/images/files/ZQY2e6T3iC.png differ diff --git a/src/assets/images/files/ZnpmKW4yBT.png b/src/assets/images/files/ZnpmKW4yBT.png new file mode 100644 index 0000000..0f56c85 Binary files /dev/null and b/src/assets/images/files/ZnpmKW4yBT.png differ diff --git a/src/assets/images/files/aNkJKqDchY.webp b/src/assets/images/files/aNkJKqDchY.webp new file mode 100644 index 0000000..dccfa73 Binary files /dev/null and b/src/assets/images/files/aNkJKqDchY.webp differ diff --git a/src/assets/images/files/b9RQ4ivVr7.webp b/src/assets/images/files/b9RQ4ivVr7.webp new file mode 100644 index 0000000..2341206 Binary files /dev/null and b/src/assets/images/files/b9RQ4ivVr7.webp differ diff --git a/src/assets/images/files/cSpSK3yM2K.png b/src/assets/images/files/cSpSK3yM2K.png new file mode 100644 index 0000000..fa003bd Binary files /dev/null and b/src/assets/images/files/cSpSK3yM2K.png differ diff --git a/src/assets/images/files/d4FWKBPcMF.png b/src/assets/images/files/d4FWKBPcMF.png new file mode 100644 index 0000000..d2be731 Binary files /dev/null and b/src/assets/images/files/d4FWKBPcMF.png differ diff --git a/src/assets/images/files/dSkkS7evzH.png b/src/assets/images/files/dSkkS7evzH.png new file mode 100644 index 0000000..99de663 Binary files /dev/null and b/src/assets/images/files/dSkkS7evzH.png differ diff --git a/src/assets/images/files/eIE64N2wNY.png b/src/assets/images/files/eIE64N2wNY.png new file mode 100644 index 0000000..60e3676 Binary files /dev/null and b/src/assets/images/files/eIE64N2wNY.png differ diff --git a/src/assets/images/files/ecXmIxV0te.png b/src/assets/images/files/ecXmIxV0te.png new file mode 100644 index 0000000..293465b Binary files /dev/null and b/src/assets/images/files/ecXmIxV0te.png differ diff --git a/src/assets/images/files/evqj3ChQLd.png b/src/assets/images/files/evqj3ChQLd.png new file mode 100644 index 0000000..4820f5a Binary files /dev/null and b/src/assets/images/files/evqj3ChQLd.png differ diff --git a/src/assets/images/files/fVx6q5vfUA.webp b/src/assets/images/files/fVx6q5vfUA.webp new file mode 100644 index 0000000..4a47c0d Binary files /dev/null and b/src/assets/images/files/fVx6q5vfUA.webp differ diff --git a/src/assets/images/files/fvJfINwpLk.webp b/src/assets/images/files/fvJfINwpLk.webp new file mode 100644 index 0000000..a1b070d Binary files /dev/null and b/src/assets/images/files/fvJfINwpLk.webp differ diff --git a/src/assets/images/files/gNtiIymDQa.png b/src/assets/images/files/gNtiIymDQa.png new file mode 100644 index 0000000..ec9a36b Binary files /dev/null and b/src/assets/images/files/gNtiIymDQa.png differ diff --git a/src/assets/images/files/gTsPVWqh24.webp b/src/assets/images/files/gTsPVWqh24.webp new file mode 100644 index 0000000..c028db3 Binary files /dev/null and b/src/assets/images/files/gTsPVWqh24.webp differ diff --git a/src/assets/images/files/gXFvLHDynC.webp b/src/assets/images/files/gXFvLHDynC.webp new file mode 100644 index 0000000..7ef182f Binary files /dev/null and b/src/assets/images/files/gXFvLHDynC.webp differ diff --git a/src/assets/images/files/ghctoURx0E.png b/src/assets/images/files/ghctoURx0E.png new file mode 100644 index 0000000..71d255c Binary files /dev/null and b/src/assets/images/files/ghctoURx0E.png differ diff --git a/src/assets/images/files/gyG38oiy8O.webp b/src/assets/images/files/gyG38oiy8O.webp new file mode 100644 index 0000000..b39b78b Binary files /dev/null and b/src/assets/images/files/gyG38oiy8O.webp differ diff --git a/src/assets/images/files/hbfVqlZi18.webp b/src/assets/images/files/hbfVqlZi18.webp new file mode 100644 index 0000000..9cda0f4 Binary files /dev/null and b/src/assets/images/files/hbfVqlZi18.webp differ diff --git a/src/assets/images/files/hlpMNIJEaX.png b/src/assets/images/files/hlpMNIJEaX.png new file mode 100644 index 0000000..ef9ab6c Binary files /dev/null and b/src/assets/images/files/hlpMNIJEaX.png differ diff --git a/src/assets/images/files/iAWixn0pW3.jpg b/src/assets/images/files/iAWixn0pW3.jpg new file mode 100644 index 0000000..c8f1422 Binary files /dev/null and b/src/assets/images/files/iAWixn0pW3.jpg differ diff --git a/src/assets/images/files/ifnT6QdNsr.webp b/src/assets/images/files/ifnT6QdNsr.webp new file mode 100644 index 0000000..b39b78b Binary files /dev/null and b/src/assets/images/files/ifnT6QdNsr.webp differ diff --git a/src/assets/images/files/inzY9vuguj.webp b/src/assets/images/files/inzY9vuguj.webp new file mode 100644 index 0000000..c60c603 Binary files /dev/null and b/src/assets/images/files/inzY9vuguj.webp differ diff --git a/src/assets/images/files/j7okT7OJBp.png b/src/assets/images/files/j7okT7OJBp.png new file mode 100644 index 0000000..574e0d3 Binary files /dev/null and b/src/assets/images/files/j7okT7OJBp.png differ diff --git a/src/assets/images/files/jaxfQEDUQQ.jpg b/src/assets/images/files/jaxfQEDUQQ.jpg new file mode 100644 index 0000000..cb694d0 Binary files /dev/null and b/src/assets/images/files/jaxfQEDUQQ.jpg differ diff --git a/src/assets/images/files/keP1j4D8XU.png b/src/assets/images/files/keP1j4D8XU.png new file mode 100644 index 0000000..d73faea Binary files /dev/null and b/src/assets/images/files/keP1j4D8XU.png differ diff --git a/src/assets/images/files/kjzjgFvKxZ.png b/src/assets/images/files/kjzjgFvKxZ.png new file mode 100644 index 0000000..293465b Binary files /dev/null and b/src/assets/images/files/kjzjgFvKxZ.png differ diff --git a/src/assets/images/files/kp7mWiDY7m.png b/src/assets/images/files/kp7mWiDY7m.png new file mode 100644 index 0000000..b362a59 Binary files /dev/null and b/src/assets/images/files/kp7mWiDY7m.png differ diff --git a/src/assets/images/files/kqPGopeKIR.png b/src/assets/images/files/kqPGopeKIR.png new file mode 100644 index 0000000..d2f76fb Binary files /dev/null and b/src/assets/images/files/kqPGopeKIR.png differ diff --git a/src/assets/images/files/kwxmOnlJAy.png b/src/assets/images/files/kwxmOnlJAy.png new file mode 100644 index 0000000..5e11102 Binary files /dev/null and b/src/assets/images/files/kwxmOnlJAy.png differ diff --git a/src/assets/images/files/laghDUXc8y.png b/src/assets/images/files/laghDUXc8y.png new file mode 100644 index 0000000..8a71b8f Binary files /dev/null and b/src/assets/images/files/laghDUXc8y.png differ diff --git a/src/assets/images/files/mPog6hCdL5.png b/src/assets/images/files/mPog6hCdL5.png new file mode 100644 index 0000000..21cb61c Binary files /dev/null and b/src/assets/images/files/mPog6hCdL5.png differ diff --git a/src/assets/images/files/n98K6K9jyG.png b/src/assets/images/files/n98K6K9jyG.png new file mode 100644 index 0000000..8a71b8f Binary files /dev/null and b/src/assets/images/files/n98K6K9jyG.png differ diff --git a/src/assets/images/files/n98dGTJsbb.png b/src/assets/images/files/n98dGTJsbb.png new file mode 100644 index 0000000..fb7c687 Binary files /dev/null and b/src/assets/images/files/n98dGTJsbb.png differ diff --git a/src/assets/images/files/nX5EqK3OtS.jpg b/src/assets/images/files/nX5EqK3OtS.jpg new file mode 100644 index 0000000..3b8dd6d Binary files /dev/null and b/src/assets/images/files/nX5EqK3OtS.jpg differ diff --git a/src/assets/images/files/pWmfGK7hWU.png b/src/assets/images/files/pWmfGK7hWU.png new file mode 100644 index 0000000..ba763b4 Binary files /dev/null and b/src/assets/images/files/pWmfGK7hWU.png differ diff --git a/src/assets/images/files/pXvH3hqSdS.jpg b/src/assets/images/files/pXvH3hqSdS.jpg new file mode 100644 index 0000000..dc8d8f7 Binary files /dev/null and b/src/assets/images/files/pXvH3hqSdS.jpg differ diff --git a/src/assets/images/files/pblvKaFLTm.png b/src/assets/images/files/pblvKaFLTm.png new file mode 100644 index 0000000..a4776b3 Binary files /dev/null and b/src/assets/images/files/pblvKaFLTm.png differ diff --git a/src/assets/images/files/pmrx1c9FZL.png b/src/assets/images/files/pmrx1c9FZL.png new file mode 100644 index 0000000..ebfb47b Binary files /dev/null and b/src/assets/images/files/pmrx1c9FZL.png differ diff --git a/src/assets/images/files/qkWtdEoBiJ.png b/src/assets/images/files/qkWtdEoBiJ.png new file mode 100644 index 0000000..5e11102 Binary files /dev/null and b/src/assets/images/files/qkWtdEoBiJ.png differ diff --git a/src/assets/images/files/rKfAyIS6EX.webp b/src/assets/images/files/rKfAyIS6EX.webp new file mode 100644 index 0000000..b39b78b Binary files /dev/null and b/src/assets/images/files/rKfAyIS6EX.webp differ diff --git a/src/assets/images/files/rdLLonb3et.png b/src/assets/images/files/rdLLonb3et.png new file mode 100644 index 0000000..965b191 Binary files /dev/null and b/src/assets/images/files/rdLLonb3et.png differ diff --git a/src/assets/images/files/s7N0aFbbbM.png b/src/assets/images/files/s7N0aFbbbM.png new file mode 100644 index 0000000..1e96939 Binary files /dev/null and b/src/assets/images/files/s7N0aFbbbM.png differ diff --git a/src/assets/images/files/sbqVWDtc4I.png b/src/assets/images/files/sbqVWDtc4I.png new file mode 100644 index 0000000..dc7b2b8 Binary files /dev/null and b/src/assets/images/files/sbqVWDtc4I.png differ diff --git a/src/assets/images/files/tOpjhq8FzT.png b/src/assets/images/files/tOpjhq8FzT.png new file mode 100644 index 0000000..1c1f098 Binary files /dev/null and b/src/assets/images/files/tOpjhq8FzT.png differ diff --git a/src/assets/images/files/tUNXxKZYdG.png b/src/assets/images/files/tUNXxKZYdG.png new file mode 100644 index 0000000..55f3b40 Binary files /dev/null and b/src/assets/images/files/tUNXxKZYdG.png differ diff --git a/src/assets/images/files/tdRtWz7Q2l.webp b/src/assets/images/files/tdRtWz7Q2l.webp new file mode 100644 index 0000000..0e4ac3a Binary files /dev/null and b/src/assets/images/files/tdRtWz7Q2l.webp differ diff --git a/src/assets/images/files/v4ZJpmctXl.png b/src/assets/images/files/v4ZJpmctXl.png new file mode 100644 index 0000000..24a23c4 Binary files /dev/null and b/src/assets/images/files/v4ZJpmctXl.png differ diff --git a/src/assets/images/files/v9C8SMnGcX.png b/src/assets/images/files/v9C8SMnGcX.png new file mode 100644 index 0000000..f7a8823 Binary files /dev/null and b/src/assets/images/files/v9C8SMnGcX.png differ diff --git a/src/assets/images/files/vVBied8Og6.webp b/src/assets/images/files/vVBied8Og6.webp new file mode 100644 index 0000000..6a32bcf Binary files /dev/null and b/src/assets/images/files/vVBied8Og6.webp differ diff --git a/src/assets/images/files/vew4NgueAK.webp b/src/assets/images/files/vew4NgueAK.webp new file mode 100644 index 0000000..c5fdf23 Binary files /dev/null and b/src/assets/images/files/vew4NgueAK.webp differ diff --git a/src/assets/images/files/wqUE5gsbR2.webp b/src/assets/images/files/wqUE5gsbR2.webp new file mode 100644 index 0000000..003f5c6 Binary files /dev/null and b/src/assets/images/files/wqUE5gsbR2.webp differ diff --git a/src/assets/images/files/wv5DGmbkwp.png b/src/assets/images/files/wv5DGmbkwp.png new file mode 100644 index 0000000..e806e53 Binary files /dev/null and b/src/assets/images/files/wv5DGmbkwp.png differ diff --git a/src/assets/images/files/xGYrPJZW0k.png b/src/assets/images/files/xGYrPJZW0k.png new file mode 100644 index 0000000..c406d7a Binary files /dev/null and b/src/assets/images/files/xGYrPJZW0k.png differ diff --git a/src/assets/images/files/xWhNkbheMX.webp b/src/assets/images/files/xWhNkbheMX.webp new file mode 100644 index 0000000..4990461 Binary files /dev/null and b/src/assets/images/files/xWhNkbheMX.webp differ diff --git a/src/assets/images/files/xZgguHQokB.png b/src/assets/images/files/xZgguHQokB.png new file mode 100644 index 0000000..293465b Binary files /dev/null and b/src/assets/images/files/xZgguHQokB.png differ diff --git a/src/assets/images/files/xbxAHqiJrm.png b/src/assets/images/files/xbxAHqiJrm.png new file mode 100644 index 0000000..f7f16ef Binary files /dev/null and b/src/assets/images/files/xbxAHqiJrm.png differ diff --git a/src/assets/images/files/yNOiYd13rv.png b/src/assets/images/files/yNOiYd13rv.png new file mode 100644 index 0000000..9ae63e0 Binary files /dev/null and b/src/assets/images/files/yNOiYd13rv.png differ diff --git a/src/assets/images/files/ypK8jYHp0Z.png b/src/assets/images/files/ypK8jYHp0Z.png new file mode 100644 index 0000000..9c238cb Binary files /dev/null and b/src/assets/images/files/ypK8jYHp0Z.png differ diff --git a/src/assets/images/files/z1ovCzjaqp.png b/src/assets/images/files/z1ovCzjaqp.png new file mode 100644 index 0000000..51fd34b Binary files /dev/null and b/src/assets/images/files/z1ovCzjaqp.png differ diff --git a/src/assets/images/files/z1uI4VxQyW.jpg b/src/assets/images/files/z1uI4VxQyW.jpg new file mode 100644 index 0000000..9b059d0 Binary files /dev/null and b/src/assets/images/files/z1uI4VxQyW.jpg differ diff --git a/src/assets/images/files/zJZkmuK6tr.webp b/src/assets/images/files/zJZkmuK6tr.webp new file mode 100644 index 0000000..ba23f6a Binary files /dev/null and b/src/assets/images/files/zJZkmuK6tr.webp differ diff --git a/src/assets/images/files/zgQpCfUAdh.jpg b/src/assets/images/files/zgQpCfUAdh.jpg new file mode 100644 index 0000000..3f359e2 Binary files /dev/null and b/src/assets/images/files/zgQpCfUAdh.jpg differ diff --git a/src/assets/images/img/brands/2.png b/src/assets/images/img/brands/2.png new file mode 100644 index 0000000..5d664f0 Binary files /dev/null and b/src/assets/images/img/brands/2.png differ diff --git a/src/assets/images/img/cities/australia-flag.png b/src/assets/images/img/cities/australia-flag.png new file mode 100644 index 0000000..a5504f9 Binary files /dev/null and b/src/assets/images/img/cities/australia-flag.png differ diff --git a/src/assets/images/img/cities/australia.png b/src/assets/images/img/cities/australia.png new file mode 100644 index 0000000..aede02f Binary files /dev/null and b/src/assets/images/img/cities/australia.png differ diff --git a/src/assets/images/img/cities/emirates-flag.png b/src/assets/images/img/cities/emirates-flag.png new file mode 100644 index 0000000..33cc6cf Binary files /dev/null and b/src/assets/images/img/cities/emirates-flag.png differ diff --git a/src/assets/images/img/cities/emirates.png b/src/assets/images/img/cities/emirates.png new file mode 100644 index 0000000..8f08152 Binary files /dev/null and b/src/assets/images/img/cities/emirates.png differ diff --git a/src/assets/images/img/cities/iran-flag.png b/src/assets/images/img/cities/iran-flag.png new file mode 100644 index 0000000..6d9a64d Binary files /dev/null and b/src/assets/images/img/cities/iran-flag.png differ diff --git a/src/assets/images/img/cities/japan-flag.png b/src/assets/images/img/cities/japan-flag.png new file mode 100644 index 0000000..e457b76 Binary files /dev/null and b/src/assets/images/img/cities/japan-flag.png differ diff --git a/src/assets/images/img/cities/japan.png b/src/assets/images/img/cities/japan.png new file mode 100644 index 0000000..d93db67 Binary files /dev/null and b/src/assets/images/img/cities/japan.png differ diff --git a/src/assets/images/img/f1.png b/src/assets/images/img/f1.png new file mode 100644 index 0000000..e61b512 Binary files /dev/null and b/src/assets/images/img/f1.png differ diff --git a/src/assets/images/img/f2.png b/src/assets/images/img/f2.png new file mode 100644 index 0000000..c4a2def Binary files /dev/null and b/src/assets/images/img/f2.png differ diff --git a/src/assets/images/img/f3.png b/src/assets/images/img/f3.png new file mode 100644 index 0000000..f37fdbe Binary files /dev/null and b/src/assets/images/img/f3.png differ diff --git a/src/assets/images/img/icons/1.png b/src/assets/images/img/icons/1.png new file mode 100644 index 0000000..fa8ea3a Binary files /dev/null and b/src/assets/images/img/icons/1.png differ diff --git a/src/assets/images/img/icons/2.png b/src/assets/images/img/icons/2.png new file mode 100644 index 0000000..355352e Binary files /dev/null and b/src/assets/images/img/icons/2.png differ diff --git a/src/assets/images/img/icons/3.png b/src/assets/images/img/icons/3.png new file mode 100644 index 0000000..8a71b8f Binary files /dev/null and b/src/assets/images/img/icons/3.png differ diff --git a/src/assets/images/img/icons/4.png b/src/assets/images/img/icons/4.png new file mode 100644 index 0000000..293465b Binary files /dev/null and b/src/assets/images/img/icons/4.png differ diff --git a/src/assets/images/img/logo-design.png b/src/assets/images/img/logo-design.png new file mode 100644 index 0000000..f8cbc97 Binary files /dev/null and b/src/assets/images/img/logo-design.png differ diff --git a/src/assets/images/img/portfolios/10.jpg b/src/assets/images/img/portfolios/10.jpg new file mode 100644 index 0000000..3b5a256 Binary files /dev/null and b/src/assets/images/img/portfolios/10.jpg differ diff --git a/src/assets/images/img/portfolios/11.jpg b/src/assets/images/img/portfolios/11.jpg new file mode 100644 index 0000000..7f6f976 Binary files /dev/null and b/src/assets/images/img/portfolios/11.jpg differ diff --git a/src/assets/images/img/portfolios/12.jpg b/src/assets/images/img/portfolios/12.jpg new file mode 100644 index 0000000..93e01b8 Binary files /dev/null and b/src/assets/images/img/portfolios/12.jpg differ diff --git a/src/assets/images/img/portfolios/13.jpg b/src/assets/images/img/portfolios/13.jpg new file mode 100644 index 0000000..4773850 Binary files /dev/null and b/src/assets/images/img/portfolios/13.jpg differ diff --git a/src/assets/images/img/portfolios/5.jpg b/src/assets/images/img/portfolios/5.jpg new file mode 100644 index 0000000..fd61765 Binary files /dev/null and b/src/assets/images/img/portfolios/5.jpg differ diff --git a/src/assets/images/img/portfolios/6.jpg b/src/assets/images/img/portfolios/6.jpg new file mode 100644 index 0000000..5a81360 Binary files /dev/null and b/src/assets/images/img/portfolios/6.jpg differ diff --git a/src/assets/images/img/portfolios/7.jpg b/src/assets/images/img/portfolios/7.jpg new file mode 100644 index 0000000..c347503 Binary files /dev/null and b/src/assets/images/img/portfolios/7.jpg differ diff --git a/src/assets/images/img/portfolios/9.jpg b/src/assets/images/img/portfolios/9.jpg new file mode 100644 index 0000000..ccb1c2a Binary files /dev/null and b/src/assets/images/img/portfolios/9.jpg differ diff --git a/src/assets/images/img/torob.png b/src/assets/images/img/torob.png new file mode 100644 index 0000000..606aa56 Binary files /dev/null and b/src/assets/images/img/torob.png differ diff --git a/src/components/AppSection.tsx b/src/components/AppSection.tsx index fad1d6f..7ab7f37 100644 --- a/src/components/AppSection.tsx +++ b/src/components/AppSection.tsx @@ -11,7 +11,7 @@ export function AppSection() {

طراحی و توسعه‌ی اپلیکیشن

-

+

Application Develop

diff --git a/src/components/BlogSection.tsx b/src/components/BlogSection.tsx index db5de8f..0dc033b 100644 --- a/src/components/BlogSection.tsx +++ b/src/components/BlogSection.tsx @@ -21,7 +21,7 @@ export async function BlogSection() {

رشدنامه، آموزشی و انگیزشی

-

+

Our Blog

diff --git a/src/components/CmsSection.tsx b/src/components/CmsSection.tsx index 29021f8..34dfd81 100644 --- a/src/components/CmsSection.tsx +++ b/src/components/CmsSection.tsx @@ -19,7 +19,7 @@ export function CmsSection() {

سیستم‌های مدیریت یکپارچه

-

+

Integrated Management System

diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 52a76bc..79b417c 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -15,7 +15,7 @@ export function Footer() {

-
+
{nav.map((item) => ( {title} -

+

{titleEn}

@@ -184,7 +184,7 @@ export function GraphicBrands({ />

{brand.nameFa}

-

+

{brand.nameEn}

diff --git a/src/components/Header.tsx b/src/components/Header.tsx index aa4a5af..1e4062d 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { useState } from "react"; -import { nav, site } from "@/data/home"; +import { nav, site, type NavItem } from "@/data/home"; import { images } from "@/data/assets"; const socials = [ @@ -13,8 +13,62 @@ const socials = [ { label: "آپارات", href: "https://aparat.com", icon: "M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm0 4a8 8 0 110 16A8 8 0 0112 4zm0 2a6 6 0 100 12A6 6 0 0012 6zm-1 3l5 3-5 3V9z" }, ]; +function DesktopNavItem({ item }: { item: NavItem }) { + if (!item.children?.length) { + return ( + + {item.label} + + ); + } + + return ( +
+ + {item.label} + + + + +
+
+ + همه نمونه‌کارها + + {item.children.map((child) => ( + + {child.label} + + ))} +
+
+
+ ); +} + export function Header() { const [open, setOpen] = useState(false); + const [expanded, setExpanded] = useState(null); return (
@@ -76,13 +130,7 @@ export function Header() {
@@ -130,14 +178,65 @@ export function Header() {
@@ -114,21 +147,7 @@ export function SeoCities({ : "" }`} > -
- {city.nameFa} -
-

- {city.nameFa} -

- - {city.nameEn} - -
-
+ ))} diff --git a/src/components/ServicePageLayout.tsx b/src/components/ServicePageLayout.tsx index f76b340..1687745 100644 --- a/src/components/ServicePageLayout.tsx +++ b/src/components/ServicePageLayout.tsx @@ -59,7 +59,7 @@ function SolutionFeatureCard({ feature }: { feature: Feature }) { {feature.title} {feature.titleEn && ( -

+

{feature.titleEn}

)} @@ -89,7 +89,7 @@ function TeamFeatureCard({ feature }: { feature: Feature }) { {feature.title} {feature.titleEn && ( -

+

{feature.titleEn}

)} @@ -150,7 +150,7 @@ export function ServicePageLayout({ {title}

{titleEn} @@ -214,7 +214,7 @@ export function ServicePageLayout({ {sec.title} {sec.titleEn && ( -

+

{sec.titleEn}

)} @@ -257,7 +257,7 @@ export function ServicePageLayout({ {sec.title} {sec.titleEn && ( -

+

{sec.titleEn}

)} diff --git a/src/components/Services.tsx b/src/components/Services.tsx index 58ea588..4ec08bf 100644 --- a/src/components/Services.tsx +++ b/src/components/Services.tsx @@ -12,7 +12,7 @@ export function Services() {

خدمات ما

-

+

Our Solutions

@@ -39,7 +39,7 @@ export function Services() {

{service.title}

-

+

{service.titleEn}

diff --git a/src/components/WebsiteCountries.tsx b/src/components/WebsiteCountries.tsx index 78e7e98..7f7b90d 100644 --- a/src/components/WebsiteCountries.tsx +++ b/src/components/WebsiteCountries.tsx @@ -1,5 +1,5 @@ const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets"; + "/assets/images"; export const websiteCountries = [ { @@ -91,7 +91,7 @@ export function WebsiteCountries({

{title}

-

+

{titleEn}

{body ? ( diff --git a/src/components/WebsiteProjects.tsx b/src/components/WebsiteProjects.tsx index 3f4c3aa..2c1d169 100644 --- a/src/components/WebsiteProjects.tsx +++ b/src/components/WebsiteProjects.tsx @@ -1,7 +1,7 @@ import { FramedImage } from "@/components/FramedImage"; const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets/files"; + "/assets/images/files"; export const websiteProjects = [ { src: `${CDN}/FmXwLrTfoV.webp` }, @@ -99,7 +99,7 @@ export function ProjectsShowcase({

{title}

-

+

{titleEn}

diff --git a/src/data/assets.ts b/src/data/assets.ts index 0ae6bb6..a401c9c 100644 --- a/src/data/assets.ts +++ b/src/data/assets.ts @@ -1,5 +1,5 @@ const CDN = - "https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/meshkee_SEEpb1zypk/assets"; + "/assets/images"; export const images = { hero: `${CDN}/files/BUUvn1ssFu.webp`, diff --git a/src/data/home.ts b/src/data/home.ts index d04855b..984ed3e 100644 --- a/src/data/home.ts +++ b/src/data/home.ts @@ -1,4 +1,8 @@ import { images } from "./assets"; +import { + portfolioCategoryHref, + topPortfolioCategories, +} from "./portfolioCategories"; export const site = { nameFa: "مشکی", @@ -12,13 +16,26 @@ export const site = { address: "قم، بلوار امام رضا، مجتمع فردوس، طبقهٔ اول تجاری، واحد ۳۰۹ و ۳۱۰", }; -export const nav = [ +export type NavItem = { + label: string; + href: string; + children?: { label: string; href: string }[]; +}; + +export const nav: NavItem[] = [ { label: "وبسایت", href: "/cms-website" }, { label: "سئو", href: "/seo" }, { label: "اپلیکیشن", href: "/dedicated-application" }, { label: "سیستم‌های مدیریتی", href: "/meshkee-cms" }, { label: "گرافیک و رسانه", href: "/graphic-designer" }, - { label: "نمونه‌کارها", href: "/portfolio" }, + { + label: "نمونه‌کارها", + href: "/portfolio", + children: topPortfolioCategories.map((category) => ({ + label: category.nameFa, + href: portfolioCategoryHref(category.slug), + })), + }, { label: "مقالات", href: "/blog" }, ]; diff --git a/src/data/portfolioCategories.ts b/src/data/portfolioCategories.ts new file mode 100644 index 0000000..7437ac7 --- /dev/null +++ b/src/data/portfolioCategories.ts @@ -0,0 +1,116 @@ +export type PortfolioCategory = { + id: string; + slug: string; + nameEn: string; + nameFa: string; + parentId?: string | null; + sortOrder?: number; +}; + +/** + * Top-level portfolio categories from Meshkee API + * (`/tenants/meshkee.com/categories?entityType=portfolio`, parentId = null). + * Ordered by API `sortOrder`. + */ +export const topPortfolioCategories: PortfolioCategory[] = [ + { + id: "1", + slug: "application", + nameEn: "Application", + nameFa: "اپلیکیشن", + parentId: null, + sortOrder: 0, + }, + { + id: "4", + slug: "content-management", + nameEn: "Content Management", + nameFa: "مدیریت محتوا", + parentId: null, + sortOrder: 1, + }, + { + id: "5", + slug: "website", + nameEn: "Website", + nameFa: "وبسایت", + parentId: null, + sortOrder: 2, + }, + { + id: "14", + slug: "graphic-and-design", + nameEn: "Graphic and Design", + nameFa: "گرافیک و طراحی", + parentId: null, + sortOrder: 3, + }, + { + id: "22", + slug: "media", + nameEn: "Media", + nameFa: "رسانه", + parentId: null, + sortOrder: 4, + }, +]; + +/** Alias used by page filters / nav fallbacks */ +export const portfolioCategories = topPortfolioCategories; + +export function findPortfolioCategory( + value: string | null | undefined, + categories: PortfolioCategory[] = topPortfolioCategories, +): PortfolioCategory | undefined { + if (!value) return undefined; + const key = value.trim().toLowerCase(); + return categories.find( + (category) => + category.slug === key || + category.id === key || + category.nameEn.toLowerCase() === key, + ); +} + +export function portfolioCategoryHref(slug?: string) { + if (!slug) return "/portfolio"; + return `/portfolio?category=${encodeURIComponent(slug)}`; +} + +export function getRootCategories(categories: PortfolioCategory[]) { + return categories + .filter((category) => !category.parentId) + .sort( + (a, b) => + (a.sortOrder ?? 0) - (b.sortOrder ?? 0) || + a.nameEn.localeCompare(b.nameEn), + ); +} + +export function getDescendantCategoryIds( + categories: PortfolioCategory[], + rootId: string, +): string[] { + const ids = [String(rootId)]; + const children = categories.filter( + (category) => String(category.parentId) === String(rootId), + ); + + for (const child of children) { + ids.push(...getDescendantCategoryIds(categories, child.id)); + } + + return ids; +} + +export function categoryLabelFa( + categoryName: string | null | undefined, + categories: PortfolioCategory[] = topPortfolioCategories, +): string | null { + if (!categoryName) return null; + const match = categories.find( + (category) => + category.nameEn.toLowerCase() === categoryName.toLowerCase(), + ); + return match?.nameFa ?? categoryName; +} diff --git a/src/lib/api.ts b/src/lib/api.ts index 7da0989..e255502 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -44,6 +44,7 @@ export type Portfolio = { titleImageUrl: string | null; mainTextHtml: string | null; publishedAt: string | null; + categoryId?: string | number | null; categoryName?: string | null; gallery?: PortfolioGalleryItem[]; }; @@ -133,6 +134,26 @@ export async function getBlog(slug: string): Promise { return data.blog; } +export type PortfolioCategoryApi = { + id: string; + businessId?: string; + entityType?: string; + parentId: string | null; + name: string; + nameFa: string | null; + slug: string; + description?: string | null; + sortOrder?: number; + isActive?: boolean; +}; + +export async function getPortfolioCategories(): Promise { + const data = await apiFetch<{ items: PortfolioCategoryApi[] }>( + `/tenants/${SITE_DOMAIN}/categories${toQuery({ entityType: "portfolio" })}`, + ); + return data.items ?? []; +} + export async function getPortfolios( options: GetPortfoliosOptions = {}, ): Promise> { @@ -146,6 +167,72 @@ export async function getPortfolios( ); } +async function getAllPortfolios(): Promise { + const pageSize = 100; + let page = 1; + let total = Infinity; + const items: Portfolio[] = []; + + while (items.length < total) { + const data = await getPortfolios({ page, pageSize }); + total = data.total; + items.push(...data.items); + if (!data.items.length) break; + page += 1; + } + + return items; +} + +/** + * Filter portfolios by a category and all of its descendants. + * Parent categories (e.g. Website) don't match API categoryId directly + * because items are tagged with leaf categories. + */ +export async function getPortfoliosByCategory(options: { + categoryId: string; + page?: number; + pageSize?: number; + categoryIds?: string[]; +}): Promise> { + const page = Math.max(1, options.page ?? 1); + const pageSize = Math.max(1, options.pageSize ?? 12); + + let allowedIds = options.categoryIds?.map(String); + if (!allowedIds?.length) { + const categories = await getPortfolioCategories(); + allowedIds = collectDescendantIds(categories, options.categoryId); + } + + const allowed = new Set(allowedIds); + const all = await getAllPortfolios(); + const filtered = all.filter((item) => + allowed.has(String(item.categoryId)), + ); + const start = (page - 1) * pageSize; + + return { + items: filtered.slice(start, start + pageSize), + total: filtered.length, + page, + pageSize, + }; +} + +function collectDescendantIds( + categories: PortfolioCategoryApi[], + rootId: string, +): string[] { + const ids = [String(rootId)]; + const children = categories.filter( + (category) => String(category.parentId) === String(rootId), + ); + for (const child of children) { + ids.push(...collectDescendantIds(categories, child.id)); + } + return ids; +} + export async function getPortfolio(slug: string): Promise { const data = await apiFetch<{ portfolio: Portfolio }>( `/tenants/${SITE_DOMAIN}/portfolios/${encodeURIComponent(slug)}`,