Skip to content

Commit

Permalink
Merge pull request #119 from APPS-sookmyung/feat/#118-card-view-api
Browse files Browse the repository at this point in the history
#118 [FEAT] 명함 보기 페이지에서 명함 조회, 상세 조회, 수정 API 연결
  • Loading branch information
junheekim61 authored Dec 23, 2024
2 parents e53a346 + 32e486f commit 5f9cc8c
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 284 deletions.
7 changes: 7 additions & 0 deletions src/apis/cards.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ export const getCards = async () => {
return response;
};

// 단건 명함 조회
export const getCardDetail = async ({ card_id }) => {
const response = await authAxios.get(`/cards/${card_id}`);
console.log(response.data.result);
return response;
};

// 명함 생성
export const postCards = async ({ data }) => {
const response = await authAxios.post(`/cards`, data);
Expand Down
2 changes: 2 additions & 0 deletions src/apis/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { getGroupList, postGroup, deleteGroup, putGroup } from './group';
export { getCards, getCardDetail, postCards, deleteCards, putCards, searchCards } from './cards';
export { getMyCard, postMyCard, deleteMyCard, putMyCard } from './myCard';
2 changes: 1 addition & 1 deletion src/axios/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const authAxios = axios.create({
baseURL: VITE_SERVER_DOMAIN,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
'Content-Type': 'multipart/form-data',
},
});

Expand Down
12 changes: 7 additions & 5 deletions src/components/CardInfo/CardInfo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import Icon from '../../components/Icon/Icon';
import { Link } from 'react-router-dom';

