-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor: #69 UserSettingPage에서 이미지, 링크 관련 코드를 컴포넌트로 분리
- Loading branch information
Showing
4 changed files
with
175 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { ChangeEvent, useState } from 'react'; | ||
import { FaPlus, FaMinus } from 'react-icons/fa6'; | ||
import { UseFormSetValue } from 'react-hook-form'; | ||
import { USER_SETTINGS } from '@/constants/userSettings'; | ||
import useToast from '@/hooks/useToast'; | ||
import { EditUserInfoForm, UserSignUpForm } from '@/types/UserType'; | ||
|
||
type LinkFormProps = { | ||
initialLinks: string[]; | ||
setValue: UseFormSetValue<UserSignUpForm | EditUserInfoForm>; | ||
}; | ||
|
||
export default function LinkForm({ initialLinks, setValue }: LinkFormProps) { | ||
const [link, setLink] = useState<string>(''); | ||
const [linksList, setLinksList] = useState<string[]>(initialLinks); | ||
const [isFocused, setIsFocused] = useState(false); | ||
const { toastWarn } = useToast(); | ||
|
||
const handleFocus = () => { | ||
setIsFocused(true); | ||
}; | ||
|
||
const handleBlur = () => { | ||
setIsFocused(false); | ||
}; | ||
|
||
const handleLinkChange = (e: ChangeEvent<HTMLInputElement>) => { | ||
setLink(e.target.value); | ||
}; | ||
|
||
const handleAddLink = (newLink: string) => { | ||
if (newLink.trim() === '') return; | ||
if (linksList.length === USER_SETTINGS.MAX_LINK_COUNT) | ||
return toastWarn(`링크는 최대 ${USER_SETTINGS.MAX_LINK_COUNT}개까지 등록할 수 있습니다.`); | ||
|
||
const updatedLinks = [...linksList, newLink.trim()]; | ||
setLinksList(updatedLinks); | ||
setValue('links', updatedLinks); | ||
setLink(''); | ||
}; | ||
|
||
const handleRemoveLink = (removeLink: string) => { | ||
const filteredData = linksList.filter((item) => item !== removeLink); | ||
setLinksList(filteredData); | ||
setValue('links', filteredData); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<h1 className="font-bold">링크</h1> | ||
<div className="flex flex-col gap-4"> | ||
{linksList.map((item) => ( | ||
<div key={item} className="flex h-30 items-center rounded-lg border border-input px-6 text-sm"> | ||
<div className="flex h-full w-full flex-row items-center gap-8"> | ||
<div className="flex grow items-center overflow-hidden border-transparent bg-inherit"> | ||
<a href={`http://${item}`} target="_blank" rel="noreferrer"> | ||
{item} | ||
</a> | ||
</div> | ||
<button | ||
type="button" | ||
onClick={() => handleRemoveLink(item)} | ||
className="flex h-20 w-20 items-center justify-center rounded-lg bg-sub px-8 font-bold shadow-md" | ||
aria-label="삭제" | ||
> | ||
<FaMinus /> | ||
</button> | ||
</div> | ||
</div> | ||
))} | ||
<div | ||
className={`flex h-30 items-center rounded-lg border border-input ${isFocused ? 'bg-white' : 'bg-disable'} px-6 text-sm`} | ||
> | ||
<div className="flex h-full w-full flex-row items-center gap-8"> | ||
<input | ||
placeholder="ex) www.github.com" | ||
value={link} | ||
onFocus={handleFocus} | ||
onBlur={handleBlur} | ||
onChange={handleLinkChange} | ||
type="text" | ||
className="flex grow bg-inherit outline-none placeholder:text-emphasis" | ||
/> | ||
<button | ||
type="button" | ||
onClick={() => handleAddLink(link)} | ||
className="flex h-20 w-20 items-center justify-center rounded-lg bg-sub px-8 font-bold shadow-md" | ||
aria-label="추가" | ||
> | ||
<FaPlus /> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { useState } from 'react'; | ||
import { GoPlusCircle } from 'react-icons/go'; | ||
import { FaRegTrashCan } from 'react-icons/fa6'; | ||
import { UseFormSetValue } from 'react-hook-form'; | ||
import { convertBytesToString } from '@/utils/converter'; | ||
import { USER_SETTINGS } from '@/constants/userSettings'; | ||
import useToast from '@/hooks/useToast'; | ||
import { EditUserInfoForm, UserSignUpForm } from '@/types/UserType'; | ||
|
||
type ProfileImgFormProps = { | ||
initialImage: string; | ||
setValue: UseFormSetValue<UserSignUpForm | EditUserInfoForm>; | ||
}; | ||
|
||
export default function ProfileImgForm({ initialImage, setValue }: ProfileImgFormProps) { | ||
const [imageUrl, setImageUrl] = useState(initialImage); | ||
const { toastWarn } = useToast(); | ||
|
||
// 이미지 관련 코드 | ||
const handleChangeImg = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
const file = e.target.files?.[0]; | ||
if (!file) return; | ||
|
||
if (file.size > USER_SETTINGS.MAX_IMAGE_SIZE) { | ||
toastWarn(`최대 ${convertBytesToString(USER_SETTINGS.MAX_IMAGE_SIZE)} 이하의 이미지 파일만 업로드 가능합니다.`); | ||
e.target.value = ''; | ||
return; | ||
} | ||
|
||
const image = URL.createObjectURL(file); | ||
setImageUrl(image); | ||
setValue('profileUrl', image); | ||
}; | ||
|
||
const handleRemoveImg = () => { | ||
setImageUrl(''); | ||
setValue('profileUrl', ''); | ||
}; | ||
|
||
return ( | ||
<div className="flex flex-col items-center gap-8"> | ||
<div className="group relative h-100 w-100 overflow-hidden rounded-[50%] border border-input"> | ||
{imageUrl ? ( | ||
<> | ||
<img src={imageUrl} alt="profileImage" className="h-full w-full object-cover" /> | ||
<div className="absolute inset-0 hidden items-center justify-center bg-black bg-opacity-50 group-hover:flex"> | ||
<p role="presentation" className="cursor-pointer" onClick={handleRemoveImg} onKeyDown={handleRemoveImg}> | ||
<FaRegTrashCan size="1.5rem" color="white" /> | ||
</p> | ||
</div> | ||
</> | ||
) : ( | ||
<label | ||
htmlFor="image" | ||
className="absolute inset-0 flex cursor-pointer flex-col items-center justify-center gap-1 text-center" | ||
> | ||
<input id="image" type="file" className="hidden" onChange={handleChangeImg} /> | ||
<GoPlusCircle size="1.5rem" color="#5E5E5E" /> | ||
</label> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.