Skip to content

Commit

Permalink
feat: ai chat | api trail feature (#611)
Browse files Browse the repository at this point in the history
* feat: api trial added

* feat: ai chat | fix issues

---------

Co-authored-by: Kabir <[email protected]>
  • Loading branch information
sumanjeet0012 and kabir0x23 authored Jan 29, 2024
1 parent bab72bf commit 132becd
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 9 deletions.
32 changes: 29 additions & 3 deletions src/components/AIChat/AIChat.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,25 @@ const AiChat = () => {
// }

const [chats, setChats] = useState([]);
const [isTrailEnded, setIsTrailEnded] = useState(false);

const trailMessage = [
{
type: "user",
content: "Your trial period has ended",
timestamp: "2024-01-29T07:15:09.752Z",
_id: "65b7507df24f3468473bb982",
},
{
type: "bot",
content: `Navigate to the Dashboard > Settings > API Key, claim your free api key and paste it in the input box to continue using this feature.`,
timestamp: "2024-01-29T07:15:09.752Z",
_id: "65b7507df24f3468473bb983",
},
];

const [userInput, setUserInput] = useState("");
const [isLoading, setIsLoading] = useState(false);

const [selectedChatId, setSelectedChatId] = useState(null);

const [toggle, setToggle] = useState(false);
Expand Down Expand Up @@ -96,7 +111,14 @@ const AiChat = () => {
setChats(chats);
setUserInput("");
} catch (error) {
toast("Please enter your API Key");
if (error.response.data.message === "Your trial period has ended") {
setIsTrailEnded(true);
toast("Your trial period has ended");
return;
}
// toast("Please enter your API Key");


// toast(error.response.data);
console.error(error);
} finally {
Expand Down Expand Up @@ -223,7 +245,11 @@ const AiChat = () => {
<SlOptionsVertical />
</ChatHeader>

<ChatMessages messages={chat.messages} />
<ChatMessages
messages={chat.messages}
isTrailEnded={isTrailEnded}
trailMessage={trailMessage}
/>

<div>
{chat.title !== "New Chat" ? null : (
Expand Down
13 changes: 11 additions & 2 deletions src/components/AIChat/ChatMessages.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useRef } from "react";
import { Messages, MessagesContainer, UserMessage } from "./AIChatElements";
import MarkdownPreview from "./MarkdownPreview";

const ChatMessages = ({ messages }) => {
const ChatMessages = ({ messages, isTrailEnded, trailMessage }) => {
const messagesContainerRef = useRef(null);

const scrollToBottom = () => {
Expand All @@ -15,7 +15,7 @@ const ChatMessages = ({ messages }) => {
setTimeout(() => {
scrollToBottom();
}, 0);
}, [messages]);
}, [messages, isTrailEnded]);

return (
<MessagesContainer>
Expand All @@ -27,6 +27,15 @@ const ChatMessages = ({ messages }) => {
<UserMessage key={index}> {message.content} </UserMessage>
),
)}

{isTrailEnded &&
trailMessage.map((message, index) =>
message.type === "bot" ? (
<MarkdownPreview key={index} source={message.content} />
) : (
<UserMessage key={index}> {message.content} </UserMessage>
),
)}
</Messages>
</MessagesContainer>
);
Expand Down
92 changes: 92 additions & 0 deletions src/components/Dashboard/Settings/Api/ApiForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { useEffect, useState } from "react";
import { getApiUrl } from "../../../../features/apiUrl";
import axios from "axios";
import { useSelector } from "react-redux";
import { toast } from "react-toastify";

export default function SettingsForm() {
const { user } = useSelector((state) => state.auth);
const API_BASE_URL = getApiUrl("api/aiChat");

const [geminiProApiKey, setApiKey] = useState({
value: "",
error: "",
});

useEffect(() => {
fetchApiKey();
}, []);

async function fetchApiKey() {
const response = await axios.get(
`${API_BASE_URL}/getApiKey`,

{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${user.token}`,
},
},
);
setApiKey({
value: response.data,
error: "",
});
}

async function handleSubmit(e) {
e.preventDefault();

if (!geminiProApiKey.value) {
return setApiKey((curr) => ({
...curr,
error: "Api Key required!",
}));
}

const response = await axios.post(
`${API_BASE_URL}/createApiKey`,
{
geminiProApiKey: geminiProApiKey.value,
},
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${user.token}`,
},
},
);

if (response.data.geminiProApiKey) {
toast("Successfully updated API Key");
}
}

function handleChange(e, setState) {
setState(() => ({
value: e.target.value,
error: "",
}));
}
console.log(geminiProApiKey);

return (
<form onSubmit={handleSubmit} className="settings-profile-form">
<div className="settings-profile-input-wrapper">
<label htmlFor="geminiProApiKey">Api Key</label>
<br />
<input
type="text"
value={geminiProApiKey.value || ""}
id="geminiProApiKey"
name="geminiProApiKey"
placeholder="Your API key"
onChange={(e) => handleChange(e, setApiKey)}
/>
</div>
<button type="submit" className="settings-profile-form-submitbtn">
Submit
</button>
</form>
);
}
64 changes: 64 additions & 0 deletions src/components/Dashboard/Settings/Api/api.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.api {
border-bottom: 1px solid #27272a;
max-width: 672px;
padding-block: 1em;
}

.api-heading {
margin-bottom: 0;
}

.api-info {
font-size: 14px;
color: #a1a1a1;
}

.api-form {
padding: 1.75em 0;
max-width: 672px;
}

.api-input-wrapper {
margin-bottom: 1em;
}

.api-form input {
background-color: #000000;
outline: none;
border: 1px solid #27272a;
height: 40px;
padding-inline-start: 1em;
border-radius: 6px;
letter-spacing: 0.7px;
color: #ffffff;
width: 100%;
margin-top: 0.5em;
transition: 300ms;
}

.api-form input:is(:hover, :focus) {
border: 1px solid #ffffff;
}

.api-form input::placeholder {
color: #a1a1a1;
}

.newApibtn {
background-color: #ff6b08;
color: #000000;
font-family: Roboto, sans-serif;
/* width: 100%; */
height: 30px;
border-radius: 6px;
border: 2px solid #ff6b08;
transition: 300ms;
font-weight: 500;
font-size: 16px;
}

.newApibtn:is(:hover, :focus) {
background-color: #000000;
color: #ff6b08;
cursor: pointer;
}
32 changes: 32 additions & 0 deletions src/components/Dashboard/Settings/Api/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import SettingsForm from "./ApiForm";
import "./api.css";

export default function Api() {
return (
<section style={{ width: "100%" }}>
<div>
<div className="api">
<h3 className="api-heading">Api</h3>
<p className="api-info">Entter Your gemini AI Api key.</p>
</div>

<div className="flex flex-row mt-2">
<p>Get your API Key:</p>
<a
className="text-white"
href="https://makersuite.google.com/app/apikey"
target="_blank"
rel="noreferrer"
>
<button className="newApibtn ml-2 pl-4 pr-4">Click here</button>
</a>
</div>

<div>
<SettingsForm />
</div>
</div>
</section>
);
}
13 changes: 9 additions & 4 deletions src/components/Dashboard/Settings/SettingsSidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,31 @@ const SIDEBAR_LINKS = [
},
{
id: 3,
label: "Api",
href: "/dashboard/settings/api",
},
{
id: 4,
label: "Appearance",
href: "/dashboard/settings/appearance",
},
{
id: 4,
id: 5,
label: "Notifications",
href: "/dashboard/settings/notifications",
},
{
id: 5,
id: 6,
label: "Display",
href: "/dashboard/settings/display",
},
{
id: 6,
id: 7,
label: "Dashboard",
href: "/dashboard",
},
{
id: 7,
id: 8,
label: "Home",
href: "/",
},
Expand Down
2 changes: 2 additions & 0 deletions src/components/Dashboard/Settings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Appearance from "./Appearance";
import Notifications from "./Notifications";
import Display from "./Display";
import NotFound from "../../../NotFound";
import Api from "./Api";

export default function SettingsRoute() {
return (
Expand All @@ -25,6 +26,7 @@ export default function SettingsRoute() {
<Route path={"appearance"} element={<Appearance />} />
<Route path={"notifications"} element={<Notifications />} />
<Route path={"display"} element={<Display />} />
<Route path={"api"} element={<Api />} />
<Route path={"*"} element={<NotFound />} />
</Routes>
</div>
Expand Down

0 comments on commit 132becd

Please sign in to comment.