Compare commits

..

1 Commits
master ... uat

Author SHA1 Message Date
Vladislav Khorev
a86d1adc57 prepare for uat 2024-02-04 13:53:49 +00:00
330 changed files with 2000 additions and 17530 deletions

2
.env Normal file
View File

@ -0,0 +1,2 @@
NEXTAUTH_SECRET=";sadmfxflpdk"
NEXTAUTH_URL="http://localhost:3000"

1
.gitignore vendored
View File

@ -5,7 +5,6 @@
/.pnp /.pnp
.pnp.js .pnp.js
.yarn/install-state.gz .yarn/install-state.gz
.env
# testing # testing
/coverage /coverage

View File

@ -1,12 +1,3 @@
## TL;DR
```
git pull
yarn install
yarn build
yarn start
```
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started ## Getting Started

7
app/about-us/page.tsx Normal file
View File

@ -0,0 +1,7 @@
import React from "react";
const page = () => {
return <div>page</div>;
};
export default page;

3
app/layout.tsx Normal file
View File

@ -0,0 +1,3 @@
import RootLayout from "@/app/App";
export default RootLayout;

3
app/page.tsx Normal file
View File

@ -0,0 +1,3 @@
import Home from "@/pages/Home/Home";
export default Home;

7
app/profile/page.tsx Normal file
View File

@ -0,0 +1,7 @@
import React from "react";
const page = () => {
return <div>page</div>;
};
export default page;

7
app/sign-in/page.tsx Normal file
View File

@ -0,0 +1,7 @@
import React from "react";
const page = () => {
return <div>page</div>;
};
export default page;

9
lib/next-auth.d.ts vendored
View File

@ -4,13 +4,6 @@ declare module "next-auth" {
interface Session { interface Session {
refresh_token: string; refresh_token: string;
access_token: string; access_token: string;
expires_in: Date;
}
interface User {
refresh_token: string;
access_token: string;
expires_in: Date;
} }
} }
@ -20,6 +13,6 @@ declare module "next-auth/jwt" {
interface JWT { interface JWT {
refresh_token: string; refresh_token: string;
access_token: string; access_token: string;
expires_in: Date; exp: number;
} }
} }

View File

@ -1,221 +0,0 @@
{
"general": {
"date": "Date",
"address": "Address",
"status": "Status",
"description": "Description",
"reviews": "Reviews",
"rating": "Rating",
"review": "Review",
"write_comment": "Write Comment",
"search": "Search",
"search_for": "Search For",
"city": "City",
"added_roads": "Added Roads",
"broken_roads": "Broken Roads",
"accident_hotspots": "Accident Hotspots",
"local_defects": "Local Defects",
"repair_plans": "Repair Plans",
"repaired": "Repaired",
"fixed_local_defects": "Fixed Local Defects",
"news": "News",
"details": "Details",
"navigation": "Navigation",
"contacts": "Contacts",
"download_our_app": "Download our app",
"socials": "Stay Connected",
"back": "Back",
"save": "Save",
"saving": "Saving",
"cancel": "Cancel",
"cancellation": "Cancellation",
"save_changes": "Save Changes",
"send": "Send",
"receive": "Receive",
"delete": "Delete",
"show_on_map": "Show on Map",
"author_of_appeal": "Author of Appeal",
"enter_city": "Enter City",
"page_not_found": "Page Not Found (404)",
"incorrect_address_or_nonexistent_page": "Incorrect Address or Nonexistent Page.",
"home": "Home",
"first_name": "First Name",
"last_name": "Last Name",
"email": "Email"
},
"navigation": {
"home": "Home",
"about_us": "About Us",
"privacy": "Privacy Policy",
"support": "Support",
"statistics": "Statistics",
"news": "News",
"volunteers": "Volunteers",
"profile": "Profile",
"login": "Login"
},
"home": {
"title": "Roads of Kyrgyzstan",
"subtitle": "Let's Make Roads Safe!",
"info": "Current information about the state of roads",
"report_broken_road": "Report Broken Road",
"road_map": "Road Map",
"latest_news": "Stay informed about the latest news on traffic, construction, and events!",
"enter_location": "Enter city, village, or region",
"broken_roads": "Broken road",
"accident_hotspots": "Accident hotspot",
"local_defects": "Local defect",
"repair_plans": "In repair plan",
"repaired": "Repaired",
"fixed_local_defects": "Fixed local defect",
"rating": "Rating",
"road_discussions": "Discussing roads: rating, experience, comfort on the way!",
"enter_address": "Enter address",
"read_more": "Read More"
},
"about_us": {
"name": "About us KGROAD",
"description1": "Transparency International is a global independent organization that studies and fights against corruption both internationally and within individual countries, one of the goals of which is to achieve greater transparency and accountability of government.",
"description2": "The team of Transparency International Kyrgyzstan has developed a platform for monitoring road construction and repair, containing an interactive map to provide access to information on roads and streets repaired in recent years, including cost of works, contractor details, warranty periods, links to procurement documents and other information on works, as well as generalized statistics on road works (e.g. road works performed by the same contractor). ",
"description3": "The platform will also provide users with the opportunity to promptly report defects on roads and the need to fix them, vote on the priority of road repairs and provide feedback in a convenient format that will allow citizens to independently analyze and monitor the use of execution of state road contracts. Information on road construction and repairs is collected from public data from the state procurement portal and the Ministry of Justice.",
"description4":"In addition to the web platform, there are two mobile applications for iOS and Android platforms with functions similar to the website."
},
"volunteers": {
"activists": "Activists",
"received_votes": "Received Votes",
"left_votes": "Left Votes",
"rating": "Rating"
},
"profile": {
"personal_cabinet": "Personal Cabinet",
"personal_data": "Personal Data",
"my_appeals": "My Appeals",
"logout": "Logout",
"write_appeal": "Write Appeal",
"profile_photo": "Profile Photo",
"others_identification": "With a profile photo, other people will recognize you, and it will be easier for you to determine which account you logged into.",
"add_profile_photo": "Add Profile Photo",
"profile_photo_updated": "Profile Photo Updated",
"delete": "Delete",
"change": "Change"
},
"authorization": {
"change_password": "Change Password",
"old_password": "Old Password",
"enter_old_password": "Enter Old Password",
"new_password": "New Password",
"enter_new_password": "Enter New Password",
"confirm_new_password": "Confirm New Password",
"confirm_new_password_prompt": "Please confirm the new password",
"password": "Password",
"forgot_password": "Forgot Password?",
"login": "Login",
"register": "Register",
"sign_in_account": "Sign in to Account",
"enter_credentials": "Please enter your credentials",
"login_via_google": "Login via Google",
"enter_password": "Enter Password",
"password_requirements": "Minimum 8 characters, 1 uppercase letter, and 1 digit",
"no_account_yet": "Don't have an account yet? Register",
"registration": "Registration",
"register_now": "Register Now",
"already_have_account": "Already have an account? Sign in",
"enter_email": "Enter Email",
"enter_email_for_code": "Enter email, and we will send a code to reset the password",
"send_code": "Send Code",
"confirm_code": "Confirm Code",
"enter_code": "Enter Code",
"enter_reset_code": "Enter code to reset and recover the password",
"reset_code": "Reset Code",
"reset_password": "Reset Password",
"check_email": "Check Your Email",
"code_sent_to": "We sent a code to the email name@gmail.com",
"confirmation_code": "Confirmation Code",
"confirm": "Confirm",
"resend_code_in": "Resend Code in",
"resend_code": "Resend Code"
},
"send_report": {
"how_to_mark_road_section": "How to mark a road section?",
"mark_road_instructions": "Place a pin and start drawing a road section (it can consist of any number of broken lines).",
"remove_segment_instruction": "To remove a segment, click on the points again.",
"add_problem_description": "Add a problem description",
"enter_description": "Enter description",
"add_photos": "Add Photos",
"upload_photos_instructions": "Upload up to 5 photos related to the road you want to mark. Photos will help better understand the problem.",
"attach_file": "Attach File (up to 5 MB)",
"submit_for_moderation": "Submit for Moderation",
"appeal_submitted": "Your appeal has been submitted",
"thanks_for_appeal": "Thank you for your appeal. It is currently under moderation.",
"view_my_appeals": "View My Appeals"
},
"months": {
"january": "January",
"february": "February",
"march": "March",
"april": "April",
"may": "May",
"june": "June",
"july": "July",
"august": "August",
"september": "September",
"october": "October",
"november": "November",
"december": "December"
},
"validation_errors": {
"invalid_email_format": "Invalid email format.",
"passwords_do_not_match": "Passwords do not match.",
"required_field_not_filled": "Required field not filled.",
"exceeded_maximum_length": "Exceeded maximum length of the field.",
"login_required_before_commenting": "Please log in or register before leaving a comment.",
"login_required_before_like": "Please log in or register before liking."
},
"server_errors": {
"invalid_email_or_password": "Invalid email or password.",
"server_error_auth_attempt": "Server error during authentication attempt.",
"login_failed": "Failed to log in. Something went wrong, please try again later.",
"account_already_exists": "An account with this email already exists.",
"account_not_found": "Account not found.",
"invalid_activation_code": "Invalid activation code.",
"invalid_activation_code_reset": "Invalid activation code for reset.",
"invalid_password_reset_code": "Invalid password reset code.",
"invalid_code": "Invalid code."
},
"disclaimer": {
"text": "This website is funded by the European Union. Its contents are the sole responsibility of Transparency International Kyrgyzstan and do not necessarily reflect the views of the European Union."
},
"rights": {
"text": "All rights reserved"
},
"PrivacyPolicy":{
"titel0":"Privacy policy",
"title1": "General provisions",
"title2": "Collection of personal data",
"title3": "Storage and use of personal data",
"title4": "Transfer of personal data",
"title5": "Destruction of personal data",
"title6": "Protection of personal data",
"title7": "User requests",
"p1": "These Privacy Policy Regulations define the procedure for processing and protecting information about individuals (hereinafter referred to as Users) using the mailing list, the feedback form of the site, and e-mail addresses located on the domain name ",
"p1o":" (hereinafter referred to as the Website). We have developed a Privacy Policy that describes how we process personal data — any actions (operations) or a set of actions (operations) performed using automation tools or without using such tools with personal data, including collection, recording, systematization, accumulation, storage, clarification (updating, modification), extraction, use, transfer (distribution, provision, access), depersonalization, blocking, deletion, destruction of personal data. The relations related to the processing of personal data and information about the users of the Website are governed by this Regulation. This Privacy Policy regulates any type of processing of personal data and personal information (any personally identifiable information and any other related information) about individuals who are users of the Website. This Policy applies to the processing of personal, personal data collected by any means, both active and passive, both via the Internet and without its use, from persons located anywhere in the world.",
"p2": "The purpose of processing personal data is to fulfill the Operator's obligations to Users regarding the use of the Website and its services. The processing of personal data of users is carried out with the consent of the personal data subject to the processing of his personal data. Personal data refers to any information relating directly or indirectly to a specific or identifiable individual (the subject of personal data) and which can be used to identify or communicate with a particular person. We may request your first name, last name, patronymic and e-mail address to include you in the mailing list with your consent and to respond to you if you have contacted us through the feedback form on the Website.",
"p3": "Users' personal data is stored exclusively on electronic media and processed using automated systems.",
"p4": "HOW WE USE YOUR PERSONAL INFORMATION",
"p5": "The personal data we collect allows us to send you e-mail notifications about news and various events in the field of anti-corruption. Your personal data may also be used when responding to your request sent via the feedback form or to our e-mail address located on the Website. If you do not wish to be included in our mailing list, you can unsubscribe at any time by informing us at the specified contacts for feedback.",
"p6":"COLLECTION AND USE OF NON-PERSONAL INFORMATION",
"p7":"We also collect personal data that is not personal data that does not allow us to directly associate it with any person. We may collect, use, transfer and disclose non-personal information for any purpose. The following are examples of non-personal information that we collect and how we can use it. We may collect personal data, such as: the source of the link to the Website, the characteristics of user behavior on the Website, the number of pages viewed on the Website. Such data is depersonalized and is not personal. This data is collected in order to better understand what information is of interest to Website visitors and improve the quality of the content.",
"p8": "Personal data of Users is not transferred to any third parties. Users who have submitted their personal data to us before the entry into force of these Rules automatically agree to the use of their personal data. At the same time, they can always withdraw their consent to the use of personal data through the feedback form. The Operator blocks personal data related to the relevant User from the moment of the request or request of the User or his legal representative, in case of identification of false personal data or illegal actions.",
"p9": "The user's personal data is destroyed when the personal data subject withdraws consent to the processing of personal data.",
"p10":"IDENTIFICATION FILES (COOKIES) AND OTHER TECHNOLOGIES",
"p11":"The Website, interactive services and applications, e-mail messages and any other communications on our behalf may use identification cookies and other technologies such as pixel tags, web beacons. Accordingly, when using the website and other services, a pop-up window may appear on your device notifying you about the use of cookies. These technologies help us better understand user behavior, tell us which sections of our site have been visited by users, and measure the effectiveness of advertising and online searches. We consider the information collected by cookies and other technologies as non-personal information. You can control cookies by following the instructions of your browser or device. As a rule, you can change your cookie settings in the 'Settings' or 'System Settings' section. As with most websites, we collect some information automatically and store it in statistics files. Such information includes the Internet Protocol address (IP address), browser type and language, information about the Internet service provider, sending and exiting pages, information about the operating system, date and time stamp, as well as information about visits. We use such information to understand and analyze trends, administer the website, study user behavior on it, and collect demographic information about our core user base. The organization may use such information for its own marketing purposes. In some of our e-mail messages, we use interactive links to information posted on the Website. When users follow such links, before they get to the destination page on our website, their requests go through a separate registration. We track such 'passing' data to help us identify interest in individual topics and measure the effectiveness of our communications with users. If you prefer that your requests are not tracked in this way, you should not follow text or image links in e-mail messages. Pixel labels allow us to send e-mail messages in a format that is readable by consumers and tell us whether such messages have been read. We may use such information to limit the number of messages sent to consumers or to stop sending them.",
"p12": "We take precautions to ensure the protection of your personal data in order to ensure the protection of the User's personal data from unauthorized or accidental access to it, destruction, modification, blocking, copying, distribution, as well as from other illegal actions of third parties.",
"p13":"INTEGRITY AND PRESERVATION OF PERSONAL INFORMATION",
"p14":"We will store your personal data and information for as long as necessary to fulfill the purposes described in this Privacy Policy. We do not collect personal data about minors. If we become aware that we have received personal data about a minor, we will take measures to delete such information as soon as possible. We strongly recommend that parents and other persons under whose supervision minors are (legal representatives — parents, adoptive parents or guardians) monitor the use of websites by minors. The Operator is not responsible for the actions of third parties who have gained access to User information as a result of using the Internet or the Website's Services and for the consequences of using data and information that, due to the nature of the Website, are available to any Internet user.",
"p15":"QUESTIONS ABOUT PRIVACY",
"p16":"If you have any questions regarding this Privacy Policy or data processing, you can contact us using the feedback contacts kyrgyzstan@transparency.org.",
"p17": "Users have the right to send their requests to the Operator, including requests regarding the use of their personal data, sending a withdrawal of consent to the processing of personal data in writing to the address specified in the General Provisions section of this regulation, or in the form of an electronic document sent via the feedback form. The Operator undertakes to review and send a response to the User's request within 30 days from the date of receipt of the request.",
"p18":"OTHER",
"p19":"A visitor to the Organization's website who provides his personal data and information thereby agrees to the provisions of this Privacy Policy. We reserve the right to make any changes to the Policy at any time at our discretion in order to further improve the system of protection against unauthorized access to personal data reported by Users without the User's consent. When we make significant changes to the Privacy Policy, a corresponding notification is posted on our website along with the updated version of the Privacy Policy.This Policy does not apply to the actions and Internet resources of third parties."
}
}

