-
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
base: develop
Are you sure you want to change the base?
header alarm 구현완료 #102
Changes from 15 commits
5df2417
8303eb7
b771cf5
d653f62
7b650e7
d5682fe
deb3f1c
48a352a
f00d848
766843e
5e067ed
9b72f22
f28db0c
c390cff
f987f73
c09bec6
020fd94
73790af
ef91700
cb8722a
0efa59a
d6e43f3
a62da14
54e36fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { createSlice } from "@reduxjs/toolkit"; | ||
| import { loadAlarmList } from "app/store/ducks/alarm/alarmThunk"; | ||
|
|
||
| export interface AlarmStateProps { | ||
| alarmList: Alarm.AlarmContent[] | null; | ||
| totalPage: number; | ||
| } | ||
|
|
||
| const initialState: AlarmStateProps = { | ||
| alarmList: null, | ||
| totalPage: 0, | ||
| }; | ||
|
|
||
| const alarmSlice = createSlice({ | ||
| name: " alarm", | ||
| initialState, | ||
| reducers: { | ||
| clearAlarmList: (state) => { | ||
| state.alarmList = null; | ||
| }, | ||
| }, | ||
| extraReducers: (build) => { | ||
| build // | ||
|
||
| .addCase(loadAlarmList.fulfilled, (state, action) => { | ||
| if (action.payload.currentPage === 1) { | ||
| state.alarmList = action.payload.content; | ||
| state.totalPage = action.payload.totalPages; | ||
| } else { | ||
| state.alarmList?.push(...action.payload.content); | ||
| } | ||
| }); | ||
| }, | ||
| }); | ||
|
|
||
| export const alarmAction = alarmSlice.actions; | ||
|
|
||
| export const alarmReducer = alarmSlice.reducer; | ||
| 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< | ||
| Alarm.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); | ||
| } | ||
| }); |
| 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/alarm_profile"; | ||
| 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: Alarm.CommonAlarm }) { | ||
| 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> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import AlarmProfile from "components/Common/Header/alarm/alarm_profile"; | ||
| import { removeRefer } from "components/Common/Header/alarm/utils"; | ||
| import FollowingModal from "components/Home/Modals/FollowingModal"; | ||
| import useGapText from "hooks/useGapText"; | ||
| import { Link } from "react-router-dom"; | ||
| import styled from "styled-components"; | ||
|
|
||
| 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}; | ||
| } | ||
| } | ||
| `; | ||
|
|
||
| export default function FollowAlarm({ alarm }: { alarm: Alarm.FollowAlarm }) { | ||
| const alarmMessage = removeRefer(alarm.message); | ||
|
|
||
| return ( | ||
| <Container> | ||
| <AlarmProfile agent={alarm.agent} /> | ||
| <div className="alarm"> | ||
| <Link to={`/profile/${alarm.agent.username}`}> | ||
| <span className="username">{alarm.agent.username}</span> | ||
| </Link> | ||
| {alarmMessage}{" "} | ||
| <span className="create-date"> | ||
| {useGapText(alarm.createdDate)} | ||
| </span> | ||
| </div> | ||
| {/* <button> */} | ||
| {alarm.following ? "팔로잉" : "팔로우"} | ||
| {/* {alarm.following ? <FollowingModal /> : <button>hi</button>} */} | ||
| {/* </button> */} | ||
| </Container> | ||
live-small marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| import AlarmItem from "components/Common/Header/alarm/alarmType/alarm_item"; | ||
| import FollowAlarm from "components/Common/Header/alarm/alarmType/follow_alarm"; | ||
| 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: Alarm.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> | ||
| ); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.