Skip to content

Commit

Permalink
Merge pull request #172 from FinalDoubleTen/FE-13--feat/NewUser
Browse files Browse the repository at this point in the history
Feat: 프로필, 성별, 연령대 기능 임시 구현
  • Loading branch information
jseo9732 authored Jan 16, 2024
2 parents dda21af + a265e2e commit 531ac64
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 151 deletions.
9 changes: 8 additions & 1 deletion src/@types/auth.types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {
import type {
FieldErrors,
UseFormGetValues,
UseFormRegister,
UseFormResetField,
UseFormSetError,
UseFormSetValue,
} from 'react-hook-form';

export interface AuthRequest {
Expand Down Expand Up @@ -50,3 +51,9 @@ export interface AuthNicknameInputBoxProps extends AuthInputBoxProps {
getValues: UseFormGetValues<any>;
setError: UseFormSetError<any>;
}

export interface AuthImgProps {
register: UseFormRegister<any>;
inputValue: string;
setValue: UseFormSetValue<any>;
}
10 changes: 6 additions & 4 deletions src/api/member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ export const putMemberPassword = async (pwDataa: EditPasswordProps) => {
};

// 프로필 이미지 업로드
export const postMember = async (imgData: any) => {
authClient.defaults.headers.post['Content-Type'] = 'multipart/form-data';
const res = await authClient.post(`member`, imgData);
authClient.defaults.headers.post['Content-Type'] = 'application/json';
export const postMember = async (formData: FormData) => {
const res = await authClient.post(`member`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});

return res;
};
Expand Down
7 changes: 0 additions & 7 deletions src/assets/images/defaultProfileImg.svg

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { getCheckNickname } from '@api/auth';
import { AuthInputWrapper, AuthInput, ErrorMessage } from './AuthInputItem';
import type { AuthNicknameInputBoxProps } from '@/@types/auth.types';
import { useRecoilValue } from 'recoil';
import { UserInfoState } from '@recoil/Auth.atom';

const AuthNicknameInputBox = ({
register,
Expand All @@ -15,8 +17,13 @@ const AuthNicknameInputBox = ({
const nicknameError = errors.nickname;
const nicknameErrorMessage = nicknameError?.message;

const userInfo = useRecoilValue(UserInfoState);

const onNicknameBlur = async () => {
if (nicknamePatternValue.test(getValues('nickname'))) {
if (
nicknamePatternValue.test(getValues('nickname')) &&
userInfo?.nickname !== inputValue
) {
try {
const res = await getCheckNickname(getValues('nickname'));
if (res.status === 200) {
Expand Down
6 changes: 2 additions & 4 deletions src/components/Auth/Login/KakaoLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ const KakaoLogin = () => {
const [searchParams, _] = useSearchParams();
const nickname = searchParams.get('nickname');
const email = searchParams.get('email');
const gender = searchParams.get('gender');
const age_range = searchParams.get('age_range');
const accessToken = searchParams.get('token');
const profile_image = searchParams.get('profile_image');
const signup = searchParams.get('signup');
Expand All @@ -24,8 +22,8 @@ const KakaoLogin = () => {
nickname: nickname!,
email: email!,
profileImageUrl: profile_image,
ageType: age_range,
genderType: gender,
ageType: null,
genderType: null,
survey: null,
});
if (signup === 'true') {
Expand Down
135 changes: 43 additions & 92 deletions src/components/Auth/SignupInfo/AuthDropDown/AuthDropDown.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import { useState } from 'react';
import AuthDropDownOption from './AuthDropDownOption';
import * as Select from '@radix-ui/react-select';
import { DownIcon } from '@components/common/icons/Icons';
import { UseFormRegister, UseFormSetValue } from 'react-hook-form';

interface Props {
label: string;
text: string;
options: SelectOption[];
name: string;
register: UseFormRegister<any>;
setValue: UseFormSetValue<any>;

// initialState: string | null;
// setState: React.Dispatch<React.SetStateAction<string | null>>;
}

const AuthDropDown = ({ label, text, options }: Props) => {
// const [isShow, setIsShow] = useState<boolean>(false);
const [_, setIsSelected] = useState<string>(text);
const AuthDropDown = ({
label,
text,
options,
name,
register,
setValue,
}: Props) => {
const onSelectClick = (e: any) => {
setValue(name, e);
};

return (
// <div className="z-10 flex flex-col">
Expand Down Expand Up @@ -45,95 +59,32 @@ const AuthDropDown = ({ label, text, options }: Props) => {
// )}
// </div>
// </div>

<Select.Root onValueChange={() => setIsSelected('dd')}>
<h2 className="body2 mb-2 text-main1">{label}</h2>
<Select.Trigger className="data-[placeholder]:body5 relative flex h-12 items-center justify-center rounded-lg border border-solid border-gray3 bg-white hover:bg-gray1 data-[state=open]:rounded-b-none data-[placeholder]:text-gray4">
<Select.Value className="body5 text-gray6" placeholder={text} />
<Select.Icon className="absolute right-[10px] top-4">
<DownIcon size={20} color="#888888" />
</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Content
position={'popper'}
collisionPadding={0}
// avoidCollisions={isSelected ? false : true}
className="h-36 overflow-hidden rounded-b-lg border-x border-b border-solid border-gray3 bg-white">
<Select.Viewport>
{options.map((option) => (
<AuthDropDownOption value={option.value}>
{option.value}
</AuthDropDownOption>
))}
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
<div className="w-full">
<Select.Root onValueChange={onSelectClick} {...register(name)}>
<h2 className="body2 mb-2 text-main1">{label}</h2>
<Select.Trigger className="data-[placeholder]:body5 relative flex h-12 w-full items-center justify-center rounded-lg border border-solid border-gray3 bg-white hover:bg-gray1 data-[state=open]:rounded-b-none data-[placeholder]:text-gray4">
<Select.Value className="body5 text-gray6" placeholder={text} />
<Select.Icon className="absolute right-[10px] top-4">
<DownIcon size={20} color="#888888" />
</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Content
position={'popper'}
collisionPadding={0}
className="h-36 overflow-hidden rounded-b-lg border-x border-b border-solid border-gray3 bg-white">
<Select.Viewport>
{options.map((option) => (
<AuthDropDownOption key={option.id} value={option.id}>
{option.value}
</AuthDropDownOption>
))}
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
</div>
);
};

export default AuthDropDown;

{
/* <Select.Root>
<Select.Trigger
className="inline-flex items-center justify-center rounded px-[15px] text-[13px] leading-none h-[35px] gap-[5px] bg-white text-violet11 shadow-[0_2px_10px] shadow-black/10 hover:bg-mauve3 focus:shadow-[0_0_0_2px] focus:shadow-black data-[placeholder]:text-violet9 outline-none"
aria-label="Food"
>
<Select.Value placeholder="Select a fruit…" />
<Select.Icon className="text-violet11">
<ChevronDownIcon />
</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Content className="overflow-hidden bg-white rounded-md shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)]">
<Select.ScrollUpButton className="flex items-center justify-center h-[25px] bg-white text-violet11 cursor-default">
<ChevronUpIcon />
</Select.ScrollUpButton>
<Select.Viewport className="p-[5px]">
<Select.Group>
<Select.Label className="px-[25px] text-xs leading-[25px] text-mauve11">
Fruits
</Select.Label>
<AuthDropDownOption value="apple">Apple</AuthDropDownOption>
<AuthDropDownOption value="banana">Banana</AuthDropDownOption>
<AuthDropDownOption value="blueberry">Blueberry</AuthDropDownOption>
<AuthDropDownOption value="grapes">Grapes</AuthDropDownOption>
<AuthDropDownOption value="pineapple">Pineapple</AuthDropDownOption>
</Select.Group>
<Select.Separator className="h-[1px] bg-violet6 m-[5px]" />
<Select.Group>
<Select.Label className="px-[25px] text-xs leading-[25px] text-mauve11">
Vegetables
</Select.Label>
<AuthDropDownOption value="aubergine">Aubergine</AuthDropDownOption>
<AuthDropDownOption value="broccoli">Broccoli</AuthDropDownOption>
<AuthDropDownOption value="carrot" disabled>
Carrot
</AuthDropDownOption>
<AuthDropDownOption value="courgette">Courgette</AuthDropDownOption>
<AuthDropDownOption value="leek">Leek</AuthDropDownOption>
</Select.Group>
<Select.Separator className="h-[1px] bg-violet6 m-[5px]" />
<Select.Group>
<Select.Label className="px-[25px] text-xs leading-[25px] text-mauve11">
Meat
</Select.Label>
<AuthDropDownOption value="beef">Beef</AuthDropDownOption>
<AuthDropDownOption value="chicken">Chicken</AuthDropDownOption>
<AuthDropDownOption value="lamb">Lamb</AuthDropDownOption>
<AuthDropDownOption value="pork">Pork</AuthDropDownOption>
</Select.Group>
</Select.Viewport>
<Select.ScrollDownButton className="flex items-center justify-center h-[25px] bg-white text-violet11 cursor-default">
<ChevronDownIcon />
</Select.ScrollDownButton>
</Select.Content>
</Select.Portal>
</Select.Root> */
}
46 changes: 32 additions & 14 deletions src/components/Auth/SignupInfo/SignupInfoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,28 @@ const SignupInfoForm = () => {
mode: 'onChange',
criteriaMode: 'all',
});
// const [genderType, setGenderType] = useState<string | null>(null);
// const [ageType, setAgeType] = useState<string | null>(null);

const navigate = useNavigate();

const userInfo = useRecoilValue(UserInfoState);
useEffect(() => {
setValue('nickname', userInfo?.nickname);
setValue('profileImageUrl', userInfo?.profileImageUrl);
setValue('genderType', userInfo?.genderType);
setValue('ageType', userInfo?.ageType);
}, [userInfo]);

const onInfoSubmit: SubmitHandler<any> = async (data) => {
const { nickname } = data;
const { nickname, profileImageUrl, genderType, ageType } = data;

try {
const res = await putMember({
nickname: nickname,
profileImageUrl: '',
ageType: null,
genderType: null,
profileImageUrl: profileImageUrl,
genderType: genderType,
ageType: ageType,
});
if (res.status === 200) {
navigate('/');
Expand All @@ -49,10 +55,16 @@ const SignupInfoForm = () => {
};

return (
<form onSubmit={handleSubmit(onInfoSubmit)} className="w-full">
<form
onSubmit={handleSubmit(onInfoSubmit)}
className="flex h-[100vh] w-full flex-col justify-between">
<div>
<div className="mb-10">
<UserInfoImg />
<UserInfoImg
register={register}
setValue={setValue}
inputValue={watch('profileImageUrl')}
/>
</div>
<AuthNicknameInputBox
register={register}
Expand All @@ -67,11 +79,17 @@ const SignupInfoForm = () => {
label="성별"
text={'성별을 선택해주세요.'}
options={genderArr}
name={'genderType'}
register={register}
setValue={setValue}
/>
<AuthDropDown
label="연령대"
text={'연령대를 선택해주세요.'}
options={ageArr}
name={'ageType'}
register={register}
setValue={setValue}
/>
</div>
</div>
Expand All @@ -85,15 +103,15 @@ const SignupInfoForm = () => {
export default SignupInfoForm;

const genderArr: SelectOption[] = [
{ id: '1', value: '여' },
{ id: '2', value: '남' },
{ id: '3', value: '기타' },
{ id: 'FEMALE', value: '여' },
{ id: 'MALE', value: '남' },
{ id: 'NON_BINARY', value: '기타' },
];

const ageArr: SelectOption[] = [
{ id: '1', value: '10대' },
{ id: '2', value: '20대' },
{ id: '3', value: '30대' },
{ id: '4', value: '40대' },
{ id: '5', value: '50대 이상' },
{ id: 'TEENAGER', value: '10대' },
{ id: 'TWENTIES', value: '20대' },
{ id: 'THIRTIES', value: '30대' },
{ id: 'FOURTIES', value: '40대' },
{ id: 'ABOVE_FIFTIES', value: '50대 이상' },
];
Loading

0 comments on commit 531ac64

Please sign in to comment.