View File

@ -1,234 +0,0 @@
{
"general": {
"date": "Күн",
"address": "Дарек",
"status": "Статус",
"description": "Көйгөй",
"reviews": "Комментарийлер",
"rating": "Рейтинг",
"review": "Комментарий",
"write_comment": "Комментарий жазуу",
"search": "Издөө",
"search_for": "Издөө",
"city": "Шаар",
"added_roads": "Белгилөөлөр",
"broken_roads": "Бузулган жолдор",
"accident_hotspots": "Авариялык абалда",
"local_defects": "Жергиликтүү кемчиликтер",
"repair_plans": "Ремонттоо планында",
"repaired": "Ремонттолгон",
"fixed_local_defects": "Жергиликтүү оңдолгон жолдор",
"news": "Жаңылыктар",
"details": "Кененирээк маалымат",
"navigation": "Навигация",
"contacts": "Байланыш",
"download_our_app": "Биздин колдонмону жүктөңүз",
"socials": "Социалдык тармактар",
"back": "Артка",
"save": "Сактоо",
"saving": "Сакталат",
"cancel": "Жокко чыгаруу",
"cancellation": "Жокко чыгаруу",
"save_changes": "Өзгөртүүлөрдү сактоо",
"send": "Жиберүү",
"receive": "Алуу",
"delete": "Жок кылуу",
"show_on_map": "Картада көрсөтүү",
"author_of_appeal": "Өтүнүчтүн автору",
"enter_city": "Жерликти киргизиңиз",
"page_not_found": "Барак табылган жок (404)",
"incorrect_address_or_nonexistent_page": "Дарек туура эмес же баракча жок",
"home": "Башкы бет",
"first_name": "Аты-жөнү",
"last_name": "Фамилия",
"email": "Электрондук почта"
},
"navigation": {
"home": "Башкы бет",
"about_us": "Биз жөнүндө",
"privacy": "Купуялык саясаты",
"support": "Колдоо",
"statistics": "Статистика",
"news": "Жаңылыктар",
"volunteers": "Ыктыярчылар",
"profile": "Профиль",
"login": "Кирүү"
},
"about_us": {
"name": "Биз жөнүндө",
"description1": "Transparency International ̶ это глобальная независимая организация по изучению и борьбе с коррупцией как в международном масштабе, так и в масштабе отдельных стран, одна из целей которой добиться большей прозрачности и подотчетности власти.",
"description2": "Команда Трансперенси Интернешнл Кыргызстан разработала платформу для мониторинга строительства и ремонта дорог, содержащая интерактивную карту по обеспечению доступа к информации о дорогах и улицах, отремонтированных за последние годы, включая стоимость работ, данные организации-подрядчика, гарантийные сроки, ссылки на закупочную документацию и другую информация о работах, а также обобщенная статистика по дорожным работам (например, дорожные работы, выполненные одним и тем же подрядчиком). ",
"description3": "Платформа также предоставит пользователям возможность оперативно сообщать о дефектах на дорогах и необходимости их устранения, голосовать за приоритетность ремонта дорог и предоставлять обратную связь в удобном формате, которые позволят гражданам самостоятельно анализировать и контролировать использование исполнения государственных дорожных контрактов. Информация по дорожным строительствам и ремонтам собирается из открытых данных портала госзакупок и Минюста.",
"description4":"Помимо веб-платформы имеются два мобильных приложения для платформ iOS и Android с функциями, аналогичными веб-сайту."
},
"home": {
"title": "Кыргызстандын жолдору",
"subtitle": "Жолдорду коопсуз кылалы!",
"info": "Жолдун абалы боюнча акыркы маалымат",
"report_broken_road": "Бузулган жолду белгилөө",
"road_map": "Жол картасы",
"latest_news": "Жол кыймылы, жасалып жатканы ж.б. тууралуу акыркы жаңылыктардан кабардар болуңуз!",
"enter_location": "Шаар, айыл же аймакты киргизиңиз",
"broken_roads": "Бузулган жол",
"accident_hotspots": "Авариялык абалда",
"local_defects": "Жергиликтүү дефект",
"repair_plans": "Ремонттоо планында",
"repaired": "Оңдолгон",
"fixed_local_defects": "Оңдолгон жергиликтүү дефект",
"rating": "Рейтинг",
"road_discussions": "Жолдорду талкуулоо: рейтинг, жеке тажрыйба, ылайык айдоо!",
"enter_address": "Даректи киргизиңиз",
"read_more": "Көбүрөөк маалымат"
},
"transparency_international_kyrgyzstan": {
"name": "Транспаренси Интернешнл-Кыргызстан",
"description": "Transparency International эл аралык уюмунун Кыргыз Республикасындагы бөлүмү.",
"mission": "Коррупциянын алдын алуу жана өлкөдө демократияны чыңдоо үчүн эффективдүү мамлекеттик саясатты жана ак ниет башкарууну алдыга жылдыруу.",
"goals_and_priorities": {
"anti-corruption_education": "Кыргызстандын калкын коррупцияга каршы күрөштүн мааниси жана зарылчылыгы жөнүндө коомчулуктун маалымдуулугун жогорулатуу;",
"study_of_corruption_practices": "Кыргызстанда жана башка өлкөлөрдө коррупция менен күрөшүүнүн тажрыйбасы жана теориясын изилдөөнү уюштуруу жана ага жарандык коом структураларынын катышуусу;",
"supporting_citizens_and_organizations": "Жарандарга жана уюмдарга алардын конституциялык укуктарын жана эркиндиктерин ишке ашырууга жардам көрсөтүү;",
"international_experience": "Коррупцияны азайтуу боюнча эл аралык тажрыйбага, анын технологияларын, ресурстарын колдонууга, ошондой эле коррупцияга каршы эл аралык диалогго жарандык коомдун түзүмдөрүн кошууга басымдуулук кылуу."
}
},
"volunteers": {
"activists": "Активисттер",
"received_votes": "Алынган добуштар",
"left_votes": "Калтырылган добуштар",
"rating": "Рейтинг"
},
"profile": {
"personal_cabinet": "Жеке кабинет",
"personal_data": "Жеке маалымат",
"my_appeals": "Менин кайрылууларым",
"logout": "Чыгуу",
"write_appeal": "Кайрылуу",
"profile_photo": "Сүрөт",
"others_identification": "Профиль сүрөтү аркылуу башка адамдар сизди тааный алышат, жана сиз кайсы аккаунтка киргениңиз белгилүү болот.",
"add_profile_photo": "Профиль сүрөтү кошуу",
"profile_photo_updated": "Сүрөттү жаңырланытуу",
"delete": "Жок кылуу",
"change": "Өзгөртүү"
},
"authorization": {
"change_password": "Сыр сөздү өзгөртүү",
"old_password": "Эски сыр сөз",
"enter_old_password": "Эски сыр сөздү киргизиңиз",
"new_password": "Жаңы сыр сөз",
"enter_new_password": "Жаңы сыр сөздү киргизиңиз",
"confirm_new_password": "Жаңы сыр сөздү ырастоо",
"confirm_new_password_prompt": "Сураныч, жаңы сыр сөздү ырастоо зарыл",
"password": "Сыр сөз",
"forgot_password": "Сыр сөздү унуттуңузбу?",
"login": "Кириш",
"register": "Каттоо",
"sign_in_account": "Аккаунтка кириңиз",
"enter_credentials": "Сураныч, киргизиңиз",
"login_via_google": "Google аркылуу кирүү",
"enter_password": "Сыр сөздү киргизиңиз",
"password_requirements": "Минимум 8 белги, 1 башкы буюк тамга жана 1 сандар",
"no_account_yet": "Аккаунтуңуз жокпу? Катталыңыз",
"registration": "Каттоо",
"register_now": "Каттоо",
"already_have_account": "Аккаунтуңуз барбы? Кириңиз",
"enter_email": "Электрондук почтаны киргизиңиз",
"enter_email_for_code": "Электрондук почтаны киргизиңиз, биз сизге сыр сөздү жөнөтөбүз",
"send_code": "Код жөнөтүү",
"confirm_code": "Кодту ырастоо",
"enter_code": "Кодду киргизиңиз",
"enter_reset_code": "Сыр сөздү өзгөртүп жаңыртуу үчүн кодту киргизиңиз",
"reset_code": "Сыр сөздү өзгөртүү коду",
"reset_password": "Сыр сөздү өзгөртүү",
"check_email": "Почтаны текшериңиз",
"code_sent_to": "Биз кодду name@gmail.com почтасына жөнөттүк",
"confirmation_code": "Ырастоо коду",
"confirm": "Ырастоо",
"resend_code_in": "Кодду кайра жөнөтүү",
"resend_code": "Кодду кайра жөнөтүү"
},
"send_report": {
"how_to_mark_road_section": "Жол бөлүмүн белгилөө",
"mark_road_instructions": "Төйнөгүчтү коюп, жолдун бир бөлүгүн тарта баштаңыз (ал каалаган сандагы сынык сызыктардан турушу мүмкүн).",
"remove_segment_instruction": "Жол бөлүгүн алып таштоо үчүн коюлган төйнөгүчтү кайра басыңыз.",
"add_problem_description": "Көйгөйдү сүрөттөңүз",
"enter_description": "Сүрөттөмөнү киргизиңиз",
"add_photos": "Сүрөт салыңыз",
"upload_photos_instructions": "Көйгөйдү ырастоо үчүн жолго тиешелүү 5 сүрөткө чеийн киргизсеңиз болот.",
"attach_file": "Сүрөт тиркөө (5 МБга чейин)",
"submit_for_moderation": "Модерацияга жиберүү",
"appeal_submitted": "Сиздин кайрылууңуз жиберилди",
"thanks_for_appeal": "Кайрылууңуз үчүн рахмат. Азырынча ал модерацияда.",
"view_my_appeals": "Менин кайрылууларымды көрүү"
},
"months": {
"january": "Үчтүн айы",
"february": "Бирдин айы",
"march": "Жалган куран",
"april": "Чын куран",
"may": "Бугу",
"june": "Кулжа",
"july": "Теке",
"august": "Баш оона",
"september": "Аяк оона",
"october": "Тогуздун айы",
"november": "Жетинин айы",
"december": "Бештин айы"
},
"validation_errors": {
"invalid_email_format": "Электрондук почтанын форматы туура эмес.",
"passwords_do_not_match": "Сыр сөздөрү туура келбейт.",
"required_field_not_filled": "Талап кылынган жер толтурулган эмес.",
"exceeded_maximum_length": "Тамгалардын максималдуу узундугу ашып кетти.",
"login_required_before_commenting": "Комментарий калтырыш үчүн жеке кабинетиңизге кириңиз же каттоодон өтүңүз.",
"login_required_before_like": "Лайк коюш үчүн жеке кабинетиңизге кириңиз же каттоодон өтүңүз."
},
"server_errors": {
"invalid_email_or_password": "Почта же сыр сөз туура эмес.",
"server_error_auth_attempt": "Авторизация аракетинде сервердеги ката.",
"login_failed": "Кирүүгө мүмкүн эмес. Кийинчирээк кайталап көрүңүз.",
"account_already_exists": "Бул почта катталган.",
"account_not_found": "Аккаунт табылган жок.",
"invalid_activation_code": "Код жараксыз.",
"invalid_activation_code_reset": "Активация коду жараксыз.",
"invalid_password_reset_code": "Сыр сөздү өзгөртүү коду жараксыз.",
"invalid_code": "Туура эмес код."
},
"disclaimer": {
"text": "Бул веб-сайт Европа Биримдиги тарабынан каржыланат. Анын мазмуну үчүн Трансперенси Интернешнл Кыргызстан гана жоопкерчиликтүү жана ал Европа Биримдигинин көз карашын сөзсүз түрдө чагылдырбайт."
},
"rights": {
"text": "Бардык укуктар корголгон"
},
"PrivacyPolicy":{
"titel0":"Купуялык саясаты",
"title1": "Жалпы жоболор",
"title2": "Жеке маалыматтарды чогултуу",
"title3": "Жеке маалыматтарды сактоо жана пайдалануу",
"title4": "Жеке маалыматтарды өткөрүп берүү",
"title5": "Жеке маалыматтарды жок кылуу",
"title6": "Жеке маалыматтарды коргоо",
"title7": "Колдонуучунун кайрылуулары",
"p1":"Бул Купуялык саясатынын билдирүүсү почта тизмесин, сайттын пикир формасын жана домендик аталышта жайгашкан электрондук почта даректерин колдонгон жеке адамдар (мындан ары - Колдонуучулар) жөнүндө маалыматты иштеп чыгуу жана коргоо тартибин аныктайт.",
"p1o":" (мындан ары Сайт деп аталат) домендик аталышта жайгашкан почталык таркатма, сайттын пикир билдирүү формасын жана электрондук почта даректерин колдонгон жеке адамдар (мындан ары - Колдонуучулар) жөнүндө маалыматты колдонуу жана коргоо тартибин аныктайт. Биз жеке маалыматтарды кантип иштетээрибизди сүрөттөгөн Купуялык саясатын иштеп чыктык - автоматташтыруу куралдарын колдонуу менен же мындай куралдарды колдонбостон аткарылган ар кандай аракеттер (операциялар) же аракеттердин (операциялардын) жыйындысы, анын ичинде жеке маалыматтарды чогултуу, жазып алуу, системалаштыруу, топтоо, сактоо, тактоо (жаңыртуу, өзгөртүү),  чыгаруу, пайдалануу, берүү (тараттуу,  көрсөтүү, жетүү),  өздүксүздөндүрүү,  жаап коюу,  өчүрүү, жок кылуу. Жеке маалыматтарды жана Сайттын колдонуучулары жөнүндө маалыматтарды иштетүүгө байланышкан мамилелер ушул Жобо менен жөнгө салынат. Бул Купуялык саясаты Сайттын колдонуучулары болуп саналган адамдар жөнүндө персоналдык маалыматтарды жана жеке мүнөздөгү маалыматтарды ( өздүктү тактаганга мүмкүндүк берген каалаган маалымат жана ага байланыштуу каалаган башка маалымат) иштетүүнүн бардык түрүн жөнгө салат. Бул Саясат дүйнөнүн каалаган жеринде жайгашкан адамдардан Интернет аркылуу да, аны колдонбостон да активдүү жана пассивдүү ар кандай каражаттар менен чогултулган жеке, персоналдык маалыматтарды иштетүүгө карата колдонулат.",
"p2":"Жеке маалыматтарды  иштетүүнүн максаты Оператор тарабынан Сайтты жана анын кызматтарын пайдалануу боюнча Колдонуучулардын алдындагы милдеттерин аткаруу болуп саналат. Колдонуучунун жеке маалыматтарын иштетүү жеке маалыматтар субъектинин анын жеке маалыматтарын иштетүүгө макулдугу менен жүзөгө ашырылат. Жеке маалыматтар  деп, аныкталган же аныкталуучу адамга (жеке маалыматтар субъектисине) түздөн-түз же кыйыр түрдө тиешелүү жана аныкталган адамды идентификациялоо же аны менен байланыштыруу үчүн колдонулушу мүмкүн болгон  каалаган  маалымат. Сиздин макулдугуңуз менен сизди почталык таркатмага киргизүү, ошондой эле Сайттагы пикир билдирүү формасы аркылуу биз менен байланышсаңыз, сизге жооп берүү үчүн атыңызды, фамилияңызды, атаңыздын атыңыздын жана электрондук почта дарегиңизди сурашыбыз мүмкүн.",
"p3": "Колдонуучулардын жеке маалыматтары электрондук алып жүрүүчүлөрдө гана сакталат жана автоматташтырылган системалардын жардамы менен иштетилет.",
"p4": "БИЗ СИЗДИН ЖЕКЕ МААЛЫМАТТАРЫНЫЗДЫ КАНТИП КОЛДОНОБУЗ",
"p5":"Биз чогулткан жеке маалыматтар бизге коррупцияга каршы күрөшүү тармагындагы жаңылыктар жана ар кандай окуялар жөнүндө электрондук почта билдирүүлөрүн жөнөтүүгө мүмкүндүк берет. Ошондой эле, сиздин жеке маалыматтарыңыз пикир билдирүү формасы аркылуу же Сайтта жайгашкан биздин электрондук почта дарегибизге жөнөтүлгөн сурооңузга жооп берүү учурунда колдонулушу мүмкүн. Эгерде сиз биздин почта таркатма тизмебизге кирүүнү каалабасаңыз, анда көрсөтүлгөн пикир билдирүү байланыштар аркылуу бизге маалымдоо аркылуу жазылууну каалаган убакта баш тартсаңыз болот.",
"p6":"ЖЕКЕ ЭМЕС МААЛЫМАТТАРДЫ ЧОГУЛТУУ ЖАНА КОЛДОНУУ",
"p7":"Биз ошондой эле жеке эмес саналган персоналдык маалыматтарды чогултабыз - кандайдыр бир аныкталган адам менен түздөн-түз байланышта болбогон маалымат. Биз ар кандай максатта жеке эмес маалыматты чогултабыз, колдонобуз, өткөрүп бере алабыз жана ачып бере алабыз. Төмөндө биз чогулткан жеке эмес маалыматтын мисалдары жана биз аны кантип колдонорубуз көрсөтүлгөн. Биз Сайтка өтүүнүн булагы, Сайттагы колдонуучунун жүрүм-турум өзгөчүлүктөрү, Сайтта каралган барактардын саны сыяктуу персоналдык маалыматтарды чогултушубуз мүмкүн. Мындай маалыматтар анонимдүү жана жеке эмес. Бул маалыматтар Сайттын конокторун кандай маалымат кызыктырарын жакшыраак түшүнүү жана мазмундун сапатын жакшыртуу максатында чогултулат.",
"p8":"Колдонуучулардын жеке маалыматтары үчүнчү жактарга берилбейт. Ушул Эрежелер күчүнө киргенге чейин бизге өздөрүнүн жеке маалыматтарын берген колдонуучулар автоматтык түрдө өздөрүнүн жеке маалыматтарын пайдаланууга макул болушат. Ошол эле учурда алар ар дайым пикир билдирүү формасы аркылуу жеке маалыматтарды колдонууга макулдугун кайта чакырып ала алышат. Оператор  Колдонуучудан же анын мыйзамдуу өкүлүнөн арыз же суроо-талап түшкөн учурдан тартып, такталбаган жеке маалыматтар же мыйзамсыз аракеттер аныкталган учурда  тиешелүү Колдонуучуга таандык жеке маалыматтарды жаап коет.",
"p9": "Жеке маалыматтардын субъекти жеке маалыматтарды иштетүүгө макулдугун  кайта чакырып алса, колдонуучунун жеке маалыматтары жок кылынат.",
"p10":"ИДЕНФИКАЦИЯЛЫК ФАЙЛДАР (КУКИ) ЖАНА БАШКА ТЕХНОЛОГИЯЛАР",
"p11":"Вебсайт, интерактивдүү кызматтар жана тиркемелер, электрондук почта билдирүүлөрү жана биздин атыбыздан башка коммуникациялар идентификациялык куки файлдарын (cookies) жана башка пиксел энбелгилерин (pixel tags), веб-маяктар (web beacons) сыяктуу башка технологияларды колдонушу мүмкүн. Демек, веб-сайтты жана башка кызматтарды колдонууда, сиздин түзмөгүңүздө кукилерди колдонуу жөнүндө эскерткен калкыма терезе пайда болушу мүмкүн. Бул технологиялар бизге колдонуучунун жүрүм-турумун жакшыраак түшүнүүгө, биздин сайттын кайсы бөлүктөрүнө колдонуучулар киргенин айтып берүүгө жана жарнаманын жана онлайн издөөлөрдүн натыйжалуулугун өлчөөгө жардам берет. Биз кукилер жана башка технологиялар тарабынан чогултулган маалыматты жеке эмес маалымат деп эсептейбиз. Сиз браузериңиздеги же түзмөгүңүздөгү нускамаларды аткаруу менен cookie файлдарын көзөмөлдөй аласыз. Адатта, сиз куки жөндөөлөрүңүздү 'Жөндөөлөр' же 'Система жөндөөлөрү' бөлүмүнөн өзгөртө аласыз. Көпчүлүк веб-сайттардагыдай эле, биз кээ бир маалыматты автоматтык түрдө чогултуп, статистикалык файлдарда сактайбыз. Бул маалыматка Интернет Протоколунун (IP) дареги, браузердин түрү жана тили, Интернет-кызмат провайдери, шилтеме берүү жана чыгуу баракчалары, операциялык тутум маалыматы, дата жана убакыт маалыматы жана кирип чыгуу маалыматы кирет. Биз мындай маалыматты тенденцияларды түшүнүү жана талдоо, сайтты башкаруу, сайттагы колдонуучунун жүрүм-турумун изилдөө жана жалпы колдонуучуларыбыз жамааты жөнүндө демографиялык маалыматты чогултуу үчүн колдонобуз. Уюм мындай маалыматты өзүнүн маркетингдик максаттары үчүн колдоно алат. Кээ бир электрондук почта билдирүүлөрүндө биз Сайтта жайгаштырылган маалыматка интерактивдүү шилтемелерди колдонобуз. Колдонуучулар биздин веб-сайттагы көздөгөн бетке жеткенге чейин мындай шилтемелер боюнча өткөндө, алардын суроо-талаптары өзүнчө катталат. Биз белгилүү бир темаларга болгон кызыгууну аныктоого жана колдонуучулар менен болгон байланышыбыздын натыйжалуулугун өлчөөгө жардам берүү үчүн бул 'өтүү' маалыматына көз салабыз. Эгер сиз өзүңүздүн байланыштарыңызга ушундай жол менен көз салууну каалабасаңыз, электрондук почта билдирүүлөрүндөгү тексттик же сүрөт шилтемелерин боюнча өтпөшүңүз керек . Пиксел энбелгилери бизге электрондук почта билдирүүлөрүн керектөөчү окуй турган форматта жеткирүүгө жана мындай билдирүүлөр окулгандыгы жөнүндө маалымат берет. Биз мындай маалыматты керектөөчүлөргө жөнөткөн байланыштарды чектөө же токтотуу үчүн колдонушубуз мүмкүн.",
"p12":"Колдонуучунун жеке маалыматтарын уруксатсыз же кокустан  жетүүдөн, жок кылуудан, өзгөртүүдөн,  жаап коюудан, көчүрүүдөн, жайылтуудан, ошондой эле үчүнчү жактардын башка мыйзамсыз аракеттеринен коргоону камсыз кылуу үчүн биз сиздин жеке маалыматтарыңыздын корголушун камсыз кылуу боюнча чараларды көрөбүз.",
"p13":"ЖЕКЕ МААЛЫМАТТАРДЫН БҮТҮНДҮГҮ ЖАНА САКТАЛЫШЫ",
"p14":"Биз сиздин жеке маалыматтарыңызды ушул Купуялык саясатында сүрөттөлгөн максаттарды аткаруу үчүн зарыл болгон мезгил ичинде сактайбыз. Биз жашы жете электердин жеке маалыматын чогултпайбыз. Эгер биз жашы жете элек бала жөнүндө жеке маалыматты чогултканыбызды билсек, биз мындай маалыматты мүмкүн болушунча тезирээк жок кылуу үчүн чараларды көрөбүз. Биз ата-энелерге жана көзөмөлүндө жашы жете элек балдар бар башка адамдарга (мыйзамдуу өкүлдөр - ата-энелер, асырап алуучулар же камкорчулар) жашы жете электердин веб-сайттарды колдонуусун көзөмөлдөөнү туруктуу сунуштайбыз. Оператор Интернетти же Сайттын Кызматтарын колдонуунун натыйжасында Колдонуучу жөнүндө маалыматка жетүү мүмкүнчүлүгүнө ээ болгон үчүнчү жактардын аракеттери үчүн жана Сайттын мүнөзүнө байланыштуу каалаган интернет колдонуучуга жеткиликтүү маалыматтарды колдонуунун кесепеттери үчүн жоопкерчилик тартпайт.",
"p15":"КУПУЯЛЫК ЖӨНҮНДӨ СУРООЛОРУ",
"p16":"Бул Купуялык саясатына же маалыматтарды иштетүүгө байланыштуу суроолоруңуз болсо, kyrgyzstan@transparency.org байланыш дареги аркылуу биз менен байланышсаңыз болот.",
"p17":"Колдонуучулар Операторго өздөрүнүн суроо-талаптарын, анын ичинде алардын жеке маалыматтарын колдонууга, жеке маалыматтарды иштетүүгө макулдукту жокко чыгарууга байланыштуу суроо-талаптарды ушул жобонун Жалпы жоболор бөлүмүндө көрсөтүлгөн дарек боюнча жазуу жүзүндө же пикир билдирүү формасы аркылуу жөнөтүлгөн электрондук документ формасында жөнөтүүгө укуктуу. Оператор суроо-талапты алган күндөн тартып 30 күндүн ичинде Колдонуучунун суроо-талабын карап чыгууга жана ага жооп жөнөтүүгө милдеттенет.",
"p18":"БАШКАЛАР",
"p19":"Уюмдун веб-сайтына өзүнүн жеке маалыматтарын жана маалыматын берген конок ушул Купуялык саясатынын жоболоруна макул болот. Колдонуучунун макулдугусуз Колдонуучулар тарабынан билдирилген жеке маалыматтарга уруксатсыз кирүүдөн коргоо тутумун андан ары өркүндөтүү максатында, биз каалаган убакта ушул Саясатка өзгөртүүлөрдү киргизүү укугун сактайбыз. Купуялык саясатыбызга олуттуу өзгөртүүлөрдү киргизгенде, биз Купуялык саясатыбыздын жаңыртылган версиясы менен бирге веб-сайтыбызга билдирүү жарыялайбыз. Бул Саясат үчүнчү жактардын аракеттерине жана интернет-ресурстарына жайылтылбайт."
}
}

