forked from Transparency/kgroad-frontend2
		
	Merge branch 'ali' of gitea.fishrungames.com:Transparency/kgroad-frontend2 into ali
This commit is contained in:
		
						commit
						b885c9c9bc
					
				| @ -5,7 +5,7 @@ | ||||
|   "scripts": { | ||||
|     "dev": "next dev", | ||||
|     "build": "next build", | ||||
|     "start": "next start -p 8004", | ||||
|     "start": "next start -p 3000", | ||||
|     "lint": "next lint" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|  | ||||
| @ -11,7 +11,6 @@ import React from "react"; | ||||
| 
 | ||||
| const Personal = async () => { | ||||
|   const session = await getServerSession(authConfig); | ||||
|   console.log(session?.expires_in); | ||||
|   const getProfile = async () => { | ||||
|     const Authorization = `Bearer ${session?.access_token}`; | ||||
|     const config = { | ||||
|  | ||||
| @ -6,7 +6,6 @@ import ReportInformation from "@/widgets/report-details/ReportInformation/Report | ||||
| import ReportImages from "@/widgets/report-details/ReportImages/ReportImages"; | ||||
| import dynamic from "next/dynamic"; | ||||
| import BreadCrumbs from "@/features/BreadCrumbs/BreadCrumbs"; | ||||
| import NotFound from "@/widgets/NotFound/NotFound"; | ||||
| import { apiInstance } from "@/shared/config/apiConfig"; | ||||
| 
 | ||||
| const DynamicMap = dynamic( | ||||
| @ -26,11 +25,11 @@ export async function generateMetadata({ | ||||
|   ); | ||||
| 
 | ||||
|   return { | ||||
|     title: `KG ROAD | ${response.data.location[0].address}`, | ||||
|     description: response.data.description, | ||||
|     title: `KG ROAD | ${response.data.description}`, | ||||
|     description: `${response.data.location[0].address}, ${response.data.description}`, | ||||
|     openGraph: { | ||||
|       title: `KG ROAD | ${response.data.location[0].address}`, | ||||
|       description: response.data.description, | ||||
|       title: `KG ROAD | ${response.data.description}`, | ||||
|       description: `${response.data.location[0].address}, ${response.data.description}`, | ||||
|       images: [response.data.image[0].image], | ||||
|       type: "article", | ||||
|     }, | ||||
|  | ||||
							
								
								
									
										70
									
								
								src/features/ReportMessage/ReportMessage.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/features/ReportMessage/ReportMessage.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | ||||
| .report-message { | ||||
|   padding: 16px; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   position: fixed; | ||||
|   top: 0; | ||||
|   left: 0; | ||||
|   z-index: 30000; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
|   background-color: rgba(0, 0, 0, 0.6); | ||||
| 
 | ||||
|   &__wrapper { | ||||
|     max-width: 400px; | ||||
|     padding: 24px; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     gap: 16px; | ||||
|     background-color: white; | ||||
|     border-radius: 12px; | ||||
|     box-shadow: 0px 8px 8px -4px rgba(16, 24, 40, 0.04), | ||||
|       0px 20px 24px -4px rgba(16, 24, 40, 0.1); | ||||
|   } | ||||
| 
 | ||||
|   &__header { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: space-between; | ||||
|   } | ||||
| 
 | ||||
|   &__text { | ||||
|     margin-bottom: 16px; | ||||
| 
 | ||||
|     h4 { | ||||
|       margin-bottom: 4px; | ||||
|       color: rgb(16, 24, 40); | ||||
|       font-family: Inter; | ||||
|       font-size: 18px; | ||||
|       font-weight: 600; | ||||
|       line-height: 28px; | ||||
|     } | ||||
| 
 | ||||
|     p { | ||||
|       color: rgb(71, 84, 103); | ||||
|       font-family: Inter; | ||||
|       font-size: 14px; | ||||
|       font-weight: 400; | ||||
|       line-height: 20px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   a { | ||||
|     padding: 10px 18px; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     text-align: center; | ||||
|     border: 1px solid rgb(72, 159, 225); | ||||
|     border-radius: 8px; | ||||
|     box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05); | ||||
|     background: rgb(72, 159, 225); | ||||
| 
 | ||||
|     color: rgb(255, 255, 255); | ||||
|     font-family: Inter; | ||||
|     font-size: 16px; | ||||
|     font-weight: 600; | ||||
|     line-height: 24px; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										54
									
								
								src/features/ReportMessage/ReportMessage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/features/ReportMessage/ReportMessage.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| import { Link, useRouter } from "@/shared/config/navigation"; | ||||
| import "./ReportMessage.scss"; | ||||
| import Image from "next/image"; | ||||
| import close from "./icons/close.svg"; | ||||
| import check from "./icons/check.svg"; | ||||
| import { useEffect } from "react"; | ||||
| 
 | ||||
| interface IReportMessageProps { | ||||
|   setShowMessage: (value: boolean) => void; | ||||
|   showMessage: boolean; | ||||
| } | ||||
| 
 | ||||
| const ReportMessage: React.FC<IReportMessageProps> = ({ | ||||
|   setShowMessage, | ||||
|   showMessage, | ||||
| }: IReportMessageProps) => { | ||||
|   const router = useRouter(); | ||||
|   useEffect(() => { | ||||
|     if (showMessage) { | ||||
|       setTimeout(() => { | ||||
|         setShowMessage(false); | ||||
|         router.push("/"); | ||||
|       }, 5000); | ||||
|     } | ||||
|   }, [showMessage]); | ||||
|   return ( | ||||
|     <div | ||||
|       onClick={() => setShowMessage(false)} | ||||
|       className="report-message" | ||||
|     > | ||||
|       <div | ||||
|         onClick={(e) => e.stopPropagation()} | ||||
|         className="report-message__wrapper" | ||||
|       > | ||||
|         <div className="report-message__header"> | ||||
|           <Image src={check} alt="Check Icon" /> | ||||
|           <button onClick={() => setShowMessage(false)} type="button"> | ||||
|             <Image src={close} alt="Close Icon" /> | ||||
|           </button> | ||||
|         </div> | ||||
|         <div className="report-message__text"> | ||||
|           <h4>Ваше обращение отправлено</h4> | ||||
|           <p> | ||||
|             Спасибо за ваше обращение. На данный момент оно в | ||||
|             модерации. | ||||
|           </p> | ||||
|         </div> | ||||
|         <Link href="/profile/my-reports">Смотреть мои обращения</Link> | ||||
|       </div> | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| export default ReportMessage; | ||||
							
								
								
									
										5
									
								
								src/features/ReportMessage/icons/check.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/features/ReportMessage/icons/check.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <rect x="4" y="4" width="48" height="48" rx="24" fill="#D1FADF"/> | ||||
| <rect x="4" y="4" width="48" height="48" rx="24" stroke="#ECFDF3" stroke-width="8"/> | ||||
| <path d="M23.5 28L26.5 31L32.5 25M38 28C38 33.5228 33.5228 38 28 38C22.4772 38 18 33.5228 18 28C18 22.4772 22.4772 18 28 18C33.5228 18 38 22.4772 38 28Z" stroke="#039855" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 491 B | 
							
								
								
									
										3
									
								
								src/features/ReportMessage/icons/close.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/features/ReportMessage/icons/close.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <path d="M13 1L1 13M1 1L13 13" stroke="#667085" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 217 B | 
| @ -6,18 +6,6 @@ import { apiInstance } from "./apiConfig"; | ||||
| import { IRefresh, ITokens } from "../types/token-type"; | ||||
| import GoogleProvider from "next-auth/providers/google"; | ||||
| 
 | ||||
| const verifyToken = async (access_token: string) => { | ||||
|   const res = await apiInstance.post("/token/verify/", { | ||||
|     token: access_token, | ||||
|   }); | ||||
| 
 | ||||
|   if ([200, 201].includes(res.status)) { | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   return false; | ||||
| }; | ||||
| 
 | ||||
| const refreshToken = async (token: JWT): Promise<JWT> => { | ||||
|   const UTC = new Date(); | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import { createSharedPathnamesNavigation } from "next-intl/navigation"; | ||||
| 
 | ||||
| export const locales = ["en", "ru", "kg"] as const; | ||||
| export const localePrefix = "always"; // Default
 | ||||
| export const localePrefix = "always"; | ||||
| 
 | ||||
| export const { Link, redirect, usePathname, useRouter } = | ||||
|   createSharedPathnamesNavigation({ locales, localePrefix }); | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
|   padding: 48px 30px 30px 30px; | ||||
|   width: 100%; | ||||
|   height: 100vh; | ||||
|   min-height: 500px; | ||||
|   min-height: 600px; | ||||
|   position: fixed; | ||||
|   top: 72px; | ||||
|   left: 0; | ||||
| @ -12,8 +12,10 @@ | ||||
|   flex-direction: column; | ||||
|   gap: 26px; | ||||
|   background-color: white; | ||||
|   overflow: scroll; | ||||
| 
 | ||||
|   a { | ||||
|   a, | ||||
|   button { | ||||
|     justify-content: flex-start; | ||||
|     font-size: 24px; | ||||
|     font-weight: 500; | ||||
| @ -22,4 +24,31 @@ | ||||
|   &__link_active { | ||||
|     color: $light-blue; | ||||
|   } | ||||
| 
 | ||||
|   &__language { | ||||
|     button { | ||||
|       margin-bottom: 20px; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       gap: 4px; | ||||
|       color: #66727f; | ||||
|       img { | ||||
|         width: 18px; | ||||
|         height: 18px; | ||||
|       } | ||||
|     } | ||||
|     &-wrapper { | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|       gap: 10px; | ||||
|       a { | ||||
|         color: #66727f; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &_active { | ||||
|       color: black !important; | ||||
|       font-weight: 700 !important; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -2,6 +2,10 @@ import { LINKS } from "@/shared/variables/links"; | ||||
| import "./NavMenu.scss"; | ||||
| import NavAuth from "../NavAuth/NavAuth"; | ||||
| import { Link, usePathname } from "@/shared/config/navigation"; | ||||
| import { useEffect, useState, useTransition } from "react"; | ||||
| import { useParams, useRouter } from "next/navigation"; | ||||
| import chevron_down from "./icons/chevron_down.svg"; | ||||
| import Image from "next/image"; | ||||
| 
 | ||||
| interface INavMenuProps { | ||||
|   setOpenMenu: (boolean: boolean) => void; | ||||
| @ -10,7 +14,37 @@ interface INavMenuProps { | ||||
| const NavMenu: React.FC<INavMenuProps> = ({ | ||||
|   setOpenMenu, | ||||
| }: INavMenuProps) => { | ||||
|   const [openMenuLanguage, setOpenMenuLanguage] = | ||||
|     useState<boolean>(false); | ||||
|   const router = useRouter(); | ||||
|   const pathname = usePathname(); | ||||
|   const { locale } = useParams(); | ||||
| 
 | ||||
|   const [_, startTransition] = useTransition(); | ||||
|   const [currentLanguage, setCurrentLanguage] = useState<string>( | ||||
|     locale as string | ||||
|   ); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     const params = window.location.search || ""; | ||||
|     startTransition(() => { | ||||
|       router.replace(`/${currentLanguage}${pathname}${params}`, { | ||||
|         scroll: false, | ||||
|       }); | ||||
|     }); | ||||
|   }, [currentLanguage]); | ||||
| 
 | ||||
|   const langKeys: Record<string, string> = { | ||||
|     ru: "Русский", | ||||
|     kg: "Кыргызча", | ||||
|     en: "English", | ||||
|   }; | ||||
| 
 | ||||
|   const languages = [ | ||||
|     { id: 1, language: "Русский", pathname: "ru" as const }, | ||||
|     { id: 2, language: "Кыргызча", pathname: "kg" as const }, | ||||
|     { id: 3, language: "English", pathname: "en" as const }, | ||||
|   ]; | ||||
| 
 | ||||
|   return ( | ||||
|     <nav className="nav-menu"> | ||||
| @ -18,7 +52,7 @@ const NavMenu: React.FC<INavMenuProps> = ({ | ||||
|         <Link | ||||
|           onClick={() => setOpenMenu(false)} | ||||
|           className={`nav-menu__link${ | ||||
|             pathname.slice(4) === link.pathname ? "_active" : "" | ||||
|             pathname === link.pathname ? "_active" : "" | ||||
|           }`}
 | ||||
|           href={`${pathname.slice(1, 3)}/${link.pathname}`} | ||||
|           key={link.id} | ||||
| @ -28,6 +62,32 @@ const NavMenu: React.FC<INavMenuProps> = ({ | ||||
|       ))} | ||||
| 
 | ||||
|       <NavAuth setOpenMenu={setOpenMenu} responsible /> | ||||
| 
 | ||||
|       <div className="nav-menu__language"> | ||||
|         <button onClick={() => setOpenMenuLanguage((prev) => !prev)}> | ||||
|           {langKeys[currentLanguage as string]} | ||||
|           <Image src={chevron_down} alt="Chevron Down" /> | ||||
|         </button> | ||||
| 
 | ||||
|         {openMenuLanguage && ( | ||||
|           <div className="nav-menu__language-wrapper"> | ||||
|             {languages.map((lang) => ( | ||||
|               <Link | ||||
|                 onClick={() => setCurrentLanguage(lang.pathname)} | ||||
|                 className={`${ | ||||
|                   currentLanguage === lang.pathname | ||||
|                     ? "nav-menu__language_active" | ||||
|                     : "" | ||||
|                 }`}
 | ||||
|                 href="#" | ||||
|                 locale={lang.pathname} | ||||
|               > | ||||
|                 {lang.language} | ||||
|               </Link> | ||||
|             ))} | ||||
|           </div> | ||||
|         )} | ||||
|       </div> | ||||
|     </nav> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										11
									
								
								src/widgets/Navbar/NavMenu/icons/chevron_down.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/widgets/Navbar/NavMenu/icons/chevron_down.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| <svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <g clip-path="url(#clip0_1252_38469)"> | ||||
| <path d="M0.246139 1.47381C-0.0820464 1.13666 -0.0820464 0.590022 0.246139 0.252867C0.574324 -0.084289 1.10642 -0.084289 1.4346 0.252867L5.59423 4.52619C5.92241 4.86334 5.92241 5.40998 5.59423 5.74713C5.26604 6.08429 4.73395 6.08429 4.40576 5.74713L0.246139 1.47381Z" fill="#66727F"/> | ||||
| <path d="M8.56495 0.252867C8.89313 -0.0842888 9.42523 -0.0842889 9.75341 0.252867C10.0816 0.590023 10.0816 1.13666 9.75341 1.47382L5.59378 5.747C5.26559 6.08416 4.7335 6.08416 4.40531 5.747C4.07713 5.40985 4.07714 4.86334 4.40532 4.52619L8.56495 0.252867Z" fill="#66727F"/> | ||||
| </g> | ||||
| <defs> | ||||
| <clipPath id="clip0_1252_38469"> | ||||
| <rect width="10" height="6" fill="white"/> | ||||
| </clipPath> | ||||
| </defs> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 807 B | 
| @ -22,6 +22,7 @@ import { useSession } from "next-auth/react"; | ||||
| import { IDisplayMap } from "@/shared/types/map-type"; | ||||
| import Loader from "@/shared/ui/components/Loader/Loader"; | ||||
| import { useRouter } from "@/shared/config/navigation"; | ||||
| import ReportMessage from "@/features/ReportMessage/ReportMessage"; | ||||
| 
 | ||||
| interface ILatLng { | ||||
|   lat: number; | ||||
| @ -30,10 +31,10 @@ interface ILatLng { | ||||
| 
 | ||||
| const ReportForm = () => { | ||||
|   const session = useSession(); | ||||
|   const router = useRouter(); | ||||
|   const [latLng, setLatLng] = useState<ILatLng[]>([]); | ||||
|   const [displayLatLng, setDisplayLatLng] = useState<string[]>([]); | ||||
|   const [images, setImages] = useState<File[]>([]); | ||||
|   const [showMessage, setShowMessage] = useState<boolean>(false); | ||||
|   const position = { | ||||
|     lat: 42.8746, | ||||
|     lng: 74.606, | ||||
| @ -110,10 +111,10 @@ const ReportForm = () => { | ||||
|     }); | ||||
|     formData.append("latitude1", latLng[0].lat.toString()); | ||||
|     formData.append("longitude1", latLng[0].lng.toString()); | ||||
|     // if (latLng.length === 2) {
 | ||||
|     if (latLng.length === 2) { | ||||
|       formData.append("latitude2", latLng[1].lat.toString()); | ||||
|       formData.append("longitude2", latLng[1].lng.toString()); | ||||
|     // }
 | ||||
|     } | ||||
| 
 | ||||
|     try { | ||||
|       setLoader(true); | ||||
| @ -124,7 +125,7 @@ const ReportForm = () => { | ||||
|       ); | ||||
| 
 | ||||
|       if ([200, 201].includes(res.status)) { | ||||
|         router.push("/"); | ||||
|         setShowMessage(true); | ||||
|       } | ||||
|     } catch (error: unknown) { | ||||
|       if (error instanceof AxiosError) { | ||||
| @ -294,6 +295,12 @@ const ReportForm = () => { | ||||
|         )} | ||||
|       </button> | ||||
|       {error ? <p className="report-form__error">{error}</p> : null} | ||||
|       {showMessage ? ( | ||||
|         <ReportMessage | ||||
|           setShowMessage={setShowMessage} | ||||
|           showMessage={showMessage} | ||||
|         /> | ||||
|       ) : null} | ||||
|     </form> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -79,7 +79,7 @@ | ||||
|           a { | ||||
|             display: flex; | ||||
|             font-size: 20px; | ||||
|             color: rgb(50, 48, 58); | ||||
|             color: rgb(72, 159, 225); | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user