From 068be964d5375c50fdd88b7e4a2ce738085247f4 Mon Sep 17 00:00:00 2001 From: nakyong82 Date: Thu, 24 Oct 2024 16:46:07 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=E2=9C=A8feat:=20=EC=84=9C=EB=A5=98=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EB=A9=94=EC=9D=B8=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=ED=98=84=ED=95=98=EA=B8=B0=20#34?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/RightArrowIcon.svg | 5 + .../Application/ApplicationCard.tsx | 89 ++++++++++++++++++ .../Application/ApplicationCardList.tsx | 20 ++++ .../SearchSortDropdown.tsx} | 10 +- .../PostSearch/PostSearchResult.tsx | 4 +- src/constants/application.ts | 25 +++++ src/pages/Application/ApplicationPage.tsx | 91 +++++++++++++++++++ src/router.tsx | 2 + src/types/application/applicationItem.ts | 21 +++++ 9 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 src/assets/icons/RightArrowIcon.svg create mode 100644 src/components/Application/ApplicationCard.tsx create mode 100644 src/components/Application/ApplicationCardList.tsx rename src/components/{PostSearch/PostSearchSortDropdown.tsx => Common/SearchSortDropdown.tsx} (89%) create mode 100644 src/constants/application.ts create mode 100644 src/pages/Application/ApplicationPage.tsx create mode 100644 src/types/application/applicationItem.ts diff --git a/src/assets/icons/RightArrowIcon.svg b/src/assets/icons/RightArrowIcon.svg new file mode 100644 index 00000000..4773e4c9 --- /dev/null +++ b/src/assets/icons/RightArrowIcon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/Application/ApplicationCard.tsx b/src/components/Application/ApplicationCard.tsx new file mode 100644 index 00000000..a5f55f3c --- /dev/null +++ b/src/components/Application/ApplicationCard.tsx @@ -0,0 +1,89 @@ +import RightArrowIcon from '@/assets/icons/RightArrowIcon.svg?react'; +import Tag from '@/components/Common/Tag'; +import { APPLICATION_STEP } from '@/constants/application'; +import { + AppicationItemType, + ApplicationStepType, +} from '@/types/application/applicationItem'; +import { useNavigate } from 'react-router-dom'; + +const statusStyler = (status: ApplicationStepType) => { + switch (status) { + case APPLICATION_STEP.APPLICATION_SUCCESS: + return 'bg-[#C7C6F6]'; + case APPLICATION_STEP.RESUME_REJECTED: + return 'bg-[#FFC6C0]'; + case APPLICATION_STEP.APPLICATION_REJECTED: + return 'bg-[#FFC6C0]'; + case APPLICATION_STEP.PENDING: + return 'bg-[#BDBDBD]'; + default: + return 'bg-[#FEF387]'; + } +}; + +type ApplicationCardType = { + applicationData: AppicationItemType; +}; + +const ApplicationCard = ({ applicationData }: ApplicationCardType) => { + const navigate = useNavigate(); + + return ( +
+
+
+

+ {applicationData.step.replace(/_/g, ' ').toLowerCase()} +

+
+
+ +
+
+
+
+
+

+ {applicationData.title} +

+

+ {applicationData.address_name} +

+
+
+
+ +

+ {applicationData.duration_of_days} Days After +