View File

@ -1,221 +0,0 @@
{
"general": {
"date": "Дата",
"address": "Адрес",
"status": "Статус",
"description": "Описание",
"reviews": "Комментарии",
"rating": "Рейтинг",
"review": "Комментарий",
"write_comment": "Написать комментарий",
"search": "Поиск",
"search_for": "Искать",
"city": "Город",
"added_roads": "Добавлено дорог",
"broken_roads": "Разбитых дорог",
"accident_hotspots": "Очагов аварийности",
"local_defects": "Локальных дефектов",
"repair_plans": "В планах ремонта",
"repaired": "Отремонтировано",
"fixed_local_defects": "Локальных дефектов исправлено",
"news": "Новости",
"details": "Подробнее",
"navigation": "Навигация",
"contacts": "Контакты",
"download_our_app": "Скачивай наше приложение",
"socials": "Социальные сети",
"back": "Назад",
"save": "Сохранить",
"saving": "Сохранение",
"cancel": "Отменить",
"cancellation": "Отмена",
"save_changes": "Сохранить изменения",
"send": "Отправить",
"receive": "Получить",
"delete": "Удалить",
"show_on_map": "Показать на карте",
"author_of_appeal": "Автор обращения",
"enter_city": "Введите населенный пункт",
"page_not_found": "Страница не найдена (404)",
"incorrect_address_or_nonexistent_page": "Неправильно набран адрес или такой страницы не существует.",
"home": "На главную",
"first_name": "Имя",
"last_name": "Фамилия",
"email": "Электронная почта"
},
"navigation": {
"home": "Главная",
"about_us": "О нас",
"privacy": "Политика конфиденциальности",
"support": "Поддержка",
"statistics": "Статистика",
"news": "Новости",
"volunteers": "Волонтеры",
"profile": "Профиль",
"login": "Войти"
},
"home": {
"title": "Дороги Кыргызстана",
"subtitle": "Сделаем дороги безопасными!",
"info": "Актуальная информация о состоянии дорог",
"report_broken_road": "Отметить разбитую дорогу",
"road_map": "Карта дорог",
"latest_news": "Будьте в курсе последних новостей о дорожном движении, строительствах и мероприятиях!",
"enter_location": "Введите город, село или регион",
"broken_roads": "Разбитая дорога",
"accident_hotspots": "Очаг аварийности",
"local_defects": "Локальный дефект",
"repair_plans": "В плане ремонта",
"repaired": "Отремонтировано",
"fixed_local_defects": "Локальный дефект исправлен",
"rating": "Рейтинг",
"road_discussions": "Обсуждаем дороги: рейтинг, опыт, комфорт в пути!",
"enter_address": "Введите адрес",
"read_more": "Читать"
},
"about_us": {
"name": "О нас",
"description1": "Transparency International ̶ это глобальная независимая организация по изучению и борьбе с коррупцией как в международном масштабе, так и в масштабе отдельных стран, одна из целей которой добиться большей прозрачности и подотчетности власти.",
"description2": "Команда Трансперенси Интернешнл Кыргызстан разработала платформу для мониторинга строительства и ремонта дорог, содержащая интерактивную карту по обеспечению доступа к информации о дорогах и улицах, отремонтированных за последние годы, включая стоимость работ, данные организации-подрядчика, гарантийные сроки, ссылки на закупочную документацию и другую информация о работах, а также обобщенная статистика по дорожным работам (например, дорожные работы, выполненные одним и тем же подрядчиком). ",
"description3": "Платформа также предоставит пользователям возможность оперативно сообщать о дефектах на дорогах и необходимости их устранения, голосовать за приоритетность ремонта дорог и предоставлять обратную связь в удобном формате, которые позволят гражданам самостоятельно анализировать и контролировать использование исполнения государственных дорожных контрактов. Информация по дорожным строительствам и ремонтам собирается из открытых данных портала госзакупок и Минюста.",
"description4":"Помимо веб-платформы имеются два мобильных приложения для платформ iOS и Android с функциями, аналогичными веб-сайту."
},
"volunteers": {
"activists": "Активисты",
"received_votes": "Получено голосов",
"left_votes": "Оставлено голосов",
"rating": "Рейтинг"
},
"profile": {
"personal_cabinet": "Личный кабинет",
"personal_data": "Личные данные",
"my_appeals": "Мои обращения",
"logout": "Выйти из аккаунта",
"write_appeal": "Написать обращение",
"profile_photo": "Фото профиля",
"others_identification": "По фото профиля другие люди смогут вас узнавать, а вам будет проще определять, в какой аккаунт вы вошли.",
"add_profile_photo": "Добавить фото профиля",
"profile_photo_updated": "Фото профиля обновлено",
"delete": "Удалить",
"change": "Сменить"
},
"authorization": {
"change_password": "Изменить пароль",
"old_password": "Старый пароль",
"enter_old_password": "Введите старый пароль",
"new_password": "Новый пароль",
"enter_new_password": "Введите новый пароль",
"confirm_new_password": "Подтвердить новый пароль",
"confirm_new_password_prompt": "Пожалуйста, подтвердите новый пароль",
"password": "Пароль",
"forgot_password": "Забыли пароль?",
"login": "Войти",
"register": "Зарегистрироваться",
"sign_in_account": "Войдите в аккаунт",
"enter_credentials": "Пожалуйста, введите свои данные",
"login_via_google": "Войти через Google",
"enter_password": "Введите пароль",
"password_requirements": "Минимум 8 символов, 1 заглавная буква и цифра",
"no_account_yet": "Еще нет аккаунта? Зарегистрируйтесь",
"registration": "Регистрация",
"register_now": "Зарегистрировать",
"already_have_account": "Уже есть аккаунт? Войти в аккаунт",
"enter_email": "Введите электронную почту",
"enter_email_for_code": "Введите электронную почту и мы отправим код для восстановления пароля",
"send_code": "Отправить код",
"confirm_code": "Потвердить код",
"enter_code": "Введите код",
"enter_reset_code": "Введите код для сброса и восстановления пароля",
"reset_code": "Код сброса пароля",
"reset_password": "Сбросить пароль",
"check_email": "Проверьте свою почту",
"code_sent_to": "Мы отправили код на почту name@gmail.com",
"confirmation_code": "Код подтверждения",
"confirm": "Подтвердить",
"resend_code_in": "Отправить код повторно через",
"resend_code": "Отправить код повторно"
},
"send_report": {
"how_to_mark_road_section": "Как отметить участок дороги?",
"mark_road_instructions": "Поставьте булавку и начните рисовать участок дороги (он может состоять из любого количества ломаных линий).",
"remove_segment_instruction": "Чтобы удалить отрезок, нажмите на точки повторно.",
"add_problem_description": "Добавьте описание проблемы",
"enter_description": "Введите описание",
"add_photos": "Добавьте фотографии",
"upload_photos_instructions": "Загрузите до 5 фотографий, связанных с дорогой, которую вы хотите отметить. Фотографии помогут лучше понять проблему.",
"attach_file": "Прикрепить файл (до 5 МБ)",
"submit_for_moderation": "Отправить на модерацию",
"appeal_submitted": "Ваше обращение отправлено",
"thanks_for_appeal": "Спасибо за ваше обращение. На данный момент оно в модерации.",
"view_my_appeals": "Смотреть мои обращения"
},
"months": {
"january": "Январь",
"february": "Февраль",
"march": "Март",
"april": "Апрель",
"may": "Май",
"june": "Июнь",
"july": "Июль",
"august": "Август",
"september": "Сентябрь",
"october": "Октябрь",
"november": "Ноябрь",
"december": "Декабрь"
},
"validation_errors": {
"invalid_email_format": "Неверный формат электронной почты.",
"passwords_do_not_match": "Пароли не совпадают.",
"required_field_not_filled": "Обязательное поле не заполнено.",
"exceeded_maximum_length": "Превышена максимальная длина поля.",
"login_required_before_commenting": "Перед тем как оставить комментарий, пожалуйста, войдите или зарегистрируйтесь.",
"login_required_before_like": "Перед тем как поставить лайк, пожалуйста, войдите или зарегистрируйтесь."
},
"server_errors": {
"invalid_email_or_password": "Неверная почта или пароль.",
"server_error_auth_attempt": "Серверная ошибка при попытке авторизации.",
"login_failed": "Не удалось войти в систему. Что-то пошло не так, попробуйте еще раз немного позже.",
"account_already_exists": "Такая учетная запись уже существует.",
"account_not_found": "Такой учетной записи не существует.",
"invalid_activation_code": "Код не действителен.",
"invalid_activation_code_reset": "Код активации не действителен.",
"invalid_password_reset_code": "Код сброса пароля не действителен.",
"invalid_code": "Неверный код."
},
"disclaimer": {
"text": "Этот веб-сайт финансируется Европейским Союзом. Ответственность за его содержание лежит исключительно на Трансперенси Интернешнл Кыргызстан и не обязательно отражает точку зрения Европейского Союза."
},
"rights": {
"text": "Все права защищены"
},
"PrivacyPolicy":{
"titel0":"Политика конфиденциальности",
"title1": "Общие положения",
"title2": "Сбор персональных данных",
"title3": "Хранение и использование персональных данных",
"title4": "Передача персональных данных",
"title5": "Уничтожение персональных данных",
"title6": "Защита персональных данных",
"title7": "Обращения пользователей ",
"p1":"Настоящее Положение о политике конфиденциальности определяет порядок обработки и защиты информации о физических лицах (далее — Пользователи), пользующихся почтовой рассылкой, формой обратной связи сайта, электронными почтовыми адресами, расположенными на доменном имени ",
"p1o":" (далее — Сайт). Мы разработали Политику Конфиденциальности, которая описывает, как мы осуществляем обработку персональных данных — любые действия (операции) или совокупность действий (операций), совершаемых с использованием средств автоматизации или без использования таких средств с персональными данными, включая сбор, запись, систематизацию, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, передачу (распространение, предоставление, доступ), обезличивание, блокирование, удаление, уничтожение персональных данных. Отношения, связанные с обработкой персональных данных и информации о пользователях Сайта, регулируются настоящим Положением. Настоящая Политика Конфиденциальности регулирует любой вид обработки персональных данных и информации личного характера (любой информации, позволяющей установить личность, и любой иной информации, связанной с этим) о физических лицах, которые являются пользователями Сайта. Настоящая Политика распространяется на обработку личных, персональных данных, собранных любыми средствами, как активными, так и пассивными, как через Интернет, так и без его использования, от лиц, находящихся в любой точке мира.",
"p2": "Целью обработки персональных данных является выполнение обязательств Оператора перед Пользователями в отношении использования Сайта и его сервисов. Обработка персональных данных пользователей осуществляется с согласия субъекта персональных данных на обработку его персональных данных. Под персональными данными понимается любая информация, относящаяся к прямо или косвенно определенному или определяемому физическому лицу (субъекту персональных данных) и которая может быть использована для идентификации определенного лица либо связи с ним. Мы можем запросить у Вас имя, фамилию, отчество и адрес электронной почты для того, чтобы включить Вас в почтовую рассылку с Вашего согласия, а также для того, чтобы ответить Вам, если Вы обратились к нам через форму обратной связи на Сайте.",
"p3": "Персональные данные Пользователей хранятся исключительно на электронных носителях и обрабатываются с использованием автоматизированных систем. ",
"p4": "КАК МЫ ИСПОЛЬЗУЕМ ВАШУ ПЕРСОНАЛЬНУЮ ИНФОРМАЦИЮ",
"p5":"Собираемые нами персональные данные позволяют направлять Вам по электронной почте уведомления о новостях и различных событиях в сфере антикоррупции. Также ваши персональные данные могут быть использованы при ответе на ваше обращение, направленное через форму обратной связи или на наш адрес электронной почты, расположенные на Сайте. Если Вы не желаете быть включенным в наш список рассылки, Вы можете в любое время отказаться от рассылки путём информирования нас по указанным контактам для обратной связи.",
"p6":"СБОР И ИСПОЛЬЗОВАНИЕ ИНФОРМАЦИИ, НЕ ЯВЛЯЮЩЕЙСЯ ПЕРСОНАЛЬНОЙ",
"p7":"Мы также собираем персональные данные, не являющиеся персональными данные, не позволяющие прямо ассоциировать их с каким-либо определённым лицом. Мы можем собирать, использовать, передавать и раскрывать информацию, не являющуюся персональной, для любых целей. Ниже приведены примеры информации, не являющейся персональной, которую мы собираем, и как мы можем её использовать. Мы можем собирать персональные данные, такие как: источник перехода на Сайт, особенности поведения пользователя на Сайте, количество просмотренных на Сайте страниц. Такие данные обезличены и не являются персональными. Эти данные собираются для того, чтобы лучше понимать, какая информация интересна посетителям Сайта и улучшать качество контента.",
"p8":"Персональные данные Пользователей не передаются каким-либо третьим лицам. Пользователи, которые передали нам свои персональные данные до вступления в силу настоящих Правил автоматически соглашаются на использование своих персональных данных. В тоже время, они всегда могут отозвать свое согласие на использование персональных данных через форму обратной связи. Оператор осуществляет блокирование персональных данных, относящихся к соответствующему Пользователю, с момента обращения или запроса Пользователя или его законного представителя, в случае выявления недостоверных персональных данных или неправомерных действий.",
"p9":"Персональные данные пользователя уничтожаются при отзыве субъектом персональных данных согласия на обработку персональных данных.",
"p10":"ИДЕНТИФИКАЦИОННЫЕ ФАЙЛЫ (СOOKIES) И ИНЫЕ ТЕХНОЛОГИИ",
"p11":"Веб-сайт, интерактивные услуги и приложения, сообщения электронной почты и любые иные коммуникации от нашего лица могут использовать идентификационные файлы cookies и иные технологии, такие как пиксельные ярлыки (pixel tags), веб-маяки (web beacons). Соответственно при пользовании веб-сайтом и иными услугами на Вашем устройстве может возникнуть всплывающее окно с уведомлением об использовании cookies. Указанные технологии помогают нам лучше понимать поведение пользователей, сообщают нам, какие разделы нашего сайта были посещены пользователями, и измеряют эффективность рекламы и сетевых поисков. Мы рассматриваем информацию, собираемую файлами cookies и иными технологиями как информацию, не являющуюся персональной. Вы можете контролировать cookies следуя инструкциям Вашего браузера или устройства. Как правило, Вы можете изменить настройки cookies в разделе «Настройки» или «Системные настройки». Как и в случае большинства веб-сайтов, мы собираем некоторую информацию автоматически и храним её в файлах статистики. Такая информация включает в себя адрес Интернет-протокола (IP-адрес), тип и язык браузера, информацию о поставщике Интернет-услуг, страницы отсылки и выхода, сведения об операционной системе, отметку даты и времени, а также сведения о посещениях. Мы используем такую информацию для понимания и анализа тенденций, администрирования сайта, изучения поведения пользователей на сайте и сбора демографической информации о нашем основном контингенте пользователей в целом. Организация может использовать такую информацию в своих маркетинговых целях. В некоторых наших сообщениях электронной почты мы используем интерактивные ссылки на информацию, размещённую на Сайте. Когда пользователи проходят по таким ссылкам, прежде чем они попадают на страницу назначения на нашем веб-сайте, их запросы проходят отдельную регистрацию. Мы отслеживаем такие «проходные» данные, для того чтобы помочь нам определить интерес к отдельным темам и измерить эффективность наших коммуникаций с пользователями. Если Вы предпочитаете, чтобы Ваши обращения не отслеживались подобным образом, Вы не должны проходить по текстовым или графическим ссылкам в сообщениях электронной почты. Пиксельные ярлыки позволяют нам направлять сообщения электронной почты в формате, читаемом потребителями, и сообщают нам, были ли такие сообщения прочитаны. Мы можем использовать такую информацию для ограничения количества направляемых потребителям сообщений или прекращения их направления.",
"p12":"Мы предпринимает меры предосторожности для обеспечения защиты Ваших персональных данных в целях обеспечения защиты персональных данных Пользователя от неправомерного или случайного доступа к ним, уничтожения, изменения, блокирования, копирования, распространения, а также от иных неправомерных действий третьих лиц.",
"p13":"ЦЕЛОСТНОСТЬ И СОХРАНЕНИЕ ПЕРСОНАЛЬНОЙ ИНФОРМАЦИИ",
"p14":"Мы будем хранить Ваши персональные данные и информацию в течение срока, необходимого для выполнения целей, описываемых в настоящей Политике Конфиденциальности. Мы не собираем персональные данные о несовершеннолетних. Если нам станет известно о том, что мы получили персональные данные о несовершеннолетнем, мы предпримем меры для удаления такой информации в максимально короткий срок. Мы настоятельно рекомендуем родителям и иным лицам, под чьим присмотром находятся несовершеннолетние (законные представители — родители, усыновители или попечители), контролировать использование несовершеннолетними веб-сайтов. Оператор не несет ответственности за действия третьих лиц, получивших в результате использования Интернета или Услуг Сайта доступ к информации о Пользователе и за последствия использования данных и информации, которые, в силу природы Сайта, доступны любому пользователю сети Интернет.",
"p15":"ВОПРОСЫ ОТНОСИТЕЛЬНО КОНФИДЕНЦИАЛЬНОСТИ",
"p16":"Если у вас возникнут вопросы в отношении настоящей Политики Конфиденциальности или обработки данных, Вы можете связаться с нами по контактам обратной связи kyrgyzstan@transparency.org.",
"p17":"Пользователи вправе направлять Оператору свои запросы, в том числе запросы относительно использования их персональных данных, направления отзыва согласия на обработку персональных данных в письменной форме по адресу, указанному в разделе Общие положения настоящего положения, или в форме электронного документа, отправленного посредством формы обратной связи. Оператор обязуется рассмотреть и направить ответ на поступивший запрос Пользователя в течение 30 дней с момента поступления обращения.",
"p18":"ДРУГОЕ",
"p19": "Посетитель сайта Организации, предоставляющий свои персональные данные и информацию, тем самым соглашается с положениями данной Политики Конфиденциальности. Мы оставляем за собой право вносить любые изменения в Политику в любое время по своему усмотрению с целью дальнейшего совершенствования системы защиты от несанкционированного доступа к сообщаемым Пользователями персональным данным без согласия Пользователя. Когда мы вносим существенные изменения в Политику Конфиденциальности, на нашем сайте размещается соответствующее уведомление вместе с обновлённой версией Политики Конфиденциальности. Действие настоящей Политики не распространяется на действия и интернет-ресурсы третьих лиц."
}
}