export default function CardInfo({
id,
name,
role,
company,
position,
department,
imageUrl,
isDeleteMode = false,
isSelected = false,
Expand All @@ -30,7 +31,7 @@ export default function CardInfo({
<S.Info>
<S.Name isSelected={isSelected}>{name}</S.Name>
<S.Role isSelected={isSelected}>
{role} / {company}
{position} / {department}
</S.Role>
</S.Info>
</S.CardWrapper>
Expand All @@ -50,14 +51,15 @@ export default function CardInfo({
return isDeleteMode ? (
cardContent
) : (
<Link to={`/card/${name}`}>{cardContent}</Link>
<Link to={`/card/${id}`}>{cardContent}</Link>
);
}

CardInfo.propTypes = {
name: PropTypes.string.isRequired,
role: PropTypes.string.isRequired,
company: PropTypes.string.isRequired,
position: PropTypes.string.isRequired,
department: PropTypes.string.isRequired,
imageUrl: PropTypes.string,
isDeleteMode: PropTypes.bool,
isSelected: PropTypes.bool,
Expand Down
18 changes: 18 additions & 0 deletions src/hooks/useFormData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useCallback } from 'react';

function useFormData(data) {
return useCallback(() => {
const formData = new FormData();

// 객체의 모든 키-값 쌍을 FormData에 추가
for (let key in data) {
if (data.hasOwnProperty(key) && data[key]) {
formData.append(key, data[key]);
}
}

return formData;
}, [data]);
}

export default useFormData;
77 changes: 46 additions & 31 deletions src/pages/CardDetailPage/CardDetailPage.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { useParams, Link } from 'react-router-dom';
import * as S from './CardDetailPage.style';
import Icon from '../../components/Icon/Icon';
import { DetailBadge } from '../../components';
import ProfileImgDefault from '../../assets/images/profile-img-default.svg';
import CARDS_SAMPLE_DATA from '../../constants/cardsSampleData';
import { getCardDetail } from '../../apis/cards';
import { useQuery } from '@tanstack/react-query';

export default function CardDetailPage() {
const [info, setInfo] = useState({});
console.log(info);
const { id } = useParams();

const { data: inputData } = useQuery({
queryKey: ['cardDetail', id],
queryFn: () => getCardDetail({ card_id: id }),
});

useEffect(() => {
if (inputData) {
setInfo(inputData.data);
}
}, [inputData]);

const badges = [
{ label: '비즈니스', value: '비즈니스' },
{ label: '방송사', value: '방송사' },
Expand All @@ -24,22 +39,22 @@ export default function CardDetailPage() {
? badges.filter((badge) => badge.value === filteredData.category)
: [];

const data = filteredData || {
imageUrl: '',
name: '이름없음',
job: '직책없음',
team: '팀없음',
company: '회사없음',
phone: '전화번호없음',
email: '이메일없음',
tel: '유선전화없음',
address: '주소없음',
memo: '메모없음',
pic1: '사진없음',
pic2: '사진없음',
};
// const data = filteredData || {
// imageUrl: '',
// name: '이름없음',
// job: '직책없음',
// team: '팀없음',
// company: '회사없음',
// phone: '전화번호없음',
// email: '이메일없음',
// tel: '유선전화없음',
// address: '주소없음',
// memo: '메모없음',
// pic1: '사진없음',
// pic2: '사진없음',
// };

const profileImageUrl = data.imageUrl || ProfileImgDefault;
const profileImageUrl = info.profImgUrl || ProfileImgDefault;

const activeBadge = filteredData ? filteredData.category : '';

Expand Down Expand Up @@ -69,16 +84,16 @@ export default function CardDetailPage() {
</S.TopBar>
<S.MidBar>
<S.PicContainer>
<S.ProfilePic src={profileImageUrl} alt={`${data.name} 프로필`} />
<S.ProfilePic src={profileImageUrl} alt={`${info.name} 프로필`} />
</S.PicContainer>
</S.MidBar>
<S.BotBar>
<S.NameBox>
<S.NameFont>{data.name}</S.NameFont>
<S.NameFont>{info.name}</S.NameFont>
<S.JobTeamFont>
{data.job} / {data.team}
{info.position} / {info.department}
</S.JobTeamFont>
<S.ComFont>{data.company}</S.ComFont>
<S.ComFont>{info.company}</S.ComFont>
</S.NameBox>
<S.SubBar />
</S.BotBar>
Expand All @@ -90,7 +105,7 @@ export default function CardDetailPage() {
<S.InfoBox>
<S.UserInfoLabel>휴대폰</S.UserInfoLabel>
<S.ContactWrapper>
<S.UserInfoValue>{data.phone}</S.UserInfoValue>
<S.UserInfoValue>{info.phone}</S.UserInfoValue>
<S.IconBox>
<Icon id='message' width='20' height='14' />
<Icon id='call' width='20' height='14' />
Expand All @@ -100,40 +115,40 @@ export default function CardDetailPage() {
<S.InfoBox>
<S.UserInfoLabel>이메일</S.UserInfoLabel>
<S.ContactWrapper>
<S.UserInfoValue>{data.email}</S.UserInfoValue>
<S.UserInfoValue>{info.email}</S.UserInfoValue>
<Icon id='mail' width='20' height='14' />
</S.ContactWrapper>
</S.InfoBox>
<S.InfoBox>
<S.UserInfoLabel>유선전화</S.UserInfoLabel>
<S.ContactWrapper>
<S.UserInfoValue>{data.tel}</S.UserInfoValue>
<S.UserInfoValue>{info.tel}</S.UserInfoValue>
<Icon id='call' width='20' height='14' />
</S.ContactWrapper>
</S.InfoBox>
<S.InfoBox>
<S.UserInfoLabel>주소</S.UserInfoLabel>
<S.UserInfoValue>{data.address}</S.UserInfoValue>
<S.UserInfoValue>{info.address}</S.UserInfoValue>
</S.InfoBox>
</S.ContactContainer>
<S.ConBar>메모</S.ConBar>
<S.ContactContainer>
<S.InfoBox>
<S.UserInfoValue>{data.memo}</S.UserInfoValue>
<S.UserInfoValue>{info.memo}</S.UserInfoValue>
</S.InfoBox>
</S.ContactContainer>
<S.GroupButtonBar>그룹</S.GroupButtonBar>
<S.GroupButtonBox>
<DetailBadge badges={filteredBadges} activeBadge={activeBadge} />
</S.GroupButtonBox>
{(data.pic1 || data.pic2) && (
{(info.pic1 || info.pic2) && (
<S.CardImageContainer>
<S.CardImageBox onClick={() => handleImageClick(data.pic1)}>
<img src={data.pic1} alt='사진 1' />
<S.CardImageBox onClick={() => handleImageClick(info.pic1)}>
<img src={info.pic1} alt='사진 1' />
</S.CardImageBox>
{data.pic2 ? (
<S.CardImageBox onClick={() => handleImageClick(data.pic2)}>
<img src={data.pic2} alt='사진 2' />
{info.pic2 ? (
<S.CardImageBox onClick={() => handleImageClick(info.pic2)}>
<img src={info.pic2} alt='사진 2' />
</S.CardImageBox>
) : (
<S.CardImageBox />
Expand Down
Loading

0 comments on commit 5f9cc8c

Please sign in to comment.