Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/assets/css/main/header.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
font-weight: bolder;
margin: 0;
}

.logoReci {
color: black; /* Reci의 기본 색상 */
}
Expand All @@ -42,3 +43,45 @@
.nav a:hover {
color: rgb(61, 60, 60);
}

.alertContainer {
position: relative; /* 알림 버튼 컨테이너 기준으로 위치 설정 */
display: inline-block;
cursor: pointer;
}

.alerts {
position: absolute; /* 부모 컨테이너를 기준으로 절대 위치 */
top: 100%; /* 컨테이너 바로 아래에 표시 */
left: -100%; /* 부모 컨테이너 기준으로 가장 왼쪽에 위치 */
background-color: white;
border: 1px solid #ccc;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 10px;
width: 250px;
z-index: 1000; /* 다른 요소 위에 표시 */
max-height: 200px; /* 최대 높이 설정 */
overflow-y: auto; /* 내용이 넘칠 경우 스크롤 */
transform: translateX(-150px); /* 알림 위치를 더 왼쪽으로 이동 */
}

.alerts ul {
list-style: none;
padding: 0;
margin: 0;
}

.alerts li {
padding: 5px 0;
border-bottom: 1px solid #eee;
}

.alerts li:last-child {
border-bottom: none;
}

.alerts p {
margin: 0;
text-align: center;
color: #666;
}
80 changes: 76 additions & 4 deletions src/components/main/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,50 @@
import React from "react";
import style from '../../assets/css/main/header.module.css';
import React, { useEffect, useState } from "react";
import axios from "axios";
import style from "../../assets/css/main/header.module.css";

