From de963c45ff22d3b6cca2fba12a99e6542dbc10e3 Mon Sep 17 00:00:00 2001 From: BunyodL Date: Thu, 24 Apr 2025 23:05:41 +0500 Subject: [PATCH 01/36] update: make charity page --- src/app/charity/page.tsx | 615 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 615 insertions(+) create mode 100644 src/app/charity/page.tsx diff --git a/src/app/charity/page.tsx b/src/app/charity/page.tsx new file mode 100644 index 0000000..b65e3ca --- /dev/null +++ b/src/app/charity/page.tsx @@ -0,0 +1,615 @@ +import { + ArrowRight, + Calendar, + CheckCircle, + Clock, + Heart, + Landmark, + MapPin, + Users, +} from 'lucide-react'; +import Image from 'next/image'; + +import { Button } from '@/shared/shadcn-ui/button'; +import { + Card, + CardContent, + CardFooter, + CardHeader, + CardTitle, +} from '@/shared/shadcn-ui/card'; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from '@/shared/shadcn-ui/tabs'; + +import { CtaSection } from '@/widgets/cta-section'; + +export const metadata = { + title: 'Благотворительность | GasNetwork - Сеть заправок в Таджикистане', + description: + 'Благотворительные проекты и инициативы GasNetwork. Мы помогаем обществу и заботимся о будущем.', +}; + +export default function CharityPage() { + return ( +
+
+ {/* Hero Section */} +
+
+ Благотворительный фонд GasNetwork +
+
+
+
+ +
+

+ Благотворительный фонд GasNetwork +

+

+ Мы верим, что бизнес должен быть социально ответственным. + Наш фонд поддерживает образование, здравоохранение и + экологические инициативы в Таджикистане. +

+
+ + +
+
+
+
+
+
+ + {/* Mission Section */} +
+
+
+
+
+ +
+

+ Наша миссия +

+

+ Благотворительный фонд GasNetwork был создан в 2020 году с + целью поддержки социально значимых проектов в Таджикистане. Мы + стремимся внести свой вклад в развитие общества и помочь тем, + кто в этом нуждается. +

+

+ Наша миссия — создавать возможности для улучшения жизни людей + через образование, здравоохранение, экологические инициативы и + поддержку уязвимых групп населения. +

+ +
+
+ +
+

Прозрачность

+

+ Мы публикуем ежегодные отчеты о всех наших проектах и + расходах, обеспечивая полную прозрачность нашей + деятельности. +

+
+
+
+ +
+

Эффективность

+

+ Мы тщательно выбираем проекты, которые могут принести + максимальную пользу обществу и имеют долгосрочное + влияние. +

+
+
+
+ +
+

Сотрудничество

+

+ Мы сотрудничаем с местными и международными + организациями для достижения наибольшего эффекта от + наших инициатив. +

+
+
+
+
+
+ Наша миссия +
+
+
+
+ + {/* Key Figures */} +
+
+
+

+ Наш вклад в цифрах +

+

+ За время существования нашего фонда мы достигли значительных + результатов +

+
+
+
+

15+

+

Реализованных проектов

+
+
+

1.2M

+

Сомони пожертвований

+
+
+

5000+

+

Людей получили помощь

+
+
+

20+

+

Партнерских организаций

+
+
+
+
+ + {/* Our Projects */} +
+
+
+
+ +
+

+ Наши проекты +

+

+ Мы поддерживаем различные инициативы, направленные на улучшение + жизни людей в Таджикистане +

+
+ + + + Образование + Здравоохранение + Экология + Социальная помощь + + + +
+ {[ + { + title: 'Школьные библиотеки', + description: + 'Мы оборудовали 10 школьных библиотек в сельских районах Таджикистана, предоставив более 5000 книг.', + image: + '/placeholder.svg?height=200&width=300&text=Школьные+библиотеки', + date: '2022-2023', + }, + { + title: 'Стипендиальная программа', + description: + 'Ежегодно мы предоставляем стипендии 20 талантливым студентам из малообеспеченных семей.', + image: + '/placeholder.svg?height=200&width=300&text=Стипендии', + date: '2021-настоящее время', + }, + { + title: 'Компьютерные классы', + description: + 'Мы оборудовали 5 компьютерных классов в школах Душанбе и других городов Таджикистана.', + image: + '/placeholder.svg?height=200&width=300&text=Компьютерные+классы', + date: '2022', + }, + ].map((project, index) => ( + +
+ {project.title} +
+ +
+ {project.title} +
+ + {project.date} +
+
+
+ +

{project.description}

+
+ + + +
+ ))} +
+
+ +
+
+ + +
+ {[ + { + title: 'Медицинское оборудование', + description: + 'Мы закупили современное медицинское оборудование для 3 районных больниц в Таджикистане.', + image: + '/placeholder.svg?height=200&width=300&text=Медицинское+оборудование', + date: '2022', + }, + { + title: 'Мобильная клиника', + description: + 'Наша мобильная клиника предоставляет базовую медицинскую помощь в отдаленных районах страны.', + image: + '/placeholder.svg?height=200&width=300&text=Мобильная+клиника', + date: '2021-настоящее время', + }, + { + title: 'Вакцинация детей', + description: + 'Мы финансируем программу вакцинации детей в сельских районах Таджикистана.', + image: + '/placeholder.svg?height=200&width=300&text=Вакцинация', + date: '2023', + }, + ].map((project, index) => ( + +
+ {project.title} +
+ +
+ {project.title} +
+ + {project.date} +
+
+
+ +

{project.description}

+
+ + + +
+ ))} +
+
+ +
+
+ + +
+ {[ + { + title: 'Посадка деревьев', + description: + 'Мы организовали посадку более 10,000 деревьев в различных регионах Таджикистана.', + image: + '/placeholder.svg?height=200&width=300&text=Посадка+деревьев', + date: '2021-настоящее время', + }, + { + title: 'Чистые реки', + description: + 'Проект по очистке рек и водоемов от мусора и загрязнений в сотрудничестве с местными сообществами.', + image: + '/placeholder.svg?height=200&width=300&text=Чистые+реки', + date: '2022-2023', + }, + { + title: 'Экологическое образование', + description: + 'Мы проводим образовательные программы по экологии для школьников и студентов.', + image: + '/placeholder.svg?height=200&width=300&text=Экологическое+образование', + date: '2023', + }, + ].map((project, index) => ( + +
+ {project.title} +
+ +
+ {project.title} +
+ + {project.date} +
+
+
+ +

{project.description}

+
+ + + +
+ ))} +
+
+ +
+
+ + +
+ {[ + { + title: 'Помощь детским домам', + description: + 'Мы регулярно оказываем материальную помощь детским домам в Таджикистане.', + image: + '/placeholder.svg?height=200&width=300&text=Детские+дома', + date: '2020-настоящее время', + }, + { + title: 'Поддержка пожилых людей', + description: + 'Программа поддержки одиноких пожилых людей, включающая доставку продуктов и медикаментов.', + image: + '/placeholder.svg?height=200&width=300&text=Пожилые+люди', + date: '2021-настоящее время', + }, + { + title: 'Инклюзивное образование', + description: + 'Мы поддерживаем программы инклюзивного образования для детей с особыми потребностями.', + image: + '/placeholder.svg?height=200&width=300&text=Инклюзивное+образование', + date: '2022-2023', + }, + ].map((project, index) => ( + +
+ {project.title} +
+ +
+ {project.title} +
+ + {project.date} +
+
+
+ +

{project.description}

+
+ + + +
+ ))} +
+
+ +
+
+
+
+
+ + {/* Upcoming Events */} +
+
+
+
+ +
+

+ Предстоящие мероприятия +

+

+ Присоединяйтесь к нашим благотворительным мероприятиям и внесите + свой вклад в общее дело +

+
+ +
+ {[ + { + title: 'Благотворительный марафон', + description: + 'Ежегодный благотворительный марафон в поддержку детей с особыми потребностями.', + date: '15 июня 2023', + location: 'Парк Рудаки, Душанбе', + image: '/placeholder.svg?height=200&width=300&text=Марафон', + }, + { + title: 'Экологическая акция', + description: + 'Очистка берегов реки Варзоб от мусора и посадка деревьев.', + date: '22 июля 2023', + location: 'Река Варзоб, Душанбе', + image: + '/placeholder.svg?height=200&width=300&text=Экологическая+акция', + }, + { + title: 'Сбор школьных принадлежностей', + description: + 'Сбор школьных принадлежностей для детей из малообеспеченных семей к новому учебному году.', + date: '1-20 августа 2023', + location: 'Все заправки GasNetwork', + image: + '/placeholder.svg?height=200&width=300&text=Школьные+принадлежности', + }, + ].map((event, index) => ( + +
+ {event.title} +
+ + {event.title} + + +

{event.description}

+
+ + {event.date} +
+
+ + {event.location} +
+
+ + + +
+ ))} +
+
+
+ + {/* How to Help */} +
+
+
+
+ +
+

+ Как вы можете помочь +

+

+ Есть много способов внести свой вклад в наши благотворительные + инициативы +

+
+ +
+ {[ + { + title: 'Сделать пожертвование', + description: + 'Ваше пожертвование поможет нам реализовать больше проектов и помочь большему количеству людей.', + icon: , + }, + { + title: 'Стать волонтером', + description: + 'Присоединяйтесь к нашей команде волонтеров и помогайте нам в реализации благотворительных проектов.', + icon: , + }, + { + title: 'Участвовать в мероприятиях', + description: + 'Принимайте участие в наших благотворительных мероприятиях и акциях.', + icon: , + }, + { + title: 'Распространять информацию', + description: + 'Расскажите о нашем фонде и его деятельности своим друзьям и знакомым.', + icon: , + }, + ].map((item, index) => ( + + +
{item.icon}
+ {item.title} +
+ +

{item.description}

+
+ + + +
+ ))} +
+
+
+ +
+
+ ); +} From 0f62d24748798e93d66b04ae1d55695628548546 Mon Sep 17 00:00:00 2001 From: khadiatullo Date: Fri, 25 Apr 2025 18:20:23 +0300 Subject: [PATCH 02/36] add: certificates page --- src/app/clients/certificates/page.tsx | 8 ++ src/pages-templates/certificates/index.tsx | 122 +++++++++++++++++++++ src/shared/language/index.tsx | 87 +++++++++++++++ src/shared/language/locales/en.json | 99 +++++++++++++++++ src/shared/language/locales/ru.json | 99 +++++++++++++++++ src/shared/providers/providers.tsx | 25 +++-- tsconfig.json | 3 +- 7 files changed, 431 insertions(+), 12 deletions(-) create mode 100644 src/app/clients/certificates/page.tsx create mode 100644 src/pages-templates/certificates/index.tsx create mode 100644 src/shared/language/index.tsx create mode 100644 src/shared/language/locales/en.json create mode 100644 src/shared/language/locales/ru.json diff --git a/src/app/clients/certificates/page.tsx b/src/app/clients/certificates/page.tsx new file mode 100644 index 0000000..94a75da --- /dev/null +++ b/src/app/clients/certificates/page.tsx @@ -0,0 +1,8 @@ +import { CertificatesPage } from "@/pages-templates/certificates" + +export default function Certificates() { + + return ( + + ) +} diff --git a/src/pages-templates/certificates/index.tsx b/src/pages-templates/certificates/index.tsx new file mode 100644 index 0000000..4511f7a --- /dev/null +++ b/src/pages-templates/certificates/index.tsx @@ -0,0 +1,122 @@ +"use client" + +import Image from "next/image" +import { Card, CardContent } from "@/shared/shadcn-ui/card" +import { Button } from "@/shared/shadcn-ui/button" +import { Download, Eye } from "lucide-react" +import { useLanguage } from "@/shared/language" + +export function CertificatesPage() { + const { t } = useLanguage() + + // This data would typically come from an API or CMS + // We're keeping it as-is since it's dynamic content + const certificates = [ + { + id: 1, + title: "ISO 9001:2015", + description: "Сертификат системы менеджмента качества", + image: "/placeholder.svg?height=400&width=300", + issueDate: "15.03.2022", + expiryDate: "15.03.2025", + }, + { + id: 2, + title: "ISO 14001:2015", + description: "Сертификат экологического менеджмента", + image: "/placeholder.svg?height=400&width=300", + issueDate: "10.05.2022", + expiryDate: "10.05.2025", + }, + { + id: 3, + title: "OHSAS 18001", + description: "Сертификат системы управления охраной труда", + image: "/placeholder.svg?height=400&width=300", + issueDate: "22.07.2022", + expiryDate: "22.07.2025", + }, + { + id: 4, + title: "Сертификат качества топлива", + description: "Подтверждение соответствия топлива стандартам качества", + image: "/placeholder.svg?height=400&width=300", + issueDate: "05.01.2023", + expiryDate: "05.01.2024", + }, + { + id: 5, + title: "Сертификат соответствия", + description: "Соответствие услуг национальным стандартам", + image: "/placeholder.svg?height=400&width=300", + issueDate: "18.09.2022", + expiryDate: "18.09.2025", + }, + { + id: 6, + title: "Лицензия на хранение ГСМ", + description: "Разрешение на хранение горюче-смазочных материалов", + image: "/placeholder.svg?height=400&width=300", + issueDate: "30.11.2021", + expiryDate: "30.11.2026", + }, + ] + + return ( + <> +
+
+

{t("certificates.title")}

+

{t("certificates.description")}

+
+ +
+ {certificates.map((certificate) => ( + +
+ {certificate.title} +
+ +

{certificate.title}

+

{certificate.description}

+
+

+ {t("certificates.issueDate")}: {certificate.issueDate} +

+

+ {t("certificates.expiryDate")}: {certificate.expiryDate} +

+
+
+ + +
+
+
+ ))} +
+ +
+

{t("certificates.requestInfo")}

+

{t("certificates.requestInfoText")}

+
+ + +
+
+
+ + ) +} diff --git a/src/shared/language/index.tsx b/src/shared/language/index.tsx new file mode 100644 index 0000000..d9d6dc3 --- /dev/null +++ b/src/shared/language/index.tsx @@ -0,0 +1,87 @@ +"use client" + +import { createContext, useContext, useState, useEffect, type ReactNode } from "react" +import enTranslations from "./locales/en.json" +import ruTranslations from "./locales/ru.json" + +// Define available languages +export const languages = { + en: { name: "English", flag: "🇬🇧" }, + ru: { name: "Русский", flag: "🇷🇺" }, +} + +export type Language = keyof typeof languages + +// Define translations type with flat structure +export type Translations = Record + +// Load translations +const translations: Record = { + en: enTranslations, + ru: ruTranslations, +} + +// Create context +type LanguageContextType = { + language: Language + setLanguage: (lang: Language) => void + t: (key: string) => string +} + +const LanguageContext = createContext(undefined) + +// Create provider +export function LanguageProvider({ children }: { children: ReactNode }) { + // Default to Russian, but check localStorage on client + const [language, setLanguageState] = useState("ru") + const [isLoaded, setIsLoaded] = useState(false) + + useEffect(() => { + // Check if we're in the browser + if (typeof window !== "undefined") { + const savedLanguage = localStorage.getItem("language") as Language + if (savedLanguage && languages[savedLanguage]) { + setLanguageState(savedLanguage) + } + setIsLoaded(true) + } + }, []) + + const setLanguage = (lang: Language) => { + setLanguageState(lang) + if (typeof window !== "undefined") { + localStorage.setItem("language", lang) + } + } + + // Translation function for flat structure + const t = (key: string): string => { + if (translations[language][key]) { + return translations[language][key] + } + + console.warn(`Translation key not found: ${key}`) + return key + } + + // Only render children when language is loaded from localStorage + if (!isLoaded && typeof window !== "undefined") { + return null // Or a loading spinner + } + + return {children} +} + +// Create hook +export function useLanguage() { + const context = useContext(LanguageContext) + if (context === undefined) { + throw new Error("useLanguage must be used within a LanguageProvider") + } + + if (typeof context.t !== 'function') { + throw new Error("Translation function (t) is not available"); + } + + return context +} \ No newline at end of file diff --git a/src/shared/language/locales/en.json b/src/shared/language/locales/en.json new file mode 100644 index 0000000..5f4d7e1 --- /dev/null +++ b/src/shared/language/locales/en.json @@ -0,0 +1,99 @@ +{ + "common.buttons.readMore": "Read More", + "common.buttons.viewAll": "View All", + "common.buttons.findStation": "Find Station", + "common.buttons.learnMore": "Learn More", + "common.buttons.download": "Download", + "common.buttons.view": "View", + "common.buttons.contactUs": "Contact Us", + "common.buttons.apply": "Apply", + "common.buttons.login": "Login", + "common.buttons.logout": "Logout", + "common.buttons.submit": "Submit", + "common.buttons.filter": "Filter", + "common.buttons.resetFilters": "Reset Filters", + "common.buttons.downloadApp": "Download App", + "common.buttons.getLoyaltyCard": "Get Loyalty Card", + "common.buttons.sendResume": "Send Resume", + "common.buttons.showAllStations": "Show All Stations", + "common.buttons.allPromotions": "All Promotions", + "common.navigation.home": "Home", + "common.navigation.about": "About Us", + "common.navigation.clients": "For Clients", + "common.navigation.stations": "Our Stations", + "common.navigation.vacancies": "Vacancies", + "common.navigation.promotions": "Promotions", + "common.navigation.charity": "Charity", + "common.navigation.certificates": "Certificates", + "common.navigation.contacts": "Contacts", + "common.footer.contacts": "Contacts", + "common.footer.navigation": "Navigation", + "common.footer.subscribe": "Subscribe", + "common.footer.subscribeText": "Subscribe to our newsletter to receive news and special offers.", + "common.footer.yourEmail": "Your email", + "common.footer.rights": "All rights reserved.", + "home.hero.title": "Modern Gas Station Network in Tajikistan", + "home.hero.description": "Quality fuel, convenient locations, and excellent service for our customers", + "home.about.title": "About Our Company", + "home.about.description1": "Our gas station network is one of the leading in Tajikistan. We provide high-quality fuel and a high level of service for our customers for more than 15 years.", + "home.about.description2": "We are constantly developing, opening new stations and improving service at existing ones. Our goal is to make refueling as convenient and fast as possible for every customer.", + "home.about.features.quality.title": "Quality Fuel", + "home.about.features.quality.description": "We guarantee the high quality of our fuel", + "home.about.features.equipment.title": "Modern Equipment", + "home.about.features.equipment.description": "All our stations are equipped with modern equipment", + "home.about.features.staff.title": "Professional Staff", + "home.about.features.staff.description": "Our employees are professionals in their field", + "home.stations.title": "Our Stations", + "home.stations.description": "Find the nearest station in our network. We are located in convenient places throughout Tajikistan.", + "home.promotions.title": "Current Promotions", + "home.promotions.description": "Special offers and promotions for our customers. Refuel profitably!", + "home.vacancies.title": "Vacancies", + "home.vacancies.description": "Join our team of professionals. We offer stable work and opportunities for growth.", + "home.vacancies.all": "All vacancies", + "home.vacancies.office": "Office", + "home.vacancies.stations": "Stations", + "home.vacancies.fullTime": "Full time", + "home.vacancies.experience": "Experience from 1 year", + "home.vacancies.shiftWork": "Shift work", + "home.vacancies.training": "Training", + "home.partners.title": "Our Partners", + "home.partners.description": "We cooperate with leading companies to provide the best services to our customers.", + "home.partners.becomePartner": "Become Our Partner", + "home.partners.becomePartnerText": "We are open to cooperation and new partnerships. Contact us to discuss opportunities.", + "home.charity.title": "Charity Foundation", + "home.charity.description": "Our charity foundation was created to support socially significant projects in Tajikistan. We strive to contribute to the development of society and help those in need.", + "home.charity.directions": "Main directions of our foundation's activities:", + "home.charity.education": "Support for educational programs", + "home.charity.children": "Help for children from low-income families", + "home.charity.ecology": "Environmental initiatives", + "home.charity.sports": "Support for sports events", + "home.charity.learnMore": "Learn More About the Foundation", + "home.cta.title": "Join Us", + "home.cta.description": "Become part of our network. Get special offers, bonuses, and discounts.", + "certificates.title": "Our Certificates", + "certificates.description": "GasNetwork adheres to high standards of quality and safety. Our certificates confirm the compliance of our products and services with international and national standards.", + "certificates.requestInfo": "Request Additional Information", + "certificates.requestInfoText": "If you need additional information about our certificates or would like to receive copies of documents, please contact our quality department.", + "certificates.issueDate": "Issue Date", + "certificates.expiryDate": "Valid Until", + "certificates.faq": "Frequently Asked Questions", + "auth.title": "Login to your account", + "auth.description": "Log in to your personal account to access information about your bonuses, transaction history and other features.", + "auth.bonusClient": "Bonus Client", + "auth.corporateClient": "Corporate Client", + "auth.bonusLogin.title": "Login for bonus clients", + "auth.bonusLogin.description": "Enter your phone number and bonus card number to log in to your personal account.", + "auth.corporateLogin.title": "Login for corporate clients", + "auth.corporateLogin.description": "Enter your phone number and corporate card number to log in to your personal account.", + "auth.phoneNumber": "Phone number", + "auth.cardNumber": "Card number", + "auth.loginIssues": "Having trouble logging in?", + "map.filters": "Filters", + "map.stationsList": "Stations List", + "map.noStations": "No stations matching the selected filters", + "map.ourStations": "Our Stations", + "map.totalStations": "Total stations", + "map.services": "Services", + "map.cities": "Cities", + "map.allCities": "All Cities" +} \ No newline at end of file diff --git a/src/shared/language/locales/ru.json b/src/shared/language/locales/ru.json new file mode 100644 index 0000000..452c553 --- /dev/null +++ b/src/shared/language/locales/ru.json @@ -0,0 +1,99 @@ +{ + "common.buttons.readMore": "Подробнее", + "common.buttons.viewAll": "Смотреть все", + "common.buttons.findStation": "Найти заправку", + "common.buttons.learnMore": "Узнать больше", + "common.buttons.download": "Скачать", + "common.buttons.view": "Просмотр", + "common.buttons.contactUs": "Связаться с нами", + "common.buttons.apply": "Оформить", + "common.buttons.login": "Вход", + "common.buttons.logout": "Выйти", + "common.buttons.submit": "Отправить", + "common.buttons.filter": "Фильтры", + "common.buttons.resetFilters": "Сбросить фильтры", + "common.buttons.downloadApp": "Скачать приложение", + "common.buttons.getLoyaltyCard": "Получить карту лояльности", + "common.buttons.sendResume": "Отправить резюме", + "common.buttons.showAllStations": "Показать все заправки", + "common.buttons.allPromotions": "Все акции", + "common.navigation.home": "Главная", + "common.navigation.about": "О нас", + "common.navigation.clients": "Клиентам", + "common.navigation.stations": "Наши заправки", + "common.navigation.vacancies": "Вакансии", + "common.navigation.promotions": "Акции", + "common.navigation.charity": "Благотворительность", + "common.navigation.certificates": "Сертификаты", + "common.navigation.contacts": "Контакты", + "common.footer.contacts": "Контакты", + "common.footer.navigation": "Навигация", + "common.footer.subscribe": "Подписка", + "common.footer.subscribeText": "Подпишитесь на нашу рассылку, чтобы получать новости и специальные предложения.", + "common.footer.yourEmail": "Ваш email", + "common.footer.rights": "Все права защищены.", + "home.hero.title": "Сеть современных заправок в Таджикистане", + "home.hero.description": "Качественное топливо, удобное расположение и отличный сервис для наших клиентов", + "home.about.title": "О нашей компании", + "home.about.description1": "Наша сеть заправок является одной из ведущих в Таджикистане. Мы предоставляем качественное топливо и высокий уровень обслуживания для наших клиентов уже более 15 лет.", + "home.about.description2": "Мы постоянно развиваемся, открывая новые станции и улучшая сервис на существующих. Наша цель - сделать заправку автомобиля максимально удобной и быстрой для каждого клиента.", + "home.about.features.quality.title": "Качественное топливо", + "home.about.features.quality.description": "Мы гарантируем высокое качество нашего топлива", + "home.about.features.equipment.title": "Современное оборудование", + "home.about.features.equipment.description": "Все наши станции оснащены современным оборудованием", + "home.about.features.staff.title": "Профессиональный персонал", + "home.about.features.staff.description": "Наши сотрудники - профессионалы своего дела", + "home.stations.title": "Наши заправки", + "home.stations.description": "Найдите ближайшую к вам заправку нашей сети. Мы расположены в удобных местах по всему Таджикистану.", + "home.promotions.title": "Актуальные акции", + "home.promotions.description": "Специальные предложения и акции для наших клиентов. Заправляйтесь выгодно!", + "home.vacancies.title": "Вакансии", + "home.vacancies.description": "Присоединяйтесь к нашей команде профессионалов. Мы предлагаем стабильную работу и возможности для роста.", + "home.vacancies.all": "Все вакансии", + "home.vacancies.office": "Офис", + "home.vacancies.stations": "Заправки", + "home.vacancies.fullTime": "Полный день", + "home.vacancies.experience": "Опыт от 1 года", + "home.vacancies.shiftWork": "Сменный график", + "home.vacancies.training": "Обучение", + "home.partners.title": "Наши партнеры", + "home.partners.description": "Мы сотрудничаем с ведущими компаниями для предоставления лучших услуг нашим клиентам.", + "home.partners.becomePartner": "Станьте нашим партнером", + "home.partners.becomePartnerText": "Мы открыты для сотрудничества и новых партнерских отношений. Свяжитесь с нами для обсуждения возможностей.", + "home.charity.title": "Благотворительный фонд", + "home.charity.description": "Наш благотворительный фонд был создан для поддержки социально значимых проектов в Таджикистане. Мы стремимся внести свой вклад в развитие общества и помочь тем, кто в этом нуждается.", + "home.charity.directions": "Основные направления деятельности нашего фонда:", + "home.charity.education": "Поддержка образовательных программ", + "home.charity.children": "Помощь детям из малообеспеченных семей", + "home.charity.ecology": "Экологические инициативы", + "home.charity.sports": "Поддержка спортивных мероприятий", + "home.charity.learnMore": "Подробнее о фонде", + "home.cta.title": "Присоединяйтесь к нам", + "home.cta.description": "Станьте частью нашей сети. Получайте специальные предложения, бонусы и скидки.", + "certificates.title": "Наши сертификаты", + "certificates.description": "GasNetwork придерживается высоких стандартов качества и безопасности. Наши сертификаты подтверждают соответствие нашей продукции и услуг международным и национальным стандартам.", + "certificates.requestInfo": "Запросить дополнительную информацию", + "certificates.requestInfoText": "Если вам требуется дополнительная информация о наших сертификатах или вы хотите получить копии документов, пожалуйста, свяжитесь с нашим отделом качества.", + "certificates.issueDate": "Дата выдачи", + "certificates.expiryDate": "Действителен до", + "certificates.faq": "Часто задаваемые вопросы", + "auth.title": "Вход в личный кабинет", + "auth.description": "Войдите в личный кабинет, чтобы получить доступ к информации о ваших бонусах, истории операций и другим возможностям.", + "auth.bonusClient": "Бонусный клиент", + "auth.corporateClient": "Корпоративный клиент", + "auth.bonusLogin.title": "Вход для бонусных клиентов", + "auth.bonusLogin.description": "Введите номер телефона и номер бонусной карты для входа в личный кабинет.", + "auth.corporateLogin.title": "Вход для корпоративных клиентов", + "auth.corporateLogin.description": "Введите номер телефона и номер корпоративной карты для входа в личный кабинет.", + "auth.phoneNumber": "Номер телефона", + "auth.cardNumber": "Номер карты", + "auth.loginIssues": "Возникли проблемы со входом?", + "map.filters": "Фильтры", + "map.stationsList": "Список заправок", + "map.noStations": "Нет заправок, соответствующих выбранным фильтрам", + "map.ourStations": "Наши заправки", + "map.totalStations": "Всего станций", + "map.services": "Услуги", + "map.cities": "Города", + "map.allCities": "Все города" +} \ No newline at end of file diff --git a/src/shared/providers/providers.tsx b/src/shared/providers/providers.tsx index 21eca5f..d4fa91b 100644 --- a/src/shared/providers/providers.tsx +++ b/src/shared/providers/providers.tsx @@ -6,6 +6,7 @@ import { store } from '../store'; import { ThemeProvider } from '../theme/theme-provider'; import { AosProvider } from './aos-provider'; import { Toaster } from './toaster'; +import { LanguageProvider } from '../language'; type ProvidersProps = { children: React.ReactNode; @@ -14,17 +15,19 @@ type ProvidersProps = { export const Providers = ({ children }: ProvidersProps) => { return ( - - - {children} - - - + + + + {children} + + + + ); }; diff --git a/tsconfig.json b/tsconfig.json index 73918f4..aef1a0e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,7 +23,8 @@ "@/entities/*": ["./src/entities/*"], "@/features/*": ["./src/features/*"], "@/shared/*": ["./src/shared/*"], - "@/widgets/*": ["./src/widgets/*"] + "@/widgets/*": ["./src/widgets/*"], + "@/pages-templates/*": ["./src/pages-templates/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], From 828d4253c01d50e57292c82528327f8997795c28 Mon Sep 17 00:00:00 2001 From: khadiatullo Date: Sat, 26 Apr 2025 15:06:33 +0300 Subject: [PATCH 03/36] changed: buttons and animation for the block --- src/widgets/about-section.tsx | 2 +- src/widgets/cta-section.tsx | 2 +- src/widgets/hero-section.tsx | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/widgets/about-section.tsx b/src/widgets/about-section.tsx index d2930b3..08455c4 100644 --- a/src/widgets/about-section.tsx +++ b/src/widgets/about-section.tsx @@ -68,7 +68,7 @@ export const AboutSection = () => {
{

-
diff --git a/src/widgets/hero-section.tsx b/src/widgets/hero-section.tsx index f5497a4..bd5ca18 100644 --- a/src/widgets/hero-section.tsx +++ b/src/widgets/hero-section.tsx @@ -29,9 +29,7 @@ export const HeroSection = () => { - From 7702809958d847dc17ae4d8a391d0e12927039ab Mon Sep 17 00:00:00 2001 From: BunyodL Date: Sat, 26 Apr 2025 18:42:35 +0500 Subject: [PATCH 04/36] fix: fix page duplication --- src/shared/language/index.tsx | 93 +++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/src/shared/language/index.tsx b/src/shared/language/index.tsx index d9d6dc3..b2daf9c 100644 --- a/src/shared/language/index.tsx +++ b/src/shared/language/index.tsx @@ -1,87 +1,96 @@ -"use client" +'use client'; -import { createContext, useContext, useState, useEffect, type ReactNode } from "react" -import enTranslations from "./locales/en.json" -import ruTranslations from "./locales/ru.json" +import { Loader } from 'lucide-react'; +import { + createContext, + type ReactNode, + useContext, + useEffect, + useState, +} from 'react'; + +import enTranslations from './locales/en.json'; +import ruTranslations from './locales/ru.json'; // Define available languages export const languages = { - en: { name: "English", flag: "🇬🇧" }, - ru: { name: "Русский", flag: "🇷🇺" }, -} + en: { name: 'English', flag: '🇬🇧' }, + ru: { name: 'Русский', flag: '🇷🇺' }, +}; -export type Language = keyof typeof languages +export type Language = keyof typeof languages; // Define translations type with flat structure -export type Translations = Record +export type Translations = Record; // Load translations const translations: Record = { en: enTranslations, ru: ruTranslations, -} +}; // Create context type LanguageContextType = { - language: Language - setLanguage: (lang: Language) => void - t: (key: string) => string -} + language: Language; + setLanguage: (lang: Language) => void; + t: (key: string) => string; +}; -const LanguageContext = createContext(undefined) +const LanguageContext = createContext( + undefined, +); // Create provider export function LanguageProvider({ children }: { children: ReactNode }) { // Default to Russian, but check localStorage on client - const [language, setLanguageState] = useState("ru") - const [isLoaded, setIsLoaded] = useState(false) + const [language, setLanguageState] = useState('ru'); + const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { // Check if we're in the browser - if (typeof window !== "undefined") { - const savedLanguage = localStorage.getItem("language") as Language + if (typeof window !== 'undefined') { + const savedLanguage = localStorage.getItem('language') as Language; if (savedLanguage && languages[savedLanguage]) { - setLanguageState(savedLanguage) + setLanguageState(savedLanguage); } - setIsLoaded(true) + setIsLoaded(true); } - }, []) + }, []); const setLanguage = (lang: Language) => { - setLanguageState(lang) - if (typeof window !== "undefined") { - localStorage.setItem("language", lang) + setLanguageState(lang); + if (typeof window !== 'undefined') { + localStorage.setItem('language', lang); } - } + }; // Translation function for flat structure const t = (key: string): string => { if (translations[language][key]) { - return translations[language][key] + return translations[language][key]; } - console.warn(`Translation key not found: ${key}`) - return key - } + console.warn(`Translation key not found: ${key}`); + return key; + }; - // Only render children when language is loaded from localStorage - if (!isLoaded && typeof window !== "undefined") { - return null // Or a loading spinner - } - - return {children} + return ( + + {children} + + ); } // Create hook export function useLanguage() { - const context = useContext(LanguageContext) + const context = useContext(LanguageContext); if (context === undefined) { - throw new Error("useLanguage must be used within a LanguageProvider") + throw new Error('useLanguage must be used within a LanguageProvider'); } if (typeof context.t !== 'function') { - throw new Error("Translation function (t) is not available"); + throw new Error('Translation function (t) is not available'); } - - return context -} \ No newline at end of file + + return context; +} From 8f52988b6caa408a6c2ea5449bc0c9280c5cef93 Mon Sep 17 00:00:00 2001 From: BunyodL Date: Sat, 26 Apr 2025 18:58:50 +0500 Subject: [PATCH 05/36] update: add language-switcher --- src/shared/language/ui/language-switcher.tsx | 44 ++++++++++++++++++++ src/widgets/header/ui/desktop-nav.tsx | 2 +- src/widgets/header/ui/index.tsx | 12 ++++-- src/widgets/header/ui/mobile-nav.tsx | 2 +- 4 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 src/shared/language/ui/language-switcher.tsx diff --git a/src/shared/language/ui/language-switcher.tsx b/src/shared/language/ui/language-switcher.tsx new file mode 100644 index 0000000..0de4ed5 --- /dev/null +++ b/src/shared/language/ui/language-switcher.tsx @@ -0,0 +1,44 @@ +'use client'; + +import { Check, Globe } from 'lucide-react'; +import { useState } from 'react'; + +import { type Language, languages, useLanguage } from '@/shared/language'; +import { Button } from '@/shared/shadcn-ui/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/shared/shadcn-ui/dropdown-menu'; + +export function LanguageSwitcher() { + const { language, setLanguage } = useLanguage(); + const [open, setOpen] = useState(false); + + return ( + + + + + + {Object.entries(languages).map(([code, { name, flag }]) => ( + { + setLanguage(code as Language); + setOpen(false); + }} + > + {flag} + {name} + {code === language && } + + ))} + + + ); +} diff --git a/src/widgets/header/ui/desktop-nav.tsx b/src/widgets/header/ui/desktop-nav.tsx index d08b2fb..b58db02 100644 --- a/src/widgets/header/ui/desktop-nav.tsx +++ b/src/widgets/header/ui/desktop-nav.tsx @@ -14,7 +14,7 @@ import { export function DesktopNav() { return ( - + diff --git a/src/widgets/header/ui/index.tsx b/src/widgets/header/ui/index.tsx index 020facc..464f14d 100644 --- a/src/widgets/header/ui/index.tsx +++ b/src/widgets/header/ui/index.tsx @@ -1,6 +1,7 @@ import Link from 'next/link'; import { Logo } from '@/shared/assets/logo'; +import { LanguageSwitcher } from '@/shared/language/ui/language-switcher'; import { Button } from '@/shared/shadcn-ui/button'; import { DesktopNav } from './desktop-nav'; @@ -12,11 +13,14 @@ export function Header() {
-
+
- - - +
+ + + + +
diff --git a/src/widgets/header/ui/mobile-nav.tsx b/src/widgets/header/ui/mobile-nav.tsx index 1fdd863..1e47b65 100644 --- a/src/widgets/header/ui/mobile-nav.tsx +++ b/src/widgets/header/ui/mobile-nav.tsx @@ -19,7 +19,7 @@ export function MobileNav() { return ( - From 6810f1c8441a282a06dcd7c628dd234bef279e60 Mon Sep 17 00:00:00 2001 From: BunyodL Date: Sat, 26 Apr 2025 19:11:31 +0500 Subject: [PATCH 06/36] refactor: divide language parts to separate folders --- .../language-provider.tsx} | 29 +++---------------- src/shared/language/hooks/use-language.ts | 18 ++++++++++++ src/shared/language/index.ts | 6 ++++ src/shared/providers/providers.tsx | 2 +- 4 files changed, 29 insertions(+), 26 deletions(-) rename src/shared/language/{index.tsx => context/language-provider.tsx} (73%) create mode 100644 src/shared/language/hooks/use-language.ts create mode 100644 src/shared/language/index.ts diff --git a/src/shared/language/index.tsx b/src/shared/language/context/language-provider.tsx similarity index 73% rename from src/shared/language/index.tsx rename to src/shared/language/context/language-provider.tsx index b2daf9c..ebf9db9 100644 --- a/src/shared/language/index.tsx +++ b/src/shared/language/context/language-provider.tsx @@ -1,16 +1,9 @@ 'use client'; -import { Loader } from 'lucide-react'; -import { - createContext, - type ReactNode, - useContext, - useEffect, - useState, -} from 'react'; +import { createContext, type ReactNode, useEffect, useState } from 'react'; -import enTranslations from './locales/en.json'; -import ruTranslations from './locales/ru.json'; +import enTranslations from '../locales/en.json'; +import ruTranslations from '../locales/ru.json'; // Define available languages export const languages = { @@ -36,7 +29,7 @@ type LanguageContextType = { t: (key: string) => string; }; -const LanguageContext = createContext( +export const LanguageContext = createContext( undefined, ); @@ -80,17 +73,3 @@ export function LanguageProvider({ children }: { children: ReactNode }) { ); } - -// Create hook -export function useLanguage() { - const context = useContext(LanguageContext); - if (context === undefined) { - throw new Error('useLanguage must be used within a LanguageProvider'); - } - - if (typeof context.t !== 'function') { - throw new Error('Translation function (t) is not available'); - } - - return context; -} diff --git a/src/shared/language/hooks/use-language.ts b/src/shared/language/hooks/use-language.ts new file mode 100644 index 0000000..6473281 --- /dev/null +++ b/src/shared/language/hooks/use-language.ts @@ -0,0 +1,18 @@ +'use client'; + +import { useContext } from 'react'; + +import { LanguageContext } from '../context/language-provider'; + +export function useLanguage() { + const context = useContext(LanguageContext); + if (context === undefined) { + throw new Error('useLanguage must be used within a LanguageProvider'); + } + + if (typeof context.t !== 'function') { + throw new Error('Translation function (t) is not available'); + } + + return context; +} diff --git a/src/shared/language/index.ts b/src/shared/language/index.ts new file mode 100644 index 0000000..35d8d88 --- /dev/null +++ b/src/shared/language/index.ts @@ -0,0 +1,6 @@ +export { + LanguageProvider, + languages, + type Language, +} from './context/language-provider'; +export { useLanguage } from './hooks/use-language'; diff --git a/src/shared/providers/providers.tsx b/src/shared/providers/providers.tsx index d4fa91b..f2c02cd 100644 --- a/src/shared/providers/providers.tsx +++ b/src/shared/providers/providers.tsx @@ -2,11 +2,11 @@ import { Provider } from 'react-redux'; +import { LanguageProvider } from '../language'; import { store } from '../store'; import { ThemeProvider } from '../theme/theme-provider'; import { AosProvider } from './aos-provider'; import { Toaster } from './toaster'; -import { LanguageProvider } from '../language'; type ProvidersProps = { children: React.ReactNode; From 2e22b4a51365e784a203d431c52e89b75edaa66e Mon Sep 17 00:00:00 2001 From: BunyodL Date: Sat, 26 Apr 2025 19:32:41 +0500 Subject: [PATCH 07/36] update: use language-hook for home page --- .../language/context/language-provider.tsx | 2 - src/widgets/about-section.tsx | 42 ++++++------ src/widgets/charity-section.tsx | 32 +++++---- src/widgets/cta-section.tsx | 25 ++++--- src/widgets/footer.tsx | 65 +++++++++---------- src/widgets/header/ui/index.tsx | 11 +++- src/widgets/hero-section.tsx | 21 ++++-- src/widgets/map-section.tsx | 20 +++--- src/widgets/partners-section.tsx | 22 ++++--- src/widgets/promotions-section.tsx | 15 +++-- src/widgets/vacancies-section.tsx | 22 ++++--- 11 files changed, 152 insertions(+), 125 deletions(-) diff --git a/src/shared/language/context/language-provider.tsx b/src/shared/language/context/language-provider.tsx index ebf9db9..de3e7c9 100644 --- a/src/shared/language/context/language-provider.tsx +++ b/src/shared/language/context/language-provider.tsx @@ -37,7 +37,6 @@ export const LanguageContext = createContext( export function LanguageProvider({ children }: { children: ReactNode }) { // Default to Russian, but check localStorage on client const [language, setLanguageState] = useState('ru'); - const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { // Check if we're in the browser @@ -46,7 +45,6 @@ export function LanguageProvider({ children }: { children: ReactNode }) { if (savedLanguage && languages[savedLanguage]) { setLanguageState(savedLanguage); } - setIsLoaded(true); } }, []); diff --git a/src/widgets/about-section.tsx b/src/widgets/about-section.tsx index 08455c4..6eb7bd3 100644 --- a/src/widgets/about-section.tsx +++ b/src/widgets/about-section.tsx @@ -1,30 +1,27 @@ +'use client'; + import { Users } from 'lucide-react'; import Image from 'next/image'; import AboutCounter from '@/shared/components/about-counter'; +import { useLanguage } from '@/shared/language'; export const AboutSection = () => { + const { t } = useLanguage(); + return (
-
+
-
+

- О нашей компании + {t('home.about.title')}

-

- Наша сеть заправок является одной из ведущих в Таджикистане. Мы - предоставляем качественное топливо и высокий уровень обслуживания - для наших клиентов уже более 15 лет. -

-

- Мы постоянно развиваемся, открывая новые станции и улучшая сервис - на существующих. Наша цель - сделать заправку автомобиля - максимально удобной и быстрой для каждого клиента. -

+

{t('home.about.description1')}

+

{t('home.about.description2')}

@@ -33,9 +30,11 @@ export const AboutSection = () => {
-

Качественное топливо

+

+ {t('home.about.features.quality.title')} +

- Мы гарантируем высокое качество нашего топлива + {t('home.about.features.quality.description')}

@@ -45,10 +44,10 @@ export const AboutSection = () => {

- Современное оборудование + {t('home.about.features.equipment.title')}

- Все наши станции оснащены современным оборудованием + {t('home.about.features.equipment.description')}

@@ -58,19 +57,16 @@ export const AboutSection = () => {

- Профессиональный персонал + {t('home.about.features.staff.title')}

- Наши сотрудники - профессионалы своего дела + {t('home.about.features.staff.description')}

-
+
About our company { + const { t } = useLanguage(); + return (
-
+
-
+
Charity Foundation {

- Благотворительный фонд + {t('home.charity.title')}

- Наш благотворительный фонд был создан для поддержки социально - значимых проектов в Таджикистане. Мы стремимся внести свой вклад в - развитие общества и помочь тем, кто в этом нуждается. -

-

- Основные направления деятельности нашего фонда: + {t('home.charity.description')}

+

{t('home.charity.directions')}

  • - Поддержка образовательных программ + {t('home.charity.education')}
  • - Помощь детям из малообеспеченных семей + {t('home.charity.children')}
  • - Экологические инициативы + {t('home.charity.ecology')}
  • - Поддержка спортивных мероприятий + {t('home.charity.sports')}
diff --git a/src/widgets/cta-section.tsx b/src/widgets/cta-section.tsx index 6d358e5..b18547b 100644 --- a/src/widgets/cta-section.tsx +++ b/src/widgets/cta-section.tsx @@ -1,21 +1,28 @@ +'use client'; + +import { useLanguage } from '@/shared/language'; import { Button } from '@/shared/shadcn-ui/button'; export const CtaSection = () => { + const { t } = useLanguage(); + return (
-
+

- Присоединяйтесь к нам + {t('home.cta.title')}

-

- Станьте частью нашей сети. Получайте специальные предложения, бонусы - и скидки. -

+

{t('home.cta.description')}

- - +
diff --git a/src/widgets/footer.tsx b/src/widgets/footer.tsx index b7ab63a..c41624f 100644 --- a/src/widgets/footer.tsx +++ b/src/widgets/footer.tsx @@ -1,22 +1,24 @@ +'use client'; + import { Fuel, Mail, MapPin, Phone } from 'lucide-react'; import Link from 'next/link'; +import { useLanguage } from '@/shared/language'; import { Button } from '@/shared/shadcn-ui/button'; export const Footer = () => { + const { t } = useLanguage(); + return (