reorganizes the code, introduces preference slice
@@ -1,11 +1,11 @@
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import Navigation from './components/Navigation';
|
||||
import Conversation from './components/Conversation/Conversation';
|
||||
import APIKeyModal from './components/APIKeyModal';
|
||||
import About from './components/About';
|
||||
import Navigation from './Navigation';
|
||||
import Conversation from './conversation/Conversation';
|
||||
import APIKeyModal from './preferences/APIKeyModal';
|
||||
import About from './About';
|
||||
import { useState } from 'react';
|
||||
import { ActiveState } from './models/misc';
|
||||
import { selectApiKeyStatus } from './store';
|
||||
import { selectApiKeyStatus } from './preferences/preferenceSlice';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
export default function App() {
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { useMediaQuery } from '../hooks';
|
||||
import { toggleApiKeyModal } from '../store';
|
||||
import Arrow1 from '../imgs/arrow.svg';
|
||||
import Hamburger from '../imgs/hamburger.svg';
|
||||
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 { ActiveState } from '../models/misc';
|
||||
import Arrow1 from './assets/arrow.svg';
|
||||
import Hamburger from './assets/hamburger.svg';
|
||||
import Key from './assets/key.svg';
|
||||
import Info from './assets/info.svg';
|
||||
import Link from './assets/link.svg';
|
||||
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
|
||||
|
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 200 B |
|
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 391 B |
|
Before Width: | Height: | Size: 254 B After Width: | Height: | Size: 254 B |
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
|
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 293 B |
@@ -1,22 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export function useMediaQuery(query: string): boolean {
|
||||
const [matches, setMatches] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const media = window.matchMedia(query);
|
||||
|
||||
if (media.matches !== matches) {
|
||||
setMatches(media.matches);
|
||||
}
|
||||
|
||||
const listener = () => {
|
||||
setMatches(media.matches);
|
||||
};
|
||||
|
||||
media.addEventListener('resize', listener);
|
||||
return () => media.removeEventListener('resize', listener);
|
||||
}, [matches, query]);
|
||||
|
||||
return matches;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { setApiKey } from '../store';
|
||||
import { setApiKey } from './preferenceSlice';
|
||||
|
||||
export default function APIKeyModal({
|
||||
modalState,
|
||||
29
frontend/src/preferences/preferenceSlice.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import store from '../store';
|
||||
|
||||
interface Preference {
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
const initialState: Preference = {
|
||||
apiKey: '',
|
||||
};
|
||||
|
||||
export const prefSlice = createSlice({
|
||||
name: 'preference',
|
||||
initialState,
|
||||
reducers: {
|
||||
setApiKey: (state, action) => {
|
||||
state.apiKey = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setApiKey } = prefSlice.actions;
|
||||
export default prefSlice.reducer;
|
||||
|
||||
type RootState = ReturnType<typeof store.getState>;
|
||||
|
||||
export const selectApiKey = (state: RootState) => state.preference.apiKey;
|
||||
export const selectApiKeyStatus = (state: RootState) =>
|
||||
!!state.preference.apiKey;
|
||||
@@ -1,48 +1,12 @@
|
||||
import {
|
||||
configureStore,
|
||||
createSelector,
|
||||
createSlice,
|
||||
PayloadAction,
|
||||
} from '@reduxjs/toolkit';
|
||||
// import { configureStore, createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
interface State {
|
||||
isApiKeyModalOpen: boolean;
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
isApiKeyModalOpen: false,
|
||||
apiKey: '',
|
||||
};
|
||||
|
||||
export const slice = createSlice({
|
||||
name: 'app',
|
||||
initialState,
|
||||
reducers: {
|
||||
toggleApiKeyModal: (state) => {
|
||||
state.isApiKeyModalOpen = !state.isApiKeyModalOpen;
|
||||
console.log('showApiKeyModal', state.isApiKeyModalOpen);
|
||||
},
|
||||
setApiKey: (state, action: PayloadAction<string>) => {
|
||||
state.apiKey = action.payload;
|
||||
console.log('setApiKey', action.payload);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { toggleApiKeyModal, setApiKey } = slice.actions;
|
||||
import { configureStore } from '@reduxjs/toolkit';
|
||||
import { prefSlice } from './preferences/preferenceSlice';
|
||||
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
app: slice.reducer,
|
||||
preference: prefSlice.reducer,
|
||||
},
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||