diff --git a/src/app/about-us/member/page.tsx b/src/app/about-us/member/page.tsx index d11bd4b..1ac9afa 100644 --- a/src/app/about-us/member/page.tsx +++ b/src/app/about-us/member/page.tsx @@ -38,16 +38,16 @@ const AboutUsMemberPage = () => { const [members, setMembers] = useState([]); useEffect(() => { - const fetchMembers = async () => { - const { members } = await WinkApi.Member.getMembers(); - setMembers(members); - }; - (async () => { await fetchMembers(); })(); }, []); + async function fetchMembers() { + const { members } = await WinkApi.Member.getMembers(); + setMembers(members); + } + return (
@@ -76,6 +76,7 @@ const AboutUsMemberPage = () => { .map(({ _id, name, avatar, description, link, role }) => ( { instagram={link.instagram} blog={link.blog} role={RoleKoreanMap[role]} + onUpdate={fetchMembers} /> ))}
@@ -91,7 +93,7 @@ const AboutUsMemberPage = () => {
{MEMBERS.map(({ title, description, filter, sort }) => ( -
+

<{title}>

{description}

@@ -102,6 +104,7 @@ const AboutUsMemberPage = () => { .map(({ _id, name, avatar, description, link, role }) => ( { instagram={link.instagram} blog={link.blog} role={role.endsWith('HEAD') ? '부장' : '차장'} + onUpdate={fetchMembers} /> ))}
@@ -124,6 +128,7 @@ const AboutUsMemberPage = () => { .map(({ _id, name, avatar, description, link }) => ( { instagram={link.instagram} blog={link.blog} role={null} + onUpdate={fetchMembers} /> ))}
diff --git a/src/component/activity/ProfileCard.tsx b/src/component/activity/ProfileCard.tsx index 760a0b3..4bf2c55 100644 --- a/src/component/activity/ProfileCard.tsx +++ b/src/component/activity/ProfileCard.tsx @@ -1,11 +1,23 @@ -import React from 'react'; +import React, { useEffect } from 'react'; +import { FaEdit } from 'react-icons/fa'; import Image from 'next/image'; import Link from 'next/link'; +import { Fields, FormContainer, Modal, TextField } from '@/component'; + +import { useMemberStore } from '@/store'; + +import { useForm } from '@/hook'; + +import { WinkApi } from '@/api'; + import avatarImage from '@/public/profile.svg'; +import * as yup from 'yup'; + interface ProfileCardProps { + id: string; name: string; description: string | null; avatar: string | null; @@ -13,9 +25,13 @@ interface ProfileCardProps { instagram: string | null; blog: string | null; role: string | null; + onUpdate?: () => void; } +type Inputs = 'description' | 'github' | 'instagram' | 'blog'; + export const ProfileCard: React.FC = ({ + id, role, name, description, @@ -23,6 +39,7 @@ export const ProfileCard: React.FC = ({ github, instagram, blog, + onUpdate, }) => { const URL = [ { @@ -39,8 +56,69 @@ export const ProfileCard: React.FC = ({ }, ]; + const fields: Fields[] = [ + { id: 'description', type: 'text', placeholder: '한 줄 소개' }, + { id: 'github', type: 'url', placeholder: 'Github URL' }, + { id: 'instagram', type: 'url', placeholder: 'Instagram URL' }, + { id: 'blog', type: 'url', placeholder: 'Blog URL' }, + ]; + + const { member, setMember } = useMemberStore(); + + const [modalOpen, setModalOpen] = React.useState(false); + + const { values, setValues, errors, onChange, validate } = useForm( + yup.object({ + description: yup.string().optional().max(20, '20자 이내로 입력해주세요.'), + github: yup.string().optional().url('유효한 URL을 입력해주세요.'), + instagram: yup.string().optional().url('유효한 URL을 입력해주세요.'), + blog: yup.string().optional().url('유효한 URL을 입력해주세요.'), + }), + ); + + useEffect(() => { + setValues({ + description: member?.description || '', + github: member?.link.github || '', + instagram: member?.link.instagram || '', + blog: member?.link.blog || '', + }); + }, []); + + const handleImageUpload = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + + if (file) { + await WinkApi.Member.updateMyAvatar(file); + const { member } = await WinkApi.Auth.myInfo(); + + setMember(member); + onUpdate?.(); + } + }; + + const handleSaveInfo = async () => { + if (!(await validate())) { + return; + } + + await WinkApi.Member.updateMyInfo(values); + const { member } = await WinkApi.Auth.myInfo(); + + setMember(member); + onUpdate?.(); + + setModalOpen(false); + }; + return (
+ {member?._id === id && ( +
+ setModalOpen(true)} /> +
+ )} + {role && (
{role} @@ -73,6 +151,58 @@ export const ProfileCard: React.FC = ({ ))}
+ + setModalOpen(false)}> +

내 프로필 수정

+
+ {member?._id === id && ( + handleImageUpload(e)} + className="hidden" + /> + )} + + Profile { + if (member?._id !== id) { + return; + } + + document.getElementById('fileInput')?.click(); + }} + /> + + + {fields.map(({ id, ...rest }) => ( +
+ + +
+ ))} +
+ + +
+
); };