View File

@ -1,9 +1,5 @@
import createNextIntlPlugin from "next-intl/plugin";
const withNextIntl = createNextIntlPlugin();
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
distDir: "build",
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
@ -12,10 +8,6 @@ const nextConfig = {
}, },
], ],
}, },
env: {
CLIENT_ID: process.env.CLIENT_ID,
CLIENT_SECRET: process.env.CLIENT_SECRET,
},
}; };
export default withNextIntl(nextConfig); export default nextConfig;

2229
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,29 +5,24 @@
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start -p 8003", "start": "next start -p 8004",
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@next/third-parties": "^14.1.0",
"axios": "^1.6.5", "axios": "^1.6.5",
"dotenv": "^16.4.1",
"html-react-parser": "^5.1.15",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"next": "^14.1.0", "next": "14.1.0",
"next-auth": "^4.24.5", "next-auth": "^4.24.5",
"next-intl": "^3.9.0",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"react-leaflet": "^4.2.1", "react-leaflet": "^4.2.1",
"sass": "^1.70.0", "sass": "^1.70.0",
"sharp": "^0.33.2",
"use-debounce": "^10.0.0", "use-debounce": "^10.0.0",
"zustand": "^4.5.0" "zustand": "^4.5.0"
}, },
"devDependencies": { "devDependencies": {
"@types/leaflet": "^1.9.8", "@types/leaflet": "^1.9.8",
"@types/node": "^20.11.16", "@types/node": "^20",
"@types/react": "^18", "@types/react": "^18",
"@types/react-dom": "^18", "@types/react-dom": "^18",
"@types/react-leaflet": "^3.0.0", "@types/react-leaflet": "^3.0.0",

File diff suppressed because it is too large Load Diff

9
src/App/App.scss Normal file
View File

@ -0,0 +1,9 @@
.app {
padding-top: 78px;
}
@media screen and (max-width: 768px) {
.app {
padding-top: 72px;
}
}

21
src/App/App.tsx Normal file
View File

@ -0,0 +1,21 @@
import "./globals.scss";
import "./fonts.scss";
import "./App.scss";
import Footer from "@/widgets/Footer/Footer";
import Navbar from "@/widgets/Navbar/Navbar";
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
<Navbar />
<div className="app">{children}</div>
<Footer />
</body>
</html>
);
}

