mirror of
https://github.com/arc53/DocsGPT
synced 2024-11-17 21:26:26 +00:00
makes the api key modal work
This commit is contained in:
parent
1b6a58520c
commit
350ccad077
@ -4,21 +4,32 @@ import Conversation from './components/Conversation/Conversation';
|
|||||||
import APIKeyModal from './components/APIKeyModal';
|
import APIKeyModal from './components/APIKeyModal';
|
||||||
import About from './components/About';
|
import About from './components/About';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { NavState } from './models/misc';
|
import { ActiveState } from './models/misc';
|
||||||
|
import { selectApiKeyStatus } from './store';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [navState, setNavState] = useState<NavState>('OPEN');
|
const isApiKeySet = useSelector(selectApiKeyStatus);
|
||||||
|
const [navState, setNavState] = useState<ActiveState>('ACTIVE');
|
||||||
|
const [apiKeyModalState, setApiKeyModalState] = useState<ActiveState>(
|
||||||
|
isApiKeySet ? 'INACTIVE' : 'ACTIVE',
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-full min-w-full transition-all">
|
<div className="min-h-full min-w-full transition-all">
|
||||||
<APIKeyModal />
|
<APIKeyModal
|
||||||
|
modalState={apiKeyModalState}
|
||||||
|
setModalState={setApiKeyModalState}
|
||||||
|
isCancellable={isApiKeySet}
|
||||||
|
/>
|
||||||
<Navigation
|
<Navigation
|
||||||
navState={navState}
|
navState={navState}
|
||||||
setNavState={(val: NavState) => setNavState(val)}
|
setNavState={(val: ActiveState) => setNavState(val)}
|
||||||
|
setApiKeyModalState={setApiKeyModalState}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
navState === 'OPEN' ? 'ml-0 md:ml-72 lg:ml-96' : ' ml-0 md:ml-16'
|
navState === 'ACTIVE' ? 'ml-0 md:ml-72 lg:ml-96' : ' ml-0 md:ml-16'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Routes>
|
<Routes>
|
||||||
|
@ -1,34 +1,42 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import {
|
import { ActiveState } from '../models/misc';
|
||||||
setApiKey,
|
import { setApiKey } from '../store';
|
||||||
toggleApiKeyModal,
|
|
||||||
selectIsApiKeyModalOpen,
|
|
||||||
} from '../store';
|
|
||||||
|
|
||||||
export default function APIKeyModal() {
|
|
||||||
//TODO - Add form validation?
|
|
||||||
//TODO - Connect to backend
|
|
||||||
//TODO - Add link to OpenAI API Key page
|
|
||||||
|
|
||||||
|
export default function APIKeyModal({
|
||||||
|
modalState,
|
||||||
|
setModalState,
|
||||||
|
isCancellable = true,
|
||||||
|
}: {
|
||||||
|
modalState: ActiveState;
|
||||||
|
setModalState: (val: ActiveState) => void;
|
||||||
|
isCancellable?: boolean;
|
||||||
|
}) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const isApiModalOpen = useSelector(selectIsApiKeyModalOpen);
|
|
||||||
const [key, setKey] = useState('');
|
const [key, setKey] = useState('');
|
||||||
const [formError, setFormError] = useState(false);
|
const [isError, setIsError] = useState(false);
|
||||||
|
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
if (key.length < 1) {
|
if (key.length <= 1) {
|
||||||
setFormError(true);
|
setIsError(true);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
dispatch(setApiKey(key));
|
dispatch(setApiKey(key));
|
||||||
dispatch(toggleApiKeyModal());
|
setModalState('INACTIVE');
|
||||||
|
setKey('');
|
||||||
|
setIsError(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCancel() {
|
||||||
|
setKey('');
|
||||||
|
setIsError(false);
|
||||||
|
setModalState('INACTIVE');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
isApiModalOpen ? 'visible' : 'hidden'
|
modalState === 'ACTIVE' ? 'visible' : 'hidden'
|
||||||
} absolute z-30 h-screen w-screen bg-gray-alpha`}
|
} absolute z-30 h-screen w-screen bg-gray-alpha`}
|
||||||
>
|
>
|
||||||
<article className="mx-auto mt-24 flex w-[90vw] max-w-lg flex-col gap-4 rounded-lg bg-white p-6 shadow-lg">
|
<article className="mx-auto mt-24 flex w-[90vw] max-w-lg flex-col gap-4 rounded-lg bg-white p-6 shadow-lg">
|
||||||
@ -46,16 +54,28 @@ export default function APIKeyModal() {
|
|||||||
placeholder="API Key"
|
placeholder="API Key"
|
||||||
onChange={(e) => setKey(e.target.value)}
|
onChange={(e) => setKey(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-between">
|
<div className="flex flex-row-reverse">
|
||||||
{formError && (
|
<div>
|
||||||
<p className="text-sm text-red-500">Please enter a valid API key</p>
|
|
||||||
)}
|
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSubmit()}
|
onClick={() => handleSubmit()}
|
||||||
className="ml-auto h-10 w-20 rounded-lg bg-violet-800 text-white transition-all hover:bg-violet-700"
|
className="ml-auto h-10 w-20 rounded-lg bg-violet-800 text-white transition-all hover:bg-violet-700"
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
|
{isCancellable && (
|
||||||
|
<button
|
||||||
|
onClick={() => handleCancel()}
|
||||||
|
className="ml-5 h-10 w-20 rounded-lg border border-violet-700 bg-white text-violet-800 transition-all hover:bg-violet-700 hover:text-white"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{isError && (
|
||||||
|
<p className="mr-auto text-sm text-red-500">
|
||||||
|
Please enter a valid API key
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,7 +8,7 @@ import Key from '../imgs/key.svg';
|
|||||||
import Info from '../imgs/info.svg';
|
import Info from '../imgs/info.svg';
|
||||||
import Link from '../imgs/link.svg';
|
import Link from '../imgs/link.svg';
|
||||||
import Exit from '../imgs/exit.svg';
|
import Exit from '../imgs/exit.svg';
|
||||||
import { NavState } from '../models/misc';
|
import { ActiveState } from '../models/misc';
|
||||||
|
|
||||||
//TODO - Need to replace Chat button to open secondary nav with scrollable past chats option and new chat at top
|
//TODO - Need to replace Chat button to open secondary nav with scrollable past chats option and new chat at top
|
||||||
//TODO - Need to add Discord and Github links
|
//TODO - Need to add Discord and Github links
|
||||||
@ -16,16 +16,18 @@ import { NavState } from '../models/misc';
|
|||||||
export default function Navigation({
|
export default function Navigation({
|
||||||
navState,
|
navState,
|
||||||
setNavState,
|
setNavState,
|
||||||
|
setApiKeyModalState,
|
||||||
}: {
|
}: {
|
||||||
navState: NavState;
|
navState: ActiveState;
|
||||||
setNavState: (val: NavState) => void;
|
setNavState: (val: ActiveState) => void;
|
||||||
|
setApiKeyModalState: (val: ActiveState) => void;
|
||||||
}) {
|
}) {
|
||||||
const openNav = (
|
const openNav = (
|
||||||
<div className="fixed h-full w-72 flex-col border-r-2 border-gray-100 bg-gray-50 transition-all md:visible md:flex lg:w-96">
|
<div className="fixed h-full w-72 flex-col border-r-2 border-gray-100 bg-gray-50 transition-all md:visible md:flex lg:w-96">
|
||||||
<div className={'h-16 w-full border-b-2 border-gray-100'}>
|
<div className={'h-16 w-full border-b-2 border-gray-100'}>
|
||||||
<button
|
<button
|
||||||
className="float-right mr-5 mt-5 h-5 w-5"
|
className="float-right mr-5 mt-5 h-5 w-5"
|
||||||
onClick={() => setNavState('CLOSED')}
|
onClick={() => setNavState('INACTIVE')}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={Arrow1}
|
src={Arrow1}
|
||||||
@ -40,7 +42,7 @@ export default function Navigation({
|
|||||||
<div
|
<div
|
||||||
className="my-auto mx-4 flex h-12 cursor-pointer gap-4 rounded-md hover:bg-gray-100"
|
className="my-auto mx-4 flex h-12 cursor-pointer gap-4 rounded-md hover:bg-gray-100"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
return;
|
setApiKeyModalState('ACTIVE');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img src={Key} alt="key" className="ml-2 w-6" />
|
<img src={Key} alt="key" className="ml-2 w-6" />
|
||||||
@ -76,7 +78,7 @@ export default function Navigation({
|
|||||||
<div className={'h-16 w-16 border-b-2 border-gray-100'}>
|
<div className={'h-16 w-16 border-b-2 border-gray-100'}>
|
||||||
<button
|
<button
|
||||||
className="float-right mr-5 mt-5 h-5 w-5"
|
className="float-right mr-5 mt-5 h-5 w-5"
|
||||||
onClick={() => setNavState('OPEN')}
|
onClick={() => setNavState('ACTIVE')}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={Arrow1}
|
src={Arrow1}
|
||||||
@ -88,12 +90,12 @@ export default function Navigation({
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
className="fixed mt-5 ml-6 h-6 w-6 md:hidden"
|
className="fixed mt-5 ml-6 h-6 w-6 md:hidden"
|
||||||
onClick={() => setNavState('OPEN')}
|
onClick={() => setNavState('ACTIVE')}
|
||||||
>
|
>
|
||||||
<img src={Hamburger} alt="menu toggle" className="w-7" />
|
<img src={Hamburger} alt="menu toggle" className="w-7" />
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
return navState === 'OPEN' ? openNav : closedNav;
|
return navState === 'ACTIVE' ? openNav : closedNav;
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
export type NavState = 'OPEN' | 'CLOSED';
|
export type ActiveState = 'ACTIVE' | 'INACTIVE';
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit';
|
import {
|
||||||
|
configureStore,
|
||||||
|
createSelector,
|
||||||
|
createSlice,
|
||||||
|
PayloadAction,
|
||||||
|
} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
isApiKeyModalOpen: boolean;
|
isApiKeyModalOpen: boolean;
|
||||||
@ -38,5 +43,6 @@ type RootState = ReturnType<typeof store.getState>;
|
|||||||
export const selectIsApiKeyModalOpen = (state: RootState) =>
|
export const selectIsApiKeyModalOpen = (state: RootState) =>
|
||||||
state.app.isApiKeyModalOpen;
|
state.app.isApiKeyModalOpen;
|
||||||
export const selectApiKey = (state: RootState) => state.app.apiKey;
|
export const selectApiKey = (state: RootState) => state.app.apiKey;
|
||||||
|
export const selectApiKeyStatus = (state: RootState) => !!state.app.apiKey;
|
||||||
|
|
||||||
export default store;
|
export default store;
|
||||||
|
Loading…
Reference in New Issue
Block a user