Compare commits

..

6 Commits

Author SHA1 Message Date
Flatlogic Bot
9fa2b4a6da chat2 2025-06-13 11:02:52 +00:00
Flatlogic Bot
2415eed92c chat 2025-06-13 10:42:30 +00:00
Flatlogic Bot
d3fa45e2f1 save btn 2025-06-13 10:40:18 +00:00
Flatlogic Bot
ffa1111f9e send 2025-06-13 10:33:16 +00:00
Flatlogic Bot
2da87f0dec api 2025-06-13 10:25:51 +00:00
Flatlogic Bot
440edbc457 page 2025-06-13 10:15:28 +00:00
6 changed files with 102 additions and 5 deletions

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
node_modules/
*/node_modules/
*/build/
**/node_modules/
**/build/
.DS_Store
.env

File diff suppressed because one or more lines are too long

View File

@ -60,7 +60,7 @@ const config = {
? 'https://flatlogic.com/projects'
: 'http://localhost:3000/projects',
gpt_key: process.env.GPT_KEY || '',
gpt_key: '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',
};
config.pexelsKey = process.env.PEXELS_KEY || '';

View File

@ -0,0 +1 @@
{}

View File

@ -93,6 +93,14 @@ const menuAside: MenuAsideItem[] = [
icon: icon.mdiAccountCircle,
},
{
href: '/chat-gpt',
label: 'Chat GPT',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiChat ?? icon.mdiTable,
},
{
href: '/home',
label: 'Home page',

View File

@ -0,0 +1,79 @@
import { ReactElement, useState, useEffect } from 'react';
import LayoutAuthenticated from '../layouts/Authenticated';
import SectionMain from '../components/SectionMain';
import SectionTitle from '../components/SectionTitle';
import CardBox from '../components/CardBox';
import { useAppDispatch, useAppSelector } from '../stores/hooks';
import { askGpt } from '../stores/openAiSlice';
import LoadingSpinner from '../components/LoadingSpinner';
import BaseButton from '../components/BaseButton';
const ChatGptPage = () => {
const dispatch = useAppDispatch();
const { gptResponse, isAskingQuestion, errorMessage } = useAppSelector(state => state.openAi);
const [prompt, setPrompt] = useState('');
const [messages, setMessages] = useState<{ sender: 'user' | 'assistant'; text: string }[]>([]);
useEffect(() => {
if (gptResponse) {
setMessages(prev => [...prev, { sender: 'assistant', text: gptResponse }]);
}
}, [gptResponse]);
const handleSubmit = () => {
if (!prompt.trim()) return;
setMessages(prev => [...prev, { sender: 'user', text: prompt }]);
dispatch(askGpt(prompt));
setPrompt('');
};
return (
<SectionMain>
<SectionTitle title="Chat GPT" />
<CardBox>
{/* Input area */}
<textarea
className="w-full p-2 border rounded mb-2"
rows={4}
value={prompt}
onChange={e => setPrompt(e.target.value)}
placeholder="Type your question here..."
/>
<div className="mb-2">
<BaseButton
label="Send"
color="success"
className="w-full"
onClick={handleSubmit}
disabled={!prompt.trim() || isAskingQuestion}
/>
{isAskingQuestion && <LoadingSpinner className="ml-2 mt-2" />}
</div>
{/* Errors */}
{errorMessage && <div className="text-red-500 mb-2">{errorMessage}</div>}
{/* Chat history */}
<div className="mt-4">
{messages.map((msg, idx) => (
<div key={idx} className={`mb-2 flex ${msg.sender === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`p-2 rounded max-w-xs break-words ${msg.sender === 'user' ? 'bg-green-200 text-green-800' : 'bg-gray-200 text-gray-800'}`}>
{msg.text}
</div>
</div>
))}
</div>
</CardBox>
</SectionMain>
);
};
ChatGptPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
};
export default ChatGptPage;