-
Notifications
You must be signed in to change notification settings - Fork 7
header alarm 구현완료 #102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
live-small
wants to merge
24
commits into
develop
Choose a base branch
from
feature/alarm
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
header alarm 구현완료 #102
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
5df2417
feat: 알람 컨테이너 UI 구현, 알람 리스트 thunk로 불러옴
live-small 8303eb7
fix: alarm list 응답 타입, index.d.ts 파일에서 관리하도록 수정
live-small b771cf5
feat: 알람 아이템 > 알람보낸 프로필 UI 구현
live-small d653f62
feat: 알림 item 하나로 통일, 로딩처리, 알람없는 경우 처리
live-small 7b650e7
feat: 알람 내 게시글 썸네일 클릭 시 해당 게시글로 이동
live-small d5682fe
fix: 알람 item UI 일부 수정
live-small deb3f1c
refactor: div 대신 ul,li 태그 이용
live-small 48a352a
Merge branch 'develop' into feature/alarm
live-small f00d848
Merge branch 'develop' into feature/alarm
live-small 766843e
feat: hashtag, mentions 링크,스타일링 적용
live-small 5e067ed
fix: useOnView 수정: parameter, useEffect deps
live-small 9b72f22
fix: Alarm 무한스크롤을 위해 Alarm type 수정
live-small f28db0c
feat: Alarm 무한스크롤 구현 - alarm list 컴포넌트에서 observing 붙임
live-small c390cff
fix: 불필요한 log 제거
live-small f987f73
Merge branch 'develop' into feature/alarm
live-small c09bec6
020fd94
feat: 알람>팔로우, 팔로잉 버튼 UI, 모달 핸들러 구현
live-small 73790af
fix: alarm type 중복되는 타입 묶어서 확장하는 방향으로 수정
live-small ef91700
feat: 알람 없을 때 UI 수정
live-small cb8722a
fix: 알람 모달상태값 isClickAlarm -> isAlarmOn
live-small 0efa59a
fix: 안쓰는 컴포넌트 import 삭제
live-small d6e43f3
fix: 알람버튼 cursor pointer
live-small a62da14
fix: 공통 컨벤션으로 수정
live-small 54e36fc
fix: Alarm 무한스크롤 구현 시 필요한 상태값, 컴포넌트에서 관리하도록 수정
live-small File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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,16 @@ | ||
| import { createSlice } from "@reduxjs/toolkit"; | ||
|
|
||
| export interface AlarmStateProps {} | ||
|
|
||
| const initialState: AlarmStateProps = {}; | ||
|
|
||
| const alarmSlice = createSlice({ | ||
| name: " alarm", | ||
| initialState, | ||
| reducers: {}, | ||
| extraReducers: (build) => {}, | ||
| }); | ||
|
|
||
| export const alarmAction = alarmSlice.actions; | ||
|
|
||
| export const alarmReducer = alarmSlice.reducer; |
This file contains hidden or 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,22 @@ | ||
| import { authorizedCustomAxios } from "customAxios"; | ||
| import { createAsyncThunk } from "@reduxjs/toolkit"; | ||
|
|
||
| export const loadAlarmList = createAsyncThunk< | ||
| AlarmType.AlarmItem, | ||
| { page: number } | ||
| >("alarm/loadList", async (payload, ThunkOptions) => { | ||
| try { | ||
| const config = { | ||
| params: { | ||
| page: payload.page, | ||
| size: 10, | ||
| }, | ||
| }; | ||
| const { | ||
| data: { data }, | ||
| } = await authorizedCustomAxios.get(`/alarms`, config); | ||
| return { ...data, currentPage: payload.page }; | ||
| } catch (error) { | ||
| ThunkOptions.rejectWithValue(error); | ||
| } | ||
| }); |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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 |
|---|---|---|
|
|
@@ -8,20 +8,19 @@ import { ReactComponent as DirectActive } from "assets/Svgs/direct-active.svg"; | |
| import { ReactComponent as NewArticle } from "assets/Svgs/new-article.svg"; | ||
| import { ReactComponent as NewArticleActive } from "assets/Svgs/new-article-active.svg"; | ||
|
|
||
| import { ReactComponent as Map } from "assets/Svgs/map.svg"; | ||
| import { ReactComponent as MapActive } from "assets/Svgs/map-active.svg"; | ||
|
|
||
| import { ReactComponent as Heart } from "assets/Svgs/heart.svg"; | ||
| import { ReactComponent as HeartActive } from "assets/Svgs/heart-active.svg"; | ||
|
|
||
| import { NavLink, Link } from "react-router-dom"; | ||
| import { NavLink } from "react-router-dom"; | ||
| import { useAppDispatch, useAppSelector } from "app/store/Hooks"; | ||
| import { selectView } from "app/store/ducks/direct/DirectSlice"; | ||
| import { uploadActions } from "app/store/ducks/upload/uploadSlice"; | ||
| import Upload from "components/Common/Header/Upload"; | ||
| import SubNav from "./SubNav"; | ||
|
|
||
| import { useRef, useState } from "react"; | ||
| import useOutsideClick from "hooks/useOutsideClick"; | ||
| import Alarm from "components/Common/Header/alarm"; | ||
|
|
||
| const Container = styled.div` | ||
| flex: 1 0 0%; | ||
|
|
@@ -71,14 +70,22 @@ const AvatarWrapper = styled(NavItemWrapper)<{ isSubnavModalOn: boolean }>` | |
|
|
||
| const NavItems = () => { | ||
| const [isSubnavModalOn, setIsSubnavMoalOn] = useState(false); | ||
| const [isAlarmOn, setIsAlarmOn] = useState(false); | ||
|
|
||
| const dispatch = useAppDispatch(); | ||
| const isUploading = useAppSelector(({ upload }) => upload.isUploading); | ||
| const userInfo = useAppSelector((state) => state.auth.userInfo); | ||
|
|
||
| // setting | ||
| const navContainerRef = useRef<HTMLDivElement | null>(null); | ||
| const subModalControllerRef = useRef<HTMLDivElement | null>(null); | ||
| const subModalControllerRef = useRef<HTMLImageElement | null>(null); | ||
| useOutsideClick(navContainerRef, setIsSubnavMoalOn, subModalControllerRef); | ||
|
|
||
| // alarm | ||
| const alarmContainerRef = useRef<HTMLDivElement | null>(null); | ||
| const alarmModalControllerRef = useRef<HTMLSpanElement | null>(null); | ||
| useOutsideClick(alarmContainerRef, setIsAlarmOn, alarmModalControllerRef); | ||
|
|
||
|
Comment on lines
+85
to
+88
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 두 Ref는
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네네 맞아요 |
||
| const navItems = [ | ||
| { | ||
| id: "홈", | ||
|
|
@@ -127,8 +134,19 @@ const NavItems = () => { | |
| { | ||
| id: "피드 활동", | ||
| path: "/", | ||
| component: <Heart />, | ||
| activeComponent: <HeartActive />, | ||
| component: ( | ||
| <span ref={alarmModalControllerRef}> | ||
| <Heart onClick={() => setIsAlarmOn(!isAlarmOn)} /> | ||
| </span> | ||
| ), | ||
| activeComponent: ( | ||
| <span ref={alarmModalControllerRef} style={{ width: `22px` }}> | ||
| <HeartActive onClick={() => setIsAlarmOn(!isAlarmOn)} /> | ||
| {isAlarmOn && ( | ||
| <Alarm alarmContainerRef={alarmContainerRef} /> | ||
| )} | ||
| </span> | ||
| ), | ||
| }, | ||
| ]; | ||
|
|
||
|
|
@@ -144,6 +162,12 @@ const NavItems = () => { | |
| ? navItem.activeComponent | ||
| : navItem.component} | ||
| </div> | ||
| ) : navItem.id === "피드 활동" ? ( | ||
| <div> | ||
| {isAlarmOn | ||
| ? navItem.activeComponent | ||
| : navItem.component} | ||
| </div> | ||
| ) : ( | ||
| <NavLink to={navItem.path}> | ||
| {navItem.component} | ||
|
|
@@ -154,7 +178,6 @@ const NavItems = () => { | |
|
|
||
| <AvatarWrapper isSubnavModalOn={isSubnavModalOn}> | ||
| <div | ||
| ref={subModalControllerRef} | ||
| onClick={() => { | ||
| setIsSubnavMoalOn(!isSubnavModalOn); | ||
| }} | ||
|
|
@@ -166,6 +189,7 @@ const NavItems = () => { | |
| data-testid="user-avatar" | ||
| draggable="false" | ||
| src={userInfo?.memberImageUrl} | ||
| ref={subModalControllerRef} | ||
| /> | ||
| </div> | ||
| {isSubnavModalOn && ( | ||
|
|
||
This file contains hidden or 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,49 @@ | ||
| import AlarmItem from "components/Common/Header/alarm/alarmType/AlarmItem"; | ||
| import FollowAlarm from "components/Common/Header/alarm/alarmType/FollowAlarm"; | ||
| import useOnView from "hooks/useOnView"; | ||
| import { useEffect, useRef } from "react"; | ||
| import styled from "styled-components"; | ||
|
|
||
| const Container = styled.ul` | ||
| display: flex; | ||
| flex-direction: column; | ||
|
|
||
| .alarm-item { | ||
| padding: 12px 16px; | ||
| } | ||
| `; | ||
|
|
||
| export default function AlarmList({ | ||
| alarmList, | ||
| onLoadExtraAlarm, | ||
| }: { | ||
| alarmList: AlarmType.AlarmContent[]; | ||
| onLoadExtraAlarm: () => void; | ||
| }) { | ||
| const lastAlarmItemRef = useRef<HTMLLIElement>(null); | ||
| const isVisible = useOnView(lastAlarmItemRef); | ||
|
|
||
| useEffect(() => { | ||
| isVisible && onLoadExtraAlarm(); | ||
| }, [isVisible]); | ||
|
|
||
| return ( | ||
| <Container> | ||
| {alarmList.map((alarm, index) => ( | ||
| <li | ||
| className="alarm-item" | ||
| key={alarm.id} | ||
| ref={ | ||
| index === alarmList.length - 4 ? lastAlarmItemRef : null | ||
| } | ||
| > | ||
| {alarm.type === "FOLLOW" ? ( | ||
| <FollowAlarm alarm={alarm} /> | ||
| ) : ( | ||
| <AlarmItem alarm={alarm} /> | ||
| )} | ||
| </li> | ||
| ))} | ||
| </Container> | ||
| ); | ||
| } |
This file contains hidden or 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,25 @@ | ||
| import { Link } from "react-router-dom"; | ||
| import styled from "styled-components"; | ||
|
|
||
| const Container = styled.div` | ||
| img { | ||
| height: 44px; | ||
| width: 44px; | ||
| border-radius: 50%; | ||
| } | ||
| `; | ||
|
|
||
| export default function AlarmProfile({ | ||
| agent, | ||
| }: Pick<AlarmType.AlarmContent, "agent">) { | ||
| return ( | ||
| <Container> | ||
| <Link to={`/profile/${agent.username}`}> | ||
| <img | ||
| src={agent.image.imageUrl} | ||
| alt={`${agent.username}님의 이미지`} | ||
| ></img> | ||
| </Link> | ||
| </Container> | ||
| ); | ||
| } |
71 changes: 71 additions & 0 deletions
71
src/components/Common/Header/alarm/alarmType/AlarmItem.tsx
This file contains hidden or 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,71 @@ | ||
| import React from "react"; | ||
| import styled from "styled-components"; | ||
| import AlarmProfile from "components/Common/Header/alarm/AlarmProfile"; | ||
| import { Link } from "react-router-dom"; | ||
| import useGapText from "hooks/useGapText"; | ||
| import { removeRefer } from "components/Common/Header/alarm/utils"; | ||
| import StringFragmentWithMentionOrHashtagLink from "components/Common/StringFragmentWithMentionOrHashtagLink"; | ||
|
|
||
| const Container = styled.div` | ||
| display: flex; | ||
| flex: 1; | ||
|
|
||
| .alarm { | ||
| margin: 0 12px; | ||
| flex: 1; | ||
|
|
||
| a { | ||
| text-decoration: none; | ||
|
|
||
| .username { | ||
| font-weight: 700; | ||
| } | ||
| } | ||
|
|
||
| .create-date { | ||
| color: ${(props) => props.theme.font.gray}; | ||
| } | ||
| } | ||
|
|
||
| .relative-image { | ||
| display: flex; | ||
| flex-direction: column; | ||
| justify-content: center; | ||
|
|
||
| img { | ||
| height: 40px; | ||
| width: 40px; | ||
| } | ||
| } | ||
| `; | ||
|
|
||
| export default function AlarmItem({ alarm }: { alarm: AlarmType.PostAlarm }) { | ||
| const alarmMessage = removeRefer(alarm.message); | ||
| // 무한스크롤 | ||
| // 컴포넌트 언마운트 -> alarm창 닫도록 | ||
|
|
||
| return ( | ||
| <Container> | ||
| <AlarmProfile agent={alarm.agent} /> | ||
| <div className="alarm"> | ||
| <Link to={`/profile/${alarm.agent.username}`}> | ||
| <span className="username">{alarm.agent.username}</span> | ||
| </Link> | ||
| {alarmMessage} | ||
| <StringFragmentWithMentionOrHashtagLink | ||
| str={alarm.content} | ||
| mentions={alarm.mentionsOfContent} | ||
| hashtags={alarm.hashtagsOfContent} | ||
| />{" "} | ||
| <span className="create-date"> | ||
| {useGapText(alarm.createdDate)} | ||
| </span> | ||
| </div> | ||
| <div className="relative-image"> | ||
| <Link to={`/p/${alarm.postId}`}> | ||
| <img src={alarm.postImageUrl} alt={"이미지 썸네일"}></img> | ||
| </Link> | ||
| </div> | ||
| </Container> | ||
| ); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안쓰는 이미지라서 삭제했습니다 @kimyoungyin
아마 저희가 저 기능 구현안하기로해서 작업안한거 맞죠..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kimyoungyin 영인님 이 부분도 봐주신거 맞나용?