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 About from './components/About';
|
||||
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() {
|
||||
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 (
|
||||
<div className="min-h-full min-w-full transition-all">
|
||||
<APIKeyModal />
|
||||
<APIKeyModal
|
||||
modalState={apiKeyModalState}
|
||||
setModalState={setApiKeyModalState}
|
||||
isCancellable={isApiKeySet}
|
||||
/>
|
||||
<Navigation
|
||||
navState={navState}
|
||||
setNavState={(val: NavState) => setNavState(val)}
|
||||
setNavState={(val: ActiveState) => setNavState(val)}
|
||||
setApiKeyModalState={setApiKeyModalState}
|
||||
/>
|
||||
<div
|
||||
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>
|
||||
|
@ -1,34 +1,42 @@
|
||||
import { useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
setApiKey,
|
||||
toggleApiKeyModal,
|
||||
selectIsApiKeyModalOpen,
|
||||
} from '../store';
|
||||
|
||||
export default function APIKeyModal() {
|
||||
//TODO - Add form validation?
|
||||
//TODO - Connect to backend
|
||||
//TODO - Add link to OpenAI API Key page
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { setApiKey } from '../store';
|
||||
|
||||
export default function APIKeyModal({
|
||||
modalState,
|
||||
setModalState,
|
||||
isCancellable = true,
|
||||
}: {
|
||||
modalState: ActiveState;
|
||||
setModalState: (val: ActiveState) => void;
|
||||
isCancellable?: boolean;
|
||||
}) {
|
||||
const dispatch = useDispatch();
|
||||
const isApiModalOpen = useSelector(selectIsApiKeyModalOpen);
|
||||
const [key, setKey] = useState('');
|
||||
const [formError, setFormError] = useState(false);
|
||||
const [isError, setIsError] = useState(false);
|
||||
|
||||
function handleSubmit() {
|
||||
if (key.length < 1) {
|
||||
setFormError(true);
|
||||
return;
|
||||
}
|
||||
if (key.length <= 1) {
|
||||
setIsError(true);
|
||||
} else {
|
||||
dispatch(setApiKey(key));
|
||||
dispatch(toggleApiKeyModal());
|
||||
setModalState('INACTIVE');
|
||||
setKey('');
|
||||
setIsError(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
setKey('');
|
||||
setIsError(false);
|
||||
setModalState('INACTIVE');
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${
|
||||
isApiModalOpen ? 'visible' : 'hidden'
|
||||
modalState === 'ACTIVE' ? 'visible' : 'hidden'
|
||||
} 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">
|
||||
@ -46,16 +54,28 @@ export default function APIKeyModal() {
|
||||
placeholder="API Key"
|
||||
onChange={(e) => setKey(e.target.value)}
|
||||
/>
|
||||
<div className="flex justify-between">
|
||||
{formError && (
|
||||
<p className="text-sm text-red-500">Please enter a valid API key</p>
|
||||
)}
|
||||
<div className="flex flex-row-reverse">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => handleSubmit()}
|
||||
className="ml-auto h-10 w-20 rounded-lg bg-violet-800 text-white transition-all hover:bg-violet-700"
|
||||
>
|
||||
Save
|
||||
</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>
|
||||
</article>
|
||||
</div>
|
||||
|
@ -8,7 +8,7 @@ import Key from '../imgs/key.svg';
|
||||
import Info from '../imgs/info.svg';
|
||||
import Link from '../imgs/link.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 add Discord and Github links
|
||||
@ -16,16 +16,18 @@ import { NavState } from '../models/misc';
|
||||
export default function Navigation({
|
||||
navState,
|
||||
setNavState,
|
||||
setApiKeyModalState,
|
||||
}: {
|
||||
navState: NavState;
|
||||
setNavState: (val: NavState) => void;
|
||||
navState: ActiveState;
|
||||
setNavState: (val: ActiveState) => void;
|
||||
setApiKeyModalState: (val: ActiveState) => void;
|
||||
}) {
|
||||
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={'h-16 w-full border-b-2 border-gray-100'}>
|
||||
<button
|
||||
className="float-right mr-5 mt-5 h-5 w-5"
|
||||
onClick={() => setNavState('CLOSED')}
|
||||
onClick={() => setNavState('INACTIVE')}
|
||||
>
|
||||
<img
|
||||
src={Arrow1}
|
||||
@ -40,7 +42,7 @@ export default function Navigation({
|
||||
<div
|
||||
className="my-auto mx-4 flex h-12 cursor-pointer gap-4 rounded-md hover:bg-gray-100"
|
||||
onClick={() => {
|
||||
return;
|
||||
setApiKeyModalState('ACTIVE');
|
||||
}}
|
||||
>
|
||||
<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'}>
|
||||
<button
|
||||
className="float-right mr-5 mt-5 h-5 w-5"
|
||||
onClick={() => setNavState('OPEN')}
|
||||
onClick={() => setNavState('ACTIVE')}
|
||||
>
|
||||
<img
|
||||
src={Arrow1}
|
||||
@ -88,12 +90,12 @@ export default function Navigation({
|
||||
</div>
|
||||
<button
|
||||
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" />
|
||||
</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 {
|
||||
isApiKeyModalOpen: boolean;
|
||||
@ -38,5 +43,6 @@ type RootState = ReturnType<typeof store.getState>;
|
||||
export const selectIsApiKeyModalOpen = (state: RootState) =>
|
||||
state.app.isApiKeyModalOpen;
|
||||
export const selectApiKey = (state: RootState) => state.app.apiKey;
|
||||
export const selectApiKeyStatus = (state: RootState) => !!state.app.apiKey;
|
||||
|
||||
export default store;
|
||||
|
Loading…
Reference in New Issue
Block a user