diff --git a/src/App.jsx b/src/App.jsx index 5f3df15..71f91c7 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,5 @@ // 📦 Imports -import React, { useState, useRef } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import ReactFlow, { Background, Controls, @@ -11,12 +11,25 @@ import 'reactflow/dist/style.css'; import axios from 'axios'; import html2canvas from 'html2canvas'; import { saveAs } from 'file-saver'; +import SettingsModal from './SettingsModal'; // 🧠 Initial State & Helpers const initialNodes = []; const initialEdges = []; let nodeId = 1; +const defaultSystemPrompt = `You are an expert in cause-and-effect analysis. + +Given a news headline or event, break it down into a chain of consequences, like a domino effect. + +Each node must: +- Be short (max 15 words) +- Represent one specific consequence +- Be categorized as either: 'positive', 'neutral', or 'negative' +- Be logically linked to the prompt + +Return only 3 outputs: one of each type.`; + const getColor = (type) => { switch (type) { case 'positive': return '#00c853'; @@ -27,7 +40,7 @@ const getColor = (type) => { }; // 🤖 AI Logic with Domino Effect Thinking (Updated: Using Puter AI API) -const createAIChildren = async (text, parentId, setNodes, setEdges, stopGenerationRef) => { +const createAIChildren = async (text, parentId, setNodes, setEdges, stopGenerationRef, systemPrompt) => { try { if (stopGenerationRef.current) return; const res = await axios.post( @@ -37,17 +50,7 @@ const createAIChildren = async (text, parentId, setNodes, setEdges, stopGenerati messages: [ { role: 'system', - content: `You are an expert in cause-and-effect analysis. - -Given a news headline or event, break it down into a chain of consequences, like a domino effect. - -Each node must: -- Be short (max 15 words) -- Represent one specific consequence -- Be categorized as either: 'positive', 'neutral', or 'negative' -- Be logically linked to the prompt - -Return only 3 outputs: one of each type.` + content: systemPrompt, }, { role: 'user', content: text } ] @@ -96,7 +99,7 @@ Return only 3 outputs: one of each type.` // Recursively expand each child one level deep for (const n of newNodes) { if (stopGenerationRef.current) break; - await createAIChildren(n.data.label, n.id, setNodes, setEdges, stopGenerationRef); + await createAIChildren(n.data.label, n.id, setNodes, setEdges, stopGenerationRef, systemPrompt); } } catch (err) { @@ -113,9 +116,20 @@ export default function App() { const [edges, setEdges] = useState(initialEdges); const [prompt, setPrompt] = useState(''); const [loading, setLoading] = useState(false); + const [isSettingsOpen, setIsSettingsOpen] = useState(false); + const [systemPrompt, setSystemPrompt] = useState(defaultSystemPrompt); + const [tempPrompt, setTempPrompt] = useState(systemPrompt); const stopGenerationRef = useRef(false); const reactFlowWrapper = useRef(null); + useEffect(() => { + const storedPrompt = localStorage.getItem('systemPrompt'); + if (storedPrompt) { + setSystemPrompt(storedPrompt); + setTempPrompt(storedPrompt); + } + }, []); + const handleExport = () => { if (reactFlowWrapper.current) { html2canvas(reactFlowWrapper.current).then((canvas) => { @@ -150,7 +164,7 @@ export default function App() { setNodes([rootNode]); setEdges([]); - await createAIChildren(prompt, rootId, setNodes, setEdges, stopGenerationRef); + await createAIChildren(prompt, rootId, setNodes, setEdges, stopGenerationRef, systemPrompt); setPrompt(''); setLoading(false); @@ -164,10 +178,20 @@ export default function App() { const onNodeClick = async (_event, node) => { stopGenerationRef.current = false; setLoading(true); - await createAIChildren(node.data.label, node.id, setNodes, setEdges, stopGenerationRef); + await createAIChildren(node.data.label, node.id, setNodes, setEdges, stopGenerationRef, systemPrompt); setLoading(false); }; + const handleSavePrompt = () => { + setSystemPrompt(tempPrompt); + localStorage.setItem('systemPrompt', tempPrompt); + setIsSettingsOpen(false); + }; + + const handleRestoreDefault = () => { + setTempPrompt(defaultSystemPrompt); + }; + return (
{/* 🔝 Header */} @@ -246,6 +270,20 @@ export default function App() { > Export as PNG +
@@ -265,6 +303,15 @@ export default function App() { + + setIsSettingsOpen(false)} + systemPrompt={tempPrompt} + setSystemPrompt={setTempPrompt} + handleSave={handleSavePrompt} + handleRestoreDefault={handleRestoreDefault} + /> ); } diff --git a/src/SettingsModal.jsx b/src/SettingsModal.jsx new file mode 100644 index 0000000..0cfb4d7 --- /dev/null +++ b/src/SettingsModal.jsx @@ -0,0 +1,110 @@ +// ⚙️ SettingsModal.jsx +import React from 'react'; + +const SettingsModal = ({ isOpen, onClose, systemPrompt, setSystemPrompt, handleSave, handleRestoreDefault }) => { + if (!isOpen) return null; + + return ( +
+
+

Settings

+

+ Customize the AI's instructions to tailor its responses for your specific needs. +

+