From e3b73d38c05d3711d46630c228d7ce16bcbcc86b Mon Sep 17 00:00:00 2001 From: ariari04 Date: Mon, 23 Sep 2024 19:35:57 +0600 Subject: [PATCH] Add profile form --- src/app/[locale]/profile/personal/page.tsx | 11 +- src/entities/TenderCard.tsx | 2 +- src/widgets/forms/ProfileForm/ProfileForm.tsx | 171 ++++++++++++++++++ src/widgets/forms/ProfileForm/icons/pen.svg | 8 + 4 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 src/widgets/forms/ProfileForm/ProfileForm.tsx create mode 100644 src/widgets/forms/ProfileForm/icons/pen.svg diff --git a/src/app/[locale]/profile/personal/page.tsx b/src/app/[locale]/profile/personal/page.tsx index f92910e..ee85649 100644 --- a/src/app/[locale]/profile/personal/page.tsx +++ b/src/app/[locale]/profile/personal/page.tsx @@ -4,12 +4,14 @@ import ProfileAvatar from "@/features/ProfileAvatar/ProfileAvatar"; import { apiInstance } from "@/shared/config/apiConfig"; import { authConfig } from "@/shared/config/authConfig"; import { IProfile } from "@/shared/types/profile-type"; +import ProfileForm from "@/widgets/forms/ProfileForm/ProfileForm"; import { AxiosError } from "axios"; import { getServerSession } from "next-auth"; import React from "react"; const Personal = async () => { const session = await getServerSession(authConfig); + console.log(session?.access_token); const getProfile = async () => { const Authorization = `Bearer ${session?.access_token}`; const config = { @@ -22,7 +24,6 @@ const Personal = async () => { "/users/profile/", config ); - return response.data; } catch (error: unknown) { if (error instanceof AxiosError) console.log(error.message); @@ -33,7 +34,13 @@ const Personal = async () => { return (
- + {/* */} +
); }; diff --git a/src/entities/TenderCard.tsx b/src/entities/TenderCard.tsx index d5ad394..19c5701 100644 --- a/src/entities/TenderCard.tsx +++ b/src/entities/TenderCard.tsx @@ -57,7 +57,7 @@ const TenderCard: React.FC = ({

Планируемая сумма

diff --git a/src/widgets/forms/ProfileForm/ProfileForm.tsx b/src/widgets/forms/ProfileForm/ProfileForm.tsx new file mode 100644 index 0000000..35c995a --- /dev/null +++ b/src/widgets/forms/ProfileForm/ProfileForm.tsx @@ -0,0 +1,171 @@ +"use client"; + +import Image from "next/image"; +import pen from "./icons/pen.svg"; +import { useState } from "react"; +import { apiInstance } from "@/shared/config/apiConfig"; +import { AxiosError } from "axios"; +import { useSession } from "next-auth/react"; +import { useRouter } from "@/shared/config/navigation"; +import Loader from "@/shared/ui/Loader/Loader"; +import LogoutButton from "@/features/LogoutButton"; + +interface IProfileFormProps { + id: number; + email: string; + first_name: string; + last_name: string; +} + +const ProfileForm: React.FC<IProfileFormProps> = ({ + id, + email, + first_name, + last_name, +}: IProfileFormProps) => { + const session = useSession(); + const router = useRouter(); + const [error, setError] = useState<string>(""); + const [loader, setLoader] = useState<boolean>(false); + + const [editFirstName, setEditFirstName] = useState<boolean>(true); + const [editLastName, setEditLastName] = useState<boolean>(true); + + const [firstName, setFirstName] = useState<string>(first_name); + const [lastName, setLastName] = useState<string>(last_name); + + const [openPopup, setOpenPopup] = useState<boolean>(false); + + const thereAreChanges = () => { + if (firstName !== first_name || lastName !== last_name) return false; + + return true; + }; + + const updateProfile: React.MouseEventHandler<HTMLFormElement> = async (e) => { + e.preventDefault(); + + const data = { + first_name: firstName, + last_name: lastName, + }; + + const Authorization = `Bearer ${session.data?.access_token}`; + const config = { + headers: { + Authorization, + }, + }; + + try { + setLoader(true); + const res = await apiInstance.patch( + "/users/profile/update/", + data, + config + ); + if ([200, 201].includes(res.status)) { + router.refresh(); + } + } catch (error: unknown) { + if (error instanceof AxiosError) { + if (error.response?.status === 400) { + setError("Были введены неккоректные данные"); + } else { + setError("Ошибка на стороне сервера"); + } + } else { + setError("Возникла непредвиденная ошибка"); + } + } finally { + setLoader(false); + } + }; + return ( + <> + <form onSubmit={updateProfile} className="flex flex-col gap-[25px]"> + <div className="flex flex-col gap-[10px]"> + <label className="text-[18px] leading-6 text-gray-500">Имя</label> + <div className="flex items-center gap-4"> + <input + value={firstName} + onChange={(e) => setFirstName(e.target.value)} + disabled={editFirstName} + type="text" + className="w-full max-w-[957px] p-4 border border-white rounded-sm text-[18px] leading-6 text-black" + /> + <button + type="button" + onClick={() => setEditFirstName((prev) => !prev)} + > + <Image className="w-[22px] h-[22px]" src={pen} alt="Pen Icon" /> + </button> + </div> + </div> + + <div className="flex flex-col gap-[10px]"> + <label className="text-[18px] leading-6 text-gray-500">Фамилия</label> + <div className="flex items-center gap-4"> + <input + value={lastName} + onChange={(e) => setLastName(e.target.value)} + disabled={editLastName} + type="text" + className="w-full max-w-[957px] p-4 border border-white rounded-sm text-[18px] leading-6 text-black" + /> + <button + type="button" + onClick={() => setEditLastName((prev) => !prev)} + > + <Image src={pen} alt="Pen Icon" className="w-[22px] h-[22px]" /> + </button> + </div> + </div> + + <div className="flex flex-col gap-[10px]"> + <label className="text-[18px] leading-6 text-gray-500">Email</label> + <div className="flex items-center gap-4"> + <input + value={email} + disabled + type="text" + className="w-full max-w-[957px] p-4 border border-white rounded-sm text-[18px] leading-6 text-black" + /> + </div> + </div> + + <div className="flex flex-col gap-[10px]"> + <label className="text-[18px] leading-6 text-gray-500">Пароль</label> + <div className="flex items-center gap-4"> + <input + value={"*****************************"} + disabled={editLastName} + type="password" + className="w-full max-w-[957px] p-4 border border-white rounded-sm text-[18px] leading-6 text-black" + /> + <button onClick={() => setOpenPopup(true)} type="button"> + <Image src={pen} alt="Pen Icon" className="w-[22px] h-[22px]" /> + </button> + </div> + </div> + + {/* {openPopup && <ChangePassword closeWindow={setOpenPopup} />} */} + + {error ? <p>{error}</p> : null} + + <button + disabled={thereAreChanges()} + type="submit" + className={`mt-[50px] w-fit p-[10px] rounded-sm bg-gray-400 cursor-auto font-bold leading-7 text-gray-200${ + thereAreChanges() ? "" : "bg-light-blue cursor-pointer" + }`} + > + {loader ? <Loader /> : "Сохранить изменения"} + </button> + <LogoutButton className="sm:block " /> + </form> + </> + ); +}; + +export default ProfileForm; diff --git a/src/widgets/forms/ProfileForm/icons/pen.svg b/src/widgets/forms/ProfileForm/icons/pen.svg new file mode 100644 index 0000000..202f2c8 --- /dev/null +++ b/src/widgets/forms/ProfileForm/icons/pen.svg @@ -0,0 +1,8 @@ +<svg width="21.908203" height="22.000000" viewBox="0 0 21.9082 22" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <desc> + Created with Pixso. + </desc> + <defs/> + <path id="Vector (Stroke)" d="M14.7539 1.22754C16.3906 -0.40918 19.041 -0.40918 20.6777 1.22754C22.3145 2.86426 22.3145 5.51562 20.6777 7.15234L8.5918 19.2383C8.45508 19.375 8.28516 19.4707 8.09766 19.5166L4.51562 20.3867C4.47852 20.3984 4.44141 20.4072 4.4043 20.4141L2.23047 20.9424C1.875 21.0293 1.5 20.9238 1.24023 20.665C0.982422 20.4062 0.876953 20.0312 0.962891 19.6758L2.38867 13.8076C2.43555 13.6211 2.53125 13.4502 2.66797 13.3145L14.7539 1.22754ZM4.53711 18.2236L7.31641 17.5479L19.1953 5.66895C20.0117 4.85156 20.0117 3.52832 19.1953 2.71094C18.377 1.89355 17.0547 1.89355 16.2363 2.71094L4.35742 14.5889L3.68359 17.3652L4.53711 18.2236Z" fill="#B2B5BE" fill-opacity="1.000000" fill-rule="evenodd"/> + <path id="Union" d="M14.5332 4.09473C14.9434 3.68652 15.6074 3.6875 16.0176 4.09766L19.123 7.21191C19.5312 7.62207 19.5312 8.28613 19.1211 8.69531C18.7109 9.10449 18.0469 9.10352 17.6367 8.69336L14.5312 5.57812C14.123 5.16797 14.123 4.50391 14.5332 4.09473ZM8.77734 19.9238C8.77734 19.3447 9.24609 18.875 9.82617 18.875L20.8594 18.875C21.4375 18.875 21.9082 19.3447 21.9082 19.9238C21.9082 20.5029 21.4375 20.9727 20.8594 20.9727L9.82617 20.9727C9.24609 20.9727 8.77734 20.5029 8.77734 19.9238Z" fill="#B2B5BE" fill-opacity="1.000000" fill-rule="evenodd"/> +</svg>