init
This commit is contained in:
94
src/context/ToolContext.jsx
Normal file
94
src/context/ToolContext.jsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import React, { createContext, useState, useContext, useEffect } from 'react';
|
||||
import { API_BASE_URL } from '../config';
|
||||
|
||||
const ToolContext = createContext();
|
||||
|
||||
export function ToolProvider({ children }) {
|
||||
const [tools, setTools] = useState([]);
|
||||
const [selectedTool, setSelectedTool] = useState(null);
|
||||
const [favorites, setFavorites] = useState(() => {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('favorites')) || [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
async function load() {
|
||||
try {
|
||||
const res = await fetch(`${API_BASE_URL}/tools`);
|
||||
const data = await res.json();
|
||||
// 'GxP 챗봇'과 'chatgpt' 카드는 도구 목록에서 제거
|
||||
const filtered = (Array.isArray(data) ? data : []).filter((tool) => !['chatbot_gxp','chatgpt','lims_text2sql','research_qa'].includes(tool.id));
|
||||
const mapped = filtered.map((tool) => {
|
||||
const category = ['전체'];
|
||||
if (['dev_chatbot', 'doc_translation'].includes(tool.id)) {
|
||||
category.push('오픈AI');
|
||||
}
|
||||
return { ...tool, category };
|
||||
});
|
||||
setTools(mapped);
|
||||
// 선택된 도구 복원 (마지막 카드 유지)
|
||||
try {
|
||||
const savedId = localStorage.getItem('selectedToolId');
|
||||
if (savedId) {
|
||||
const found = mapped.find((t) => t.id === savedId);
|
||||
if (found) setSelectedTool(found);
|
||||
}
|
||||
// URL 경로가 카드 ID일 경우 해당 카드로 강제 설정 (예: /dev_chatbot)
|
||||
const path = window.location.pathname.replace(/^\/+/, '');
|
||||
const menuPaths = new Set(['chatting', 'tools', 'lecture', 'community', '']);
|
||||
if (path && !menuPaths.has(path)) {
|
||||
const fromUrl = mapped.find((t) => t.id === path);
|
||||
if (fromUrl) setSelectedTool(fromUrl);
|
||||
}
|
||||
} catch {}
|
||||
// 즐겨찾기에 남아 있을 수 있는 제거 대상 정리
|
||||
setFavorites((prev) => prev.filter((id) => !['chatbot_gxp','chatgpt','lims_text2sql','research_qa'].includes(id)));
|
||||
} catch (_) {}
|
||||
}
|
||||
load();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem('favorites', JSON.stringify(favorites));
|
||||
}, [favorites]);
|
||||
|
||||
// 선택된 도구 지속화: 메뉴 이동 후에도 마지막 카드가 유지되도록 저장
|
||||
useEffect(() => {
|
||||
try {
|
||||
if (selectedTool?.id) localStorage.setItem('selectedToolId', selectedTool.id);
|
||||
} catch {}
|
||||
}, [selectedTool?.id]);
|
||||
|
||||
const toggleFavorite = (id) => {
|
||||
setFavorites((prev) => (prev.includes(id) ? prev.filter((f) => f !== id) : [...prev, id]));
|
||||
};
|
||||
|
||||
// 카드 선택 시 URL을 카드 경로로 반영 (메뉴 페이지가 아닌 경우)
|
||||
useEffect(() => {
|
||||
if (!selectedTool?.id) return;
|
||||
const path = `/${selectedTool.id}`;
|
||||
const menuPaths = new Set(['/chatting','/tools','/lecture','/community','/']);
|
||||
if (!menuPaths.has(window.location.pathname) && window.location.pathname === path) return;
|
||||
// 도구 화면에서 카드 선택 시 URL을 카드 경로로 업데이트
|
||||
if (window.location.pathname !== path) {
|
||||
window.history.pushState({}, '', path);
|
||||
}
|
||||
}, [selectedTool?.id]);
|
||||
|
||||
const value = {
|
||||
tools,
|
||||
selectedTool,
|
||||
setSelectedTool,
|
||||
favorites,
|
||||
toggleFavorite,
|
||||
};
|
||||
|
||||
return <ToolContext.Provider value={value}>{children}</ToolContext.Provider>;
|
||||
}
|
||||
|
||||
export function useTool() {
|
||||
return useContext(ToolContext);
|
||||
}
|
||||
Reference in New Issue
Block a user