9
src/App/fonts.scss Normal file
View File

@ -0,0 +1,9 @@
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700;800;900&display=swap");
@import url("https://fonts.cdnfonts.com/css/arial");
@import url("../shared/fonts/TildaSans.css");
* {
font-family: Tilda Sans;
}

25
src/App/globals.scss Normal file
View File

@ -0,0 +1,25 @@
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
button,
a {
cursor: pointer;
color: black;
display: flex;
align-items: center;
justify-content: center;
border: none;
background-color: transparent;
text-decoration: none;
font-size: 16px;
}
ul,
ol,
li {
list-style-type: none;
list-style: none;
}

View File

@ -3,7 +3,6 @@
import Image, { StaticImageData } from "next/image"; import Image, { StaticImageData } from "next/image";
import "./NewsCard.scss"; import "./NewsCard.scss";
import Link from "next/link"; import Link from "next/link";
import { useTranslations } from "next-intl";
interface INewsCard { interface INewsCard {
id: number; id: number;
@ -20,7 +19,6 @@ const NewsCard: React.FC<INewsCard> = ({
description, description,
date, date,
}: INewsCard) => { }: INewsCard) => {
const t = useTranslations("general");
const sliceTitle = (title: string) => { const sliceTitle = (title: string) => {
if (title.length > 35) { if (title.length > 35) {
return `${title.slice(0, 35)}...`; return `${title.slice(0, 35)}...`;
@ -29,7 +27,10 @@ const NewsCard: React.FC<INewsCard> = ({
return title; return title;
}; };
const sliceDate = (date: string) => { const sliceDate = (date: string) => {
return `${date.slice(8, 10)}/${date.slice(5, 7)}/${date.slice(0, 4)}`; return `${date.slice(8, 10)}/${date.slice(5, 7)}/${date.slice(
0,
4
)}`;
}; };
const sliceDescription = (description: string) => { const sliceDescription = (description: string) => {
@ -55,14 +56,8 @@ const NewsCard: React.FC<INewsCard> = ({
<p>{sliceDescription(description)}</p> <p>{sliceDescription(description)}</p>
</div> </div>
<Link <Link href={`/news/${id}`} className="news-card__more-btn">
href={{ Подробнее
pathname: `/news/${id}`,
query: { новость: title },
}}
className="news-card__more-btn"
>
{t("details")}
</Link> </Link>
</div> </div>
); );

View File

@ -0,0 +1,47 @@
.section-header {
margin-bottom: 52px;
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
text-align: center;
h3 {
font-size: 42px;
font-weight: 500;
line-height: 50px;
}
p {
font-size: 24px;
font-weight: 300;
line-height: 29px;
}
}
@media screen and (max-width: 768px) {
.section-header {
margin-bottom: 42px;
h3 {
font-size: 36px;
line-height: 43px;
}
}
}
@media screen and (max-width: 550px) {
.section-header {
margin-bottom: 42px;
h3 {
font-size: 24px;
line-height: 29px;
}
p {
font-size: 18px;
line-height: 22px;
}
}
}

View File

@ -0,0 +1,22 @@
import "./SectionHeader.scss";
interface ISectionHeaderProps {
title: string;
description?: string;
style?: object;
}
const SectionHeader: React.FC<ISectionHeaderProps> = ({
title,
description,
style,
}: ISectionHeaderProps) => {
return (
<div style={style} className="section-header">
<h3>{title}</h3>
{description && <p>{description}</p>}
</div>
);
};
export default SectionHeader;

View File

@ -0,0 +1,2 @@
export const baseAPI =
"https://api.kgroaduat.fishrungames.com/api/v1";

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -5,5 +5,4 @@
url("TildaSans-Black.woff2") format("woff2"), url("TildaSans-Black.woff2") format("woff2"),
url("TildaSans-Black.woff") format("woff"); url("TildaSans-Black.woff") format("woff");
font-weight: 900; font-weight: 900;
font-style: normal;
} }

View File

@ -5,5 +5,4 @@
url("TildaSans-Regular.woff2") format("woff2"), url("TildaSans-Regular.woff2") format("woff2"),
url("TildaSans-Regular.woff") format("woff"); url("TildaSans-Regular.woff") format("woff");
font-weight: 400; font-weight: 400;
font-style: normal;
} }

View File

@ -1,5 +1,5 @@
export interface IFetch { export interface IFetch {
error: string; error: string;
data?: any; data: any;
isLoading: boolean; isLoading: boolean;
} }

View File

@ -0,0 +1,5 @@
export interface IList {
count: number | null;
previous: number | null;
next: number | null;
}

View File

@ -1,5 +1,3 @@
import { IList } from "./list-type";
export interface INews { export interface INews {
id: number; id: number;
image: string; image: string;
@ -10,7 +8,3 @@ export interface INews {
updated_at: string; updated_at: string;
count_reviews: number; count_reviews: number;
} }
export interface INewsList extends IList {
results: INews[];
}

View File

@ -0,0 +1,32 @@
export interface IAuthor {
id: number;
first_name: string;
last_name: string;
govern_status: unknown;
}
export interface ILocation {
id: 4;
latitude: number;
longitude: number;
address: string;
}
export interface IReportImage {
id: number;
image: string;
}
export interface IReport {
results: any;
id: number;
image: IReportImage[];
description: string;
author: IAuthor;
created_at: string;
updated_at: string;
location: ILocation[];
category: number;
total_likes: number;
count_reviews: number;
}

View File

@ -6,5 +6,4 @@ $light-green: rgb(74, 192, 63);
$gray-300: #d0d5dd; $gray-300: #d0d5dd;
$gray-500: #667085; $gray-500: #667085;
$gray-700: #344054; $gray-700: #344054;
$gray-900: rgb(16, 24, 40);
$black: rgb(50, 48, 58); $black: rgb(50, 48, 58);

View File

@ -0,0 +1,7 @@
export const LINKS = [
{ id: 1, pagename: "Главная", pathname: "/" },
{ id: 2, pagename: "О нас", pathname: "/about-us" },
{ id: 3, pagename: "Статистика", pathname: "/statistics" },
{ id: 4, pagename: "Новости", pathname: "/news" },
{ id: 5, pagename: "Волонтеры", pathname: "/volunteers" },
];

View File

@ -0,0 +1,26 @@
export const ROAD_TYPES_STATS: Record<number, string> = {
1: "Разбитых дорог",
2: "Очагов аварийности",
3: "Локальных дефектов",
4: "В планах ремонта",
5: "Отремонтировано",
6: "Локальных дефектов исправлено",
};
export const ROAD_TYPES: Record<number, string> = {
1: "Разбитая дорога",
2: "Очаг аварийности",
3: "Локальный дефект",
4: "В планах ремонта",
5: "Отремонтировано",
6: "Локальный дефект исправлен",
};
export const ROAD_TYPES_COLORS: Record<number, string> = {
1: "rgb(230, 68, 82)",
2: "rgb(194, 136, 226)",
3: "rgb(135, 40, 157)",
4: "rgb(255, 172, 51)",
5: "rgb(254, 211, 99)",
6: "rgb(143, 222, 106)",
};

View File

@ -1,41 +1,16 @@
.footer { .footer {
padding: 48px 80px; padding: 48px 80px;
// display: flex; display: grid;
// grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 30px; gap: 30px;
background-color: rgb(15, 23, 42); background-color: rgb(15, 23, 42);
&__logo {
display: flex;
flex-direction: column;
gap: 24px;
p {
color: white;
font-family: "Inter", sans-serif;
font-size: 16px;
}
}
&__copyright {
display: flex;
flex-direction: column;
margin-top: auto;
}
.top-row {
display: flex;
justify-content: space-between;
// gap: 30px;
}
.bottom-div {
margin-top: 10px;
}
a, a,
li, li,
h4 { h4 {
height: fit-content; height: fit-content;
color: white; color: white;
justify-content: flex-start; justify-content: flex-start;
font-family: "Inter", sans-serif; font-family: "Inter";
font-size: 16px; font-size: 16px;
} }

View File

@ -0,0 +1,60 @@
import "./Footer.scss";
import logo from "../../shared/assets/logo.svg";
import Link from "next/link";
import Image from "next/image";
import { LINKS } from "@/shared/variables/links";
import youtube from "./icons/youtube.svg";
import facebook from "./icons/facebook.svg";
import instagram from "./icons/instagram.svg";
import app_store_btn from "./icons/app-store-btn.svg";
import play_market_btn from "./icons/play-market-btn.svg";
const Footer = () => {
return (
<footer className="footer">
<Link href="/">
<Image src={logo} alt="Logo" />
</Link>
<div className="footer__links">
<h4>Навигация</h4>
<ul>
{LINKS.map((link) => (
<li>
<Link href={link.pathname} key={link.id}>
{link.pagename}
</Link>
</li>
))}
</ul>
</div>
<div className="footer__contacts">
<h4>Контакты</h4>
<ul>
<li>namename@gmail.com</li>
<li>+09646895467</li>
<li>
{[youtube, facebook, instagram].map((net) => (
<Link href="#">
<Image src={net} alt="Net Icon" key={net} />
</Link>
))}
</li>
</ul>
</div>
<div className="footer__apps">
<h4>Скачивай наше приложение</h4>
<div className="footer__apps-btns">
{[app_store_btn, play_market_btn].map((app) => (
<Link href="#">
<Image src={app} alt="App Button" key={app} />
</Link>
))}
</div>
</div>
</footer>
);
};
export default Footer;

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 1007 B

After

Width:  |  Height:  |  Size: 1007 B

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,6 +1,6 @@
.header { .header {
position: relative; position: relative;
height: 500px; height: 386px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@ -13,7 +13,6 @@
} }
&__text { &__text {
width: 100%;
padding: 0 90px; padding: 0 90px;
height: 100%; height: 100%;
position: relative; position: relative;

View File

@ -2,10 +2,8 @@ import "./Header.scss";
import Image from "next/image"; import Image from "next/image";
import background from "./assets/background.svg"; import background from "./assets/background.svg";
import HeaderLink from "./HeaderLink/HeaderLink"; import HeaderLink from "./HeaderLink/HeaderLink";
import { useTranslations } from "next-intl";
const Header = () => { const Header = () => {
const t = useTranslations("home");
return ( return (
<header className="header"> <header className="header">
<Image <Image
@ -14,8 +12,12 @@ const Header = () => {
alt="Background Image" alt="Background Image"
/> />
<div className="header__text"> <div className="header__text">
<h1>{t("title")}</h1> <h1>
<p>{t("subtitle")}</p> Borem ipsum dolor sit amet, consectetur adipiscing elit.
</h1>
<p>
Borem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div> </div>
<HeaderLink /> <HeaderLink />

View File

@ -7,9 +7,6 @@
font-size: 20px; font-size: 20px;
font-weight: 500; font-weight: 500;
line-height: 24px; line-height: 24px;
display: flex;
justify-content: center;
align-items: center;
gap: 30px; gap: 30px;
border-radius: 15px; border-radius: 15px;
background-color: #fff; background-color: #fff;

View File

@ -1,15 +1,12 @@
import "./HeaderLink.scss"; import "./HeaderLink.scss";
import Image from "next/image"; import Image from "next/image";
import arrow_right from "./icons/arrow-right-circle.svg"; import arrow_right from "./icons/arrow-right-circle.svg";
import { Link } from "@/shared/config/navigation"; import Link from "next/link";
import { useTranslations } from "next-intl";
const HeaderLink = () => { const HeaderLink = () => {
const t = useTranslations("home");
return ( return (
<Link href="/create-report" className="header-link"> <Link href="/create-report" className="header-link">
{t("report_broken_road")} Отметить разбитую дорогу
<Image src={arrow_right} alt="Arrow Right Icon" /> <Image src={arrow_right} alt="Arrow Right Icon" />
</Link> </Link>
); );

View File

Before

Width:  |  Height:  |  Size: 934 B

After

Width:  |  Height:  |  Size: 934 B

View File

Before

Width:  |  Height:  |  Size: 332 KiB

After

Width:  |  Height:  |  Size: 332 KiB

View File

@ -1,5 +1,5 @@
.home-map { .home-map {
width: 88%; width: 100%;
height: 580px; height: 580px;
border-radius: 8px; border-radius: 8px;

View File

@ -0,0 +1,88 @@
"use client";
import "./HomeMap.scss";
import "leaflet/dist/leaflet.css";
import {
MapContainer,
Marker,
Popup,
TileLayer,
} from "react-leaflet";
import geo_green_icon from "./icons/geo-green.svg";
import geo_orange_icon from "./icons/geo-orange.svg";
import geo_pink_icon from "./icons/geo-pink.svg";
import geo_purple_icon from "./icons/geo-purple.svg";
import geo_red_icon from "./icons/geo-red.svg";
import geo_yellow_icon from "./icons/geo-yellow.svg";
import { DivIcon, Icon, LatLngTuple } from "leaflet";
import { StaticImageData } from "next/image";
import Link from "next/link";
import { ILocation } from "@/shared/types/report-type";
interface IData {
id: number;
location: ILocation[];
category: number;
}
interface IHomeMapProps {
data: IData[] | undefined;
}
const HomeMap: React.FC<IHomeMapProps> = ({
data,
}: IHomeMapProps) => {
const createCustomIcon = (icon: StaticImageData) => {
const customIcon = new Icon({
iconUrl: icon.src,
iconSize: [32, 32],
});
return customIcon;
};
const icons: Record<string, DivIcon> = {
1: createCustomIcon(geo_red_icon),
2: createCustomIcon(geo_pink_icon),
3: createCustomIcon(geo_purple_icon),
4: createCustomIcon(geo_orange_icon),
5: createCustomIcon(geo_green_icon),
6: createCustomIcon(geo_yellow_icon),
};
const position = [42.8746, 74.606];
return (
<MapContainer
center={position as LatLngTuple}
zoom={14}
scrollWheelZoom={false}
className="home-map"
>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{data?.map((marker) => (
<Marker
key={marker.id}
icon={icons[marker.category]}
position={
[
+marker.location[0].latitude,
+marker.location[0].longitude,
] as LatLngTuple
}
>
<Popup>
<Link href={`/report/${marker.location[0].id}`}>
{marker.location[0].address}
</Link>
</Popup>
</Marker>
))}
</MapContainer>
);
};
export default HomeMap;

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

@ -4,15 +4,6 @@
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
&__header {
margin-bottom: 50px;
text-align: center;
display: flex;
align-items: center;
flex-direction: column;
gap: 24px;
}
&__categories { &__categories {
margin-bottom: 60px; margin-bottom: 60px;
display: flex; display: flex;
@ -37,13 +28,9 @@
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {
.map-section { .map-section {
&__header {
margin-bottom: 40px;
gap: 20px;
}
&__categories { &__categories {
margin-bottom: 40px; margin-bottom: 40px;
gap: 25px; gap: 25px;
} }
} }
@ -51,13 +38,9 @@
@media screen and (max-width: 550px) { @media screen and (max-width: 550px) {
.map-section { .map-section {
&__header {
margin-bottom: 25px;
gap: 16px;
}
&__categories { &__categories {
margin-bottom: 25px; margin-bottom: 25px;
padding: 0 16px; padding: 0 16px;
width: 100%; width: 100%;
align-items: flex-start; align-items: flex-start;

View File

@ -0,0 +1,123 @@
"use client";
import "./MapSection.scss";
import SearchForm from "@/features/SearchBar/SearchForm";
import { useEffect, useState } from "react";
import SectionHeader from "@/entities/SectionHeader/SectionHeader";
import {
ROAD_TYPES,
ROAD_TYPES_COLORS,
} from "@/shared/variables/road-types";
import HomeMap from "./HomeMap/HomeMap";
import { useRouter } from "next/navigation";
import { useMapStore } from "./mapSectionStore";
import Switch from "./Switch/Switch";
import { useShallow } from "zustand/react/shallow";
interface IMapSectionProps {
[key: string]: string;
}
const MapSection: React.FC<IMapSectionProps> = ({
categories = "1,2,3,4,5,6",
queryMap,
queryRating,
}: IMapSectionProps) => {
const [mapSearch, setMapSearch] = useState<string>(queryMap || "");
const data = useMapStore(useShallow((state) => state.data));
const getReports = useMapStore(
useShallow((state) => state.getReports)
);
const router = useRouter();
useEffect(() => {
getReports(categories);
}, [categories]);
const handleSubmit: React.FormEventHandler<
HTMLFormElement
> = async (e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
setMapSearch(formData.get("map-search") as string);
router.push(
`/?тип-дороги=${categories}${
mapSearch ? `&поиск-на-карте=${mapSearch}` : ""
}${queryRating ? `&поиск-рейтинг=${queryRating}` : ""}`,
{
scroll: false,
}
);
};
const setSearchParams = (category: string) => {
const availableCategories = ["1", "2", "3", "4", "5", "6"];
if (!categories || !availableCategories.includes(category))
return categories;
if (categories?.includes(category)) {
const updatedCategories = categories
?.replace(category + ",", "")
.replace("," + category, "")
.replace(category, "");
return updatedCategories;
} else {
const newValue = category + ",";
const updatedCategories = newValue + categories;
return updatedCategories;
}
};
return (
<section className="map-section">
<SectionHeader
title="Карта дорог"
description="Будьте в курсе последних новостей о дорожном движении, строительствах и мероприятиях!"
/>
<SearchForm
onChange={(e) => setMapSearch(e.target.value)}
name="map-search"
value={mapSearch}
placeholder="Введите город, село или регион"
handleSubmit={handleSubmit}
/>
<div className="map-section__categories">
<ul className="map-section__categories_left">
{[1, 2, 3].map((sw) => (
<li key={sw}>
<Switch
href={`/?тип-дороги=${setSearchParams(
sw.toString()
)}`}
color={ROAD_TYPES_COLORS[sw]}
defaultState={categories.includes(sw.toString())}
/>
<label>{ROAD_TYPES[sw]}</label>
</li>
))}
</ul>
<ul className="map-section__categories_right">
{[4, 5, 6].map((sw) => (
<li key={sw}>
<Switch
href={`/?тип-дороги=${setSearchParams(
sw.toString()
)}`}
color={ROAD_TYPES_COLORS[sw]}
defaultState={categories.includes(sw.toString())}
/>
<label>{ROAD_TYPES[sw]}</label>
</li>
))}
</ul>
</div>
<HomeMap data={data?.results} />
</section>
);
};
export default MapSection;

View File

@ -5,7 +5,7 @@ import "./Switch.scss";
import Link from "next/link"; import Link from "next/link";
interface ISwitchProps { interface ISwitchProps {
defaultState: boolean; defaultState?: boolean;
color?: string; color?: string;
href: string; href: string;
} }
@ -25,7 +25,7 @@ const Switch: React.FC<ISwitchProps> = ({
onClick={() => setToggleSwitch((prev) => !prev)} onClick={() => setToggleSwitch((prev) => !prev)}
style={{ style={{
backgroundColor: !toggleSwitch backgroundColor: !toggleSwitch
? "rgb(71, 85, 105)" ? "rgb(50, 48, 58)"
: color : color
? color ? color
: "rgb(230, 68, 82)", : "rgb(230, 68, 82)",

View File

@ -0,0 +1,41 @@
import { baseAPI } from "@/shared/api/baseAPI";
import { IFetch } from "@/shared/types/fetch-type";
import { IList } from "@/shared/types/list-type";
import { IReport } from "@/shared/types/report-type";
import axios from "axios";
import { create } from "zustand";
interface IFetchReports extends IList {
results: IReport[];
}
interface IMapStore extends IFetch {
data: IFetchReports;
getReports: (categories: string) => Promise<void>;
}
export const useMapStore = create<IMapStore>((set) => ({
data: {
count: 0,
previous: null,
next: null,
results: [],
},
isLoading: false,
error: "",
getReports: async (categories: string = "1,2,3,4,5,6") => {
try {
set({ isLoading: true });
const response = await axios.get<IFetchReports>(
`${baseAPI}/report/?category=${categories}`
);
set({ data: response.data });
} catch (error: any) {
set({ error: error.message });
} finally {
set({ isLoading: false });
}
},
}));

View File

@ -0,0 +1,22 @@
@import "../../../shared/ui/variables.scss";
.nav-auth-profile-lg,
.nav-auth-signin-lg {
width: fit-content;
padding: 8px 16px;
background-color: $light-blue;
border-radius: 5px;
font-weight: 900;
color: white;
}
.nav-auth-profile-sm,
.nav-auth-signin-sm {
width: fit-content;
}
.nav-auth-profile-sm_active,
.nav-auth-signin-sm_active {
width: fit-content;
color: $light-blue;
}

View File

@ -1,41 +1,31 @@
import Link from "next/link";
import "./NavAuth.scss"; import "./NavAuth.scss";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { useSession } from "next-auth/react";
import { Link } from "@/shared/config/navigation";
import { useTranslations } from "next-intl";
interface INavAuthProps { interface INavAuthProps {
responsible?: boolean; responsible?: boolean;
setOpenMenu: (boolean: boolean) => void;
} }
const NavAuth: React.FC<INavAuthProps> = ({ const NavAuth: React.FC<INavAuthProps> = ({
responsible, responsible,
setOpenMenu,
}: INavAuthProps) => { }: INavAuthProps) => {
const t = useTranslations("navigation"); const auth = false;
const session = useSession();
const auth = session.status === "authenticated" ? true : false;
const pathname = usePathname(); const pathname = usePathname();
return ( return (
<> <>
{auth ? ( {auth ? (
<Link <Link
onClick={() => setOpenMenu(false)} href="/profile"
href="/profile/personal"
className={`nav-auth-profile-${ className={`nav-auth-profile-${
responsible responsible
? `sm${pathname === "/profile" ? "_active" : ""}` ? `sm${pathname === "/profile" ? "_active" : ""}`
: "lg" : "lg"
}`} }`}
> >
{t("profile")} Профиль
</Link> </Link>
) : ( ) : (
<Link <Link
onClick={() => setOpenMenu(false)}
href="/sign-in" href="/sign-in"
className={`nav-auth-signin-${ className={`nav-auth-signin-${
responsible responsible
@ -43,7 +33,7 @@ const NavAuth: React.FC<INavAuthProps> = ({
: "lg" : "lg"
}`} }`}
> >
{t("login")} Войти
</Link> </Link>
)} )}
</> </>

View File

@ -10,22 +10,18 @@
min-width: 130px; min-width: 130px;
position: absolute; position: absolute;
top: 120%; top: 120%;
z-index: 9;
} }
&__option, &__option,
&__option_active { &__option_active {
padding: 10px 14px;
width: 100%; width: 100%;
display: flex; padding: 10px 14px;
font-weight: 900; font-weight: 900;
justify-content: flex-start; justify-content: flex-start;
background-color: #fff;
} }
&__option_active { &__option_active {
background-color: rgb(249, 250, 251); background-color: rgb(249, 250, 251);
align-items: center;
justify-content: space-between; justify-content: space-between;
} }

View File

@ -0,0 +1,47 @@
import "./NavLanguage.scss";
import Image from "next/image";
import { useState } from "react";
import globus from "./icons/globus.svg";
import chevron from "./icons/chevron-down.svg";
import check from "./icons/check.svg";
const NavLanguage = () => {
const [language, setLanguage] = useState<string>("ru");
const [openMenu, setOpenMenu] = useState<boolean>(false);
const LANGUAGES = [
{ id: 1, language: "Русский", index: "ru" },
{ id: 2, language: "Кыргызча", index: "kg" },
{ id: 3, language: "English", index: "en" },
];
return (
<div className="nav-language">
<button
onClick={() => setOpenMenu((prev) => !prev)}
className="nav-language__btn"
>
<Image src={globus} alt="globus icon" />
<Image src={chevron} alt="chevron icon" />
</button>
{openMenu && (
<div className="nav-language__select">
{LANGUAGES.map((lang) => (
<button
className={`nav-language__option${
language === lang.index ? "_active" : ""
}`}
onClick={() => setLanguage(lang.index)}
key={lang.id}
>
{lang.language}
{lang.index === language ? (
<Image src={check} alt="check icon" />
) : null}
</button>
))}
</div>
)}
</div>
);
};
export default NavLanguage;

View File

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 406 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,25 @@
@import "@/shared/ui/variables.scss";
.nav-menu {
padding: 48px 30px 30px 30px;
width: 100%;
height: 100vh;
min-height: 500px;
position: fixed;
top: 72px;
left: 0;
display: flex;
flex-direction: column;
gap: 26px;
background-color: white;
a {
justify-content: flex-start;
font-size: 24px;
font-weight: 500;
}
&__link_active {
color: $light-blue;
}
}

View File

@ -0,0 +1,29 @@
import { LINKS } from "@/shared/variables/links";
import "./NavMenu.scss";
import Link from "next/link";
import { usePathname } from "next/navigation";
import NavAuth from "../NavAuth/NavAuth";
const NavMenu = () => {
const auth = false;
const pathname = usePathname();
return (
<nav className="nav-menu">
{LINKS.map((link) => (
<Link
className={`nav-menu__link${
pathname === link.pathname ? "_active" : ""
}`}
href={link.pathname}
key={link.id}
>
{link.pagename}
</Link>
))}
<NavAuth responsible />
</nav>
);
};
export default NavMenu;

View File

@ -1,35 +1,18 @@
@import "../../shared/ui/variables.scss"; @import "../../shared/ui/variables.scss";
.navbar { .navbar {
padding: 15px 90px; padding: 0 90px;
width: 100%; width: 100%;
height: 78px;
position: fixed;
z-index: 10000;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
background-color: #fff; background-color: #fff;
box-shadow: 0 4px 6px #0000001a;
&__logo {
display: flex;
align-items: center;
gap: 10px;
&_last {
// min-width: 78px;
// max-width: 78px;
// height: 100%;
margin-top: 30px;
height: 120px;
width: 120px;
display: inline-block;
margin-right: 10px;
object-fit: cover;
}
}
&__links { &__links {
height: 40%; height: 60%;
display: flex; display: flex;
gap: 60px; gap: 60px;
} }
@ -44,8 +27,8 @@
&__link_active { &__link_active {
opacity: 1; opacity: 1;
font-weight: 800; font-weight: 900;
// border-bottom: 2px solid black; border-bottom: 2px solid black;
} }
&__lang-and-auth { &__lang-and-auth {
@ -63,16 +46,6 @@
} }
} }
@media screen and (max-width: 1220px) {
.navbar {
// padding: 0 60px;
&__links {
gap: 40px;
}
}
}
@media screen and (max-width: 1024px) { @media screen and (max-width: 1024px) {
.navbar { .navbar {
padding: 0 30px; padding: 0 30px;
@ -87,7 +60,7 @@
} }
} }
@media screen and (max-width: 900px) { @media screen and (max-width: 768px) {
.navbar { .navbar {
height: 72px; height: 72px;

Some files were not shown because too many files have changed in this diff Show More