Skip to content

Commit 641ade0

Browse files
authored
Merge pull request #358 from devpalsPlus/feat/#355
feat : 실행 환경에 따른 조건부 렌더링 추가( issue #355 )
2 parents 0aa5956 + 5d8cc71 commit 641ade0

File tree

8 files changed

+105
-8
lines changed

8 files changed

+105
-8
lines changed

public/robots.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
User-agent: *
2+
Allow: /
3+
4+
# Sitemap
5+
Sitemap: https://www.devpals.site/sitemap.xml
6+
7+
# Crawl-delay (선택사항)
8+
Crawl-delay: 1

public/sitemap.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3+
<url>
4+
<loc>https://www.devpals.site/</loc>
5+
<lastmod>2024-01-01</lastmod>
6+
<changefreq>daily</changefreq>
7+
<priority>1.0</priority>
8+
</url>
9+
<url>
10+
<loc>https://www.devpals.site/main</loc>
11+
<lastmod>2024-01-01</lastmod>
12+
<changefreq>daily</changefreq>
13+
<priority>0.9</priority>
14+
</url>
15+
<url>
16+
<loc>https://www.devpals.site</loc>
17+
<lastmod>2024-01-01</lastmod>
18+
<changefreq>weekly</changefreq>
19+
<priority>0.7</priority>
20+
</url>
21+
</urlset>

src/components/common/avatar/Avatar.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ import defaultImg from '../../../assets/defaultImg.png';
55
export interface AvatarProps {
66
size: string;
77
image: string | ReactNode;
8+
alt?: string;
89
}
910

10-
function Avatar({ size, image }: AvatarProps) {
11+
function Avatar({ size, image, alt = '사용자 프로필 이미지' }: AvatarProps) {
1112
const releasedImg =
1213
typeof image === 'string' && image.trim() ? image : defaultImg;
1314
return (
1415
<S.AvatarContainer size={size}>
1516
{typeof image === 'string' || !image ? (
16-
<S.AvatarImg src={releasedImg} alt='Avatar' />
17+
<S.AvatarImg src={releasedImg} alt={alt} />
1718
) : (
1819
image
1920
)}

src/hooks/useIsMobile.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useState, useEffect } from 'react';
2+
3+
const useIsMobile = () => {
4+
const [isMobile, setIsMobile] = useState(false);
5+
6+
useEffect(() => {
7+
const checkIsMobile = () => {
8+
setIsMobile(window.innerWidth <= 768);
9+
};
10+
11+
// 초기 체크
12+
checkIsMobile();
13+
14+
// 리사이즈 이벤트 리스너 추가
15+
window.addEventListener('resize', checkIsMobile);
16+
17+
// 클린업 함수
18+
return () => {
19+
window.removeEventListener('resize', checkIsMobile);
20+
};
21+
}, []);
22+
23+
return isMobile;
24+
};
25+
26+
export default useIsMobile;

src/hooks/user/CommentHooks/usePostComment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const usePostComment = (id: number) => {
1010
onSuccess: () => {
1111
queryClient.invalidateQueries({
1212
queryKey: [ProjectCommentList.projectComment, id],
13-
exact: true,
13+
exact: false,
1414
});
1515
},
1616
onError: (error) => {

src/pages/user/apply/Apply.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import LoadingSpinner from '../../../components/common/loadingSpinner/LoadingSpi
1515
import PhoneComponent from '../../../components/user/applyComponents/phoneComponent/PhoneComponent';
1616
import CareersComponent from '../../../components/user/applyComponents/careersComponent/CareersComponent';
1717
import Input from '../../../components/user/projectFormComponents/inputComponent/InputComponent';
18+
import ApplyStep from './ApplyStep';
19+
import useIsMobile from '../../../hooks/useIsMobile';
1820

1921
const Apply = () => {
2022
const { projectId } = useParams();
@@ -23,6 +25,7 @@ const Apply = () => {
2325
const { data: projectData, isLoading, isFetching } = useGetProjectData(id);
2426
const { applyProject } = useApplyProject({ id, handleModalOpen });
2527
const userEmail = useAuthStore((state) => state.userData?.email);
28+
const isMobile = useIsMobile();
2629

2730
const {
2831
handleSubmit: onSubmitHandler,
@@ -65,6 +68,12 @@ const Apply = () => {
6568
if (isLoading) return <LoadingSpinner />;
6669
if (isFetching) return <LoadingSpinner />;
6770

71+
// 모바일 환경이면 ApplyStep 컴포넌트 렌더링
72+
if (isMobile) {
73+
return <ApplyStep />;
74+
}
75+
76+
// 데스크톱 환경이면 기존 Apply 컴포넌트 렌더링
6877
return (
6978
<S.Container>
7079
<S.Title>프로젝트 지원</S.Title>

src/pages/user/projectDetail/ProjectDetail.tsx

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@ const ProjectDetail = () => {
3131
}
3232
}, [data, handleModalOpen, isLoading, isFetching]);
3333

34+
// 간단한 메타 정보 설정
35+
useEffect(() => {
36+
if (data) {
37+
document.title = `${data.title} - 프로젝트 상세`;
38+
39+
// 메타 설명 추가
40+
const metaDescription = document.querySelector(
41+
'meta[name="description"]'
42+
);
43+
if (metaDescription) {
44+
metaDescription.setAttribute(
45+
'content',
46+
`${data.title} 프로젝트에 대한 상세 정보입니다.`
47+
);
48+
} else {
49+
const newMetaDescription = document.createElement('meta');
50+
newMetaDescription.name = 'description';
51+
newMetaDescription.content = `${data.title} 프로젝트에 대한 상세 정보입니다.`;
52+
document.head.appendChild(newMetaDescription);
53+
}
54+
}
55+
}, [data]);
56+
3457
if (isLoading || isFetching) return <LoadingSpinner />;
3558

3659
if (!data) {
@@ -63,27 +86,33 @@ const ProjectDetail = () => {
6386
<S.Title>{data.title}</S.Title>
6487
<S.ProfileContainer>
6588
<S.ProfileImageContainer onClick={handleMovetoUserPage}>
66-
<Avatar size='2.5rem' image={data.user.img} />
89+
<Avatar
90+
size='2.5rem'
91+
image={data.user.img}
92+
alt={`${data.user.nickname}의 프로필 이미지`}
93+
/>
6794
</S.ProfileImageContainer>
6895
<S.UserInfo>
6996
<S.UserName onClick={handleMovetoUserPage}>
7097
{data.user.nickname}
7198
</S.UserName>
7299
<S.PostDate>{formatDate(data.recruitmentEndDate)}</S.PostDate>
73100
<S.ViewCount>
74-
<EyeIcon />
101+
<EyeIcon aria-label='조회수' />
75102
{data.views}
76103
</S.ViewCount>
77104
</S.UserInfo>
78105
</S.ProfileContainer>
79106
</S.Header>
107+
80108
<S.Content>
81109
<ProjectInformation data={data} />
82-
<br></br>
110+
<br />
83111
<S.ProjectDescription>
84112
<MarkdownEditorView description={data.description} />
85113
</S.ProjectDescription>
86114
</S.Content>
115+
87116
<S.ApplyButtonContainer>
88117
{userData &&
89118
userData.id !== data.user.id &&
@@ -99,14 +128,17 @@ const ProjectDetail = () => {
99128
</Button>
100129
) : null}
101130
</S.ApplyButtonContainer>
102-
<hr></hr>
131+
132+
<hr />
133+
103134
<CommentLayout
104135
projectId={data.id}
105136
createrId={data.user.id}
106137
loginUserId={userData?.id}
107138
/>
108139
</S.Wrapper>
109140
</S.Container>
141+
110142
<Modal
111143
isOpen={isOpen}
112144
onClose={handleModalClose}

src/routes/AppRoutes.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const Inquiry = lazy(
2727
);
2828
const MyPage = lazy(() => import('../pages/user/mypage/MyPage'));
2929
const UserPage = lazy(() => import('../pages/user/userpage/UserPage'));
30-
const Apply = lazy(() => import('../pages/user/apply/ApplyStep'));
30+
const Apply = lazy(() => import('../pages/user/apply/Apply'));
3131
const CreateProject = lazy(
3232
() => import('../pages/user/createProject/CreateProject')
3333
);

0 commit comments

Comments
 (0)