+
+
+
+ {/* TODO: 각각 공고의 id로 이동하기, 지원 상태 상세로 이동하기 */} + + +
+
+ ); +}; + +export default ApplicationCard; diff --git a/src/components/Application/ApplicationCardList.tsx b/src/components/Application/ApplicationCardList.tsx new file mode 100644 index 00000000..4944e160 --- /dev/null +++ b/src/components/Application/ApplicationCardList.tsx @@ -0,0 +1,20 @@ +import ApplicationCard from '@/components/Application/ApplicationCard'; +import { AppicationItemType } from '@/types/application/applicationItem'; + +type ApplicationCardListType = { + applicationListData: AppicationItemType[]; +}; + +const ApplicationCardList = ({ + applicationListData, +}: ApplicationCardListType) => { + return ( +
+ {applicationListData.map((data) => ( + + ))} +
+ ); +}; + +export default ApplicationCardList; diff --git a/src/components/PostSearch/PostSearchSortDropdown.tsx b/src/components/Common/SearchSortDropdown.tsx similarity index 89% rename from src/components/PostSearch/PostSearchSortDropdown.tsx rename to src/components/Common/SearchSortDropdown.tsx index f0030107..ec7d2dd4 100644 --- a/src/components/PostSearch/PostSearchSortDropdown.tsx +++ b/src/components/Common/SearchSortDropdown.tsx @@ -10,7 +10,7 @@ type DropdownProps = { // DropdownModal 컴포넌트: 드롭다운 옵션을 표시하는 모달 const DropdownModal = ({ options, value, onSelect }: DropdownProps) => { return ( -
+
{options.map((option, index) => (
{ ); }; -const PostSearchSortDropdown = ({ - options, - value, - onSelect, -}: DropdownProps) => { +const SearchSortDropdown = ({ options, value, onSelect }: DropdownProps) => { const [isOpen, setIsOpen] = useState(false); const onSelectOption = (option: string) => { @@ -63,4 +59,4 @@ const PostSearchSortDropdown = ({
); }; -export default PostSearchSortDropdown; +export default SearchSortDropdown; diff --git a/src/components/PostSearch/PostSearchResult.tsx b/src/components/PostSearch/PostSearchResult.tsx index 650e8507..e5eba338 100644 --- a/src/components/PostSearch/PostSearchResult.tsx +++ b/src/components/PostSearch/PostSearchResult.tsx @@ -2,7 +2,7 @@ import NoSearchResultImg from '@/assets/images/NoSearchResultImg.png'; import { JobPostingItemType } from '@/types/common/jobPostingItem'; import JobPostingCard from '@/components/Common/JobPostingCard'; import { useState } from 'react'; -import PostSearchSortDropdown from '@/components/PostSearch/PostSearchSortDropdown'; +import SearchSortDropdown from '@/components/Common/SearchSortDropdown'; // 공고 목록 더미데이터 const JOB_POSTING_LIST: JobPostingItemType[] = [ @@ -59,7 +59,7 @@ const PostSearchResult = () => {

Search Result

- setSelectedSort(sort as SortType)} diff --git a/src/constants/application.ts b/src/constants/application.ts new file mode 100644 index 00000000..05cd1dfa --- /dev/null +++ b/src/constants/application.ts @@ -0,0 +1,25 @@ +export const enum APPLICATION_STEP { + RESUME_UNDER_REVIEW = 'RESUME_UNDER_REVIEW', + WAITING_FOR_INTERVIEW = 'WAITING_FOR_INTERVIEW', + FILLING_OUT_DOCUMENTS = 'FILLING_OUT_DOCUMENTS', + DOCUMENT_UNDER_REVIEW = 'DOCUMENT_UNDER_REVIEW', + APPLICATION_IN_PROGRESS = 'APPLICATION_IN_PROGRESS', + APPLICATION_SUCCESS = 'APPLICATION_SUCCESS', + APPLICATION_REJECTED = 'APPLICATION_REJECTED', + RESUME_REJECTED = 'RESUME_REJECTED', + PENDING = 'PENDING', + REGISTRATION_RESULTS = 'REGISTRATION_RESULTS', +} + +export const APPLICATION_SORT_TYPE = { + ASCENDING: 'Ascending', + DESCENDING: 'Descending', +} as const; + +export const APPLICATION_STATUS_TYPE = { + INPROGRESS: 'Inprogress', + APPLICATION_SUCCESSFUL: 'Applicatioin successful', + APPLICATION_REJECTED: 'Applicatioin rejected', + RESUME_REJECTED: 'resume rejected', + PENDING: 'pending', +} as const; diff --git a/src/pages/Application/ApplicationPage.tsx b/src/pages/Application/ApplicationPage.tsx new file mode 100644 index 00000000..3cb46a94 --- /dev/null +++ b/src/pages/Application/ApplicationPage.tsx @@ -0,0 +1,91 @@ +import ApplicationCardList from '@/components/Application/ApplicationCardList'; +import BaseHeader from '@/components/Common/Header/BaseHeader'; +import SearchSortDropdown from '@/components/Common/SearchSortDropdown'; +import { + APPLICATION_SORT_TYPE, + APPLICATION_STATUS_TYPE, +} from '@/constants/application'; +import { AppicationItemType } from '@/types/application/applicationItem'; +import { useState } from 'react'; + +type SortType = + (typeof APPLICATION_SORT_TYPE)[keyof typeof APPLICATION_SORT_TYPE]; + +type StatusType = + (typeof APPLICATION_STATUS_TYPE)[keyof typeof APPLICATION_STATUS_TYPE]; + +// 더미데이터 +const APPLICATION_LIST_DATA: AppicationItemType[] = [ + { + id: 1, + icon_img_url: 'https://example.com/icon1.png', + title: 'Frontend Developer', + address_name: '123 Tech Avenue, Seoul', + step: 'RESUME_UNDER_REVIEW', + hourly_rate: 25, + duration_of_days: 90, + }, + { + id: 2, + icon_img_url: 'https://example.com/icon2.png', + title: 'Backend Developer', + address_name: '456 Code Street, Busan', + step: 'PENDING', + hourly_rate: 30, + duration_of_days: 120, + }, + { + id: 3, + icon_img_url: 'https://example.com/icon3.png', + title: 'Full Stack Developer', + address_name: '789 Web Road, Incheon', + step: 'APPLICATION_REJECTED', + hourly_rate: 28, + duration_of_days: 60, + }, + { + id: 4, + icon_img_url: 'https://example.com/icon3.png', + title: 'Full Stack Developer', + address_name: '789 Web Road, Incheon', + step: 'APPLICATION_SUCCESS', + hourly_rate: 28, + duration_of_days: 60, + }, +]; + +const ApplicationPage = () => { + const [selectedSort, setSelectedSort] = useState( + APPLICATION_SORT_TYPE.ASCENDING, + ); + const [selectedStatus, setSelectedStatus] = useState( + APPLICATION_STATUS_TYPE.INPROGRESS, + ); + + return ( + <> + +
+
+ setSelectedSort(sort as SortType)} + /> + setSelectedStatus(sort as StatusType)} + /> +
+ +
+ + ); +}; + +export default ApplicationPage; diff --git a/src/router.tsx b/src/router.tsx index b926b951..1985270f 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -6,6 +6,7 @@ import InformationPage from '@/pages/Information/InformationPage'; import ApplicationDocumentsPage from '@/pages/ApplicationDocuments/ApplicationDocumentsPage'; import PostSearchPage from '@/pages/PostSearch/PostSearchPage'; import PostSearchFilterPage from '@/pages/PostSearchFilter/PostSearchFilterPage'; +import ApplicationPage from '@/pages/Application/ApplicationPage'; const Router = () => { return ( @@ -21,6 +22,7 @@ const Router = () => { /> } /> } /> + } /> ); diff --git a/src/types/application/applicationItem.ts b/src/types/application/applicationItem.ts new file mode 100644 index 00000000..c019f4b4 --- /dev/null +++ b/src/types/application/applicationItem.ts @@ -0,0 +1,21 @@ +export type ApplicationStepType = + | 'RESUME_UNDER_REVIEW' + | 'WAITING_FOR_INTERVIEW' + | 'FILLING_OUT_DOCUMENTS' + | 'DOCUMENT_UNDER_REVIEW' + | 'APPLICATION_IN_PROGRESS' + | 'APPLICATION_SUCCESS' + | 'APPLICATION_REJECTED' + | 'RESUME_REJECTED' + | 'PENDING' + | 'REGISTRATION_RESULTS'; + +export type AppicationItemType = { + id: number; + icon_img_url: string; + title: string; + address_name: string; + step: ApplicationStepType; + hourly_rate: number; + duration_of_days: number; +}; From 84b5dcc378c86ba2e6700f0853b0c3cdfbbdd9c6 Mon Sep 17 00:00:00 2001 From: Hyeona01 Date: Thu, 24 Oct 2024 16:56:11 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=E2=9C=A8=20feat:=20edit=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20get/patch=20=ED=83=80=EC=9E=85=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20#28?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Profile/ProfileCard.tsx | 5 +- src/constants/profile.ts | 21 +++++++- src/pages/Profile/EditProfilePage.tsx | 71 ++++++++++++++++++++------ src/pages/Profile/ProfilePage.tsx | 2 +- src/types/api/profile.ts | 28 ++++++++-- src/utils/editProfileData.ts | 22 ++++++++ 6 files changed, 124 insertions(+), 25 deletions(-) create mode 100644 src/utils/editProfileData.ts diff --git a/src/components/Profile/ProfileCard.tsx b/src/components/Profile/ProfileCard.tsx index f6438d81..f5653247 100644 --- a/src/components/Profile/ProfileCard.tsx +++ b/src/components/Profile/ProfileCard.tsx @@ -25,7 +25,10 @@ const ProfileCard = ({ data }: ProfileCardProps) => { {data.first_name} {data.last_name}
{/* 생년월일 */} -
{data.birth}
+
+ {data.birth.replace(/-/g, '.')} +
+ {/* 교육 정보 */} {data.school_name === '' ? ( diff --git a/src/constants/profile.ts b/src/constants/profile.ts index 14f3c3f1..77607a9f 100644 --- a/src/constants/profile.ts +++ b/src/constants/profile.ts @@ -5,4 +5,23 @@ export const enum IconType { NOTIFICATION = 'NOTIFICATION', LANGUAGE = 'LANGUAGE', LOGOUT = 'LOGOUT', -} \ No newline at end of file +} + +export const enum GenderType { + MALE='MALE', + FEMALE='FEMALE', + NONE='NONE', +} + +export const enum VisaType{ + D_2_1='D_2_1', + D_2_2='D_2_2', + D_2_3='D_2_3', + D_2_4='D_2_4', + D_2_6='D_2_6', + D_2_7='D_2_7', + D_2_8='D_2_8', + D_4_1='D_4_1', + D_4_7='D_4_7', + F_2='F_2' +} \ No newline at end of file diff --git a/src/pages/Profile/EditProfilePage.tsx b/src/pages/Profile/EditProfilePage.tsx index 105302c8..3f1c4bff 100644 --- a/src/pages/Profile/EditProfilePage.tsx +++ b/src/pages/Profile/EditProfilePage.tsx @@ -3,23 +3,25 @@ import BaseHeader from '@/components/Common/Header/BaseHeader'; import Input from '@/components/Common/Input'; import EditProfilePicture from '@/components/Profile/EditProfilePicture'; import { buttonTypeKeys } from '@/constants/components'; -import { UserEditProfileDataType } from '@/types/api/profile'; +import { GenderType, VisaType } from '@/constants/profile'; +import { UserProfileDetailDataType } from '@/types/api/profile'; import { InputType } from '@/types/common/input'; +import { transformToEditProfileData } from '@/utils/editProfileData'; import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; const EditProfilePage = () => { const navigate = useNavigate(); - const [userData, setUserData] = useState( - undefined, - ); + const [userData, setUserData] = useState< + UserProfileDetailDataType | undefined + >(undefined); const [profileImage, setProfileImage] = useState(null); const handleInputChange = - (field: keyof UserEditProfileDataType) => (value: string) => { + (field: keyof UserProfileDetailDataType) => (value: string) => { setUserData((prevData) => { if (!prevData) { - return { [field]: value } as UserEditProfileDataType; + return { [field]: value } as UserProfileDetailDataType; } return { ...prevData, @@ -36,24 +38,59 @@ const EditProfilePage = () => { } }; - const handleSubmit = () => { - // API - 3.5 (유학생) 프로필 수정 + const handleSubmit = async (): Promise => { + // TODO : API - 3.5 (유학생) 프로필 수정 + if (!userData) return; console.log('file 변경 - ' + profileImage); - navigate('/profile'); + + // get -> patch 데이터 변환 + const transformedData = transformToEditProfileData( + userData, + profileImage, + Boolean(profileImage), // 이미지 변경 여부 확인 + ); + try { + const formData = new FormData(); + + // 이미지가 있을 경우 FormData에 추가 + if (transformedData.image) { + formData.append('image', transformedData.image); + } + + // JSON 데이터를 Blob으로 변환 후 FormData에 추가 + formData.append( + 'body', + new Blob([JSON.stringify(transformedData.body)], { + type: 'application/json', + }), + ); + /* + const response = await axios.patch('/api/v1/users', formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + console.log('API 성공:', response.data); + */ + navigate('/profile'); + } catch (error) { + console.error('API 호출 중 에러 발생:', error); + } }; useEffect(() => { + // TODO : API - 3.1 (유학생) 유저 프로필 조회하기 setUserData({ profile_img_url: 'https://images.pexels.com/photos/1458926/pexels-photo-1458926.jpeg?cs=srgb&dl=pexels-poodles2doodles-1458926.jpg&fm=jpg', first_name: 'Hyeona', last_name: 'Seol', - birth: '0000.00.00', - gender: 'Female', + birth: '0000-00-00', + gender: GenderType.FEMALE, nationality: 'Korea', - visa_satus: 'D_2_7', - telephone_number: '010-1111-2222', + visa: VisaType.D_2_1, + phone_number: '010-1111-2222', }); }, []); @@ -110,15 +147,15 @@ const EditProfilePage = () => {
diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index 2c7f25ce..a1524bbd 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -56,7 +56,7 @@ const ProfilePage = () => { 'https://images.pexels.com/photos/1458926/pexels-photo-1458926.jpeg?cs=srgb&dl=pexels-poodles2doodles-1458926.jpg&fm=jpg', first_name: 'Hyeona', last_name: 'Seol', - birth: '0000.00.00', + birth: '0000-00-00', school_name: 'Dongguk University', grade: 3, gpa: 3.5, diff --git a/src/types/api/profile.ts b/src/types/api/profile.ts index 8d00fd6d..4792fedc 100644 --- a/src/types/api/profile.ts +++ b/src/types/api/profile.ts @@ -1,3 +1,5 @@ +import { GenderType, VisaType } from "@/constants/profile"; + export type UserProfileData = { user_information: UserInformationType language_level: LanguageLevelType @@ -38,12 +40,28 @@ export type ApplicationCountType = { } export type UserEditProfileDataType ={ - profile_img_url: string; + image?: File; // multipart-form-data + body: UserEditBodyType; +} + +export type UserEditBodyType = { first_name: string; last_name: string; - birth: string; - gender: string; + birth: string; // yyyy-MM-dd + gender: GenderType; // Enum(MALE, FEMALE, NONE) + nationality: string; + visa: VisaType; // Enum(D_2_1, D_2_2, D_2_3, D_2_4, D_2_6, D_2_7, D_2_8, D_4_1, D_4_7, F_2) + phone_number: string; + is_profile_img_changed: boolean; +} + +export type UserProfileDetailDataType = { + profile_img_url: string, + first_name: string; + last_name: string; + birth: string; // yyyy-MM-dd + gender: GenderType; // Enum(MALE, FEMALE, NONE) nationality: string; - visa_satus: string; - telephone_number: string; + visa: VisaType; // Enum(D_2_1, D_2_2, D_2_3, D_2_4, D_2_6, D_2_7, D_2_8, D_4_1, D_4_7, F_2) + phone_number: string; } \ No newline at end of file diff --git a/src/utils/editProfileData.ts b/src/utils/editProfileData.ts new file mode 100644 index 00000000..9163ab59 --- /dev/null +++ b/src/utils/editProfileData.ts @@ -0,0 +1,22 @@ +import { UserEditProfileDataType, UserProfileDetailDataType } from "@/types/api/profile"; + +// GET 데이터를 PATCH 요청 데이터로 변환 +export const transformToEditProfileData = ( + userData: UserProfileDetailDataType, + profileImage: File | null, + isProfileImgChanged: boolean, +): UserEditProfileDataType => { + return { + image: profileImage || undefined, + body: { + first_name: userData.first_name, + last_name: userData.last_name, + birth: userData.birth, + gender: userData.gender, + nationality: userData.nationality, + visa: userData.visa, + phone_number: userData.phone_number, + is_profile_img_changed: isProfileImgChanged, + }, + }; +}; \ No newline at end of file From 92019848dc2c5ab2d19191247c83aadba5124d5b Mon Sep 17 00:00:00 2001 From: Hyeona01 Date: Thu, 24 Oct 2024 17:44:35 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=E2=9C=A8=20feat:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=88=98=EC=A0=95=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20#28?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Profile/EditProfilePicture.tsx | 2 - src/constants/profile.ts | 2 +- src/pages/Profile/EditProfilePage.tsx | 228 +++++++++++++----- src/utils/editProfileData.ts | 4 +- 4 files changed, 172 insertions(+), 64 deletions(-) diff --git a/src/components/Profile/EditProfilePicture.tsx b/src/components/Profile/EditProfilePicture.tsx index 36044ba7..254f7102 100644 --- a/src/components/Profile/EditProfilePicture.tsx +++ b/src/components/Profile/EditProfilePicture.tsx @@ -68,8 +68,6 @@ const EditProfilePicture = ({ onChange={handlePictureChange} style={{ display: 'none' }} /> - - {imagePreviewUrl &&

Profile picture has been changed.

}
); }; diff --git a/src/constants/profile.ts b/src/constants/profile.ts index 77607a9f..7b39f875 100644 --- a/src/constants/profile.ts +++ b/src/constants/profile.ts @@ -24,4 +24,4 @@ export const enum VisaType{ D_4_1='D_4_1', D_4_7='D_4_7', F_2='F_2' -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/pages/Profile/EditProfilePage.tsx b/src/pages/Profile/EditProfilePage.tsx index 3f1c4bff..2bf55a04 100644 --- a/src/pages/Profile/EditProfilePage.tsx +++ b/src/pages/Profile/EditProfilePage.tsx @@ -1,6 +1,8 @@ import Button from '@/components/Common/Button'; +import Dropdown from '@/components/Common/Dropdown'; import BaseHeader from '@/components/Common/Header/BaseHeader'; import Input from '@/components/Common/Input'; +import RadioButton from '@/components/Information/RadioButton'; import EditProfilePicture from '@/components/Profile/EditProfilePicture'; import { buttonTypeKeys } from '@/constants/components'; import { GenderType, VisaType } from '@/constants/profile'; @@ -9,6 +11,7 @@ import { InputType } from '@/types/common/input'; import { transformToEditProfileData } from '@/utils/editProfileData'; import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; +import { country, phone, visa } from '@/constants/information'; const EditProfilePage = () => { const navigate = useNavigate(); @@ -16,6 +19,11 @@ const EditProfilePage = () => { UserProfileDetailDataType | undefined >(undefined); const [profileImage, setProfileImage] = useState(null); + const [phoneNum, setPhoneNum] = useState({ + start: '', + middle: '', + end: '', + }); const handleInputChange = (field: keyof UserProfileDetailDataType) => (value: string) => { @@ -41,15 +49,17 @@ const EditProfilePage = () => { const handleSubmit = async (): Promise => { // TODO : API - 3.5 (유학생) 프로필 수정 if (!userData) return; - console.log('file 변경 - ' + profileImage); + navigate('/profile'); // get -> patch 데이터 변환 const transformedData = transformToEditProfileData( userData, + phoneNum, profileImage, Boolean(profileImage), // 이미지 변경 여부 확인 ); + // console.log('transformedData: ', transformedData); try { const formData = new FormData(); @@ -79,6 +89,14 @@ const EditProfilePage = () => { } }; + // 전화번호를 3개의 파트로 구분 + useEffect(() => { + if (userData?.phone_number) { + const [start, middle, end] = userData.phone_number.split('-'); + setPhoneNum({ start, middle, end }); + } + }, [userData]); + useEffect(() => { // TODO : API - 3.1 (유학생) 유저 프로필 조회하기 setUserData({ @@ -86,9 +104,9 @@ const EditProfilePage = () => { 'https://images.pexels.com/photos/1458926/pexels-photo-1458926.jpeg?cs=srgb&dl=pexels-poodles2doodles-1458926.jpg&fm=jpg', first_name: 'Hyeona', last_name: 'Seol', - birth: '0000-00-00', + birth: '2001-02-09', gender: GenderType.FEMALE, - nationality: 'Korea', + nationality: 'South Korea', visa: VisaType.D_2_1, phone_number: '010-1111-2222', }); @@ -109,65 +127,155 @@ const EditProfilePage = () => { profileImgUrl={userData.profile_img_url} onImageUpdate={setProfileImage} /> - - - - - - - -
-
+ {/* 성 작성 */} +
+
+ Last Name +
+ +
+
+
+ Gender +
+
+ + setUserData({ + ...userData, + gender: value as GenderType, + }) + } + isOn={userData.gender === GenderType.FEMALE} + /> + + setUserData({ + ...userData, + gender: value as GenderType, + }) + } + isOn={userData.gender === GenderType.MALE} + /> + + setUserData({ + ...userData, + gender: value as GenderType, + }) + } + isOn={userData.gender === GenderType.NONE} + /> +
+
+ {/* 생년월일 선택 */} +
+
+ Date of birth +
+ setUserData({ ...userData, birth: value })} + /> +
+ {/* 국적 선택 */} +
+
+ Nationality +
+ + setUserData({ ...userData, nationality: value }) + } + /> +
+ {/* 비자 선택 */} +
+
+ Visa Status +
+ + setUserData({ ...userData, visa: value as VisaType }) + } + /> +
+ {/* 전화번호 선택, dropdown으로 앞 번호를, 중간 번호와 뒷 번호는 각각 input으로 입력 받음 */} +
+
+ Telephone No. +
+
+
+ + setPhoneNum({ ...phoneNum, start: value }) + } + /> +
+ + setPhoneNum({ ...phoneNum, middle: value }) + } + canDelete={false} + /> + setPhoneNum({ ...phoneNum, end: value })} + canDelete={false} + /> +
+
+
+
+
) : ( diff --git a/src/utils/editProfileData.ts b/src/utils/editProfileData.ts index 9163ab59..42f74b71 100644 --- a/src/utils/editProfileData.ts +++ b/src/utils/editProfileData.ts @@ -3,6 +3,7 @@ import { UserEditProfileDataType, UserProfileDetailDataType } from "@/types/api/ // GET 데이터를 PATCH 요청 데이터로 변환 export const transformToEditProfileData = ( userData: UserProfileDetailDataType, + phoneNum: { start: string; middle: string; end: string }, profileImage: File | null, isProfileImgChanged: boolean, ): UserEditProfileDataType => { @@ -15,7 +16,8 @@ export const transformToEditProfileData = ( gender: userData.gender, nationality: userData.nationality, visa: userData.visa, - phone_number: userData.phone_number, + // phone_number 통합 + phone_number: `${phoneNum.start}-${phoneNum.middle}-${phoneNum.end}`, is_profile_img_changed: isProfileImgChanged, }, }; From 9c93a4b56c18bab0c5f8c51cf2ff3f871e823516 Mon Sep 17 00:00:00 2001 From: Hyeona01 Date: Thu, 24 Oct 2024 17:46:34 +0900 Subject: [PATCH 4/7] =?UTF-8?q?=F0=9F=94=A7chore:=20merge=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From cb8ae5023e622fc1216737aa6ac5d7718911f58b Mon Sep 17 00:00:00 2001 From: nakyong82 Date: Thu, 24 Oct 2024 18:54:31 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=90=9B=20fix:=206.1=20api=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=EC=84=9C=20=EB=B3=80=EA=B2=BD=EB=90=9C=20=EA=B2=83?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EC=B6=94=EC=96=B4=20type=20=EC=9E=AC?= =?UTF-8?q?=EC=A0=95=EC=9D=98=ED=95=98=EA=B8=B0=20#34?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Application/ApplicationCard.tsx | 2 +- src/components/Application/ApplicationCardList.tsx | 5 ++++- src/pages/Application/ApplicationPage.tsx | 12 ++++++++---- src/types/application/applicationItem.ts | 3 ++- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/components/Application/ApplicationCard.tsx b/src/components/Application/ApplicationCard.tsx index a5f55f3c..39d68c7e 100644 --- a/src/components/Application/ApplicationCard.tsx +++ b/src/components/Application/ApplicationCard.tsx @@ -74,7 +74,7 @@ const ApplicationCard = ({ applicationData }: ApplicationCardType) => { {/* TODO: 각각 공고의 id로 이동하기, 지원 상태 상세로 이동하기 */} diff --git a/src/components/Application/ApplicationCardList.tsx b/src/components/Application/ApplicationCardList.tsx index 4944e160..c1ed8a59 100644 --- a/src/components/Application/ApplicationCardList.tsx +++ b/src/components/Application/ApplicationCardList.tsx @@ -11,7 +11,10 @@ const ApplicationCardList = ({ return (
{applicationListData.map((data) => ( - + ))}
); diff --git a/src/pages/Application/ApplicationPage.tsx b/src/pages/Application/ApplicationPage.tsx index 3cb46a94..583b6ea2 100644 --- a/src/pages/Application/ApplicationPage.tsx +++ b/src/pages/Application/ApplicationPage.tsx @@ -17,7 +17,8 @@ type StatusType = // 더미데이터 const APPLICATION_LIST_DATA: AppicationItemType[] = [ { - id: 1, + job_posting_id: 1, + user_owner_job_posting_id: 1, icon_img_url: 'https://example.com/icon1.png', title: 'Frontend Developer', address_name: '123 Tech Avenue, Seoul', @@ -26,7 +27,8 @@ const APPLICATION_LIST_DATA: AppicationItemType[] = [ duration_of_days: 90, }, { - id: 2, + job_posting_id: 2, + user_owner_job_posting_id: 2, icon_img_url: 'https://example.com/icon2.png', title: 'Backend Developer', address_name: '456 Code Street, Busan', @@ -35,7 +37,8 @@ const APPLICATION_LIST_DATA: AppicationItemType[] = [ duration_of_days: 120, }, { - id: 3, + job_posting_id: 3, + user_owner_job_posting_id: 3, icon_img_url: 'https://example.com/icon3.png', title: 'Full Stack Developer', address_name: '789 Web Road, Incheon', @@ -44,7 +47,8 @@ const APPLICATION_LIST_DATA: AppicationItemType[] = [ duration_of_days: 60, }, { - id: 4, + job_posting_id: 4, + user_owner_job_posting_id: 4, icon_img_url: 'https://example.com/icon3.png', title: 'Full Stack Developer', address_name: '789 Web Road, Incheon', diff --git a/src/types/application/applicationItem.ts b/src/types/application/applicationItem.ts index c019f4b4..f852e515 100644 --- a/src/types/application/applicationItem.ts +++ b/src/types/application/applicationItem.ts @@ -11,7 +11,8 @@ export type ApplicationStepType = | 'REGISTRATION_RESULTS'; export type AppicationItemType = { - id: number; + job_posting_id: number; + user_owner_job_posting_id: number; icon_img_url: string; title: string; address_name: string; From d11874ff13758fa389c28f605de3fd4e4589e334 Mon Sep 17 00:00:00 2001 From: Hyeona01 Date: Thu, 24 Oct 2024 23:52:38 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=90=9B=20fix:=20patch=20data=20type?= =?UTF-8?q?=20=EC=84=9C=EB=B2=84=EC=99=80=20=ED=9A=8D=EC=9D=BC=ED=99=94=20?= =?UTF-8?q?#28?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/profile.ts | 34 +++++++++++++++++---------- src/pages/Profile/EditProfilePage.tsx | 8 +++---- src/utils/editProfileData.ts | 9 +++---- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/constants/profile.ts b/src/constants/profile.ts index 7b39f875..73349895 100644 --- a/src/constants/profile.ts +++ b/src/constants/profile.ts @@ -8,20 +8,28 @@ export const enum IconType { } export const enum GenderType { - MALE='MALE', - FEMALE='FEMALE', - NONE='NONE', + MALE='Maile', + FEMALE='Femail', + NONE='None', } export const enum VisaType{ - D_2_1='D_2_1', - D_2_2='D_2_2', - D_2_3='D_2_3', - D_2_4='D_2_4', - D_2_6='D_2_6', - D_2_7='D_2_7', - D_2_8='D_2_8', - D_4_1='D_4_1', - D_4_7='D_4_7', - F_2='F_2' + D_2_1='D-2-1', + D_2_2='D-2-2', + D_2_3='D-2-3', + D_2_4='D-2-4', + D_2_6='D-2-6', + D_2_7='D-2-7', + D_2_8='D-2-8', + D_4_1='D-4-1', + D_4_7='D-4-7', + F_2='F-2' +} + +export const enum NationalityType{ + SOUTH_KOREA= 'South Korea', + JAPAN= 'Japan', + CHINA= 'China', + VIETNAME= 'Vietname', + UZBEKISTAN= 'Uzbekistan', } \ No newline at end of file diff --git a/src/pages/Profile/EditProfilePage.tsx b/src/pages/Profile/EditProfilePage.tsx index 2bf55a04..9783ae42 100644 --- a/src/pages/Profile/EditProfilePage.tsx +++ b/src/pages/Profile/EditProfilePage.tsx @@ -5,7 +5,7 @@ import Input from '@/components/Common/Input'; import RadioButton from '@/components/Information/RadioButton'; import EditProfilePicture from '@/components/Profile/EditProfilePicture'; import { buttonTypeKeys } from '@/constants/components'; -import { GenderType, VisaType } from '@/constants/profile'; +import { GenderType, NationalityType, VisaType } from '@/constants/profile'; import { UserProfileDetailDataType } from '@/types/api/profile'; import { InputType } from '@/types/common/input'; import { transformToEditProfileData } from '@/utils/editProfileData'; @@ -106,7 +106,7 @@ const EditProfilePage = () => { last_name: 'Seol', birth: '2001-02-09', gender: GenderType.FEMALE, - nationality: 'South Korea', + nationality: NationalityType.SOUTH_KOREA, visa: VisaType.D_2_1, phone_number: '010-1111-2222', }); @@ -212,7 +212,7 @@ const EditProfilePage = () => { setUserData({ ...userData, nationality: value }) } @@ -224,7 +224,7 @@ const EditProfilePage = () => { Visa Status
diff --git a/src/utils/editProfileData.ts b/src/utils/editProfileData.ts index 42f74b71..f4238945 100644 --- a/src/utils/editProfileData.ts +++ b/src/utils/editProfileData.ts @@ -1,3 +1,4 @@ +import { GenderType, NationalityType, VisaType } from "@/constants/profile"; import { UserEditProfileDataType, UserProfileDetailDataType } from "@/types/api/profile"; // GET 데이터를 PATCH 요청 데이터로 변환 @@ -12,10 +13,10 @@ export const transformToEditProfileData = ( body: { first_name: userData.first_name, last_name: userData.last_name, - birth: userData.birth, - gender: userData.gender, - nationality: userData.nationality, - visa: userData.visa, + birth: userData.birth.replace(/\//g, '-'), + gender: userData.gender.toUpperCase() as GenderType, + nationality: userData.nationality.toUpperCase().replace(/ /g, '_') as NationalityType, + visa: userData.visa.replace(/-/g, '_') as VisaType, // phone_number 통합 phone_number: `${phoneNum.start}-${phoneNum.middle}-${phoneNum.end}`, is_profile_img_changed: isProfileImgChanged, From 90d77fdffe0eb96befc425e37f5cff5fa7c52c00 Mon Sep 17 00:00:00 2001 From: Hyeona01 Date: Thu, 24 Oct 2024 23:55:13 +0900 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=94=A7=20chore:=20complete=20merge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit