Skip to content

Commit

Permalink
Feat/#116: 텍스트 내 하이퍼링크 활성화 기능 추가 (#139)
Browse files Browse the repository at this point in the history
* feat: 텍스트 중 링크 텍스트를 하이퍼링크 기능 활성화토록 변경하는 컴포넌트 추가

* refactor: 게시글 상세 페이지 중 내가 작성한 글일 경우 프로필 페이지 라우팅 하지않도록 변경

* refactor: 댓글 작성 부분 line-height px 단위로 변경

* feat: 텍스트 내 하이퍼링크 활성화 기능 추가

* refactor: 글쓰기 수정 후 이전페이지로 라우팅하도록 수정

* refactor: 글쓰기 및 글쓰기 수정 본문 line-height 조정

* fix: 하이퍼링크 같은 줄에 일반 단어를 확인하도록 변경

* refactor: Wrapper로 감싸서 사용처의 Flex CSS 영향을 받지 않도록 변경 및 일부 컴포넌트 네이밍 변경

* refactor: 글 작성 직후 무한스크롤 업데이트 오류 보완

* refactor: 더 보기 페이지 띄어쓰기 오타 수정
  • Loading branch information
semnil5202 authored May 4, 2024
1 parent ce608d0 commit 45c7133
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 19 deletions.
11 changes: 9 additions & 2 deletions src/components/ProfileInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ interface Props {
imageUrl: string;
nickname: string;
mainSkill: string;
owner: boolean;
}

// TODO: 프로필 이미지 사진 오류 시 보여줄 기본 프로필 이미지 사진 URL