function Header() {
const [userPk, setUserPk] = useState(null); // JWT에서 추출한 userPk
const [alerts, setAlerts] = useState([]); // 알림 데이터
const [showAlerts, setShowAlerts] = useState(false); // 알림 표시 여부

// JWT에서 userPk 추출하는 함수
function getUserPkFromToken(token) {
try {
const payload = token.split(".")[1]; // 토큰의 payload 부분
const decoded = JSON.parse(atob(payload)); // Base64 디코딩 후 JSON 파싱
return decoded.username; // username에 담긴 userPk 반환
} catch (error) {
console.error("Failed to decode token:", error);
return null;
}
}

// API 요청 함수
async function fetchAlerts(userPk) {
try {
const response = await axios({
method: "post",
url: "http://localhost:8080/ingredient/alert",
data: { userPk },
});
setAlerts(response.data);
} catch (error) {
console.error("Failed to fetch alerts:", error);
}
}

// 컴포넌트가 마운트될 때 실행
useEffect(() => {
const token = localStorage.getItem("token"); // 로컬스토리지에서 JWT 가져오기
if (token) {
const extractedUserPk = getUserPkFromToken(token); // userPk 추출
setUserPk(extractedUserPk); // 상태 업데이트
if (extractedUserPk) {
fetchAlerts(extractedUserPk); // API 호출
}
}
}, []);

return (
<header className={style.header}>
<div className={style.logo}>
Expand All @@ -14,8 +57,37 @@ function Header() {
<a href="/">홈</a>
<a href="/ingredient">내 냉장고</a>
<a href="/recipe">레시피</a>
<a href="/ingredient">즐겨찾기</a>
<a href="/login">로그인</a>
{userPk ? (
<>
<a href="/logout">로그아웃</a>
<div
className={style.alertContainer}
onMouseEnter={() => setShowAlerts(true)} // 마우스를 올렸을 때
onMouseLeave={() => setShowAlerts(false)} // 마우스가 벗어났을 때
>
<span>알림 ({alerts.length})</span>
{showAlerts && (
<div className={style.alerts}>
{alerts.length > 0 ? (
<ul>
{alerts.map((alert) => (
<li key={alert.ingredientMyRefrigeratorPk}>
{alert.ingredientManagement.ingredientName}
({alert.ingredientManagement.ingredientStorage.ingredientStorage})
- {alert.remainDate}일 남음
</li>
))}
</ul>
) : (
<p>알림이 없습니다.</p>
)}
</div>
)}
</div>
</>
) : (
<a href="/login">로그인</a>
)}
</nav>
</header>
);
Expand Down
1 change: 0 additions & 1 deletion src/pages/recipe/Recipe.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useEffect, useState,useCallback } from "react"
import { getRecipeList } from "../../sources/api/recipeAPI.jsx";
import {Link, Route, useNavigate} from "react-router-dom";
import { AddRecipe} from "./addRecipe.jsx";
import {Route, useNavigate} from "react-router-dom";
import RecipeItem from "../../components/recipe/RecipeItem.jsx"
import "../../assets/css/recipe/recipe.css"

Expand Down
32 changes: 27 additions & 5 deletions src/sources/api/IngredientAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ import axios from "axios";

const BASE_URL = "http://localhost:8080/ingredient";

function getUserPkFromToken(token) {
try {
const payload = token.split(".")[1]; // 토큰의 payload 부분
const decoded = JSON.parse(atob(payload)); // Base64 디코딩 후 JSON 파싱
return decoded.username; // username에 담긴 userPk 반환
} catch (error) {
console.error("Failed to decode token:", error);
return null;
}
}


export async function getAllIngredients() {
try {
const response = await axios.get(`${BASE_URL}`); // 백엔드에 전체 재료 목록을 가져오는 API 필요
Expand All @@ -13,12 +25,15 @@ export async function getAllIngredients() {
}

export async function addIngredientToMyRefrigerator(ingredientData) {
const token = localStorage.getItem("token")
const extractedUserPk = getUserPkFromToken(token);

try {
const response = await axios({
url: `${BASE_URL}`,
method: "post",
params: {
userPk: 1, // 실제 로그인된 사용자 PK로 교체 필요
userPk: extractedUserPk, // 실제 로그인된 사용자 PK로 교체 필요
ingredientManagementPk: ingredientData.ingredientManagementPk,
},
data: {
Expand All @@ -35,12 +50,15 @@ export async function addIngredientToMyRefrigerator(ingredientData) {
}

export async function createIngredient(ingredientData) {
const token = localStorage.getItem("token")
const extractedUserPk = getUserPkFromToken(token);

try {
const response = await axios({
url: `${BASE_URL}`,
method: "post",
params: {
userPk: 1,
userPk: extractedUserPk,
ingredientManagementPk: ingredientData.ingredientManagementPk,
},
data: {
Expand Down Expand Up @@ -83,12 +101,14 @@ export async function deleteIngredient(
}

export async function getUsersIngredient() {
const token = localStorage.getItem("token")
const extractedUserPk = getUserPkFromToken(token);
try {
const response = await axios({
url: `${BASE_URL}`,
method: "get",
params: {
userPk: 1,
userPk: extractedUserPk,
},
});
return response.data; // 데이터를 반환
Expand All @@ -99,12 +119,14 @@ export async function getUsersIngredient() {
}

export function updateIngredientBookmark(userPk, isBookmarked, ingredient) {
const token = localStorage.getItem("token")
const extractedUserPk = getUserPkFromToken(token);
if (!isBookmarked) {
axios({
url: `${BASE_URL}/bookmark/regist`,
method: "post",
data: {
userPk: userPk,
userPk: extractedUserPk,
ingredientMyRefrigeratorPk: ingredient.ingredientMyRefrigeratorPk,
},
})
Expand All @@ -120,7 +142,7 @@ export function updateIngredientBookmark(userPk, isBookmarked, ingredient) {
url: `${BASE_URL}/bookmark/delete`,
method: "delete",
data: {
userPk: userPk,
userPk: extractedUserPk,
ingredientBookmarkPk: ingredient.ingredientBookmarkPk,
},
})
Expand Down