Skip to content

Commit

Permalink
Merge pull request #63 from yu-senier-project/feat/alarm
Browse files Browse the repository at this point in the history
feat : 알림창 구현 + 알림 왔을 때 ui 생성
  • Loading branch information
yeongipark authored Aug 14, 2024
2 parents 542f716 + fec2f35 commit be21155
Show file tree
Hide file tree
Showing 24 changed files with 547 additions and 42 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"axios": "^1.6.8",
"date-fns": "^3.6.0",
"dhtmlx-gantt": "^8.0.7",
"event-source-polyfill": "^1.0.31",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
Expand Down
9 changes: 8 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import ProJectPost from "./pages/project/ProjectPost";
import { UpdateProject } from "./pages/project/UpdateProject";
import { UpdateParticipants } from "./pages/project/UpdateParticipants";
import { Todo } from "./pages/project/Todo";
import { Alarm } from "./component/alarm/Alarm";
import AlarmModal from "./pages/AlarmModal";

import { isAuthenticated } from "./util/auth";
import ProtectedRoute from "./util/ProtectedRoute";
Expand All @@ -42,14 +44,17 @@ function App() {
return (
<>
<BrowserRouter>
{/* <AlarmModal /> */}
{toggle && <CreateFeed />}
{login ? <Alarm /> : null}
<Routes>
<Route path="/" element={<HomeRedirect />} />
<Route path="/login" element={<Login />} />
<Route path="Id" element={<IdFind />} />
<Route path="CheckId" element={<IdCheck />} />
<Route path="Password" element={<PwInitCheckId />} />
<Route path="PasswordInit" element={<PwInit />} />
{/* sns 라우터*/}
<Route path="/" element={<SmallNav />}>
<Route path="Home" element={<ProtectedRoute element={Home} />} />
<Route
Expand Down Expand Up @@ -79,8 +84,10 @@ function App() {
<Route
path="Message"
element={<ProtectedRoute element={Message} />}
/>
/>{" "}
{/* <Route path="Alarm" element={<ProtectedRoute element={Alarm} />} /> */}
</Route>
{/* 프로젝트 라우터 */}
<Route
path="ProjectHome"
element={<ProtectedRoute element={ProjectNav} />}
Expand Down
12 changes: 12 additions & 0 deletions src/apis/alarmApis.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import apiClient from "../util/BaseUrl";

// 모든 알람 불러오는 api 호출 함수 (무한스크롤)
export const getAllAlarms = async (cursor) => {
let data;
if (cursor === 0) {
data = await apiClient.get(`/api/v1/notification/all`);
} else {
data = await apiClient.get(`/api/v1/notification/all?cursor=${cursor}`);
}
return data?.data;
};
2 changes: 1 addition & 1 deletion src/apis/registerApis.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const sendAuthCode = async (formData, companyEmail, toggle) => {
const res = await axios.get(
`${BaseUrl}/api/v1/email-auth/request/${formData.email}@${companyEmail}`
);

return { statusCode: res.status, data: res.data };
} catch (err) {
alert("이메일 전송에 실패했습니다.");
Expand Down
23 changes: 23 additions & 0 deletions src/component/alarm/Alarm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { useEffect, useState, useRef } from "react";
import "../../styles/alarm/alarm.scss";
import { FaRegBell } from "react-icons/fa6";
import CloseButton from "../basic/CloseButton";
import { useAlarm } from "../../hooks/useAlarm";
export const Alarm = () => {
const { message, className, newAlarm, handleClose } = useAlarm();

return (
<div className={`Alarm ${className}`}>
<div className="Alarm-top">
<div className="Alarm-top-left">
<FaRegBell />
<span style={{ marginLeft: "10px" }}>알림</span>
</div>
<div className="Alarm-top-right">
<CloseButton size={15} onCloseButton={handleClose} />
</div>
</div>
<div className="Alarm-text">{message}</div>
</div>
);
};
21 changes: 21 additions & 0 deletions src/component/alarm/AlarmItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import User from "/image/dp.jpg";
import { detailDate } from "../../util/detailDate";

export const AlarmItem = ({ text, createdAt, postId, type }) => {
return (
<div className="AlarmItem">
<div className="AlarmItem-left">
{/* 이미지랑 텍스트 */}
<div>
<img src={User} alt="유저이미지" />
</div>
<p>{text}</p>
</div>
<div className="AlarmItem-right">
{/* 시간 */}
<p style={{ color: "lightgrey" }}>{detailDate(new Date(createdAt))}</p>
</div>
</div>
);
};
45 changes: 45 additions & 0 deletions src/component/alarm/AlarmList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useEffect, useRef } from "react";
import { useGetAlarmAll } from "../../react-query/useAlarm";
import { AlarmItem } from "./AlarmItem";
import { useIntersectionObserve } from "../../hooks/useIntersectionObserve";

export const AlarmList = () => {
// 알람 데이터 받아오기
const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } =
useGetAlarmAll();

// 감시할 요소 저장할 ref
const nextFetchTargetRef = useRef(null);

// IntersectionObserve 커스텀 훅 가져옴
useIntersectionObserve({
ref: nextFetchTargetRef,
fetchNextPage,
hasNextPage,
data,
});

if (isLoading) return "로딩중...";

return (
<div className="AlarmList">
{data &&
Array.isArray(data) &&
data
.flat()
.map((item) => (
<AlarmItem
id={item.notificationId}
text={item.message}
createdAt={item.createdAt}
postId={item.subjectId}
type={item.type}
/>
))}
{isFetchingNextPage && "로딩중..."}
{!isFetchingNextPage && hasNextPage && (
<div ref={nextFetchTargetRef}>더 불러오기</div>
)}
</div>
);
};
14 changes: 7 additions & 7 deletions src/component/feed/main/UserInfo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ const UserInfo = ({
profile,
id,
}) => {
let time = `${clock[0]}-${clock[1]}-${clock[2]} ${clock[3]}:${clock[4]}:${clock[5]}`;
time = new Date(time).getTime();
let currentTime = new Date().getTime();
let diffTime = (currentTime - time) / (1000 * 60);
// 시간 저장
time = getTime(diffTime);
// let time = `${clock[0]}-${clock[1]}-${clock[2]} ${clock[3]}:${clock[4]}:${clock[5]}`;
// time = new Date(time).getTime();
// let currentTime = new Date().getTime();
// let diffTime = (currentTime - time) / (1000 * 60);
// // 시간 저장
// time = getTime(diffTime);

// 로그인한 정보 가져와서 게시물 아이디랑 같은지 확인해서 설정창 보여줄지 말지 결정
const myName = localStorage.getItem("userNickName");
Expand All @@ -39,7 +39,7 @@ const UserInfo = ({
height={"height-40"}
img={img}
></UserCard>
<p className="UserInfo-clock">{time}</p>
<p className="UserInfo-clock">{1}</p>
{myName == username ? (
<button
className="UserInfo-setting-btn"
Expand Down
46 changes: 32 additions & 14 deletions src/component/nav/SmallNav.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import "../../styles/nav/SmallNav.scss";
import { Link, Outlet } from "react-router-dom";
import { Alarm } from "@mui/icons-material";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faHouse,
faMessage,
faMagnifyingGlass,
faCalendarDays,
faUser,
faSquarePlus,
faGear,
} from "@fortawesome/free-solid-svg-icons";
import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons";
import useCreateFeed from "../../store/feed/useCreateFeed";
import useAlarmStore from "../../store/alarm/useAlarmStore";
import AlarmModal from "../../pages/AlarmModal";
import CreateFeed from "../feed/create/CreateFeed";
import { logout } from "../../util/auth";
import { TiMessages } from "react-icons/ti";
Expand All @@ -20,17 +15,36 @@ import { FaRegCalendarAlt } from "react-icons/fa";
import { FaRegSquarePlus } from "react-icons/fa6";
import { useNavigate } from "react-router-dom";
import { RiLogoutBoxLine } from "react-icons/ri";
import { FaRegHeart } from "react-icons/fa";

const SmallNav = () => {
// 알람 모달 버튼 클릭했는지 안했는지 zustand에서 상태 가져오기
const { open, setOpen } = useAlarmStore();
const nav = useNavigate();
const { setToggle } = useCreateFeed((state) => state);
const onCreate = () => {
allCloseAlarm();
nav("/Home");
setToggle();
};

// 알람 아이콘 클릭했을 떄 실행
const handleAlarmIconClick = () => {
console.log(open);
setOpen(!open);
};

// 알림 모달이 열려있는 상태에서 다른 메뉴로 이동시 알림 모달 닫기
const allCloseAlarm = () => {
if (open) {
setOpen(false);
}
};

const myId = localStorage.getItem("memberId");
return (
<div>
<AlarmModal />
<div className="SmallNav">
<h1
style={{
Expand All @@ -43,31 +57,31 @@ const SmallNav = () => {
CNS
</h1>
<div className="SmallNav-menuWrap">
<Link to={"/Home"}>
<Link to={"/Home"} onClick={allCloseAlarm}>
<div className="SmallNav-menu">
<FiHome className="icon" />
<p></p>
</div>
</Link>
<Link to={"/Message"}>
<Link to={"/Message"} onClick={allCloseAlarm}>
<div className="SmallNav-menu">
<TiMessages className="icon" />
<p>메시지</p>
</div>
</Link>
<Link to={"/search"}>
<Link to={"/search"} onClick={allCloseAlarm}>
<div className="SmallNav-menu">
<FontAwesomeIcon icon={faMagnifyingGlass} className="icon" />
<p>검색</p>
</div>
</Link>
<Link to={"/Project"}>
<Link to={"/Project"} onClick={allCloseAlarm}>
<div className="SmallNav-menu">
<FaRegCalendarAlt className="icon" />
<p>프로젝트</p>
</div>
</Link>
<Link to={`/Profile/${myId}`}>
<Link to={`/Profile/${myId}`} onClick={allCloseAlarm}>
<div className="SmallNav-menu">
<FaRegUser className="icon" />
<p>프로필</p>
Expand All @@ -77,6 +91,10 @@ const SmallNav = () => {
<FaRegSquarePlus className="icon" />
<p>게시글 작성</p>
</div>
<div className="SmallNav-menu" onClick={handleAlarmIconClick}>
<FaRegHeart className="icon" />
<p>알림</p>
</div>
</div>

<div className="SmallNav-menu">
Expand Down
Loading

0 comments on commit be21155

Please sign in to comment.