const ProfileInfo = ({ memberId, imageUrl, nickname, mainSkill }: Props) => {
const ProfileInfo = ({ memberId, imageUrl, nickname, mainSkill, owner }: Props) => {
const { goProfilePage } = useNavigatePage();

const onClickProfileInfo = () => {
if (owner) return;

goProfilePage(memberId);
};

return (
<Flex alignItems="center" gap={10} onClick={() => goProfilePage(memberId)} cursor="pointer">
<Flex alignItems="center" gap={10} onClick={onClickProfileInfo} cursor={owner ? '' : 'pointer'}>
<Box width={36} height={36} overflow="hidden" borderRadius="0 150px 150px 0">
<ImageView src={imageUrl} alt="프로필" defaultSrc={PNGDefaultProfileInfo36} />
</Box>
Expand Down
8 changes: 6 additions & 2 deletions src/pages/Feed/hooks/useFeedInfiniteFetch.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { useQueryClient } from '@tanstack/react-query';
import { MutableRefObject, useEffect } from 'react';
import { useIntersection } from 'react-use';

export const useFeedInfiniteFetch = (intersectionRef: MutableRefObject<null>, fetchCallback: () => void) => {
const queryClient = useQueryClient();
const intersection = useIntersection(intersectionRef, {
root: null,
rootMargin: `0px`,
threshold: 1,
});

useEffect(() => {
if (intersection?.isIntersecting) {
const feedState = queryClient.getQueryState(['ideas']);

if (intersection?.isIntersecting && feedState?.fetchStatus !== 'fetching') {
fetchCallback();
}
}, [intersection, fetchCallback]);
}, [intersection, queryClient, fetchCallback]);
};
7 changes: 4 additions & 3 deletions src/pages/FeedDetail/FeedDetail.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import SEOMeta from '../../components/SEOMeta/SEOMeta';
import useConfirm from '../../hooks/useConfirm';
import Back from '../../layouts/Back';
import Logo from '../../layouts/Logo';
import HyperLinkText from '../components/HyperLinkText/HyperLinkText';
import { useDeleteIdea } from '../components/NewIdeaCard/hooks/mutations/useDeleteIdea';
import { formatCommentDate } from '../Feed/utils/formatCommentDate';

Expand Down Expand Up @@ -64,7 +65,7 @@ const FeedDetailPage = () => {
</Header>

<Box padding="30px 22px 30px 22px" marginTop={48}>
<ProfileInfo memberId={memberId} imageUrl={imageUrl} nickname={nickname} mainSkill={mainSkill} />
<ProfileInfo memberId={memberId} imageUrl={imageUrl} nickname={nickname} mainSkill={mainSkill} owner={owner} />
<Spacer size={20} />
<Box>
<div>
Expand All @@ -88,9 +89,9 @@ const FeedDetailPage = () => {
</div>
</Box>
<Divider color="l3" top={16} bottom={16} />
<Text font="suit15ra" color="b6" style={{ lineHeight: '24px', whiteSpace: 'pre-wrap' }}>
<HyperLinkText font="suit15ra" color="b6" lineHeight="24px">
{introduce}
</Text>
</HyperLinkText>
</Box>

<Divider color="bg1" height={8} />
Expand Down
5 changes: 3 additions & 2 deletions src/pages/FeedDetail/components/Comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ModifyDropdown from './ModifyDropdown';
import Recomment from './Recomment';
import WriteRecomment from './WriteRecomment';
import useConfirm from '../../../hooks/useConfirm';
import HyperLinkText from '../../components/HyperLinkText/HyperLinkText';
import { get999PlusCount } from '../../utils';
import useDeleteCommentMutation from '../hooks/mutations/useDeleteComment';
import useFocusEditComment from '../hooks/useFocusEditComment';
Expand Down Expand Up @@ -96,9 +97,9 @@ const Comment = ({
{!deleted && <ModifyDropdown owner={owner} isInComment onEdit={onEditComment} onDelete={onDeleteComment} />}
</Flex>
<Spacer size={20} />
<Text font="suit14r" color="t" style={{ lineHeight: '22px', whiteSpace: 'pre-wrap' }}>
<HyperLinkText font="suit14r" color="t" lineHeight="22px">
{deleted ? '삭제된 댓글입니다.' : content}
</Text>
</HyperLinkText>
<Spacer size={10} />
<Flex>
<Flex alignItems="center" cursor="pointer" gap={4} onClick={onOpenRecommentTextarea}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/FeedDetail/components/EditComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const Textarea = styled.textarea`
color: ${theme.color.b4};
font-size: ${theme.font.suit14r.fontSize}px;
font-weight: ${theme.font.suit14r.fontWeight};
line-height: 160%;
line-height: 22px;
::placeholder {
color: ${theme.color.ba};
Expand Down
5 changes: 3 additions & 2 deletions src/pages/FeedDetail/components/Recomment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import CommentProfileInfo from './CommentProfileInfo';
import EditComment from './EditComment';
import ModifyDropdown from './ModifyDropdown';
import useConfirm from '../../../hooks/useConfirm';
import HyperLinkText from '../../components/HyperLinkText/HyperLinkText';
import { get999PlusCount } from '../../utils';
import useDeleteCommentMutation from '../hooks/mutations/useDeleteComment';
import useFocusEditComment from '../hooks/useFocusEditComment';
Expand Down Expand Up @@ -83,9 +84,9 @@ const Recomment = ({
owner={owner}
/>
<Spacer size={20} />
<Text font="suit14r" color="t" style={{ lineHeight: '22px', whiteSpace: 'pre-wrap' }}>
<HyperLinkText font="suit14r" color="t" lineHeight="22px">
{deleted ? '삭제된 답글입니다.' : content}
</Text>
</HyperLinkText>
<Spacer size={10} />
<Flex>
<Flex alignItems="center" gap={4} onClick={toggleLikeComment} cursor="pointer">
Expand Down
2 changes: 1 addition & 1 deletion src/pages/FeedDetail/components/WriteComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const Textarea = styled.textarea<{ isFocus: boolean }>`
color: ${theme.color.b4};
font-size: ${theme.font.suit14r.fontSize}px;
font-weight: ${theme.font.suit14r.fontWeight};
line-height: 160%;
line-height: 22px;
::placeholder {
color: ${theme.color.ba};
Expand Down
2 changes: 1 addition & 1 deletion src/pages/FeedDetail/components/WriteRecomment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const Textarea = styled.textarea`
color: ${theme.color.b4};
font-size: ${theme.font.suit14r.fontSize}px;
font-weight: ${theme.font.suit14r.fontWeight};
line-height: 160%;
line-height: 22px;
::placeholder {
color: ${theme.color.ba};
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Profile/More.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ const More = () => {
return (
<>
{isDeleteAccountPending && <Spinner backdrop />}
<SEOMeta title="컨셉비 | 더보기" description="아이디어 기반의 안전하고 자유로운 팀원 찾기 플랫폼" />
<SEOMeta title="컨셉비 | 더 보기" description="아이디어 기반의 안전하고 자유로운 팀원 찾기 플랫폼" />
<Container>
<Header spacerPosition="end">
<Header.Item>
<Back />
</Header.Item>
<Header.Item>
<Text font="suit16sb" color="b4">
더보기
더 보기
</Text>
</Header.Item>
</Header>
Expand Down
5 changes: 3 additions & 2 deletions src/pages/Profile/components/ProfileInfoSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { theme, Badge, Spacer, Text, Flex, ImageView, PNGDefaultProfileBackgroun
import { useNavigate } from 'react-router-dom';

import Padding from '../../../components/Padding';
import HyperLinkText from '../../components/HyperLinkText/HyperLinkText';
import { Member } from '../types';

type Props = {
Expand Down Expand Up @@ -59,9 +60,9 @@ const ProfileInfoSection = ({ memberInfo }: Props) => {
</div>
{isMyProfile === true && <EditButton onClick={() => navigate(`/profile-edit`)}>프로필 수정</EditButton>}
</ProfileMainBox>
<Text font="suit15rb" color="b4" style={{ lineHeight: 1.5 }}>
<HyperLinkText font="suit15rb" color="b4" lineHeight="22px">
{introduction}
</Text>
</HyperLinkText>
<div>
<Text font="suit14m">세부 스킬</Text>
<Spacer size={10} />
Expand Down
1 change: 1 addition & 0 deletions src/pages/Write/components/TitleAndIntroduceSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const BodyTextarea = styled.textarea`
font-weight: 400;
resize: none;
color: ${theme.color.b4};
line-height: 22px;
::placeholder {
color: ${theme.color.ba};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const BodyTextarea = styled.textarea`
font-weight: 400;
resize: none;
color: ${theme.color.b4};
line-height: 22px;
::placeholder {
color: ${theme.color.ba};
Expand Down
2 changes: 1 addition & 1 deletion src/pages/WriteEdit/hooks/mutations/usePutIdea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const usePutIdea = () => {
mutationFn: _putIdea,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['ideas'] });
navigate('/');
navigate(-1);
},
onError: (error: PutIdeaError) => {
openAlert({ content: error.response?.data.message ?? '글 수정에 실패했습니다.' });
Expand Down
58 changes: 58 additions & 0 deletions src/pages/components/HyperLinkText/HyperLinkText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import styled from '@emotion/styled';
import { Text } from 'concept-be-design-system';

import { ColorKeyType, FontKeyType } from '../../../styles/theme';

interface Props {
font: FontKeyType;
color: ColorKeyType;
lineHeight?: string;
children: string;
}

const LINK_REG_EXP = /(https?:\/\/|www\.)/;
const convertHyperLinkTexts = ({ font, color, lineHeight = 'normal', children: text }: Props) => {
const generatedTexts = text.split('\n').map((line, idx) => {
if (line === '') return <br key={idx} />;

return (
<Paragraph as="p" key={idx} font={font} color={color} lineHeight={lineHeight}>
{line.split(' ').map((word, idx) => {
const isFirst = idx === 0;

if (LINK_REG_EXP.test(word)) {
return (
<HyperLink as="a" key={idx} href={word} target="_blank" font={font} color={color} lineHeight={lineHeight}>
{word}
</HyperLink>
);
}

return <>{isFirst ? word : ` ${word}`}</>;
})}
</Paragraph>
);
});

return generatedTexts;
};

const HyperLinkText = (props: Props) => {
const convertedTexts = convertHyperLinkTexts(props);

return <Wrapper>{convertedTexts}</Wrapper>;
};

export default HyperLinkText;

const Wrapper = styled.div`
white-space: pre-wrap;
`;

const Paragraph = styled(Text)<{ lineHeight: string }>`
line-height: ${({ lineHeight }) => lineHeight};
`;

const HyperLink = styled(Paragraph)`
color: #448cef;
`;

0 comments on commit 45c7133

Please sign in to comment.