Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fa2b4a6da | ||
|
|
2415eed92c | ||
|
|
d3fa45e2f1 | ||
|
|
ffa1111f9e | ||
|
|
2da87f0dec | ||
|
|
440edbc457 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,8 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
*/node_modules/
|
*/node_modules/
|
||||||
*/build/
|
*/build/
|
||||||
|
|
||||||
|
**/node_modules/
|
||||||
|
**/build/
|
||||||
|
.DS_Store
|
||||||
|
.env
|
||||||
File diff suppressed because one or more lines are too long
@ -60,7 +60,7 @@ const config = {
|
|||||||
? 'https://flatlogic.com/projects'
|
? 'https://flatlogic.com/projects'
|
||||||
: 'http://localhost:3000/projects',
|
: 'http://localhost:3000/projects',
|
||||||
|
|
||||||
gpt_key: process.env.GPT_KEY || '',
|
gpt_key: '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',
|
||||||
};
|
};
|
||||||
|
|
||||||
config.pexelsKey = process.env.PEXELS_KEY || '';
|
config.pexelsKey = process.env.PEXELS_KEY || '';
|
||||||
|
|||||||
1
frontend/json/runtimeError.json
Normal file
1
frontend/json/runtimeError.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -93,6 +93,14 @@ const menuAside: MenuAsideItem[] = [
|
|||||||
icon: icon.mdiAccountCircle,
|
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',
|
href: '/home',
|
||||||
label: 'Home page',
|
label: 'Home page',
|
||||||
|
|||||||
79
frontend/src/pages/chat-gpt.tsx
Normal file
79
frontend/src/pages/chat-gpt.tsx
Normal 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;
|
||||||
Loading…
x
Reference in New Issue
Block a user