-
{user?.username}
+
{user?.username}님 {/* Added "님" */}
diff --git a/src/screens/AddIngredientPage/AddIngredientPage.jsx b/src/screens/AddIngredientPage/AddIngredientPage.jsx
index 19f69ce..6d907fe 100644
--- a/src/screens/AddIngredientPage/AddIngredientPage.jsx
+++ b/src/screens/AddIngredientPage/AddIngredientPage.jsx
@@ -1,5 +1,5 @@
-import React, { useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
+import React, { useState, useEffect } from "react";
+import { Link, useNavigate } from "react-router-dom"; // Removed useLocation
import { UnifiedHeader } from "../../components/UnifiedHeader";
import "./style.css";
@@ -27,6 +27,10 @@ const MOCK_INGREDIENT_DATABASE = [
export const AddIngredientPage = () => {
const navigate = useNavigate();
+ // Removed useLocation and onAddMultipleIngredients here
+ // const location = useLocation();
+ // const onAddMultipleIngredients = location.state?.onAddMultipleIngredients;
+
const [selectedCategory, setSelectedCategory] = useState("전체");
const [searchQuery, setSearchQuery] = useState("");
const [selectedIngredients, setSelectedIngredients] = useState([]);
@@ -43,15 +47,26 @@ export const AddIngredientPage = () => {
if (exists) {
return prev.filter((item) => item.id !== ingredient.id);
} else {
- return [...prev, { ...ingredient, expiryDays: 7 }];
+ return [...prev, { ...ingredient, expiryDays: 7 }]; // Default expiry days
}
});
};
const handleAddIngredients = () => {
- // TODO: Send selected ingredients to backend
- console.log("Adding ingredients:", selectedIngredients);
- navigate("/desktop");
+ if (selectedIngredients.length === 0) {
+ alert("추가할 식재료를 선택해주세요.");
+ return;
+ }
+
+ // Directly update localStorage for userIngredients
+ const currentIngredients = JSON.parse(localStorage.getItem("userIngredients") || "[]");
+ const updatedIngredients = [...currentIngredients, ...selectedIngredients];
+ localStorage.setItem("userIngredients", JSON.stringify(updatedIngredients));
+
+ // TODO: Backend Integration: Send selectedIngredients to backend
+ console.log("Adding ingredients to mock DB:", selectedIngredients);
+
+ navigate("/desktop"); // Navigate back to desktop
};
return (
diff --git a/src/screens/CommunityContent/sections/Communitycontentpage/Communitycontentpage.jsx b/src/screens/CommunityContent/sections/Communitycontentpage/Communitycontentpage.jsx
index c36c180..6773391 100644
--- a/src/screens/CommunityContent/sections/Communitycontentpage/Communitycontentpage.jsx
+++ b/src/screens/CommunityContent/sections/Communitycontentpage/Communitycontentpage.jsx
@@ -1,12 +1,11 @@
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
import { Link, useLocation, useParams } from "react-router-dom";
import { useAuth } from "../../../../contexts/AuthContext";
import { CommunitypageWrapper } from "../../../../components/CommunitypageWrapper";
-import { PageButton } from "../../../../components/PageButton";
import "./style.css";
-const ALL_POSTS = [
- // TODO: Backend Integration: Replace with API call to fetch all community posts
+// Default posts for fallback if localStorage is empty
+const DEFAULT_POSTS = [
{ id: 1, title: "돼지고기 100g 나눔합니다.", author: "test3User", date: "2025-11-03", category: "나눔", content: "돼지고기를 너무 많이 샀네요 남는 돼지고기 나눔해요" },
{ id: 2, title: "양파 2개 나눔해요", author: "user123", date: "2025-11-02", category: "나눔", content: "양파 2개 필요하신 분 가져가세요" },
{ id: 3, title: "닭고기 500g 나눔", author: "foodlover", date: "2025-11-01", category: "나눔", content: "신선한 닭고기 나눔합니다" },
@@ -24,35 +23,46 @@ export const Communitycontentpage = () => {
const { id } = useParams();
const { user, isAuthenticated } = useAuth();
const [newComment, setNewComment] = useState("");
-
- // Load comments from localStorage for this specific post
- const [comments, setComments] = useState(() => {
+ const [allCommunityPosts, setAllCommunityPosts] = useState([]);
+
+ // Load comments from localStorage for this specific post, and re-load when 'id' changes
+ const [comments, setComments] = useState([]);
+
+ useEffect(() => {
const storedComments = localStorage.getItem(`comments_${id}`);
- return storedComments ? JSON.parse(storedComments) : [];
- });
-
- const post = location.state?.post || {
- // TODO: Backend Integration: Fetch post details by ID if not available in state
- id: id,
- title: "돼지고기 100g 나눔합니다.",
- author: "test3User",
- date: "2025-11-03",
- category: "나눔",
- content: "돼지고기를 너무 많이 샀네요 남는 돼지고기 나눔해요"
- };
+ setComments(storedComments ? JSON.parse(storedComments) : []);
+ }, [id]); // Dependency array includes 'id'
+
+ useEffect(() => {
+ // Load all community posts from localStorage to find related posts
+ const storedPosts = JSON.parse(localStorage.getItem("communityPosts") || "[]");
+ const combined = [...storedPosts, ...DEFAULT_POSTS];
+ setAllCommunityPosts(combined);
+ }, []); // This effect runs only once on mount
+
+ const post = location.state?.post ||
+ allCommunityPosts.find(p => p.id === parseInt(id)) || // Try to find post from allCommunityPosts
+ { // Fallback if not found
+ id: id,
+ title: "게시글을 찾을 수 없습니다.",
+ author: "알 수 없음",
+ date: "",
+ category: "",
+ content: "해당 게시글을 불러오는 데 실패했습니다."
+ };
// Get related posts (2 before and 2 after current post)
- const currentIndex = ALL_POSTS.findIndex(p => p.id === parseInt(id));
+ const currentIndex = allCommunityPosts.findIndex(p => p.id === parseInt(id));
const relatedPosts = [];
// Get 2 posts before
for (let i = Math.max(0, currentIndex - 2); i < currentIndex; i++) {
- if (ALL_POSTS[i]) relatedPosts.push(ALL_POSTS[i]);
+ if (allCommunityPosts[i]) relatedPosts.push(allCommunityPosts[i]);
}
// Get 2 posts after
- for (let i = currentIndex + 1; i <= Math.min(ALL_POSTS.length - 1, currentIndex + 2); i++) {
- if (ALL_POSTS[i]) relatedPosts.push(ALL_POSTS[i]);
+ for (let i = currentIndex + 1; i <= Math.min(allCommunityPosts.length - 1, currentIndex + 2); i++) {
+ if (allCommunityPosts[i]) relatedPosts.push(allCommunityPosts[i]);
}
const handleCommentSubmit = (e) => {
diff --git a/src/screens/Desktop/Desktop.jsx b/src/screens/Desktop/Desktop.jsx
index 0df0f3b..599f6c4 100644
--- a/src/screens/Desktop/Desktop.jsx
+++ b/src/screens/Desktop/Desktop.jsx
@@ -1,4 +1,5 @@
-import React from "react";
+import React, { useState, useEffect } from "react";
+import { useLocation } from "react-router-dom"; // Import useLocation
import { UnifiedHeader } from "../../components/UnifiedHeader";
import { Community } from "./sections/Community";
import { Footer } from "./sections/Footer";
@@ -6,7 +7,52 @@ import { IngredientInventory } from "./sections/IngredientInventory";
import { MenuInventory } from "./sections/MenuInventory";
import "./style.css";
+const INITIAL_INGREDIENTS = [
+ { id: 1, name: "양파", category: "채소류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-1.png", expiryDays: 5 },
+ { id: 2, name: "닭고기", category: "육류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 3 },
+ { id: 3, name: "고추장", category: "가공류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 30 },
+ { id: 4, name: "고춧가루", category: "가공류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 60 },
+ { id: 5, name: "양배추", category: "채소류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 7 },
+ { id: 6, name: "스테비아", category: "가공류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 90 },
+ { id: 7, name: "마늘", category: "채소류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 14 },
+];
+
export const Desktop = () => {
+ const [ingredients, setIngredients] = useState([]);
+ const location = useLocation(); // Initialize useLocation
+
+ useEffect(() => {
+ // This effect will run on mount and when location changes,
+ // ensuring fresh data when returning from AddIngredientPage
+ const storedIngredients = JSON.parse(localStorage.getItem("userIngredients") || "[]");
+ if (storedIngredients.length > 0) {
+ setIngredients(storedIngredients);
+ } else {
+ setIngredients(INITIAL_INGREDIENTS);
+ localStorage.setItem("userIngredients", JSON.stringify(INITIAL_INGREDIENTS));
+ }
+ }, [location.pathname]); // Re-run when pathname changes
+
+ const handleAddIngredient = (newIngredient) => {
+ setIngredients((prevIngredients) => {
+ const updatedIngredients = [...prevIngredients, newIngredient];
+ localStorage.setItem("userIngredients", JSON.stringify(updatedIngredients));
+ // TODO: Backend Integration: Send newIngredient to backend
+ console.log("Added ingredient to mock DB:", newIngredient);
+ return updatedIngredients;
+ });
+ };
+
+ const handleAddMultipleIngredients = (newIngredients) => {
+ setIngredients((prevIngredients) => {
+ const updatedIngredients = [...prevIngredients, ...newIngredients];
+ localStorage.setItem("userIngredients", JSON.stringify(updatedIngredients));
+ // TODO: Backend Integration: Send newIngredients to backend
+ console.log("Added multiple ingredients to mock DB:", newIngredients);
+ return updatedIngredients;
+ });
+ };
+
return (
@@ -14,7 +60,11 @@ export const Desktop = () => {
오늘의 메뉴를 골라보세요
-
+
diff --git a/src/screens/Desktop/sections/IngredientInventory/IngredientInventory.jsx b/src/screens/Desktop/sections/IngredientInventory/IngredientInventory.jsx
index b15217e..313ccd9 100644
--- a/src/screens/Desktop/sections/IngredientInventory/IngredientInventory.jsx
+++ b/src/screens/Desktop/sections/IngredientInventory/IngredientInventory.jsx
@@ -7,26 +7,10 @@ import "./style.css";
const CATEGORIES = ["전체", "육류", "채소류", "가공류", "유제품", "기타"];
-const INITIAL_INGREDIENTS = [
- // TODO: Backend Integration: Replace with API call to fetch user's ingredients
- { id: 1, name: "양파", category: "채소류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-1.png", expiryDays: 5 },
- { id: 2, name: "닭고기", category: "육류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 3 },
- { id: 3, name: "고추장", category: "가공류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 30 },
- { id: 4, name: "고춧가루", category: "가공류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 60 },
- { id: 5, name: "양배추", category: "채소류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 7 },
- { id: 6, name: "스테비아", category: "가공류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 90 },
- { id: 7, name: "마늘", category: "채소류", image: "https://c.animaapp.com/sjWITF5i/img/ingredientimage-7@2x.png", expiryDays: 14 },
-];
-
-export const IngredientInventory = () => {
+export const IngredientInventory = ({ ingredients, onAddIngredient }) => { // Removed onAddMultipleIngredients from props
const [selectedCategory, setSelectedCategory] = useState("전체");
const [showCategoryMenu, setShowCategoryMenu] = useState(false);
const [showAddPopup, setShowAddPopup] = useState(false);
- const [ingredients, setIngredients] = useState(INITIAL_INGREDIENTS);
-
- const handleAddIngredient = (newIngredient) => {
- setIngredients([...ingredients, newIngredient]);
- };
const filteredIngredients = selectedCategory === "전체"
? ingredients
@@ -71,7 +55,10 @@ export const IngredientInventory = () => {
expiryDays={ingredient.expiryDays}
/>
))}
-
+
추가하기
@@ -102,7 +89,7 @@ export const IngredientInventory = () => {
{showAddPopup && (
setShowAddPopup(false)}
- onAdd={handleAddIngredient}
+ onAdd={onAddIngredient} // Use the prop function
/>
)}
diff --git a/src/screens/MenuRecommendationPage/MenuRecommendationPage.jsx b/src/screens/MenuRecommendationPage/MenuRecommendationPage.jsx
index f8f657f..714280e 100644
--- a/src/screens/MenuRecommendationPage/MenuRecommendationPage.jsx
+++ b/src/screens/MenuRecommendationPage/MenuRecommendationPage.jsx
@@ -3,6 +3,33 @@ import { Link } from "react-router-dom";
import { UnifiedHeader } from "../../components/UnifiedHeader";
import "./style.css";
+// Placeholder for WebSpeech API integration
+const startVoiceRecognition = () => {
+ alert("음성 인식 기능은 WebSpeech API와 연동 예정입니다.");
+ // const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+ // if (!SpeechRecognition) {
+ // alert("이 브라우저는 음성 인식을 지원하지 않습니다.");
+ // return;
+ // }
+ // const recognition = new SpeechRecognition();
+ // recognition.lang = 'ko-KR';
+ // recognition.interimResults = false;
+ // recognition.maxAlternatives = 1;
+
+ // recognition.start();
+
+ // recognition.onresult = (event) => {
+ // const speechResult = event.results[0][0].transcript;
+ // console.log('Speech Result:', speechResult);
+ // // setSearchQuery(speechResult); // Update search query with speech result
+ // };
+
+ // recognition.onerror = (event) => {
+ // console.error('Speech recognition error:', event.error);
+ // alert('음성 인식 중 오류가 발생했습니다: ' + event.error);
+ // };
+};
+
const MOCK_RECIPES = [
// TODO: Backend Integration: Replace with API call to fetch all available recipes
{
@@ -224,6 +251,9 @@ export const MenuRecommendationPage = () => {
+
diff --git a/src/screens/MenuRecommendationPage/style.css b/src/screens/MenuRecommendationPage/style.css
index 6fec0be..d7168f1 100644
--- a/src/screens/MenuRecommendationPage/style.css
+++ b/src/screens/MenuRecommendationPage/style.css
@@ -91,6 +91,25 @@
background-color: #e58209;
}
+.menu-voice-btn {
+ width: 50px;
+ height: 50px;
+ background-color: #f6910b;
+ border: none;
+ border-radius: 12px;
+ color: #ffffff;
+ cursor: pointer;
+ font-size: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background-color 0.2s;
+}
+
+.menu-voice-btn:hover {
+ background-color: #e58209;
+}
+
.menu-recommendation-buttons {
align-self: stretch;
display: flex;