Add profile page
This commit is contained in:
parent
a106044047
commit
95674a489c
@ -1,8 +1,6 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { INews, INewsData, NewsDataResponse } from "@/shared/types/news-type";
|
||||
import Image from "next/image";
|
||||
import calendar from "./icons/calendar.svg";
|
||||
import { INews, NewsDataResponse } from "@/shared/types/news-type";
|
||||
import { Metadata } from "next";
|
||||
import { Container, Title } from "@/shared/ui";
|
||||
|
||||
|
45
src/app/[locale]/profile/layout.tsx
Normal file
45
src/app/[locale]/profile/layout.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { AxiosError } from "axios";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { authConfig } from "@/shared/config/authConfig";
|
||||
import { Title } from "@/shared/ui";
|
||||
import ProfileNav from "@/widgets/ProfileNav/ProfileNav";
|
||||
|
||||
const Profile = async ({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) => {
|
||||
const session = await getServerSession(authConfig);
|
||||
|
||||
const getProfile = async () => {
|
||||
const Authorization = `Bearer ${session?.access_token}`;
|
||||
const config = {
|
||||
headers: {
|
||||
Authorization,
|
||||
},
|
||||
};
|
||||
try {
|
||||
const response = await apiInstance.get<{
|
||||
report_count: number;
|
||||
}>("/users/profile/", config);
|
||||
|
||||
return response.data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError) console.log(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
const data = await getProfile();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<Title text="Личный кабинет" className="mb-[50px]" />
|
||||
<ProfileNav report_count={data?.report_count as number} />
|
||||
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Profile;
|
13
src/app/[locale]/profile/page.tsx
Normal file
13
src/app/[locale]/profile/page.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
"use client";
|
||||
import { useRouter } from "@/shared/config/navigation";
|
||||
import { useEffect } from "react";
|
||||
|
||||
const Profile = () => {
|
||||
const router = useRouter();
|
||||
useEffect(() => {
|
||||
router.push("/profile/personal");
|
||||
}, []);
|
||||
return <></>;
|
||||
};
|
||||
|
||||
export default Profile;
|
29
src/features/LogoutButton.tsx
Normal file
29
src/features/LogoutButton.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { signOut } from "next-auth/react";
|
||||
|
||||
interface ILogoutButtonProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const LogoutButton: React.FC<ILogoutButtonProps> = ({
|
||||
className,
|
||||
}: ILogoutButtonProps) => {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"p-[10px] border border-red-500 rounded-sm font-semibold leading-5 text-red-500",
|
||||
className
|
||||
)}
|
||||
onClick={() =>
|
||||
signOut({
|
||||
callbackUrl: "/",
|
||||
})
|
||||
}
|
||||
>
|
||||
Выйти из аккаунта
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default LogoutButton;
|
@ -1,6 +1,5 @@
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { Link } from "@/shared/config/navigation";
|
||||
import { Link, usePathname } from "@/shared/config/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface INavAuthProps {
|
||||
@ -8,29 +7,30 @@ interface INavAuthProps {
|
||||
setOpenMenu: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const NavAuth: React.FC<INavAuthProps> = ({
|
||||
responsible,
|
||||
setOpenMenu,
|
||||
}: INavAuthProps) => {
|
||||
const NavAuth: React.FC<INavAuthProps> = ({ responsible, setOpenMenu }) => {
|
||||
const t = useTranslations("navigation");
|
||||
const session = useSession();
|
||||
const auth = session.status === "authenticated" ? true : false;
|
||||
|
||||
const auth = session.status === "authenticated";
|
||||
const pathname = usePathname();
|
||||
const isActiveProfile = pathname === "/profile";
|
||||
const isActiveSignIn = pathname === "/sign-in";
|
||||
|
||||
const linkStyles = (isActive: boolean) =>
|
||||
`w-fit px-5 py-3 border-3 rounded-lg font-semibold transition-colors duration-300 ${
|
||||
responsible
|
||||
? isActive
|
||||
? "bg-[#3695d8] text-white"
|
||||
: "bg-white text-[#3695d8] border-[#3695d8]"
|
||||
: "bg-[#3695d8] text-white border-[#3695d8]"
|
||||
}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
{auth ? (
|
||||
<Link
|
||||
onClick={() => setOpenMenu(false)}
|
||||
href="/profile/personal"
|
||||
className={`${
|
||||
responsible
|
||||
? `w-fit px-5 py-3 border-3 rounded-lg font-semibold transition-colors duration-300 ${"bg-[#3695d8] text-white"}`
|
||||
: "w-fit px-5 py-3 border-3 rounded-lg font-semibold transition-colors duration-300 bg-[#3695d8] text-white border-[#3695d8]"
|
||||
}`}
|
||||
className={linkStyles(isActiveProfile)}
|
||||
>
|
||||
{t("profile")}
|
||||
</Link>
|
||||
@ -38,15 +38,7 @@ const NavAuth: React.FC<INavAuthProps> = ({
|
||||
<Link
|
||||
onClick={() => setOpenMenu(false)}
|
||||
href="/sign-in"
|
||||
className={`${
|
||||
responsible
|
||||
? `w-fit px-5 py-3 border-3 rounded-lg font-semibold transition-colors duration-300 ${
|
||||
isActiveSignIn
|
||||
? "bg-[#3695d8] text-white"
|
||||
: "bg-white text-[#3695d8] border-[#3695d8]"
|
||||
}`
|
||||
: "w-fit px-5 py-3 border-3 rounded-lg font-semibold transition-colors duration-300 bg-[#3695d8] text-white"
|
||||
}`}
|
||||
className={linkStyles(isActiveSignIn)}
|
||||
>
|
||||
{t("login")}
|
||||
</Link>
|
||||
|
@ -48,7 +48,7 @@ const Navbar = () => {
|
||||
{LINKS().map((link) => (
|
||||
<Link
|
||||
className={`text-black opacity-0.5 size-4 font-normal min-w-[150px] flex justify-center${
|
||||
pathname === link.pathname ? " opacity-1 font-extrabold" : ""
|
||||
pathname === link.pathname ? "opacity-1 font-bold" : ""
|
||||
}`}
|
||||
key={link.id}
|
||||
href={link.pathname}
|
||||
|
47
src/widgets/ProfileNav/ProfileNav.tsx
Normal file
47
src/widgets/ProfileNav/ProfileNav.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
"use client";
|
||||
|
||||
import LogoutButton from "@/features/LogoutButton";
|
||||
import { Link, usePathname } from "@/shared/config/navigation";
|
||||
|
||||
interface IProfileNavProps {
|
||||
report_count?: number;
|
||||
}
|
||||
|
||||
const ProfileNav: React.FC<IProfileNavProps> = ({
|
||||
report_count,
|
||||
}: IProfileNavProps) => {
|
||||
const pathname = usePathname();
|
||||
return (
|
||||
<nav className="mb-[55px] flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<Link
|
||||
id={pathname === "/profile/personal" ? "profile-nav__link" : ""}
|
||||
href="/profile/personal"
|
||||
className="mr-[46px] text-[20px] font-semibold leading-6 text-gray-500"
|
||||
>
|
||||
Личные данные
|
||||
</Link>
|
||||
<Link
|
||||
id={pathname === "/profile/my-reports" ? "profile-nav__link" : ""}
|
||||
href="/profile/my-reports"
|
||||
className="text-[20px] font-semibold leading-6 text-gray-500"
|
||||
>
|
||||
Мои обращения
|
||||
</Link>
|
||||
<span className="ml-4 py-[2px] px-[10px] rounded-md bg-white text-[14px] font-semibold leading-6 text-light-blue cursor-auto ">
|
||||
{report_count}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{pathname === "/profile/personal" ? (
|
||||
<LogoutButton />
|
||||
) : (
|
||||
<Link id="profile-nav__create-report" href="/create-report">
|
||||
Написать обращение
|
||||
</Link>
|
||||
)}
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfileNav;
|
Loading…
Reference in New Issue
Block a user