diff --git a/src/app/globals.css b/src/app/globals.css index ddbe8cf..c35f930 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -158,7 +158,7 @@ .container { width: 100%; - padding-inline: 10rem; + padding-inline: 1rem; @media (width >=40rem) { max-width: 40rem; @@ -167,7 +167,7 @@ @media (width >=48rem) { max-width: 48rem; - padding-inline: 1rem; + padding-inline: 2rem; } @media (width >=64rem) { diff --git a/src/app/products/page.tsx b/src/app/products/page.tsx new file mode 100644 index 0000000..0d48eba --- /dev/null +++ b/src/app/products/page.tsx @@ -0,0 +1,55 @@ +import images from '@/assets/images/images'; +import InnerPageBanner from '@/components/layout/innerPages/banner'; +import ProductsCategoryCard from '@/components/pages/products/ProductCategoryCard'; +import type { IProductCategoryCardProps } from '@/components/pages/products/productCategoryCard.d'; +import { t } from '@/locales/translates'; + +export default function ProductsPage() { + const productCategories = [ + { + id: '1', + title: t('com_products_category_Ghazaghi_title') as string, + icon: 'categoryGhazaghi', + typesCount: 22, + priceTypeTitle: 'Economy', + bestForTitle: 'Best For Interior Part', + }, + { + id: '2', + title: t('com_products_category_Ghermez_title') as string, + icon: 'categoryGhermez', + typesCount: 12, + priceTypeTitle: 'Luxury', + bestForTitle: 'Best For Exterior Part', + }, + { + id: '3', + title: t('com_products_category_Zard_title') as string, + icon: 'categoryZard', + typesCount: 11, + priceTypeTitle: 'Economy', + bestForTitle: 'Best For Facing', + }, + { + id: '40', + title: t('com_products_category_Semirom_title') as string, + icon: 'categorySemirom', + typesCount: 40, + priceTypeTitle: 'Economy', + bestForTitle: 'Best For Building', + }, + ] as IProductCategoryCardProps[]; + return ( +
+ +
+ {productCategories.map((category) => ( + + ))} +
+
+ ); +} diff --git a/src/assets/images/products_banner.png b/src/assets/images/products_banner.png new file mode 100644 index 0000000..cd21368 Binary files /dev/null and b/src/assets/images/products_banner.png differ diff --git a/src/components/pages/products/ProductCategoryCard.tsx b/src/components/pages/products/ProductCategoryCard.tsx new file mode 100644 index 0000000..6b01d7e --- /dev/null +++ b/src/components/pages/products/ProductCategoryCard.tsx @@ -0,0 +1,39 @@ +import { Icon } from '@/components/uikit/icons'; +import type { IProductCategoryCardProps } from './productCategoryCard.d'; +import AchievementTextBox from '@/components/layout/achievementTextBox'; +import { t } from '@/locales/translates'; +import Button from '@/components/uikit/button'; +import routeFactory from '@/assets/constants/routeFactory'; + +export default function ProductsCategoryCard({ + icon, + title, + typesCount, + priceTypeTitle, + bestForTitle, + id, +}: IProductCategoryCardProps) { + return ( +
+
+ +
+ +
+

{title}

+ + + +
+
+ +
+
+ ); +} diff --git a/src/components/pages/products/productCategoryCard.d.ts b/src/components/pages/products/productCategoryCard.d.ts new file mode 100644 index 0000000..aa684a6 --- /dev/null +++ b/src/components/pages/products/productCategoryCard.d.ts @@ -0,0 +1,10 @@ +import { IconName } from '@/components/uikit/icons'; + +export interface IProductCategoryCardProps { + id: string; + title: string; + icon: IconName; + typesCount: number; + priceTypeTitle: string; + bestForTitle: string; +} diff --git a/src/components/uikit/button/button.d.ts b/src/components/uikit/button/button.d.ts index 09efbf8..940c1d5 100644 --- a/src/components/uikit/button/button.d.ts +++ b/src/components/uikit/button/button.d.ts @@ -1,3 +1,4 @@ +import { URL } from 'url'; import { IconName } from '../icons'; export interface IBaseButtonProps @@ -6,6 +7,7 @@ export interface IBaseButtonProps loading?: boolean; disabled?: boolean; className?: string; + link?: URL | string; } export interface ITextButtonProps extends IBaseButtonProps { diff --git a/src/components/uikit/button/index.tsx b/src/components/uikit/button/index.tsx index edd943e..872ca2c 100644 --- a/src/components/uikit/button/index.tsx +++ b/src/components/uikit/button/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { IIconButtonProps, ITextButtonProps } from './button'; import { Icon } from '../icons'; +import Link from 'next/link'; const Button: React.FC = ({ children, @@ -9,52 +10,69 @@ const Button: React.FC = ({ disabled = false, endIcon, className, + link, ...props }) => { - return ( - ); }; +const ButtonBody: React.FC = ({ + children, + loading, + endIcon, +}) => ( +
+ {loading ? ( + + + + + ) : null} + +
+ {children} +
+ + {endIcon && !loading ? ( + + + + ) : null} +
+); + export default Button; export const IconButton: React.FC = ({ diff --git a/src/components/uikit/icons/achievementIcon.tsx b/src/components/uikit/icons/achievementIcon.tsx index 03aa88f..4a61bee 100644 --- a/src/components/uikit/icons/achievementIcon.tsx +++ b/src/components/uikit/icons/achievementIcon.tsx @@ -14,9 +14,9 @@ export const AchievementIcon = (props: React.SVGProps) => ( ); diff --git a/src/components/uikit/icons/categoryGhazaghiIcon.tsx b/src/components/uikit/icons/categoryGhazaghiIcon.tsx new file mode 100644 index 0000000..8594dc1 --- /dev/null +++ b/src/components/uikit/icons/categoryGhazaghiIcon.tsx @@ -0,0 +1,36 @@ +export default function CategoryGhazaghiIcon( + props: React.SVGProps, +) { + return ( + + + + + + ); +} diff --git a/src/components/uikit/icons/categoryGhermezIcon.tsx b/src/components/uikit/icons/categoryGhermezIcon.tsx new file mode 100644 index 0000000..39c68ec --- /dev/null +++ b/src/components/uikit/icons/categoryGhermezIcon.tsx @@ -0,0 +1,43 @@ +export default function CategoryGhermezIcon( + props: React.SVGProps, +) { + return ( + + + + + + + ); +} diff --git a/src/components/uikit/icons/categorySemiromIcon.tsx b/src/components/uikit/icons/categorySemiromIcon.tsx new file mode 100644 index 0000000..2b0d98b --- /dev/null +++ b/src/components/uikit/icons/categorySemiromIcon.tsx @@ -0,0 +1,55 @@ +export default function categorySemiromIcon( + props: React.SVGProps, +) { + return ( + + + + + + + + + + + ); +} diff --git a/src/components/uikit/icons/categoryZardIcon.tsx b/src/components/uikit/icons/categoryZardIcon.tsx new file mode 100644 index 0000000..4b0b01c --- /dev/null +++ b/src/components/uikit/icons/categoryZardIcon.tsx @@ -0,0 +1,58 @@ +export default function CategoryZardIcon(props: React.SVGProps) { + return ( + + + + + + + + + + + + ); +} diff --git a/src/components/uikit/icons/index.tsx b/src/components/uikit/icons/index.tsx index 252ce2b..6565ad9 100644 --- a/src/components/uikit/icons/index.tsx +++ b/src/components/uikit/icons/index.tsx @@ -6,6 +6,10 @@ import { AchievementIcon } from './achievementIcon'; import { PhoneIcon } from './phoneIcon'; import { InstagramIcon } from './instagramIcon'; import ShowMoreIcon from './showMoreIcon'; +import CategoryGhazaghiIcon from './categoryGhazaghiIcon'; +import CategoryGhermezIcon from './categoryGhermezIcon'; +import categorySemiromIcon from './categorySemiromIcon'; +import CategoryZardIcon from './categoryZardIcon'; export const icons = { close: CloseIcon, @@ -15,6 +19,10 @@ export const icons = { phone: PhoneIcon, instagram: InstagramIcon, showMore: ShowMoreIcon, + categoryGhazaghi: CategoryGhazaghiIcon, + categoryGhermez: CategoryGhermezIcon, + categorySemirom: categorySemiromIcon, + categoryZard: CategoryZardIcon, }; export type IconName = keyof typeof icons; diff --git a/src/components/uikit/icons/phoneIcon.tsx b/src/components/uikit/icons/phoneIcon.tsx index e0a2968..526004b 100644 --- a/src/components/uikit/icons/phoneIcon.tsx +++ b/src/components/uikit/icons/phoneIcon.tsx @@ -11,22 +11,22 @@ export const PhoneIcon = (props: React.SVGProps) => ( diff --git a/src/components/uikit/icons/settingIcon.tsx b/src/components/uikit/icons/settingIcon.tsx index 7c2d8e9..04e42b6 100644 --- a/src/components/uikit/icons/settingIcon.tsx +++ b/src/components/uikit/icons/settingIcon.tsx @@ -10,18 +10,18 @@ export const SettingIcon = (props: React.SVGProps) => ( ); diff --git a/src/locales/en.ts b/src/locales/en.ts index 6542a7f..ec3f2c2 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -51,6 +51,14 @@ const en = { com_home_story_projects_count: 'Completed Projects', com_home_story_customer_count: 'Happy Customers', com_home_story_experience: 'Years of Experience', + + // Products Page Components + com_products_category_Ghazaghi_title: 'Ghazaghi', + com_products_category_Ghermez_title: 'Ghermez', + com_products_category_Semirom_title: 'Semirom', + com_products_category_Zard_title: 'Zard', + com_products_category_types_count: ({ count }: { count: number }) => + `${count} Types`, }; export default en; diff --git a/src/locales/translates.ts b/src/locales/translates.ts index 17adc01..6b0f35b 100644 --- a/src/locales/translates.ts +++ b/src/locales/translates.ts @@ -39,19 +39,31 @@ export function changeLanguage(lang: TLocales, days = 365) { } export const locales = { - en: en as Translates, + en: en as unknown as Translates, fa, } as Record; -export const translates = (key: keyof Translates): string | (() => string) => { +export const translates = ( + key: keyof Translates, + dynamicValue?: Record, +): string | ((dynamicValue: Record) => string) => { const lang = (getCookie('lang') || 'en') as TLocales; - return locales[lang][key] || locales.en[key] || key; + const value = locales[lang][key] || locales.en[key] || key; + if (typeof value === 'function') { + return value(dynamicValue || {}); + } + return value; }; -export const t = (key: keyof Translates) => translates(key); +export const t = ( + key: keyof Translates, + dynamicValue?: Record, +) => translates(key, dynamicValue); export type TLocales = 'en' | 'fa'; export type Translates = { - [K in keyof typeof en]: string | (() => string); + [K in keyof typeof en]: + | string + | ((dynamicValue: Record) => string); };